refactor: 访问结果内容改用七牛云/本地存储,与 config 文件存储方式一致
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 '响应耗时(毫秒)',
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user