From 0568923ce9d5a047eb16aafff5e7115410758757 Mon Sep 17 00:00:00 2001 From: mediabot-pt <295750538+mediabot-pt@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:41:15 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E8=AE=BF=E9=97=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E5=86=85=E5=AE=B9=E6=94=B9=E7=94=A8=E4=B8=83=E7=89=9B?= =?UTF-8?q?=E4=BA=91/=E6=9C=AC=E5=9C=B0=E5=AD=98=E5=82=A8=EF=BC=8C?= =?UTF-8?q?=E4=B8=8E=20config=20=E6=96=87=E4=BB=B6=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AccessResultController.java | 8 ++--- .../com/par/core/dto/AccessResultDTO.java | 1 + .../com/par/core/entity/AccessResult.java | 4 +-- .../par/core/service/AccessResultService.java | 12 +++---- .../service/impl/AccessResultServiceImpl.java | 34 +++++++++++++++---- .../db/migration/V10__access_results.sql | 2 +- web/src/views/AccessResults.vue | 11 ++++-- 7 files changed, 50 insertions(+), 22 deletions(-) diff --git a/par-api/src/main/java/com/par/api/controller/AccessResultController.java b/par-api/src/main/java/com/par/api/controller/AccessResultController.java index e13e09d..f6ee7e9 100644 --- a/par-api/src/main/java/com/par/api/controller/AccessResultController.java +++ b/par-api/src/main/java/com/par/api/controller/AccessResultController.java @@ -74,15 +74,15 @@ public class AccessResultController { } /** - * 获取单个访问结果详情(含完整内容) + * 获取单个访问结果详情(含完整内容,从存储读取) */ @GetMapping("/api/v1/admin/access-results/{id}") public ApiResponse getById(@PathVariable("id") Long id) { - AccessResult result = accessResultService.getById(id); - if (result == null) { + AccessResultDTO dto = accessResultService.getDetailById(id); + if (dto == null) { return ApiResponse.error(404, "访问结果不存在"); } - return ApiResponse.success(accessResultService.toDTO(result)); + return ApiResponse.success(dto); } /** diff --git a/par-core/src/main/java/com/par/core/dto/AccessResultDTO.java b/par-core/src/main/java/com/par/core/dto/AccessResultDTO.java index 5b181e1..7b254b9 100644 --- a/par-core/src/main/java/com/par/core/dto/AccessResultDTO.java +++ b/par-core/src/main/java/com/par/core/dto/AccessResultDTO.java @@ -15,6 +15,7 @@ public class AccessResultDTO { private String configVersion; private String clientId; private String contentType; + private String storagePath; private String content; private String url; private Integer statusCode; diff --git a/par-core/src/main/java/com/par/core/entity/AccessResult.java b/par-core/src/main/java/com/par/core/entity/AccessResult.java index 888bf91..dd69bbd 100644 --- a/par-core/src/main/java/com/par/core/entity/AccessResult.java +++ b/par-core/src/main/java/com/par/core/entity/AccessResult.java @@ -27,8 +27,8 @@ public class AccessResult { @TableField("content_type") private String contentType; - @TableField("content") - private String content; + @TableField("storage_path") + private String storagePath; @TableField("url") private String url; diff --git a/par-core/src/main/java/com/par/core/service/AccessResultService.java b/par-core/src/main/java/com/par/core/service/AccessResultService.java index 3e38ecd..305dddf 100644 --- a/par-core/src/main/java/com/par/core/service/AccessResultService.java +++ b/par-core/src/main/java/com/par/core/service/AccessResultService.java @@ -11,26 +11,26 @@ import java.util.List; public interface AccessResultService { /** - * 提交访问结果(mediabot 调用) + * 提交访问结果(mediabot 调用),内容存储到七牛云/本地 */ AccessResult submit(String siteId, String configVersion, String clientId, String contentType, String content, String url, Integer statusCode, Integer responseTimeMs, Long submitterId); /** - * 获取所有访问结果 + * 获取所有访问结果(不含内容) */ List listAll(); /** - * 获取指定站点的访问结果 + * 获取指定站点的访问结果(不含内容) */ List listBySiteId(String siteId); /** - * 获取单个访问结果详情 + * 获取单个访问结果(从存储读取内容) */ - AccessResult getById(Long id); + AccessResultDTO getDetailById(Long id); /** * 标记验证结果(有效/无效) @@ -38,7 +38,7 @@ public interface AccessResultService { AccessResult validate(Long id, Boolean isValid, String note); /** - * 实体转 DTO + * 实体转 DTO(不含内容) */ AccessResultDTO toDTO(AccessResult entity); } diff --git a/par-core/src/main/java/com/par/core/service/impl/AccessResultServiceImpl.java b/par-core/src/main/java/com/par/core/service/impl/AccessResultServiceImpl.java index 0c8b1da..13c227f 100644 --- a/par-core/src/main/java/com/par/core/service/impl/AccessResultServiceImpl.java +++ b/par-core/src/main/java/com/par/core/service/impl/AccessResultServiceImpl.java @@ -4,11 +4,13 @@ import com.par.core.dto.AccessResultDTO; import com.par.core.entity.AccessResult; import com.par.core.mapper.AccessResultMapper; import com.par.core.service.AccessResultService; +import com.par.core.storage.CachedStorageService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; @Slf4j @@ -17,24 +19,32 @@ import java.util.stream.Collectors; public class AccessResultServiceImpl implements AccessResultService { private final AccessResultMapper mapper; + private final CachedStorageService storageService; @Override public AccessResult submit(String siteId, String configVersion, String clientId, String contentType, String content, String url, Integer statusCode, Integer responseTimeMs, Long submitterId) { + String type = (contentType != null && !contentType.isBlank()) ? contentType : "html"; + String ext = "json".equalsIgnoreCase(type) ? "json" : "html"; + String storagePath = String.format("access-results/%s/%d_%s.%s", + siteId, System.currentTimeMillis(), UUID.randomUUID().toString().substring(0, 8), ext); + + // 存储到抽象存储层(七牛云或本地) + storageService.store(storagePath, content); + AccessResult result = new AccessResult(); result.setSiteId(siteId); result.setConfigVersion(configVersion); result.setClientId(clientId); - result.setContentType(contentType != null ? contentType : "html"); - result.setContent(content); + result.setContentType(type); + result.setStoragePath(storagePath); result.setUrl(url); result.setStatusCode(statusCode); result.setResponseTimeMs(responseTimeMs); result.setSubmitterId(submitterId != null ? submitterId : 0L); mapper.insert(result); - log.info("Access result submitted: siteId={}, version={}, clientId={}, id={}", - siteId, configVersion, clientId, result.getId()); + log.info("Access result submitted: siteId={}, version={}, clientId={}, id={}", siteId, configVersion, clientId, result.getId()); return result; } @@ -49,8 +59,18 @@ public class AccessResultServiceImpl implements AccessResultService { } @Override - public AccessResult getById(Long id) { - return mapper.selectById(id); + public AccessResultDTO getDetailById(Long id) { + AccessResult result = mapper.selectById(id); + if (result == null) return null; + AccessResultDTO dto = toDTO(result); + // 从存储读取内容 + try { + dto.setContent(storageService.read(result.getStoragePath())); + } catch (Exception e) { + log.error("读取访问结果内容失败 id={} path={}: {}", id, result.getStoragePath(), e.getMessage()); + dto.setContent("读取内容失败: " + e.getMessage()); + } + return dto; } @Override @@ -73,7 +93,7 @@ public class AccessResultServiceImpl implements AccessResultService { dto.setConfigVersion(entity.getConfigVersion()); dto.setClientId(entity.getClientId()); dto.setContentType(entity.getContentType()); - dto.setContent(entity.getContent()); + dto.setStoragePath(entity.getStoragePath()); dto.setUrl(entity.getUrl()); dto.setStatusCode(entity.getStatusCode()); dto.setResponseTimeMs(entity.getResponseTimeMs()); diff --git a/par-core/src/main/resources/db/migration/V10__access_results.sql b/par-core/src/main/resources/db/migration/V10__access_results.sql index 313c34e..74e4090 100644 --- a/par-core/src/main/resources/db/migration/V10__access_results.sql +++ b/par-core/src/main/resources/db/migration/V10__access_results.sql @@ -5,7 +5,7 @@ CREATE TABLE access_results ( config_version VARCHAR(20) COMMENT '使用的配置版本号', client_id VARCHAR(128) COMMENT '提交者标识(mediabot 客户端 ID)', content_type VARCHAR(10) NOT NULL DEFAULT 'html' COMMENT '数据类型:html / json', - content MEDIUMTEXT NOT NULL COMMENT '访问站点返回的内容', + storage_path VARCHAR(500) NOT NULL COMMENT '内容存储路径(七牛云/本地)', url VARCHAR(500) COMMENT '访问的站点 URL', status_code INT COMMENT 'HTTP 状态码', response_time_ms INT COMMENT '响应耗时(毫秒)', diff --git a/web/src/views/AccessResults.vue b/web/src/views/AccessResults.vue index 3cb9a45..4836de8 100644 --- a/web/src/views/AccessResults.vue +++ b/web/src/views/AccessResults.vue @@ -157,9 +157,16 @@ const fetchAll = async () => { finally { loading.value = false } } -const handleView = (row) => { - detail.value = { ...row } +const handleView = async (row) => { + // 详情需从服务端获取完整内容 detailVisible.value = true + try { + const r = await api.accessResults.get(row.id) + detail.value = r.data || {} + } catch { + ElMessage.error('获取详情失败') + detail.value = { ...row } + } } const handleValidate = async (row, isValid) => {