refactor: 访问结果内容改用七牛云/本地存储,与 config 文件存储方式一致

This commit is contained in:
mediabot-pt
2026-06-30 22:41:15 +08:00
parent 83e150b8c9
commit 0568923ce9
7 changed files with 50 additions and 22 deletions

View File

@@ -74,15 +74,15 @@ public class AccessResultController {
}
/**
* 获取单个访问结果详情(含完整内容)
* 获取单个访问结果详情(含完整内容,从存储读取)
*/
@GetMapping("/api/v1/admin/access-results/{id}")
public ApiResponse<AccessResultDTO> 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);
}
/**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<AccessResultDTO> listAll();
/**
* 获取指定站点的访问结果
* 获取指定站点的访问结果(不含内容)
*/
List<AccessResultDTO> 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);
}

View File

@@ -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());

View File

@@ -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 '响应耗时(毫秒)',

View File

@@ -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) => {