# 模板切换功能闭环 — 改动与验证清单 > 目标:后台 `/templates` 选用模板 → 公开站 `website-template` 首页(及各页)自动渲染所选模板。 > 闭环真相源:`cms_website.template_id`(按租户),后台写、前台读。 ## 〇、架构路由(关键:写/读分属两个后端,共享 Redis) - **写路径** `POST /api/cms/cms-template/use {templateId}` 与 `GET /current`: 后台 website-admin `_websopy` 代理 → `websopy-api.websoft.top` = **websopy-java**。 `CmsTemplateController.use()` 按 `loginUser.getTenantId()` 写 `cms_website.template_id`。 - **读路径** `GET /cms/cms-website/getSiteInfo`: 公开站 `modulesApiBase` 与 后台 `_cms` 代理 → `cms-api.websoft.top` = **mp-java**。 返回 `ShopVo`(站点信息),被 Redis 缓存 1 天(key `SiteInfo:{tenantId}`)。 - 两后端**共享同一 Redis**(prod `1Panel-redis-Q1LE`;dev `47.119.165.234`,同密码), 故 websopy-java 的 `use()` 清缓存能清掉 mp-java 读的 `SiteInfo:{tenantId}`。 ## 一、已实施的代码改动 ### 读路径(mp-java / cms-api,必须部署) **A. `mp-java/src/main/java/com/gxwebsoft/shop/vo/ShopVo.java`** — 新增字段 ```java @Schema(description = "模板ID(cms_template.id,1~6,对应前端 template-XX),由后台模板选择器选用写入") private Integer templateId; ``` > 修复「断链」:`getSiteInfo` 返回体原本不带 `templateId`,前台永远拿不到所选模板。 **B. `mp-java/src/main/java/com/gxwebsoft/cms/service/impl/CmsWebsiteServiceImplHelper.java` 的 `convertToVO()`** — 搬运字段 ```java // 搬运所选模板ID:后台模板选择器(/use, websopy-java)写入 cms_website.template_id,前台据此渲染 template-XX vo.setTemplateId(website.getTemplateId()); ``` ### 写路径(websopy-java / websopy-api) **C. `websopy-java/src/main/java/com/gxwebsoft/cms/controller/CmsTemplateController.java` 的 `use()`** — 选用后清缓存 ```java website.setTemplateId(templateId); if (cmsWebsiteService.updateById(website)) { // 选用成功后清除站点信息缓存,使前台 getSiteInfo 立即返回新模板 // (否则 mp-java "SiteInfo:{tenantId}" 缓存 1 天内不刷新,首页不会自动切换;两后端共享 Redis) cmsWebsiteService.clearSiteInfoCache(loginUser.getTenantId()); return success("选用成功"); } ``` > 修复「时效」:mp-java 的 `getSiteInfo` 用 Redis 缓存 1 天;`use()` 清缓存使前台立即生效。 ## 二、必须完成的数据库前提(线上 CMS 库,mp-java 使用) 迁移脚本:`website-template/database/migrate-cms-website-template-id.sql` 作用:`cms_website` 新增 `template_id` 列(真正模板ID);原 `template_id` 列改名 `clone_tenant_id`(克隆来源)。 核查: ```sql SHOW COLUMNS FROM cms_website LIKE 'template_id'; SHOW COLUMNS FROM cms_website LIKE 'clone_tenant_id'; ``` 存量 `template_id` 为 NULL 的站点 → 前台回落默认 `template-01`;管理员在 `/templates` 重新选用一次即写入正确值,不丢数据。 ## 三、前端改动(website-template,已加临时日志) - `app/composables/useTemplate.ts` 的 `loadTemplate()` 增加仅 dev 日志,打印 `resolvedTemplateId`。**验证通过后删除该日志块。** - 部署环境 `.env` 必须确认**未设置** `NUXT_PUBLIC_FORCE_TEMPLATE_ID`(本地 `.env` 已注释 OK;该变量优先级最高,会盖掉后台选用)。 ## 四、端到端验证 1. 构建部署 **mp-java**(含 A、B)+ **websopy-java**(含 C);线上 CMS 库执行迁移。 2. website-template:本地 dev 设 `NUXT_PUBLIC_TENANT_ID=目标租户` 后 `pnpm dev`;已部署按域名自动解析。 3. 后台 `/templates` 选 `template-03` → 提示成功,卡片高亮「当前使用」。 4. 公开站首页**硬刷** → 渲染 `template-03`;DevTools Console 见 `[useTemplate] loadTemplate id= undefined | resolvedTemplateId= template-03`。 5. 后台切 `template-05` → 首页再次硬刷 → **立刻**渲染 `template-05`(缓存已清,无需等 1 天)。 6. 验证 `/about`、`/product`、`/article`、`/case` 等页也同步切换(全站 13 处共用 `useTemplate` 状态)。 7. 验证无误后,删除 `useTemplate.ts` 中的临时日志块。 ## 五、回滚 A、B 在 mp-java,C 在 websopy-java,均为增量、向后兼容(ShopVo 仅多一个可选字段)。 需回滚时各自 `git revert` 对应提交即可。