diff --git a/par-api/src/main/java/com/par/api/controller/AdminController.java b/par-api/src/main/java/com/par/api/controller/AdminController.java index ec6ec8c..da93b5a 100644 --- a/par-api/src/main/java/com/par/api/controller/AdminController.java +++ b/par-api/src/main/java/com/par/api/controller/AdminController.java @@ -337,6 +337,21 @@ public class AdminController { // ===================== 站点审核 ===================== + /** 发布站点配置到七牛云(生成 manifest/manifest.json) */ + @PostMapping("/sites/publish") + public ApiResponse> publishManifest(HttpServletRequest request) { + checkAdmin(request); + try { + var manifest = buildManifest(); + String json = new com.fasterxml.jackson.databind.ObjectMapper() + .writerWithDefaultPrettyPrinter().writeValueAsString(manifest); + storageService.store("manifest/manifest.json", json); + log.info("Manifest published: {} sites", ((List)manifest.get("sites")).size()); + return ApiResponse.success(Map.of("version", manifest.get("version"), + "sites", ((List)manifest.get("sites")).size())); + } catch (Exception e) { return ApiResponse.error(500, "发布失败: " + e.getMessage()); } + } + @GetMapping("/sites") public ApiResponse> listAllSites(HttpServletRequest request) { checkAdmin(request); @@ -505,6 +520,43 @@ public class AdminController { catch (Exception e) { return java.util.List.of(); } } + // buildManifest = 复用 ManifestController 逻辑 + @SuppressWarnings("unchecked") + private Map buildManifest() { + var sites = siteService.listAllSites(); + List> list = new ArrayList<>(); + int total = 0; + for (var site : sites) { + var dto = siteService.toDTO(site); + Map e = new LinkedHashMap<>(); + e.put("siteId", site.getSiteId()); + e.put("names", dto.getNames()); + e.put("urls", dto.getUrls()); + e.put("tags", dto.getTags()); + e.put("description", dto.getDescription()); + e.put("siteType", site.getSiteType() != null ? site.getSiteType().getValue() : null); + e.put("status", site.getStatus() != null ? site.getStatus().getValue() : null); + e.put("version", site.getVersion() != null ? site.getVersion() : 1); + var latest = siteConfigMapper.selectLatestBySiteId(site.getSiteId()); + e.put("latestVersion", latest != null ? latest.getVersion() : null); + e.put("hasScript", latest != null && latest.getScriptStoragePath() != null && !latest.getScriptStoragePath().isBlank()); + e.put("hasPages", sitePagesMapper.selectCount( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(com.par.core.entity.SitePages::getSiteId, site.getSiteId()) + .eq(com.par.core.entity.SitePages::getDeleted, 0)) > 0); + e.put("hasRisk", riskRuleMapper.selectCount( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(com.par.core.entity.RiskRule::getSiteType, site.getSiteType().getValue()) + .eq(com.par.core.entity.RiskRule::getDeleted, 0)) > 0); + total += (site.getVersion() != null ? site.getVersion() : 1); + list.add(e); + } + Map m = new LinkedHashMap<>(); + m.put("version", total); + m.put("sites", list); + return m; + } + private void checkAdmin(HttpServletRequest request) { TrustLevel level = (TrustLevel) request.getAttribute("trustLevel"); if (level == null || level != TrustLevel.ADMIN) { diff --git a/web/src/views/Sites.vue b/web/src/views/Sites.vue index b3be8c2..aaf6ee0 100644 --- a/web/src/views/Sites.vue +++ b/web/src/views/Sites.vue @@ -55,8 +55,9 @@

站点编辑: {{ editSiteId }}

- 保存 返回列表 + 保存 + 发布
@@ -106,7 +107,7 @@