From b3667d7b7da586f96dd23d79aba4982aa93a9ac6 Mon Sep 17 00:00:00 2001 From: mediabot-pt <295750538+mediabot-pt@users.noreply.github.com> Date: Wed, 1 Jul 2026 08:50:06 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=80=82=E9=85=8D=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E9=A1=B5=E9=87=8D=E6=9E=84=E4=B8=BA=E9=A1=B6=E6=A0=8F?= =?UTF-8?q?=E9=80=89=E9=85=8D=E7=BD=AE+=E8=87=AA=E5=8A=A8=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E8=A7=A3=E6=9E=90+URL=E5=8D=A1=E7=89=87=E5=86=85?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E6=8F=90=E5=8F=96=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../par/api/controller/AdapterController.java | 77 ++- web/src/api/index.js | 1 + web/src/views/AccessResultCheck.vue | 587 +++++++----------- 3 files changed, 291 insertions(+), 374 deletions(-) diff --git a/par-api/src/main/java/com/par/api/controller/AdapterController.java b/par-api/src/main/java/com/par/api/controller/AdapterController.java index 34b3d09..621df08 100644 --- a/par-api/src/main/java/com/par/api/controller/AdapterController.java +++ b/par-api/src/main/java/com/par/api/controller/AdapterController.java @@ -13,7 +13,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** * 适配器解析控制器 @@ -77,6 +78,80 @@ public class AdapterController { return ApiResponse.success(result); } + /** + * 批量解析:用指定配置解析站点所有URL的最新访问结果 + */ + @PostMapping("/api/v1/admin/adapter/parse-batch") + public ApiResponse> parseBatch(@RequestBody Map payload) { + Long configId = toLong(payload.get("configId")); + String siteId = (String) payload.get("siteId"); + + if (configId == null || siteId == null) { + return ApiResponse.error(400, "configId and siteId are required"); + } + + // 加载配置 + SiteConfig siteConfig = siteConfigMapper.selectById(configId); + if (siteConfig == null) return ApiResponse.error(404, "配置不存在"); + + String configJson; + try { configJson = storageService.read(siteConfig.getStoragePath()); } + catch (Exception e) { return ApiResponse.error(500, "读取配置失败: " + e.getMessage()); } + if (configJson == null) return ApiResponse.error(404, "配置内容为空"); + + AdapterConfig adapterConfig; + try { adapterConfig = objectMapper.readValue(configJson, AdapterConfig.class); } + catch (Exception e) { return ApiResponse.error(400, "配置格式无效: " + e.getMessage()); } + + // 获取该站点所有结果,按URL分组取最新 + List allResults = accessResultMapper.selectBySiteId(siteId); + Map latestByUrl = allResults.stream() + .filter(r -> r.getUrl() != null && !r.getUrl().isBlank()) + .collect(Collectors.toMap( + AccessResult::getUrl, + r -> r, + (a, b) -> a.getCreatedAt().isAfter(b.getCreatedAt()) ? a : b)); + + // 批量解析 + Map response = new LinkedHashMap<>(); + response.put("configId", configId); + response.put("configVersion", siteConfig.getVersion()); + response.put("totalUrls", latestByUrl.size()); + response.put("totalResults", allResults.size()); + + List> pages = new ArrayList<>(); + for (Map.Entry entry : latestByUrl.entrySet()) { + String url = entry.getKey(); + AccessResult ar = entry.getValue(); + Map item = new LinkedHashMap<>(); + item.put("url", url); + item.put("accessResultId", ar.getId()); + item.put("statusCode", ar.getStatusCode()); + item.put("responseTimeMs", ar.getResponseTimeMs()); + item.put("createdAt", ar.getCreatedAt()); + item.put("totalCount", allResults.stream().filter(r -> url.equals(r.getUrl())).count()); + item.put("validCount", allResults.stream().filter(r -> url.equals(r.getUrl()) && Boolean.TRUE.equals(r.getIsValid())).count()); + item.put("invalidCount", allResults.stream().filter(r -> url.equals(r.getUrl()) && Boolean.FALSE.equals(r.getIsValid())).count()); + item.put("uncheckedCount", allResults.stream().filter(r -> url.equals(r.getUrl()) && r.getIsValid() == null).count()); + + // 解析 HTML + try { + String html = storageService.read(ar.getStoragePath()); + if (html != null) { + Map parsed = adapterEngine.extract(adapterConfig, html, url); + item.put("parsed", parsed); + } + } catch (Exception e) { + item.put("parseError", e.getMessage()); + } + + pages.add(item); + } + + response.put("pages", pages); + return ApiResponse.success(response); + } + private Long toLong(Object val) { if (val instanceof Number n) return n.longValue(); if (val instanceof String s) { diff --git a/web/src/api/index.js b/web/src/api/index.js index d9f1916..84ecfcd 100644 --- a/web/src/api/index.js +++ b/web/src/api/index.js @@ -88,6 +88,7 @@ export default { }, adapter: { parse: (configId, accessResultId) => api.post('/admin/adapter/parse', { configId, accessResultId }), + parseBatch: (configId, siteId) => api.post('/admin/adapter/parse-batch', { configId, siteId }), }, health: () => api.get('/health', { baseURL: '' }) } diff --git a/web/src/views/AccessResultCheck.vue b/web/src/views/AccessResultCheck.vue index f9ef82c..a2c7258 100644 --- a/web/src/views/AccessResultCheck.vue +++ b/web/src/views/AccessResultCheck.vue @@ -1,473 +1,314 @@