package com.yunhai.cms.service.impl; import com.yunhai.cms.model.vo.ThemeVo; import com.yunhai.cms.theme.ThemeInfo; import com.yunhai.cms.theme.ThemeRegistry; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * 主题管理(方案 §5.1/§5.2):主题列表(含参数 schema)供管理端卡片选择与 * 参数表单动态生成;screenshot 与预览资产经 /api/theme/{name}/asset/** 代理。 */ @Service @RequiredArgsConstructor public class ThemeService { private final ThemeRegistry themeRegistry; private final com.yunhai.cms.repository.CmsSiteRepository siteRepository; /** 可用主题(default 优先,其余按名称排序),管理端建站向导与站点编辑共用。 * W1(G1/T-W1-14):增 source/inUseCount/editable——来源与删除保护口径同源(findByTheme)。 */ public List list() { List result = new ArrayList<>(); for (ThemeInfo info : themeRegistry.list()) { result.add(voOf(info)); } return result; } /** 单个包 VO 装配(来源/被用数/可编辑随 Registry sourceOf 与站点仓储实时装配) */ public ThemeVo voOf(ThemeInfo info) { ThemeVo vo = ThemeVo.of(info); String source = themeRegistry.sourceOf(info.getName()) == null ? ThemeRegistry.SOURCE_BUILTIN : themeRegistry.sourceOf(info.getName()); vo.setSource(source); java.util.List usedBy = siteRepository.findByTheme(info.getName()); vo.setInUseCount(usedBy.size()); java.util.List usedNames = new ArrayList<>(); for (com.yunhai.cms.entity.CmsSite s : usedBy) { usedNames.add(s.getName()); } vo.setUsedBySiteNames(usedNames); // 任务四:语义改为「可编辑元数据」——内置包亦可改显示名/描述(.meta 覆盖层),内容仍只读 vo.setEditable(true); return vo; } /** 未注册主题返回 null(白名单判断用) */ public ThemeInfo get(String name) { return themeRegistry.get(name); } /** 未注册主题抛 PARAM_ERROR(预览接口明确 400 语义,不静默回退,方案 §5.5/T27) */ public ThemeInfo requireRegistered(String name) { ThemeInfo info = themeRegistry.get(name); if (info == null) { throw new com.yunhai.platform.apistd.BizException( com.yunhai.platform.utils.exception.ErrorCode.PARAM_ERROR, "皮肤包未注册:" + name); } return info; } /** * 提取预览 p_* 前缀参数并按主题 schema 过滤(方案 §5.5): * key 为 theme.json 声明过的,# 由前端 URLSearchParams 自动编码为 %23(容器已解码)。 */ public java.util.Map extractPreviewParams(ThemeInfo info, java.util.Map parameterMap) { java.util.Map raw = new java.util.LinkedHashMap<>(); if (parameterMap != null) { for (java.util.Map.Entry e : parameterMap.entrySet()) { if (e.getKey().startsWith("p_") && e.getValue() != null && e.getValue().length > 0) { raw.put(e.getKey().substring(2), e.getValue()[0]); } } } return info.filterValidValues(raw); } }