Files
SEONexus/docs/1270-SEONexus-Codex多版本协作交接总文档.md

3956 lines
114 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 1270-SEONexus Codex 多版本协作交接总文档
## 正式服接手极简版
如果新的 Codex 会话是在正式服或其他机器上接手,而且当前目标是继续追回 GPT 模板深页 `seo_copy` 资产,先直接执行这一段,不要先大范围自由发挥。
### 当前共识
1. GPT 模板结构恢复主线已经跑通
2. `jpjdxs-com` 已验证:
- 首页可命中 `guide-collection`
- 详情页可命中 `guide-detail`
- 播放页可命中 `guide-play`
3. 当前仓库内真正已经确认有非 default 深页资产的正式 host主要是
- `chuanjiafeng-net`
- `liangzuan-net`
- `jpjdxs-com`
4. 下面这批 host 当前仓库里仍然只是 `detail/play default-only`,下一步应优先去正式服或其他机器找历史产物:
- `pcslcl-com`
- `lsrxs-com`
- `lmjcg-com`
- `nblssy-com`
### 当前 Git 节点
2026-04-16 本轮已经完成一笔主链提交:
- commit: `2a905bbf`
- message: `restore gpt seo copy pipeline and stabilize seo tkd output`
这一笔提交已经落下的内容包括:
- `videoGpt1``seo_copy` 模块重新挂载
- `VideoService / SiteContext` 的 TKD 输出主链恢复
- `title / keywords / description` 输出净化
- 路由兼容与 `slug + id` 场景取数修复
- DPlayer 容器初始化修复
- `jpjdxs-com` 样本文案回灌
- 交接文档同步更新
### 当前提交后的边界
这次提交之后,仓库里仍然保留一批未整理残留,后续接手时不要误判成“本轮漏提”:
- 其它 `videoGpt1` 页面模板改动
- `VideoCategoryModel / VideoModel` 的独立改动
- `seo_copy_release_run.php` 等脚本改动
- `chuanjiafeng-net / liangzuan-net` 下的大量生成或回灌数据
- `code/public/_seo_copy_release/` 下的发布产物
因此后续如果要继续提交,默认进入的是“第二批整理阶段”,不是继续补提第一批主链。
### 接手后先做什么
按这个顺序:
1. 先看本机目标项目目录下是否存在:
- `code/data/seo_copy_published/<host>/detail`
- `code/data/seo_copy_published/<host>/play`
- `code/storage/domain_bootstrap_bundles`
- `code/storage/seo_copy_publish_logs/backups`
2. 重点只找两类文件:
- `detail/*.json` 中非 `default.json`
- `play/*.json` 中非 `default.json`
3. 如果找到真实深页文件,就回灌到:
- `code/data/seo_copy_published/<host>/detail`
- `code/data/seo_copy_published/<host>/play`
4. 回灌后必须再做页面验证:
- 详情页是否命中 `guide-detail`
- 播放页是否命中 `guide-play`
### 不要再重复做的事
1. 不要再默认当前开发仓库里一定还有第二份历史资产
2. 不要再把“模板入口丢失”和“深页资产缺失”混成一件事
3. 不要用域名原文去跑目录脚本
例如:
- 错:`--host=jpjdxs.com`
- 对:`--host=jpjdxs-com`
### 接手时建议直接回报的最小信息
只要回复这 6 条就够主线继续判断:
1. 当前排查机器名
2. 当前项目根目录
3. 目标 host
4. 是否存在非 default `detail/*.json`
5. 是否存在非 default `play/*.json`
6. 回灌后是否命中 `guide-detail / guide-play`
### 2026-04-16 晚间补充结论GPT 模板“已做优化突然像没了”的真实根因
这段是给后续 Codex 专门避坑用的。
当出现下面这些现象时:
- 详情页 / 播放页的引导文像突然没了
- 播放页 canonical 又指回详情页
- 详情页切集链接退化成 `/bf-76359-/douban-1`
- 你感觉“之前已经测试通过的 GPT 模板优化好像被覆盖了”
不要先判断成:
- `seo_copy` 数据丢了
- `seotkd` 数据被删了
- 只是数据库被覆盖了
本轮已经确认过,至少在 `videoGpt1` 这条线上,更常见的真实根因是:
1. 活跃模板链路里重新混入了旧模板写法
2. 旧写法继续使用 `{site:vpurl ...}`,没有稳定走 `VideoService::getVideoPlayUrl(...)`
3. 结果就是:
- 详情页切集列表可能退回旧格式
- 播放页内部切集入口可能退回旧格式
- 播放页 canonical / og:url / JSON-LD url 可能重新指错
4. 所以最终表现会让人误以为“之前做过的 SEO/UI 优化全部消失了”
### 这次已经确认修过的活跃入口
如果后面又出现类似问题,优先检查这些文件,而不是先去怀疑数据库:
- `code/app/home/view/videoGpt1/video/getVideoPlayUrl.html`
- `code/app/home/view/videoGpt1/module/playline/layout/layout_A.html`
- `code/app/home/view/videoGpt1/module/playline/layout/layout_B.html`
- `code/app/home/view/videoGpt1/module/playline/layout/layout_C.html`
- `code/app/home/view/videoGpt1/module/play/play_01.html`
- `code/app/home/view/videoGpt1/module/play/play_02.html`
- `code/app/home/view/videoGpt1/module/play/play_03.html`
- `code/app/home/view/videoGpt1/module/play/play_04.html`
- `code/app/home/view/videoGpt1/module/play/play_05.html`
- `code/app/home/view/videoGpt1/module/detail_main/action.html`
- `code/app/home/view/videoGpt1/module/detail_main/cover.html`
### 这次已经确认过的验证标准
后续 Codex 不要只看页面“能打开”,而要按下面标准验:
1. 详情页包含 `guide-detail`
2. 播放页包含 `guide-play`
3. 详情页切集链接必须带 slug例如
- `/bf-76359-san-fen-zhi-yi-qing-ren/douban-1`
4. 不能再出现:
- `/bf-76359-/douban-1`
5. 播放页 canonical 必须指向播放页自己,而不是详情页
6. `og:url` 与 JSON-LD `url` 也必须同步指向播放页自己
### 模板表达式的额外坑
本轮还确认了一个模板层坑:
- 在模板 `{: ... }` 表达式里直接写 `app(\app\services\VideoService::class)`,某些场景下会被模板解析吞掉命名空间
- 报错形式通常像:
- `类不存在: appservicesVideoService`
因此模板内联调用更稳的写法是:
- `app('app\\services\\VideoService')->getVideoPlayUrl(...)`
如果后续又出现“明明逻辑没问题,但模板页直接系统错误”,优先先查这一条。
### DPlayer 那条旧问题的当前结论
之前出现过:
- `TypeError: Cannot read properties of null (reading 'classList')`
本轮复核后,当前正式生效的编译脚本是:
- `code/public/static/js/compiled/48dd19fee8.js`
其中与 DPlayer fullscreen 相关的 `classList` 访问已经带容器判空保护,因此:
- 当前仓库主链并没有重新把这条空指针直接引回来
- 如果后续线上再次出现这类报错,优先怀疑:
- 老旧静态资源缓存未清
- 旧模板 JS 被覆盖回线上
- 不是本轮这批 `videoGpt1` 模板修复本身造成的
### 2026-04-16 GPT 模板快速验收清单
这份清单给后续所有 Codex 共用。
目标不是“页面能打开就算过”,而是快速确认:
- `seo_copy` 引导块还在
- TKD 还在
- URL 没退化
- detail / play 主链没被旧模板重新接管
#### 验收前提
默认以某个已验证 host 为样本,例如:
- `jpjdxs.com`
本轮验证样本里常用的页面有:
- 首页:`/`
- 榜单首页:`/phb-index`
- 一级分类页:`/videotype/1-dian-ying`
- 二级分类页:`/videotype/dian-ying/shao-shi-dian-ying-1`
- 搜索结果页:`/get-index?keyword=test`
- 详情页:`/neirong-76359-san-fen-zhi-yi-qing-ren`
- 播放页:`/bf-76359-san-fen-zhi-yi-qing-ren/douban-1`
#### 页面级验收标准
1. 首页
- 必须命中:`guide-collection`
- 必须能看到:首页导览、自定义首页引导块
- 必须有正常 `title / keywords / description`
2. 榜单首页
- 必须命中:`guide-collection`
- 必须有正常榜单页 TKD
3. 一级分类页
- 必须命中:`guide-collection`
- 必须有正常分类页 TKD
4. 二级分类列表页
- 必须命中:`guide-collection`
- 必须有正常列表页 TKD
5. 搜索结果页
- 必须命中:`guide-collection`
- `canonical` 必须指向当前真实搜索页
- `og:url` 必须与 `canonical` 一致
- `CollectionPage.url` 必须与 `canonical` 一致
6. 详情页
- 必须命中:`guide-detail`
- `canonical / og:url / JSON-LD url` 必须都指向详情页自己
- 切集链接必须带 slug
- 不能出现 `/bf-76359-/douban-1` 这种退化链接
7. 播放页
- 必须命中:`guide-play`
- `canonical / og:url / JSON-LD url` 必须都指向播放页自己
- 播放页内部切集链接不能退化成无 slug 形式
#### 最小命令清单
以下命令是后续 Codex 可直接复用的最小验收方式。
假设当前本地回放入口是:
- `http://127.0.0.1:18081`
- Host 头是:`jpjdxs.com`
1. 首页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/' | rg -n 'guide-collection|首页导览|<title>|<meta name="keywords"|<meta name="description"'
```
2. 榜单首页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/phb-index' | rg -n 'guide-collection|<title>|排行榜|榜单'
```
3. 一级分类页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/videotype/1-dian-ying' | rg -n 'guide-collection|<title>|<meta name="keywords"|<meta name="description"'
```
4. 二级分类页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/videotype/dian-ying/shao-shi-dian-ying-1' | rg -n 'guide-collection|<title>|<meta name="keywords"|<meta name="description"'
```
5. 搜索结果页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/get-index?keyword=test' | rg -n 'guide-collection|canonical|og:url|<title>'
```
6. 详情页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/neirong-76359-san-fen-zhi-yi-qing-ren' | rg -n 'guide-detail|canonical|og:url|/bf-76359-san-fen-zhi-yi-qing-ren/douban-1|/bf-76359-/'
```
7. 播放页
```bash
curl -s -H 'Host: jpjdxs.com' 'http://127.0.0.1:18081/bf-76359-san-fen-zhi-yi-qing-ren/douban-1' | rg -n 'guide-play|canonical|og:url|https://jpjdxs.com/bf-76359-san-fen-zhi-yi-qing-ren/douban-1'
```
#### 通过 / 不通过的最小结论模板
后续 Codex 回报时,尽量只按这个格式,不要写散:
1. 首页:通过 / 不通过
2. 榜单首页:通过 / 不通过
3. 一级分类页:通过 / 不通过
4. 二级分类页:通过 / 不通过
5. 搜索结果页:通过 / 不通过
6. 详情页:通过 / 不通过
7. 播放页:通过 / 不通过
8. 当前唯一阻塞点:
#### 如果搜索页再次异常,优先先查什么
搜索页这条容易和其它主链问题混在一起,后续若异常,先按这个顺序看:
1. `getSearchVideo.html` 是否仍包含 `module/seo_copy/collection`
2. `canonical / og:url / CollectionPage.url` 是否一致
3. 是否又误用了错误类名
- 错误示例:`app\services\UrlBuilder`
- 正确类:`app\common\helper\UrlBuilder`
4. 如果是本地 PHP 内置服务回放异常,再区分:
- 是模板真报错
- 还是仅本地回放对 query 参数存在边角波动
## 目的
这份文档用于让多个 Codex 在 `SEONexus` 新版与旧版本之间长期协作时,保持:
- 交接清楚
- 边界清楚
- 合并节奏清楚
- 不互相覆盖
- 不重复试错
适用场景:
- 你会在正式环境再安装一个或多个 Codex
- 一个 Codex 主要盯新版优化
- 另一个 Codex 主要盯旧版本蜘蛛抓取与优化
- 后续还可能出现第 3 个、第 4 个 Codex
开工约定:
- 每个 Codex 开始实际工作前,先阅读本文件
- 没看完 `1270` 前,不进入代码改动阶段
- 如有对应专题文档,再继续看 `1269` 或最近的 `production-fix` 文档
---
## 核心原则
### 1. 同一时间只优化一份代码
这是最重要的规则。
任何时刻只允许:
- 新版在优化
- 旧版本在优化
不允许两个 Codex 同时分别改两份代码后再互相猜着合。
正确节奏是:
1. 先在一份代码上完成一轮优化
2. 验证通过
3. 合并/同步到另一份代码
4. 再开始另一份代码的分析与优化
---
### 2. 另一份代码在未同步最新前,只做“观察”,不做“改动”
如果旧版本还没合并新版最新修复,则旧版本 Codex
- 可以看日志
- 可以写分析
- 可以整理建议
- 不能先改一套自己的实现
否则后面很容易出现:
- 同一问题两边各修一版
- 路由/模板/观测逻辑走偏
- 合并时冲突越来越重
---
### 3. 新版是主验证场,旧版本是回灌场
除非明确说明某个问题只在旧版本存在,否则默认:
- 新版先验证
- 旧版本后回灌
这条规则适用于:
- 蜘蛛抓取分析
- 路由兼容
- 抓取入口修复
- sitemap / rss / robots 修复
- 前端站群 Nginx 动态回源策略
不适用于:
- 旧模板专属结构问题
- 旧模板专属页面 bug
- 旧模板专属样式/模板分支问题
---
## 版本边界
### 新版负责什么
新版主要承担:
- SEO 主线优化
- 蜘蛛抓取分析
- 新路由兼容策略验证
- 抓取入口修复
- 深页 `301/404/500` 治理
- RSS / sitemap / canonical 规范
- 新功能验证
### 旧版本负责什么
旧版本主要承担:
- 已验证能力的回灌
- 老模板抓取稳定性修复
- 老模板历史路由兼容
- 老模板蜘蛛行为观察
- 老模板入口层与规范层修复
### 不要让旧版本先承担的内容
这些优先在新版验证,不要先在旧版本自由发挥:
- Bootstrap 总控台整条链
- 站外 SEO 全量工作台
- 大型后台运营工作流
- 新模板展示层重构
- URL 主输出风格大改
---
## 多 Codex 协作角色建议
### Codex-A新版主线 Codex
职责:
- 新版 SEO 优化
- 蜘蛛日志分析
- 路由兼容修复
- 抓取入口修复
- 新功能验证
- 输出可回灌结论
### Codex-B旧版本回灌 Codex
职责:
- 等待旧版本合并最新版代码
- 分析旧版本蜘蛛抓取
- 验证回灌效果
- 只做老模板特有问题修复
- 不先发明与新版不同的实现
### Codex-C / Codex-D后续扩展 Codex
职责建议:
- 专项观察
- 文档整理
- 日志归纳
- 回归验收
不建议一上来让多个 Codex 同时改核心路由/模板。
---
## 每次开始工作前必须确认的事项
任何一个 Codex 开工前,先确认以下 8 条:
0. 先看完:
- `1270-SEONexus-Codex多版本协作交接总文档`
1. 当前自己负责的是:
- 新版
还是
- 旧版本
2. 另一份代码是否已经合并了最新修复
3. 当前轮次是:
- 观察
- 修复
- 回灌
- 验收
4. 这轮是否允许改代码
5. 是否已有上一个 Codex 的交接结论
6. 本轮修复目标是否只限定在一个主题
7. 当前结论是应该先写本地分析,还是已经可以回流主文档
8. 当前这轮是否涉及多服务器协作,如果涉及,谁是主线收口责任人
例如:
- 蜘蛛抓取概览
- 深页兼容
- RSS 修复
- 旧模板入口规范
不要一轮里又修蜘蛛、又修广告、又修 Bootstrap、又补后台工作台。
如果当前是新开会话或新装的 Codex建议固定顺序
1. 先看 `1270`
2. 再看当前阶段执行文档,例如 `1269`
3. 再看最近一次相关 `production-fix` 文档
4. 最后再去读代码、日志和本地分析文档
---
## 严格边界
### 1. 不自动跨版本做“顺手修复”
例如当前在旧版本分析蜘蛛问题时,不要顺手:
- 改新版模板
- 改新版站外 SEO 面板
- 改新版 Bootstrap
反过来也一样。
### 2. 不自动提交
除非用户明确要求,否则:
- 不自动 commit
- 不自动 push
先把改动留在工作区,等用户确认。
### 3. 不整包恢复历史提交
`22cc72ee` 这种历史提交,只能作为:
- 缺失源码来源
不能整包恢复。
因为这类提交往往还混着:
- 运行产物
- 测试数据
- storage 输出
- 临时样板文件
正确做法是:
- 定点恢复源码
- 然后继续冒烟验证
### 4. 不在两个版本上同时独立发明方案
例如:
- 新版把深页兼容做成 A
- 旧版本同时自己做成 B
这是最容易制造后续冲突的做法。
---
## 本轮关键经验补充
这一节记录 2026-04-16 这轮 `videoGpt1` 恢复与排障中已经确认的高价值结论。
后续任何 Codex 如果再遇到:
- GPT 模板首页/详情/播放页引导文突然消失
- 分类首页、榜单列表、搜索页突然 404 或系统错误
- 某些域名正常,某些域名不正常
请优先先看这一节,再决定是否继续深挖。
### 1. 不是所有“页面丢内容”都是数据库问题
这轮已经确认GPT 模板前面做过的引导文、补料、搜索引导、详情引导、播放引导,并不一定是数据库被删。
更常见的真实原因有 3 类:
1. 模板文件被较轻版本覆盖
2. 路由把请求导错了模板
3. 服务层类型约束变严后,旧模板传空值直接报错
所以不要一看到:
- title 空了
- 引导文没了
- 分类页报错
- 搜索页 404
就直接判断成:
- seo_key 丢了
- 数据库被覆盖了
- AI 生成没执行
正确顺序应该是:
1. 先看实际命中的模板
2. 再看实际命中的路由
3. 再看服务层是否因为 `null / ''` 被强类型拦截
4. 最后才去怀疑数据层
### 2. GPT 模板当前已确认恢复的主线页面
这轮已经恢复并验证通过的页面包括:
- 首页引导层
- 详情页引导层
- 播放页引导层
- 分类首页
- 一级分类页
- 二级分类页
- 榜单首页
- 榜单列表页
- 搜索结果页
- 历史记录页
其中首页、详情页、播放页的引导层恢复,不是只在一个域名生效,而是已经按多种路由家族做过抽查。
### 3. 本轮确认过的三条高频根因
#### 根因 A模板层被“轻量 seo_copy include”替换后深页补料不再显性输出
现象:
- 首页还有一点东西
- 详情页/播放页引导感明显变弱
- 页面不报错,但前面测试过的引导文 UI、卡片、提示区块明显没了
结论:
- 不是整套模板消失
- 是 richer 版本页面级引导层退化成了轻量 include
处理原则:
- 优先从历史 git 内容里恢复页面级引导结构
- 不要简单再重写一套全新的风格
#### 根因 B路由注册错位页面请求被导到了错误模板
本轮已确认过两个典型错位:
1. `category_home` 错导到 `video/getCategory.html`
2. `rank_list` 错导到 `video/getRankIndex.html`
后果:
- 分类首页会拿分类列表模板跑
- 榜单列表会拿榜单首页模板跑
- 页面可能有 title但正文报 `系统发生错误`
处理原则:
- 先检查 `code/app/home/config/router.php`
- 再确认当前 page code 应该落到哪一个视图
#### 根因 C服务层 URL 方法后来加了强类型,旧模板空参数直接炸
本轮确认过的典型报错:
- `getVideoCategoryIndexUrl(): Argument #1 must be of type string, null given`
- `getVideoRankUrl(): Argument #1 must be of type string, null given`
这类问题的本质不是业务逻辑坏了,而是:
- 模板原来允许空值
- 服务层后来把参数收紧成强类型
- 一些分类首页 / 榜单页 / 空场景入口就直接报错
处理原则:
- 先恢复服务层对 `null / ''` 的兼容
- 不要先大面积改模板传参
原因很简单:
- 兼容服务层后,多个模板家族都会一起恢复
- 如果只修模板,很容易这里修好,别处再炸一个
### 4. `.html` 冻结路由是 GPT 新路由分支的重点兼容项
这一条非常重要。
当前 `videoGpt1` 不是走旧模板那套通用路由,而是走前面的 GPT 新路由分支,并且中途会直接 `return`
这意味着:
- 后面的旧版搜索/历史等通用路由根本不会执行
- 任何冻结 family 里定义的搜索、历史、分类、榜单入口,都必须在 GPT 新路由分支里完整注册
本轮已确认一批域名使用:
- `get.html`
- `record.html`
这类带 `.html` 的冻结路径。
如果 GPT 新路由只按普通字符串注册,而不补 `->ext('html')` 兼容别名,就会出现:
- 无点路径域名正常
- `.html` 路径域名全部 404
这轮已经验证通过的 dot-family 域名包括:
- `chuanjiafeng.net`
- `lcdchq.com`
- `lgyz.net`
- `oronorent.com`
- `sdxhtgcl.com`
这些域名现在都已经确认:
- `/get.html?keyword=test` 正常返回搜索结果页
- `/record.html` 正常返回历史记录页
### 5. 以后排查顺序建议
如果后面 снова 遇到 GPT 模板页面回退、404、搜索失效、分类页异常优先按这个顺序
1. 看当前域名 `theme_cache` 里的 `url_family`
2. 看该路由在 `code/app/home/config/router.php` 是否注册到正确视图
3. 看是不是 `.html` 冻结路径
4. 看服务层 URL 方法有没有因为 `null` 参数炸掉
5. 看页面实际 HTML 是否已经命中 `guide-collection / dm-desc-guide / guide-play`
6. 最后再怀疑数据层或 AI 生成层
不要一开始就:
- 回滚整仓
- 重建全部 SEO 数据
- 重新写一套模板
这样很容易把已经修好的主线再覆盖掉。
---
## 本轮主线可复用修复
以下内容属于“主线可复用修复”,后续如果旧版本或其它服务器出现同类问题,可以优先对照吸收:
### 路由层
- `category_home` 应落到 `video/getMap.html`
- `rank_list` 应落到 `video/getRankList.html`
-`.html` 的冻结路径需要补无后缀 `ext('html')` 兼容别名
### 服务层
- `getVideoCategoryIndexUrl()` 需要兼容 `null`
- `getVideoRankUrl()` 需要兼容 `null`
### 模板层
- 首页需要有显性导览区,不要只剩纯卡片瀑布流
- 详情页需要保留剧情说明 + 延伸词入口 + 播放跳转提示
- 播放页需要保留当前线路 / 当前剧集 / 返回详情页 / 观看建议
---
## 交接提醒
后续 Codex 如果接到类似任务,请先确认:
1. 当前问题到底是模板退化、路由错位,还是类型约束报错
2. 当前域名是否使用 `.html` 风格冻结搜索/历史路由
3. 当前问题是否已经在新版主线修过,可以直接回灌而不是重做
如果是同类问题,优先复用本轮思路,不要再重新设计一套实现。
---
## SEO 文案发布层特别注意
### 1. 不要把“页面退化”直接等同于“模板被回滚”
`videoGpt1` 这类模板里,页面最终看到的引导文、补料、差异化说明,至少分成两层:
- 模板层是否还渲染对应区块
- `seo_copy_published` 是否真的存在细粒度发布结果
如果模板还在,但 `seo_copy_published/<host>/detail``play` 下面只剩:
- `default.json`
那么前台虽然还能出内容,但只会退回默认文案,不会再有:
- 单视频差异化文案
- 单播放页差异化文案
- 之前那种“每个域名、每个页面不完全一样”的细粒度表现
也就是说:
- 页面看起来像“前面的优化没了”
- 不一定是模板没了
- 很可能是发布层退回默认版了
### 2. 当前仓库已经确认的事实
`2026-04-16` 本地排查中,已确认:
- `code/data/seo_copy_published` 共 27 个域名
- 27 个域名全部只有 `detail/default.json`
- 27 个域名全部只有 `play/default.json`
- 没有任何 `detail/<video_id>.json`
- 没有任何 `play/<video_id>-play-<type>-<index>.json`
这说明当前仓库里的“已发布文案目录”本身就是默认版,不是单个页面偶发异常。
### 3. 审计命令
后续任何 Codex 遇到“差异化文案是不是又丢了”时,先跑:
```bash
php code/scripts/seo_copy_published_audit.php --format=text
```
按域名单查:
```bash
php code/scripts/seo_copy_published_audit.php --host=lmjcg-com --format=text
```
带样本页检查预期 key 是否存在:
```bash
php code/scripts/seo_copy_published_audit.php \
--host=lmjcg-com \
--sample-detail=76310 \
--sample-play=76310:default:1 \
--format=text
```
如果输出里看到:
- `detail_default_only: yes`
- `play_default_only: yes`
- `expected_checks ... exists=no`
就说明问题在发布层,不要先去重写模板。
### 4. Git 历史判断规则
如果怀疑是 git 覆盖导致退化,优先同时检查两块:
- 模板源码历史
- `code/data/seo_copy_published` 历史
这次已经确认:
- 模板关键文件并没有发生整包回滚到很老版本
-`code/data/seo_copy_published` 当前提交内容本身就是 default-only 版本
所以后续排查顺序应固定为:
1. 先审计 `seo_copy_published`
2. 再确认模板区块是否还在
3. 最后才决定是否需要从历史发布批次恢复细粒度文案
### 5. Git 推送只能使用 `www` 用户
这是当前机器的固定约束,不要忽略。
原因:
- `root` 用户可以排查问题、读日志、跑测试
-`root` 没有 `origin2` 的可用 SSH 私钥
- `www` 用户已经配置好可用私钥,且已验证可正常推送到 `origin2`
因此后续所有 Codex 都必须遵守:
- 可以用 `root` 做分析、读取、验证
- 一旦涉及 `git push`,只能切到 `www`
- 不要再直接用 `root` 执行 `git push origin2 dev`
标准推送命令:
```bash
su -s /bin/bash www -c 'git -C /www/wwwroot/diff-maccms/SEONexus push origin2 dev'
```
如果需要先查看状态,也建议保持同一口径:
```bash
su -s /bin/bash www -c 'git -C /www/wwwroot/diff-maccms/SEONexus status'
su -s /bin/bash www -c 'git -C /www/wwwroot/diff-maccms/SEONexus log --oneline -n 3'
```
已验证结论:
- `root` 推送会报 `Permission denied (publickey...)`
- `www` 推送 `origin2` 正常成功
所以这不是代码问题,也不是远端仓库问题,而是当前机器上的 Git 身份边界。
### 5.1 仓库 ownership 也必须保持 `www:www`
除了 `git push` 只能使用 `www`,当前机器上还要额外遵守一条:
- `SEONexus` 仓库目录本身也必须保持 `www:www`
尤其不能让下面这些路径长期混入 `root:root`
- `.git`
- `.git/index`
- `.git/objects/*`
- `docs/`
- 其它会被 `git pull` / `git checkout` 自动写入的目录
已经验证过的真实故障现象包括:
- `error: insufficient permission for adding an object to repository database .git/objects`
- `fatal: failed to write object`
- `fatal: unpack-objects failed`
- `error: unable to create file docs/...: Permission denied`
这类问题的根因不是远端仓库异常,而是:
- 前面曾用 `root` 对仓库做过 `commit`、写文件或目录创建
- 导致 `www` 后续执行 `pull` / `push` / `stash` 时权限链断掉
因此后续建议固定为:
- 与 Git 直接相关的操作优先都用 `www`
- `root` 只做日志排查、系统命令、权限修复
- 不要再用 `root` 在仓库里直接 `commit``pull``push`
如果已经出现 ownership 混乱,优先修复命令为:
```bash
chown -R www:www /www/wwwroot/diff-maccms/SEONexus
```
如果只是 `.git` 或仓库内同步文档目录出错,也至少要修:
```bash
chown -R www:www /www/wwwroot/diff-maccms/SEONexus/.git
chown -R www:www /www/wwwroot/diff-maccms/SEONexus/docs
```
这条规则和“只能 `www` 推送”应视为同一组约束,不能只做一半。
### 6. `SEONexus` 与 `SEONexusAdmin` 是同机双仓协作
当前机器上:
- `SEONexus`
- `SEONexusAdmin`
都位于同一台机器的 `/www/wwwroot/` 下。
这意味着:
- 它们适合联合排查
- 但仍然是两个独立仓库
- 不能因为同机就默认一起改
推荐理解方式:
- `SEONexus` 主要负责后端接口、路由、helper、model、日志、返回结构
- `SEONexusAdmin` 主要负责前端页面、接口调用、参数、token/header、错误展示
- Nginx / 域名 / 反代 / CORS / 登录态链路属于同机环境层
因此遇到后台报错时:
- 可以跨仓一起查
- 但修复时先判断主战场
- 一轮优先只改一个主仓
例如:
- 如果是接口 500、类缺失、helper 丢失、路由没挂,主战场通常是 `SEONexus`
- 如果是 axios 参数、header、token、前端展示层误报主战场通常是 `SEONexusAdmin`
- 如果是跨域、代理、cookie、header 丢失,主战场通常是 Nginx / 反代配置
这条规则的核心不是“分开”,而是:
- 同机便于联查
- 分仓便于控边界
### 7. 不建议现在把所有项目硬并成一个 Git 仓库
当前更适合的结构是:
- 多个独立 Git 仓库
- 通过仓库内 `doc/` 文档同步协作规则
- 通过明确边界控制多 Codex 并行协作
不建议现在把所有项目直接并成一个大仓,原因包括:
- `SEONexus``SEONexusAdmin`、node 工具链、蜘蛛代理脚本、历史参考目录,生命周期并不一致
- 不同项目的提交节奏不同,强行并仓后日志会很乱
- 后续回滚、比对、定向发布会更重
- 正式服未必需要开发机当前的总目录结构
- 现在真正需要同步的是规则和关键文档,不是把所有杂项目录绑成一个提交历史
当前阶段更推荐:
- 业务主仓继续独立维护
- 关键协作文档同步到主仓的 `doc/`
- 需要跨仓排查时,通过文档说明目录关系和排查顺序
只有在未来满足以下条件时,才考虑是否要做 monorepo
- 多个仓长期高度耦合
- 发布必须严格同版本号
- CI/CD 也准备统一
- 权限、分支策略、回滚策略都已经设计清楚
在当前阶段,最稳的结论是:
- 不要把所有项目硬归成一个 Git
- 先把“协作规则归一、文档入口归一、推送口径归一”做好
- 这样收益更大,风险更小
### 8. 本轮 GPT 模板“像被覆盖了”的根因结论
这条是 `2026-04-16` 本地持续排查后新增的强结论,后续 Codex 看到“首页 title 变空、引导文没了、播放页像退回毛坯版”时,先按这里理解,不要再一上来误判成“整个 GPT 模板被回滚没了”。
#### 8.1 早期 GPT 模板主骨架其实还在
从 git 历史看,真正把 `videoGpt1` 模板做起来的关键提交主要是:
1. `eb8c0977 gpttemp`2025-12-31
2. `90fc16fb gpt`2026-01-09
3. `04f303ca index`2026-01-10
4. `e23bf61f indextitle`2026-01-10
这些提交当时一起改了:
- `code/app/home/view/videoGpt1/...`
- `code/app/services/VideoService.php`
- `code/app/services/SiteContext.php`
- 列表、评论、播放、详情等页面层
因此本轮看到的退化现象,不应直接理解成“那批 GPT 模板代码整包没了”。
#### 8.2 真正可疑的覆盖点在 `origin2/dev`
当前分支关系已确认:
1. `origin/dev` 停在较早位置
2. `origin2/dev``origin/dev` 多出一整串后续提交
3. 其中与这次问题最直接相关的关键提交是:
- `887e9528 debug`2026-04-14
这个提交做了一个非常关键的动作:
1. 首次把 `code/data/seo_copy_published` 批量纳入 git
2. 但纳入的内容是低覆盖版本
3. 对 27 个域名来说,`detail` / `play` 基本只有 `default.json`
4. 没有原先那种按视频 id、播放线路、集数拆开的细粒度深页发布结果
#### 8.3 所以当前更像是“发布数据覆盖”,不是“模板源码被删”
更准确的判断应该是:
1. 模板骨架大部分仍在
2. `theme_cache` 和模块布局大部分仍在
3. 但是模板后续开始接入 `seo_copy` 后,读取到的是 default-only 的发布产物
4. 于是原先更细的深页引导文,被统一的默认文案层盖平
用户体感上就会变成:
- 差异化引导文没了
- 页面排版味道变弱了
- 看起来像之前做过的 SEO 优化都被抹掉了
#### 8.4 当前已锁定的责任边界
后续排查和恢复,优先按下面结论执行:
1. `origin/dev` 不是这次 `seo_copy_published` 覆盖的主要来源
2. 当前已知问题链,主要来自 `origin2/dev` 这一串后续提交
3. 其中 `887e9528 debug` 是这次“深页差异化内容退化”的关键观察点
4. `bd073c67``7fff1a99` 主要修路由、id-first、helper 恢复,不是这次内容退化的首因
#### 8.5 恢复优先级
既然根因更偏向“发布数据被低覆盖版本顶掉”,恢复顺序必须固定为:
1. 先恢复历史深页 `seo_copy` 发布数据
2. 再验证模板区块是否需要微调
3. 最后才考虑是否补新的内容生成
这一条必须强调:
- 优先恢复历史已验收资产
- 不要先用新的通用 AI 文案把旧资产覆盖掉
否则会继续出现:
- 页面能显示
- 但和之前测试通过的那版体验不一致
- 用户感觉“怎么又被重新写坏了”
---
## 工作顺序标准流程
### 场景 A新版先优化旧版本后回灌
1. 新版 Codex 分析问题
2. 新版 Codex 实施修复
3. 新版验证通过
4. 文档记录“哪些能力适合回灌旧版本”
5. 旧版本合并最新代码
6. 旧版本 Codex 开始观察与回灌验证
7. 只补旧模板特有问题
### 场景 B旧版本先发现问题
1. 先判断该问题是不是旧模板专属
2. 如果不是旧模板专属,先回新版验证
3. 新版验证后再回灌旧版本
4. 如果是旧模板专属,再只在旧版本修
---
## 哪些优化适合回灌旧版本
### 适合
这些通常适合回灌:
- 蜘蛛抓取日志分析
- 抓取概览工作台
- `robots.txt` 修复
- `rss/baidu.xml` 修复
- `sitemap` 修复
- canonical 规范
- 历史 `detail/play/category` 路由兼容
- 深页 `404/301` 治理
- 前端站群 Nginx 统一动态回源策略
### 慎回灌
这些要单独评估:
- 坏链随机视频兜底
- 播放页 SEO 策略大改
- URL 主输出规则变更
- 复杂站外 SEO 面板
- 导入健康台全家桶
- Bootstrap 总控台整条链
---
## 多 Codex 的交接模板
每个 Codex 每轮结束时,至少留下以下内容:
### 1. 本轮工作对象
- 新版 / 旧版本
- 目录路径
- 当前分支
### 2. 本轮目标
例如:
- 修复百度深页 `301 -> 404`
- 验证旧模板蜘蛛抓取概览
- 补回 rebase 丢失 helper
### 3. 本轮已改动文件
必须列路径。
### 4. 本轮未提交改动
说明是否:
- 仅工作区修改
- 已暂存
- 已提交但未 push
### 5. 本轮验证结果
至少说明:
- 哪些通过
- 哪些没通过
- 哪些未验证
### 6. 下一位 Codex 的注意事项
必须写明:
- 不要碰哪些文件
- 先看哪个文档
- 下一个最值动作是什么
---
## 文档同步规则
每轮有效优化后,至少同步两类文档中的一种:
### 1. 主题执行文档
例如:
- [1269-SEONexus-老模板第一阶段回灌执行文档](/www/wwwroot/diff-maccms/docs/1269-SEONexus-老模板第一阶段回灌执行文档.md)
适合记录:
- 旧模板回灌目标
- 分阶段策略
- 验收口径
### 2. Codex 交接总文档
也就是当前这份文档,适合记录:
- 协作规则
- 边界
- 交接模板
- 多版本协作方法
如果后续发现某条规则经常踩坑,就更新本文件,不要只留在聊天记录里。
### 3. 单次线上事件排障文档
这类文档适合记录:
- 某一次正式服报错的完整排查过程
- 问题阶段
- 根因
- 线上改动
- 验证结果
- 下一位 Codex 的接手建议
当前已沉淀样例:
- [2026-04-16-admin2-spider-workbench-production-fix.md](/www/wwwroot/diff-maccms/SEONexus/docs/2026-04-16-admin2-spider-workbench-production-fix.md)
使用原则:
- `1269` 这类文档负责阶段执行
- `1270` 这类文档负责长期协作规则
- `2026-xx-xx-...production-fix` 这类文档负责单次线上事件闭环
这样后续主 Codex 接手时:
- 先看长期规则
- 再看当前阶段执行文档
- 最后看最近一次线上事件文档
就不会只靠聊天记录反推上下文。
### 4. 项目本地持续分析文档
除了需要进入 Git 的正式文档外,每个项目还允许保留一套“只服务当前项目持续优化”的本地分析文档。
这类文档推荐放在项目自己的:
- `code/storage/_analysis/`
使用原因:
- 每个项目都有自己的蜘蛛日志来源、观察窗口和异常轨迹
- 这类分析如果完全不记录,后续优化容易断档
- 但如果全部提交进 Git又会把大量过程性观察和未确认判断写进正式历史
因此这类文档的定位是:
- 允许持续记录
- 默认不提交
- 以项目私有观察为主
- 适合记录尚在观察期的中间结论
推荐最少按两层组织:
- `code/storage/_analysis/sources/`
- `code/storage/_analysis/domains/`
例如:
- `code/storage/_analysis/sources/baiduspider.md`
- `code/storage/_analysis/sources/sogou.md`
- `code/storage/_analysis/domains/sjzyunyang.com.md`
- `code/storage/_analysis/domains/jingxifa.com.md`
边界规则:
- 可以在每个独立项目里持续写自己的分析文档
- 也允许每个独立项目优化“本项目私有层”
- 但不建议每个项目独立发明一套公共核心方案
也就是:
- 项目私有观察可以分散记录
- 公共核心方案仍应集中验证、集中沉淀、再回灌
### 5. 本地分析必须回流主文档
`code/storage/_analysis/` 只负责本地持续观察,不应成为最终知识沉淀的终点。
只要本地分析满足以下任一条件,就必须再整理回主文档:
1. 已确认根因
2. 已验证修复有效
3. 结论能跨机器复用
4. 结论能跨模板族复用
5. 结论能减少其它 Codex 的重复劳动
6. 结论会影响协作边界或排查顺序
推荐回流判断方式:
- 如果只是某台机器、某个时间窗口的临时观察,可以先留在 `storage/_analysis/`
- 如果已经形成“别人以后不用再重新验证”的结论,就应升级到 `SEONexus/docs/`
推荐回流路径:
- 全局协作规则 -> `1270`
- 阶段执行 / 回灌策略 -> `1269`
- 单次正式服事件闭环 -> `2026-xx-xx-...production-fix.md`
- 其它模板族或专题结论 -> 对应专题正式文档
这条规则的目标是:
- 本地分析负责探索
- 主文档负责共享
- 不让每台机器都重复学习同一件事
### 6. 多服务器可以并行分析,但主线应单点收口
允许多台服务器同时进行:
- 日志分析
- 外网复测
- 各自写本地 `storage/_analysis`
- 提交各自的中间结论
但不建议多台服务器同时直接改同一个主线核心方案。
推荐规则:
- 本地分析可以并行
- 主线代码修改尽量单线
- 正式共享文档尽量单一主责任人收口
尤其是以下内容,不建议多台机器同时独立改:
- 深页兼容核心逻辑
- 路由兼容总逻辑
- 404 / 500 兜底主链
- 蜘蛛抓取核心统计逻辑
- 同一份正式共享文档
更稳的协作方式是:
1. 多台机器并行做观察
2. 各自把中间结论写到本地分析
3. 主 Codex 统一判断哪些结论已经收敛
4. 由一个主责任人修改主线代码或更新正式共享文档
这条规则的目标是:
- 允许大家同时学习
- 避免大家同时改乱主线
---
## 特别注意事项
### 1. 前端 Nginx 不要继续按 URL 模板枚举
前端站群应坚持:
- 静态资源缓存
- 非静态请求 MISS 后统一回后端
不要每新增一种 URL family就去补前端 Nginx 前缀。
### 2. 旧版本不要轻易改主输出 URL 风格
旧版本更适合:
- 加兼容层
- 不推翻当前主输出
### 3. 观测和修复要分开记录
不要把:
- 日志观察
- 推测
- 已验证修复
写混。
### 4. 真实缺失源码与 CLI 冒烟假阳性要区分
像之前的:
- `Class not found`
- 路由没挂
- helper 丢失
这类是真缺失。
但像:
- `Undefined array key 9999`
在 CLI 直接调控制器时,可能只是 admin 配置上下文不完整,不一定是真缺源码。
---
## 推荐的交接口径
每个 Codex 对下一个 Codex 的交接,建议用这种结构:
1. 当前负责版本
2. 当前主题
3. 已完成
4. 未完成
5. 禁止动作
6. 下一步建议
例如:
1. 当前负责版本:旧版本
2. 当前主题:蜘蛛抓取概览与深页兼容验证
3. 已完成:日志分析、入口检查、深页 `404` 修复验证
4. 未完成:下一轮百度深抓效果观察
5. 禁止动作:不要先改新版,不要整包恢复历史提交,不要自动 commit
6. 下一步建议:先合并最新版后,再观察旧模板的 `detail/play` 抓取变化
---
## 最后的工作纪律
多个 Codex 长期协作时,最重要的不是“每个都很聪明”,而是:
- 同步节奏一致
- 边界清楚
- 不抢改
- 不乱回滚
- 不各自发明一套实现
只要坚持这几条,后面就算扩到 3 个、4 个 Codex也仍然能稳。
---
## videoGpt1 页面来源地图
`videoGpt1` 当前页面体验,不是由单一模块决定,而是至少由下面 4 层共同组成:
### 1. `theme_cache`
位置:
- `code/storage/theme_cache/<host>.json`
作用:
- 域名级 `seed`
- `dom_prefix`
- 页面模块顺序
- 首页 / 分类 / 详情 / 播放的布局参数
- 标题文案槽位
- URL family
判断:
- 这是 GPT 模板“每个域名看起来不一样”的核心来源之一
- 当前排查中,这一层没有整体丢失
### 2. 模板原生结构
位置:
- `code/app/home/view/videoGpt1/...`
作用:
- 页面骨架
- 标题样式
- meta 栏
- 行为按钮
- 播放器外壳
- 列表结构
详情页主链:
- `video/getVideoInfo.html`
- `module/page/page_router.html`
- `module/detail_main/detail_main_router.html`
- `module/detail_main/layout/layout_B.html`
播放页主链:
- `video/getVideoPlayUrl.html`
- `module/page/page_router.html`
- `module/player/player_router.html`
- `module/player/engine/dplayer.html`
### 3. `seoaddon`
入口:
- `module/detail_main/desc.html`
- `{video:seoaddon ... /}`
- `module/detail/_seo_addon.html`
后端:
- `code/app/services/VideoService.php`
- `code/app/common/helper/SiteStyle.php`
作用:
- 详情页摘要
- 标签
- 提示语
判断:
- 这是原始 GPT 模板的重要组成部分
- 不是后加的统一卡片层
### 4. `seo_copy`
入口:
- 首页:`index/index.html`
- 详情:`module/detail_main/desc.html`
- 播放:`video/getVideoPlayUrl.html`
模板:
- `module/seo_copy/collection.html`
- `module/seo_copy/detail.html`
- `module/seo_copy/play.html`
后端:
- `VideoService::getSeoCopyBlock()`
- `SeoCopyStore`
作用:
- 补充说明
- FAQ
- guide cards 卡片
判断:
- 这是后加层
- 不是原始 GPT 模板的主体
---
## 当前恢复策略
为了尽量恢复到前面测试通过时更接近的 GPT 模板体验,当前策略如下:
### 1. `site:seotkd` 不允许输出空 TKD
位置:
- `code/app/services/SiteContext.php`
兜底顺序:
1. 新 GPT SEO 池
2. 旧 SubjectFormat key
3. domain 表字段
目标:
- 不再出现空 `title`
- 不再出现空 `keywords`
- 不再出现空 `description`
### 2. `detail` / `play` 页面不强行渲染 default-only `seo_copy`
位置:
- `code/app/services/VideoService.php`
原因:
- 当前 `code/data/seo_copy_published` 中 27 个域名的 `detail``play` 全部只有 `default.json`
- 同时 `module/seo_copy/detail.html` / `play.html` 是统一卡片式输出
- 这会让详情页和播放页迅速退化成“通用说明卡片”
处理:
- 如果详情/播放页没有命中具体 page key
- 只命中 `default`
- 就先不渲染这一层
目标:
- 页面重新回到 `theme_cache + 模板原生结构 + seoaddon` 主导
- 尽量靠近之前 GPT 模板实测通过时的观感
---
## 当前判断顺序
如果用户反馈“前面做好的 GPT 模板体验又没了”,应按以下顺序排查:
1.`title/keywords/description` 是否为空
2.`theme_cache` 是否还在且命中正常
3. 看详情 / 播放页是否只剩 `default-only seo_copy`
4. 再判断是否真的发生过模板 Git 回退
不要先入为主认定“全部是 Git 覆盖”,因为当前更明显的现象是:
- 域名级模板差异仍在
- `seo_copy` 深页细粒度内容缺失
- 叠加 TKD 取值异常后,页面体感会明显变差
---
## 2026-04-16 深页 `seo_copy` 恢复验证结论
### 已验证结论
本地仓库内,细粒度 `detail/play` 文案并不是“从未存在”,而是:
- 以前真实生成过
- 历史备份仍然存在
- 当前生效目录退回成了 default-only
可追溯来源主要包括:
- `code/storage/seo_copy_publish_logs`
- `code/storage/domain_bootstrap_bundles`
- `code/storage/seo_copy_batch`
### 已完成样本恢复
#### 1. `chuanjiafeng-net`
恢复来源:
- `code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy`
恢复结果:
- `detail_default_only: no`
- `play_default_only: no`
- `detail: total=17, default=yes, non_default=16`
- `play: total=17, default=yes, non_default=16`
样本核验:
- `detail | key=154229 | exists=yes`
- `play | key=154229-play-douban-1 | exists=yes`
#### 2. `liangzuan-net`
恢复来源:
- `code/storage/domain_bootstrap_bundles/liangzuan-next-stage-b1/data/seo_copy`
恢复结果:
- `detail_default_only: no`
- `play_default_only: no`
- `detail: total=1, default=no, non_default=1`
- `play: total=1, default=no, non_default=1`
样本核验:
- `detail | key=154124 | exists=yes`
- `play | key=154124-play-youzhi-1 | exists=yes`
### 已新增恢复脚本
脚本位置:
- `code/scripts/seo_copy_restore_from_source.php`
用途:
- 从历史来源目录恢复某个 host 的 `detail/play` 深页 JSON
- 支持先 `--dry-run`
- 支持指定 `--host`
- 支持指定 `--source`
- 默认写入 `code/data/seo_copy_published`
示例:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=chuanjiafeng-net \
--source=code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy \
--dry-run
```
正式写入:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=chuanjiafeng-net \
--source=code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy
```
### 批量恢复原则
不要直接对全部 27 个域名做无差别恢复,推荐顺序:
1. 先做单域名样本恢复
2. 恢复后立刻跑审计
3. 确认该域名前台表现符合预期
4. 再决定是否扩大到更多真实域名
原因:
- 不同域名的历史覆盖程度不同
- 有的来源完整,有的来源只有 1 组样本
- 有些 bundle 是测试/并发演练产物,不适合无脑全量导回
### 推荐的后续恢复策略
优先从这类来源中选择恢复源:
1. 单域名专属 bundle
2. next-stage / compact 这类更像正式沉淀的 bundle
3. 再考虑 publish_logs
不建议优先使用:
- 并发批次演练 bundle
- 只包含样例域名的测试包
### 2026-04-16 当前 27 域名可恢复性分层
按本地仓库现状盘点:
#### A. 已完成样本恢复
- `chuanjiafeng-net`
- 当前生效:`detail` 非默认 16`play` 非默认 16
- 最优来源:`code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy/chuanjiafeng-net`
- `publish_logs` 也存在历史样本11 + 11
- `liangzuan-net`
- 当前生效:`detail` 非默认 1`play` 非默认 1
- 最优来源:`code/storage/domain_bootstrap_bundles/liangzuan-next-stage-b1/data/seo_copy/liangzuan-net`
- `publish_logs` 也存在历史样本1 + 1
#### B. 当前仓库内暂未发现可恢复深页来源
以下域名在本地盘点时:
- `domain_bootstrap_bundles` 中未发现可用 `detail/play` 深页 JSON
- `seo_copy_publish_logs` 中也未发现对应历史深页 JSON
名单如下:
- `caosheninan-com`
- `cnzhenbang-com`
- `codohealth-com`
- `glae-cc`
- `gxhongzhuang-com`
- `gz-yxsw-com`
- `hbczccq-com`
- `hyjssb-com`
- `jingxifa-com`
- `jpjdxs-com`
- `jxxgygy-com`
- `lcdchq-com`
- `leici1940-com`
- `lgyz-net`
- `lmjcg-com`
- `lsrxs-com`
- `nblssy-com`
- `oronorent-com`
- `pcslcl-com`
- `sdxhtgcl-com`
- `sdxtwnc-com`
- `sjzyunyang-com`
- `ukoys-com`
- `vikau-com`
- `visitsumenep-com`
- `zbsv3-com`
### 当前批量策略结论
基于现有本地仓库不建议直接做“27 域名全量恢复”,原因很直接:
1. 当前已验证可恢复的真实域名只有 2 个
2. 其余 26 个域名,至少在当前本地仓库中还没找到可靠深页来源
3. 如果强行批量恢复,只会造成:
- 一部分域名真的恢复
- 大部分域名仍然 default-only
- 后续误判“脚本没效果”或“恢复逻辑不一致”
因此当前更稳的策略是:
1. 先保留已恢复样本域名
2. 继续从其它机器 / 旧仓库 / 历史备份中找剩余域名来源
3. 每新增一批可靠来源,再做分批恢复
### 2026-04-16 新增结论:`publish_logs/backups` 比之前判断更有价值
继续深挖后,发现前面的判断还可以再前进一步:
1. `code/storage/seo_copy_release_runs/20260408/*/run-summary.json`
2. `code/storage/seo_copy_release_runs/20260408/*/batch_publish.summary.json`
这两类文件明确证明,当时并不是只有 default-only 的发布层。
已确认的历史事实包括:
1. 2026-04-08 的发布运行里,校验过 `232` 个文件
2. 其中包含:
- `detail: 37`
- `play: 39`
- `category_list: 41`
- `search: 35`
- 以及 `home / category_index / rank_index / rank_list / forge`
3. `front_verify` 里还能直接看到真实页面文案预览,说明当时这些页面不只是存在文件,而且前台命中验证也通过过
这条结论非常重要,因为它说明:
1. 历史资产在这个仓库里确实存在过
2. 不是用户记忆偏差
3. 也不是“从来就没做过”
4. 只是当前工作树里主数据层已经不完整,剩下的更多是发布备份残留
### 新增脚本:从发布备份聚合恢复
为了避免手工从各个 backup 目录一个一个抄,当前新增:
- `code/scripts/seo_copy_restore_from_publish_logs.php`
作用:
1. 直接扫描 `code/storage/seo_copy_publish_logs/backups`
2. 聚合某个 host 在所有历史发布备份里出现过的页面键
3. 按场景写回 `code/data/seo_copy_published`
4. 支持 `--dry-run`
示例:
```bash
php code/scripts/seo_copy_restore_from_publish_logs.php \
--host=chuanjiafeng-net \
--dry-run
```
正式写入:
```bash
php code/scripts/seo_copy_restore_from_publish_logs.php \
--host=chuanjiafeng-net
```
### 用新脚本恢复后的当前结果
#### chuanjiafeng-net
当前已从 `publish_logs/backups` 聚合恢复到:
1. `home = 1`
2. `category_index = 1`
3. `category_list = 21`
4. `search = 11`
5. `rank_index = 1`
6. `rank_list = 1`
7. `detail = 11`
8. `forge = 11`
9. `play = 11`
再加上之前从 bundle 恢复过的 `detail/play` 样本,现在本地发布目录里已达到:
1. `detail = 17`
2. `play = 17`
3. `home = 1`
4. `category_index = 2`
5. `category_list = 22`
6. `search = 12`
7. `rank_index = 1`
8. `rank_list = 1`
9. `forge = 11`
也就是说,`chuanjiafeng-net` 已经不只是“恢复了几个播放页”而是整套首页、分类、搜索、榜单、详情、播放、forge 都恢复出一批真实历史资产。
#### liangzuan-net
当前已从 `publish_logs/backups` 聚合恢复到完整单样本链:
1. `home = 1`
2. `category_index = 1`
3. `category_list = 1`
4. `search = 1`
5. `rank_index = 1`
6. `rank_list = 1`
7. `detail = 1`
8. `forge = 1`
9. `play = 1`
虽然数量不大,但它是完整的场景闭环,不再只是 `detail/play` 两个点。
### 这一步对后续排查的意义
从现在开始,后续 Codex 处理“GPT 模板引导文是不是被覆盖没了”这类问题时,应该按下面顺序:
1. 先看 `seo_copy_published` 当前是否 default-only
2. 再看 `seo_copy_publish_logs/backups` 是否还有历史备份
3. 能恢复就先恢复历史资产
4. 最后才考虑模板微调或重新生成内容
不要再跳过第 2 步直接重写,否则很容易把已经存在过、且曾经验证通过的资产再次覆盖掉。
## 2026-04-16 补充结论:模板接入未丢,缺的是正式域名深页成品数据
这一轮继续追查后,已经可以把“为什么首页还有引导块,但详情页/播放页很多看不到”说明白:
### 现状不是“GPT 模板又被删了一次”
当前工作树里,`videoGpt1` 模板实际上已经接入了 `seo_copy` 模块,且这些接入点都还在:
1. 首页:
- `code/app/home/view/videoGpt1/index/index.html`
- 已有 `video:seocopy scene="home"` + `module/seo_copy/collection`
2. 分类页:
- `code/app/home/view/videoGpt1/video/getCategory.html`
- `code/app/home/view/videoGpt1/video/getCategoryType.html`
- `code/app/home/view/videoGpt1/video/getRankIndex.html`
- `code/app/home/view/videoGpt1/video/getRankList.html`
- `code/app/home/view/videoGpt1/video/getSearchVideo.html`
3. 详情页:
- `code/app/home/view/videoGpt1/module/detail_main/desc.html`
- 已有 `video:seocopy scene="detail"` + `module/seo_copy/detail`
4. 播放页:
- `code/app/home/view/videoGpt1/video/getVideoPlayUrl.html`
- 已有 `video:seocopy scene="play"` + `module/seo_copy/play`
也就是说,模板层“挂载引导文模块”这件事本身没有消失。
### 为什么首页能看到,详情/播放很多域名却看不到
根因已经验证清楚:多数正式域名当前的 `seo_copy_published` 只有粗粒度页面成品,深页只有 `default.json`,没有当时实际生成过的 detail/play 样本。
抽查结果:
1. `jpjdxs-com`
2. `pcslcl-com`
3. `lsrxs-com`
4. `lmjcg-com`
5. `nblssy-com`
它们目前都满足:
1. `home/index.json` 存在
2. `category_index/index.json` 存在
3. `search/landing.json` 存在
4. `detail/default.json` 存在,但没有 `detail/154229.json` 这类真实深页文件
5. `play/default.json` 存在,但没有 `play/154229-play-douban-1.json` 这类真实播放页文件
因此:
1. 首页能正常出现 `guide-collection`
2. 详情页和播放页会因为 `default-only``VideoService` 的抑制逻辑直接隐藏
这不是模板再次被误删,而是“深页成品资产后来丢了”。
### 实页验证结果
已直接用本地后端端口 `13205` + `Host` 头验证:
1. `jpjdxs.com`
2. `pcslcl.com`
3. `lsrxs.com`
4. `lmjcg.com`
5. `nblssy.com`
验证现象一致:
1. 首页 HTML 能搜到 `guide-collection`
2. 详情页搜不到 `guide-detail`
3. 播放页搜不到 `guide-play`
这和 `seo_copy_published_audit.php` 的审计结果完全一致。
### 对“是不是被 git 覆盖了”的判断
当前更准确的表述不是“整套 GPT 模板被 git 覆盖没了”,而是:
1. 模板接入层还在
2. 一部分首页/分类/搜索成品还在
3. 当时生成并发布过的 detail/play 深页成品,大概率在后续同步、回滚、清理或目录覆盖过程中丢失
已知更强证据:
1. `v20260413-openai-batch-26/openai_batch_result.json`
2. `v20260413-openai-batch-26/openai_deep_batch_26_rerun_20260414.json`
里面明确记录了 `jpjdxs.com / pcslcl.com / lsrxs.com / lmjcg.com / nblssy.com` 都是:
- `已生成并发布首页/分类/搜索/详情/播放页文案`
说明这些深页文案当时真实存在过。
### 目前能下的结论
1. 你记得的那批首页引导文、详情引导文、播放引导文,并不是“记混了”
2. 模板挂载位并没有整体消失
3. 当前缺的是正式域名的历史深页成品文件
4. 后续恢复应继续优先走“历史资产找回”,而不是重新手写一版替代品
### 后续恢复顺序
后面的 Codex 接手时,应按下面顺序继续:
1. 先审计目标 host 是否 `detail_default_only / play_default_only`
2. 再在 `publish_logs / release_runs / batch / bundle / 其它运行产物` 中找历史成品
3. 找到就恢复原始 page-key 文件
4. 只有在确定历史成品完全无法找回时,才考虑重生成
### 2026-04-16 补充结论:通用发布链和 bootstrap 发布链不是一回事
这次继续排查后,已经可以把“为什么很多正式域名只剩 `default.json`”说得更准确一些:
1. 当前仓库里的“通用 AI 生成/发布链”本身就只覆盖粗粒度页面
2. 其中 `detail` 只写 `detail/default`
3. 其中 `play` 只写 `play/default`
4. 它并不会自动产出 `detail/<videoId>.json`
5. 也不会自动产出 `play/<videoId>-<line>-<episode>.json`
已确认的代码位置:
1. `code/app/common/helper/SeoCopyGenerationHelper.php`
2. `code/app/common/helper/SeoCopyAiProviderHelper.php`
3. `code/app/admin/controller/Site.php`
这些位置目前都还是按下面的固定目标处理:
1. `home/index`
2. `category_index/index`
3. `category_list/default`
4. `search/landing`
5. `detail/default`
6. `play/default`
也就是说:
1. 如果某个域名只跑过这条“通用链路”
2. 那它最终落盘到 `seo_copy_published` 的结果,本来就很可能只有默认深页
### bootstrap 链路才会生成真实深页 page-key
和上面不同,`seo_copy_domain_bootstrap.php` 这条链路会生成:
1. `detail/<videoId>.json`
2. `forge/<videoId>-forge-<n>.json`
3. `play/<videoId>-play-<line>-<episode>.json`
因此真正的“详情页/播放页差异化补料”主要来自 bootstrap 或等价的深页发布流程,而不是后台那条通用发布流程。
### 为什么 `chuanjiafeng-net` / `liangzuan-net` 还看得到深页差异化
继续查 `storage/seo_copy_release_runs``storage/domain_bootstrap_bundles` 后,已经拿到了更直接的证据:
1. `chuanjiafeng-net` 的 release run 里明确记录过 `detail/154229.json`
2. 同一批记录里也明确记录过 `play/154229-play-douban-1.json`
3. `storage/domain_bootstrap_bundles/chuanjiafeng-compact/` 下也保留了大量真实深页素材
4. `liangzuan-net` 也有类似 bundle / 历史产物
这说明它们确实走过“深页发布链”,所以今天还能看到更完整的差异化补料。
### 为什么 `jpjdxs-com` 这批正式域名目前看起来像“只剩默认”
对下面这些 host
1. `jpjdxs-com`
2. `pcslcl-com`
3. `lsrxs-com`
4. `lmjcg-com`
5. `nblssy-com`
6. `lcdchq-com`
7. `lgyz-net`
8. `oronorent-com`
9. `sdxhtgcl-com`
当前仓库里已经确认:
1. `code/data/seo_copy_published/<host>/detail/` 只有 `default.json`
2. `code/data/seo_copy_published/<host>/play/` 只有 `default.json`
3. `storage/seo_copy_release_runs` 里几乎搜不到这些 host 的深页发布记录
4. `storage/domain_bootstrap_bundles` 里也搜不到它们对应的历史 bundle
这意味着更大的概率不是“这次模板把深页补料删了”,而是下面两种情况之一:
1. 这些 host 当时根本没有在当前仓库/当前机器里完成 bootstrap 深页发布
2. 它们的深页发布资产存在于另一台机器、另一份工作区,后来没有同步回来
### 关于“后台预览看起来全没了”的补充说明
后台当前的已发布预览接口也会加重误判,因为它只展示:
1. `detail/default`
2. `play/default`
而不会枚举展示真实的:
1. `detail/<videoId>`
2. `play/<videoId>-<line>-<episode>`
对应代码位置:
1. `code/app/admin/controller/Site.php`
2. 方法:`getDomainSeoCopyPublishedPreview`
所以后台看到“只有 default”不一定等于前台一定没有具体深页但对本轮这批正式域名来说前台与文件审计结果已经相互印证确实是深页资产缺失。
### 当前最可靠的判断
截至 2026-04-16这个问题应拆成两层分别处理
1. 页面模板/UI 层
这层已经恢复,首页/详情/播放的 GPT 模板挂载位、引导块和正文块都在
2. 深页发布资产层
这层在多数正式域名上仍缺历史 page-key 文件,因此只能 fallback 或直接抑制显示
后续任何 Codex 接手时,不要再把这两个问题混在一起判断。
### 2026-04-16 再补一条关键证据:`openai_batch_result` 里的“已发布详情/播放”不是深页发布
这次继续把运行结果、代码和 git 历史对齐后,可以更明确地纠正一个容易误解的点:
1. `v20260413-openai-batch-26/openai_batch_result.json`
2. `v20260413-openai-batch-26/openai_deep_batch_26_rerun_20260414.json`
里面对很多正式域名都写着:
1. `written_pages = 6`
2. `已生成并发布首页/分类/搜索/详情/播放页文案`
但这里的“6 个页面”不是:
1. 首页
2. 分类
3. 搜索
4. 真实详情深页
5. 真实播放深页
6. 其它真实样本页
而是固定指向这 6 个槽位:
1. `home/index`
2. `category_index/index`
3. `category_list/default`
4. `search/landing`
5. `detail/default`
6. `play/default`
### 已核实的代码证据
以下代码都由同一个提交引入固定槽位配置:
1. `code/app/common/helper/SeoCopyGenerationHelper.php`
2. `code/app/common/helper/SeoCopyAiProviderHelper.php`
3. `code/app/admin/controller/Site.php`
对应 `git blame` 结果显示,这几处固定配置都来自:
1. 提交:`0794c903`
2. 时间:`2026-04-15 14:00:19 +0800`
也就是从这套通用链路落地开始,它的设计目标就不是“为每个 host 发布真实 deep page key”。
### 对批处理成功记录的正确理解
因此当批处理结果里看到:
1. `jpjdxs.com`
2. `pcslcl.com`
3. `lsrxs.com`
4. `lmjcg.com`
5. `nblssy.com`
6. `lcdchq.com`
7. `lgyz.net`
8. `oronorent.com`
9. `sdxhtgcl.com`
都显示:
1. `status = success`
2. `written_pages = 6`
更准确的解释应该是:
1. 它们成功写入了“6 个固定 SEO 文案槽位”
2. 不是成功写入了真实 `detail/<videoId>.json`
3. 也不是成功写入了真实 `play/<videoId>-play-<line>-<episode>.json`
### 对“当时明明说发布过详情/播放”的最终解释
现在可以把这句话解释完整了:
1. 当时说“发布过详情/播放”
2. 在通用链路语义里成立
3. 但它指的是 `detail/default``play/default`
4. 不等于深页差异化资产已经落盘
所以后面再排查“深页引导文为什么没有了”时,不能再单纯依据 `openai_batch_result` 里的成功状态下结论,必须继续看:
1. `seo_copy_published/<host>/detail/`
2. `seo_copy_published/<host>/play/`
3. 是否真的存在非 default 的 page-key 文件
### 2026-04-16 外部找回清单
截至当前排查结果,下面这些正式域名在当前仓库内的发布状态完全一致:
1. `jpjdxs-com`
2. `pcslcl-com`
3. `lsrxs-com`
4. `lmjcg-com`
5. `nblssy-com`
6. `lcdchq-com`
7. `lgyz-net`
8. `oronorent-com`
9. `sdxhtgcl-com`
它们当前在 `code/data/seo_copy_published/<host>/` 下都只有:
1. `home/index.json`
2. `category_index/index.json`
3. `category_list/default.json`
4. `search/landing.json`
5. `detail/default.json`
6. `play/default.json`
没有任何:
1. `detail/<videoId>.json`
2. `play/<videoId>-play-<line>-<episode>.json`
同时也已经确认:
1. 当前机器 `/www/wwwroot` 范围内未发现这批 host 的第二份深页 JSON 副本
2. `storage/seo_copy_release_runs` 内未发现这批 host 的非 default `detail/play` 发布证据
3. `storage/domain_bootstrap_bundles` 内未发现这批 host 对应 bundle
因此,如果还要继续“找回历史成果”,应优先去当前仓库之外的地方找。
### 外部找回优先顺序
建议按下面顺序查:
1. 旧服务器或旧工作区里的 `code/data/seo_copy_published`
2. 旧服务器或旧工作区里的 `code/data/seo_copy`
3. 旧服务器或旧工作区里的 `code/storage/domain_bootstrap_bundles`
4. 旧服务器或旧工作区里的 `code/storage/seo_copy_publish_logs`
5. 旧服务器或旧工作区里的 `code/storage/seo_copy_release_runs`
6. 当时跑批使用过但未纳入 git 的临时目录、压缩包、备份盘
重点只看下面两类文件:
1. `detail/*.json` 中非 `default.json` 的文件
2. `play/*.json` 中非 `default.json` 的文件
### 外部找回时的最小判断标准
只要满足下面任意一条,就说明该 host 存在可恢复价值:
1. 找到至少 1 个 `detail/<videoId>.json`
2. 找到至少 1 个 `play/<videoId>-play-<line>-<episode>.json`
3. 找到对应 host 的 bootstrap bundle
4. 找到 release log / publish log 明确记录了非 default 的 `detail/play` page_key
如果四条都没有,再默认该 host 的历史深页资产在现有环境中不可恢复。
### 找回后的恢复原则
一旦在外部目录找到了某个 host 的深页资产,恢复时必须遵守下面原则:
1. 只回灌该 host 缺失的 `detail/play` 非 default 文件
2. 不覆盖已经存在的首页、分类、搜索固定槽位
3. 不修改模板逻辑
4. 不修改路由逻辑
5. 不改数据库
6. 先 dry-run 审计,再正式复制
恢复目标目录仍然是:
1. `code/data/seo_copy_published/<host>/detail/`
2. `code/data/seo_copy_published/<host>/play/`
### 如果外部也找不到,最小代价重建方案
只有在确认外部目录也找不到历史资产后,才进入重建方案。
重建时不要直接“大面积重写所有文案”,而应采用最小代价方案:
1. 继续保留当前首页、分类、搜索固定槽位
2. 只补 `detail/play` 深页资产
3. 先补少量高频样本页,不一次性铺满全站
4. 补料逻辑必须保持“同域名稳定、同视频稳定、同线路稳定”
5. 优先生成真实 page-key 文件,而不是再写回 `default.json`
### 重建边界
如果进入重建,必须遵守下面边界,避免再把历史成果覆盖成统一模板:
1. 不改现有 `home/index`
2. 不改现有 `category_index/index`
3. 不改现有 `category_list/default`
4. 不改现有 `search/landing`
5. 只新增非 default 的 `detail/play` 文件
6. 不把新增深页资产重新压回 `detail/default` / `play/default`
### 推荐的重建节奏
建议节奏如下:
1. 每个 host 先选 10 到 20 个真实详情页样本
2. 每个详情页只补 1 个主播放线路、1 个主集数
3. 先验证前台是否能稳定命中这些 page-key
4. 再观察蜘蛛是否重新命中并抓取
5. 只有验证有效后,才继续扩到更多样本
### 当前阶段最重要的判断
截至 2026-04-16最重要的判断不是“模板还要不要继续改”而是
1. 先确认正式域名有没有可找回的历史深页资产
2. 若没有,再进入“新增深页资产”的最小重建方案
在这一步之前,不建议继续大改 GPT 模板页面结构,否则容易把“资产缺失问题”误判成“模板呈现问题”。
### 2026-04-16 最小重建方案的技术实施蓝图
如果后续确认外部环境也找不到历史深页资产,推荐按下面的技术路径做“最小重建”,并且只做深页资产补回,不做模板重写。
### 目标
目标只做一件事:
1. 为缺失的 host 新增少量真实 `detail/play` page-key JSON
不是要做下面这些事情:
1. 不是重做首页 SEO
2. 不是重做分类页 SEO
3. 不是重做搜索页 SEO
4. 不是重改 GPT 模板结构
5. 不是把 fallback 文案整体替换成 AI 文案
### 已有可复用链路
当前仓库里,已经有一条能生成真实深页 page-key 的现成链路,可作为最小重建基础:
1. `code/scripts/seo_copy_domain_bootstrap.php`
2. `code/scripts/seo_copy_release_run.php`
3. `code/app/common/helper/SeoCopyFallbackBuilder.php`
4. `code/app/common/helper/SeoCopyStore.php`
5. `code/app/services/VideoService.php`
其中最关键的是:
1. `seo_copy_domain_bootstrap.php`
它本来就会生成:
- `detail/<videoId>.json`
- `forge/<videoId>-forge-<n>.json`
- `play/<videoId>-play-<line>-<episode>.json`
2. `VideoService::buildSeoCopyPageKeys()`
前台读取时也本来就优先查这些真实 page-key
所以最小重建不需要重新发明一套新格式,重点是把这条深页资产生成链安全地用在正式域名上。
### 建议的实施顺序
推荐按下面顺序推进:
1. 样本选择
2. 深页 JSON 生成
3. 只回灌 `published` 目录
4. 前台命中验证
5. 蜘蛛抓取观察
6. 再决定是否扩样本
### 第 1 步:样本选择
每个 host 先不要全量铺,而是先选小样本:
1. `detail` 先选 10 到 20 个 `videoId`
2. `play` 每个 `videoId` 只先选 1 条主线路
3. 每条线路只先选 1 个集数
样本建议优先来自:
1. 当前站点首页正在推荐的内容
2. 分类页正在曝光的内容
3. 蜘蛛日志最近命中的真实 `detail/play` URL
4. 数据库里播放线路稳定、标题稳定的内容
### 第 2 步:深页 JSON 生成
生成深页资产时,优先使用现有 bootstrap 链路:
1.`seo_copy_domain_bootstrap.php` 生成单 host 小批量 bundle
2. 让它输出真实 `detail/play` page-key JSON
3. 源内容先允许走 `SeoCopyFallbackBuilder`
这样做的原因是:
1. 先恢复“深页资产存在”这件事
2. 再考虑文案质量迭代
3. 避免一开始把问题扩大成“AI 质量 + 资产缺失 + 模板呈现”三件事同时处理
### 第 3 步:只回灌 `published`
真正回灌时,只把生成结果写到:
1. `code/data/seo_copy_published/<host>/detail/`
2. `code/data/seo_copy_published/<host>/play/`
不建议第一步就把内容同时写回:
1. `code/data/seo_copy`
2. 大批量 `approved`
3. 旧的通用 AI 发布链
因为当前最重要的是验证“前台是否会优先命中真实深页 page-key”。
### 第 4 步:前台命中验证
每次小批量回灌后,必须做 3 类验证:
1. 文件验证
- `detail/<videoId>.json` 是否存在
- `play/<videoId>-play-<line>-<episode>.json` 是否存在
2. 页面验证
- 详情页是否从“空/抑制”变成命中 `guide-detail`
- 播放页是否从“空/抑制”变成命中 `guide-play`
3. 回退验证
- 其他没有补样本的页面,仍然保持原有 default/fallback 行为
### 第 5 步:蜘蛛抓取观察
回灌后不要立刻扩全站,先观察:
1. 百度是否重新命中这批 `detail/play`
2. 命中后是否稳定返回 200
3. 页面正文是否能稳定被抓到,不再出现空白深页
### 当前最应该复用的代码点
后续实施时,优先围绕下面这些点展开,而不是另起炉灶:
1. `code/scripts/seo_copy_domain_bootstrap.php`
已具备真实深页 page-key 生成能力
2. `code/app/services/VideoService.php`
已具备优先查真实 page-key、缺失时回退 `default` 的读取逻辑
3. `code/app/common/helper/SeoCopyStore.php`
已具备按 host / scene / page_key 写入 JSON 的能力
4. `code/scripts/seo_copy_restore_from_source.php`
可作为“把 source 写回 published”的参考工具
5. `code/scripts/seo_copy_published_audit.php`
可作为回灌后的审计工具
### 当前不建议直接改动的代码点
在进入最小重建阶段时,下面这些位置不建议先动:
1. `code/app/home/view/videoGpt1/*`
页面层已经恢复,不是当前主问题
2. `code/app/home/config/router.php`
路由层已稳定,先不要把问题重新引入
3. `code/app/admin/controller/Site.php` 的通用 AI 发布逻辑
这条链本身就是固定槽位链,短期不必强改成深页链
### 如果后续一定要补“后台一键深页发布”
那应该作为第二阶段做,而不是第一阶段。
第二阶段的方向应该是:
1. 保留当前后台“固定 6 槽位”能力
2. 另外新增“深页样本发布”入口
3. 让后台可以按 host + videoId + playType + playIndex 生成和发布小批量深页 JSON
不要直接把原来的通用 AI 发布按钮改成全深页逻辑,否则风险很高。
### 最小重建阶段的成功标准
第一阶段不追求“恢复整站所有历史差异化”,只追求下面 4 条:
1. 某个正式域名出现至少 10 个真实 `detail/<videoId>.json`
2. 同一域名出现对应的 `play/<videoId>-play-<line>-<episode>.json`
3. 详情页和播放页前台能稳定命中这些 page-key
4. 蜘蛛开始重新抓到这些非空深页
做到这 4 条,就说明“深页资产链”已经重新打通,后面再扩量才有意义。
### 2026-04-16 试点重建 checklist
下面这份 checklist 用于“先拿 1 个正式域名做小样本试点”,目标是先验证链路,不追求一次铺满。
### 一、试点前准备
开始前先确认下面 4 件事:
1. 只选 1 个 host不并行多 host
2. 不改模板
3. 不改路由
4. 不改数据库结构
建议优先试点 host
1. `lgyz-net`
2. `lcdchq-com`
3. `jpjdxs-com`
原因:
1. 这几个 host 当前都属于典型 default-only
2. 前台路由已经验证过可访问
3. 更适合做“补深页资产后是否立刻生效”的观察
### 二、样本选择 checklist
每次试点先准备:
1. 10 到 20 个 `videoId`
2. 每个 `videoId` 只选 1 条主线路
3. 每条线路只选 1 个主集数
样本优先级:
1. 首页正在推荐的内容
2. 分类页正在曝光的内容
3. 蜘蛛最近命中的详情/播放 URL
4. 播放线路最稳定的内容
不建议选:
1. 没有稳定播放线路的视频
2. 刚入库、字段不完整的视频
3. 需要复杂 slug 才能访问、当前又不稳定的视频
### 三、生成 bundle 的建议方式
推荐优先用现有 bootstrap 脚本做单 host 小样本 bundle。
参考命令模板:
```bash
php scripts/seo_copy_domain_bootstrap.php <host> \
--detail-id=<videoId> \
--detail-slug=<slug> \
--search-keyword=<keyword> \
--category-parent=<parent> \
--category-child=<child> \
--bundle-root=storage/domain_bootstrap_bundles/<bundle-name> \
--index-root=storage/domain_bootstrap_bundles \
--portal-root=public/_seo_copy_release
```
说明:
1. 这一步的核心是拿到 bundle 里的真实 `detail/play` page-key JSON
2. 不要求一开始就把 10 到 20 个样本一次性都塞进去
3. 可以先跑通 1 个样本,再扩到 10 个
### 四、bundle 生成后先做 dry-run
生成 bundle 后,先不要正式应用,先 dry-run。
建议顺序:
```bash
php scripts/domain_bootstrap_run.php <bundle-root> --dry-run=1 --format=text
```
必要时再分步:
```bash
php scripts/domain_bootstrap_register.php <bundle-root>/site-register.sample.json --dry-run=1 --format=text
php scripts/domain_seo_bootstrap_apply.php <bundle-root>/site-bootstrap.sample.json --dry-run=1 --format=text
```
dry-run 通过后,再决定是否继续。
### 五、写回 `published` 前的文件检查
在真正回灌前,先确认 bundle/source 里已经出现:
1. `detail/<videoId>.json`
2. `play/<videoId>-play-<line>-<episode>.json`
如果只有:
1. `detail/default.json`
2. `play/default.json`
那说明这次生成仍然没有产出真实深页资产,不能继续写回。
### 六、回灌方式
如果 bundle/source 中已经有真实深页文件,优先用现成恢复脚本回灌:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=<host-dir> \
--source=<bundle-or-source-root> \
--dry-run
```
确认无误后,再正式写入:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=<host-dir> \
--source=<bundle-or-source-root>
```
当前版本的这个脚本已经升级为:
1. 不传 `--scenes` 时,自动识别 source 里实际存在的已知场景并回灌
2.`--scenes=...` 时,只恢复指定场景
目前默认支持:
1. `home`
2. `category_index`
3. `category_list`
4. `search`
5. `rank_index`
6. `rank_list`
7. `detail`
8. `forge`
9. `play`
如果只想做最小恢复,仍然可以显式指定:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=<host-dir> \
--source=<bundle-or-source-root> \
--scenes=detail,play \
--dry-run
```
### 七、回灌后的文件审计
写回后第一时间跑审计:
```bash
php scripts/seo_copy_published_audit.php --host=<host-dir> --format=text
```
必要时加样本检查:
```bash
php scripts/seo_copy_published_audit.php \
--host=<host-dir> \
--sample-detail=<videoId> \
--sample-play=<videoId>:<playType>:<episode> \
--format=text
```
通过标准:
1. `detail_default_only: no`
2. `play_default_only: no`
3. 指定 sample 的 `expected_page_key` 存在
### 八、前台命中验证
文件审计通过后,再做前台读取验证。
读回验证:
```bash
php scripts/seo_copy_readback.php <host> detail <videoId> --format=text
php scripts/seo_copy_readback.php <host> play <videoId> <playType> <episode> --format=text
```
前台验证:
```bash
php scripts/seo_copy_front_verify.php <host> detail <videoId> --base-url=http://127.0.0.1:13205 --format=text
php scripts/seo_copy_front_verify.php <host> play <videoId> <playType> <episode> --base-url=http://127.0.0.1:13205 --format=text
```
通过标准:
1. 详情页命中 `guide-detail` 或等价正文引导块
2. 播放页命中 `guide-play` 或等价正文引导块
3. 不是继续走空白或被抑制状态
### 九、试点观察窗口
第一次试点完成后,不要立刻扩全量,建议至少观察一个抓取窗口:
1. 先观察数小时到 1 天
2. 看蜘蛛是否回打这批深页
3. 看命中后是否稳定 200
4. 看正文是否真实输出,不再是空深页
### 十、试点成功后的扩量规则
只有试点成功后,才允许扩量。
扩量时建议:
1. 先从 10 个样本扩大到 30 个
2. 再从 30 个扩大到 100 个
3. 每次扩量后都要重复审计和前台验证
不要直接:
1. 一次生成全站所有 `detail/play`
2. 一次回灌所有 host
### 十一、试点失败时怎么判断原因
如果试点失败,优先按下面顺序排查:
1. bundle/source 是否真的产出非 default `detail/play`
2. `restore_from_source` 是否真的写入 `published`
3. `seo_copy_published_audit` 是否仍显示 default-only
4. `seo_copy_readback` 是否能读到真实 page-key
5. `seo_copy_front_verify` 是否命中了对应前台 URL
只有先把这 5 层排干净,才允许怀疑模板或路由。
### 2026-04-16 第一试点 host 建议
基于当前仓库与本机回测结果,第一试点 host 建议优先选:
1. `jpjdxs.com`
原因:
1. 当前属于典型 `detail_default_only / play_default_only`
2. 首页和详情页都能稳定打开
3. 已经能从详情页直接抽到真实播放链接
4. 详情 URL 和播放 URL 规则相对清晰,便于做第一批 dry-run
当前已确认的 URL 形态:
1. 详情页:`/neirong-<videoId>-<slug>`
2. 播放页:`/bf-<videoId>-<slug>/<playType>-<episode>`
例如:
1. 详情页:`/neirong-154229-xiang-feng-bu-shi-jiu-shi-ren`
2. 播放页:`/bf-154229-xiang-feng-bu-shi-jiu-shi-ren/douban-1`
同时也已确认:
1. `seo_copy_published` 下不存在 `detail/154229.json`
2. `seo_copy_published` 下不存在 `play/154229-play-douban-1.json`
这正适合作为第一批“从无到有补深页资产”的试点。
### `jpjdxs.com` 第一批样本候选
当前已从首页与详情页抽到一批真实样本,建议先从下面 8 个详情样本开始:
1. `76342` / `se-jiang-zhi-xue-mei-gui`
2. `76318` / `she-sha-shou`
3. `76347` / `se-jie`
4. `76341` / `se-qing-dian-ying-da-shui-qiang-de-liu-de-wang`
5. `76324` / `shao-nv-de-you-huo`
6. `76346` / `se-gui-tou-tai`
7. `76359` / `san-fen-zhi-yi-qing-ren`
8. `76325` / `shao-nv-de-you-huo`
对应已抽到的播放页候选如下:
1. `76342`
- `default-1`
- `douban-1`
- `youzhi-1`
2. `76318`
- `default-1`
- `douban-1`
- `youzhi-1`
3. `76347`
- `default-1`
- `douban-1`
4. `76341`
- `default-1`
- `douban-1`
5. `76324`
- `default-1`
- `douban-1`
6. `76346`
- `default-1`
- `douban-1`
- `youzhi-1`
7. `76359`
- `default-1`
- `douban-1`
- `youzhi-1`
8. `76325`
- `default-1`
- `douban-1`
### 第一试点最小建议组合
如果要把风险再压低,建议第一轮不是 8 个全上,而是先从下面 3 个 detail + 3 个 play 开始:
1. `detail/76342`
2. `detail/76318`
3. `detail/76347`
4. `play/76342-play-douban-1`
5. `play/76318-play-douban-1`
6. `play/76347-play-douban-1`
原因:
1. 这 3 个样本都来自首页当前真实曝光内容
2. 详情页与播放页链接都已实测能抽到
3. `douban-1` 在线路上最统一,适合先打通第一轮
### 当前试点前的已知空缺验证
已直接验证:
1. `jpjdxs.com detail 154229` 当前无对应 `seo_copy_published` 深页文件
2. `jpjdxs.com play 154229 douban 1` 当前无对应 `seo_copy_published` 深页文件
这说明当前环境仍然符合试点前置条件:
1. 深页资产缺失是真实存在的
2. 不是已经生成但前台没命中
## 2026-04-16 `jpjdxs.com` 第一批深页试点已落地
这段不是计划,是本地已经执行过的结果。
### 本次选择的最小样本
详情页:
1. `76318`
2. `76342`
3. `76347`
播放页:
1. `76318-play-douban-1`
2. `76342-play-douban-1`
3. `76347-play-douban-1`
### 已执行动作
1.`seo_copy_domain_bootstrap.php` 分别为这 3 个样本生成 bundle
2. 从 bundle 中抽出真实 `detail/play` page-key JSON
3. 先在临时目录做了 `seo_copy_batch_import.php` 闭环验证
4. 再把这 6 个深页 JSON 回灌到真实:
- `code/data/seo_copy_published/jpjdxs-com/detail/`
- `code/data/seo_copy_published/jpjdxs-com/play/`
### 当前结果
当前 `jpjdxs-com` 已从原来的深页接近 `default-only`,变成:
1. `detail` 目录:
- `default.json`
- `76318.json`
- `76342.json`
- `76347.json`
2. `play` 目录:
- `default.json`
- `76318-play-douban-1.json`
- `76342-play-douban-1.json`
- `76347-play-douban-1.json`
### 审计结果
重新跑 `seo_copy_published_audit.php` 后已确认:
1. `detail_default_only: no`
2. `play_default_only: no`
3. `detail non_default_count: 3`
4. `play non_default_count: 3`
也就是说:
1. 第一批深页资产链已经重新打通
2. 当前不是停留在“理论上可恢复”
3. 而是 `jpjdxs.com` 已经具备最小规模的真实深页 page-key 资产
## 2026-04-16 再确认:当前仓库里的“生成能力”和“导入能力”边界
这段是给后续所有接手的 Codex 看的,避免再把问题判断错方向。
### 1. `SeoCopyAiProviderHelper` 这条通用链,只会发布固定槽位
已再次核对:
- `code/app/common/helper/SeoCopyAiProviderHelper.php`
- `code/app/common/helper/SeoCopyGenerationHelper.php`
当前通用发布链固定只处理:
1. `home/index`
2. `category_index/index`
3. `category_list/default`
4. `search/landing`
5. `detail/default`
6. `play/default`
也就是说:
1. 它不会自动产出 `detail/<videoId>.json`
2. 它不会自动产出 `play/<videoId>-play-<line>-<episode>.json`
3. 所以某个 host 就算“通用 AI 发布成功”,深页也仍然可能是 `default-only`
这一点非常重要,后面不要再把“通用发布成功”误判成“深页差异化一定已经恢复”。
### 2. 真正的深页差异化资产,来自 bootstrap 深页链
已再次核对:
- `code/scripts/seo_copy_domain_bootstrap.php`
这条链会直接生成真实 page-key
1. `detail/<videoId>.json`
2. `forge/<videoId>-forge-<n>.json`
3. `play/<videoId>-play-<line>-<episode>.json`
因此:
1. 你之前记得的那批 GPT 模板详情引导文、播放引导文、差异化块
2. 本质上更接近 bootstrap 深页资产链的结果
3. 不是后台那条“固定 6 槽位”通用发布链的自然产物
### 2.1 2026-04-17 再确认:旧 `restore_from_source` 的缺口已经补上
这轮继续排查 `jpjdxs.com` 后,已经进一步确认:
1. 有些 host 不是“source 没有资产”
2. 而是“source 里有更多场景,但旧恢复脚本只写回了 `detail/play`
以本机这次实际找到的 source 为例:
- `code/storage/domain_bootstrap_bundles/jpjdxs-seed-a1/data/seo_copy/jpjdxs-com`
里面实际存在:
1. `home/index.json`
2. `category_index/dian-ying.json`
3. `category_list/dian-ying--shao-shi-dian-ying.json`
4. `search/h-2d9bf00ea1f2e5ee.json`
5. `rank_index/index.json`
6. `rank_list/daily.json`
7. `detail/76342.json`
8. `forge/76342-forge-1.json`
9. `play/76342-play-douban-1.json`
但旧版 `code/scripts/seo_copy_restore_from_source.php` 只会扫:
1. `detail`
2. `play`
所以会出现一种很容易把人带偏的现象:
1. bundle/source 里明明有榜单、forge、分类、搜索资产
2. 执行恢复后却只有 `detail/play` 被补进 `published`
3. 前台就会表现成“有些引导文回来了,有些还是像没恢复”
这轮已经把:
- `code/scripts/seo_copy_restore_from_source.php`
升级成“按 source 中实际存在场景自动回灌”的版本,默认支持:
1. `home`
2. `category_index`
3. `category_list`
4. `search`
5. `rank_index`
6. `rank_list`
7. `detail`
8. `forge`
9. `play`
并且已在本机对 `jpjdxs-com` 做过 dry-run 与正式写回验证:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=jpjdxs-com \
--source=code/storage/domain_bootstrap_bundles/jpjdxs-seed-a1/data/seo_copy \
--dry-run
php code/scripts/seo_copy_restore_from_source.php \
--host=jpjdxs-com \
--source=code/storage/domain_bootstrap_bundles/jpjdxs-seed-a1/data/seo_copy
```
写回后重新审计,已经新增恢复出:
1. `category_index/dian-ying.json`
2. `category_list/dian-ying--shao-shi-dian-ying.json`
3. `search/h-2d9bf00ea1f2e5ee.json`
4. `rank_index/index.json`
5. `rank_list/daily.json`
6. `forge/76342-forge-1.json`
同时前台闭环验证已经通过:
```bash
php code/scripts/seo_copy_front_verify.php jpjdxs.com rank_index --target-root=code/data/seo_copy_published --base-url=https://jpjdxs.com --format=text
php code/scripts/seo_copy_front_verify.php jpjdxs.com rank_list daily --target-root=code/data/seo_copy_published --base-url=https://jpjdxs.com --format=text
php code/scripts/seo_copy_front_verify.php jpjdxs.com forge 76342 1 --target-root=code/data/seo_copy_published --base-url=https://jpjdxs.com --format=text
```
结果都已经:
1. `status: 200`
2. `all_matched: yes`
这条结论以后非常重要:
1. 如果 `source` 里有 `rank_index / rank_list / forge / category / search`
2.`published` 里只有 `detail / play`
优先先查:
1. 当前机器上的 `seo_copy_restore_from_source.php` 是否已经是“全场景版本”
2. 之前是不是只跑过旧脚本或 `--scenes=detail,play`
不要再直接误判成:
1. 这些资产从来没生成过
2. bundle/source 已经失效
3. 之前做好的差异化已经全部被删光
### 3. 系统并不是“不能导入深页文件”,而是“缺少深页源文件”
已再次核对:
- `code/scripts/seo_copy_batch_import.php`
- `code/app/common/helper/SeoCopyBatchImportHelper.php`
当前导入器支持的目录结构就是:
1. `<source-dir>/<host-dir>/<scene>/<page_key>.json`
这意味着:
1. 它支持导入任意 `detail/<videoId>.json`
2. 它支持导入任意 `play/<videoId>-play-<line>-<episode>.json`
3. 当前真正缺的不是导入能力
4. 当前真正缺的是:
- 历史深页源文件
- 或新生成出来的深页源文件
### 4. 以后再排查“引导文没了”,统一按这个顺序
1. 先看模板层是不是挂载还在
2. 再看运行时是不是被 suppress / fallback 卡住
3. 再看 `seo_copy_published/<host>/detail``play` 是否只剩 `default.json`
4. 再看 `storage/domain_bootstrap_bundles` / `storage/seo_copy_publish_logs` / `storage/seo_copy_release_runs` 里有没有历史深页成品
5. 确认历史成品确实不存在后,才进入“小批量 bootstrap 深页重建”
## 2026-04-16 深夜补充:不是“模板又没了”,而是 `runtime/home/temp` 权限污染
这次线上又出现了一次很容易误判的现象,必须单独记下来。
### 1. 现象
当时看到的是:
1. 首页 `title/keywords/description` 正常
2. 详情页大多正常
3. 播放页有时正常,有时直接变成 ThinkPHP 错误页
4. 从体感上很像:
- 之前做好的 GPT 模板引导文又没了
- 页面又像被 git 覆盖回旧状态
- SEO 头信息像“忽然空掉”
### 2. 实际根因
实测抓到的不是模板逻辑丢失,而是:
- `code/runtime/home/temp` 里混进了一批 `root:root` 的编译模板文件
- 实际 PHP-FPM 进程是 `www` 用户
- 所以当 ThinkPHP 需要重写这些模板缓存时,会报:
- `file_put_contents(...runtime/home/temp/...php): Failed to open stream: Permission denied`
### 3. 为什么它会表现得像“优化被覆盖了”
因为这个问题不是“所有页面一起死”,而是:
1. 已经命中旧缓存的页面,可能还能正常显示
2. 需要重新编译模板的页面,会直接报错
3. 于是现场看起来就像:
- 一部分 GPT 引导文还在
- 一部分页面像恢复成旧样子
- 一部分页面干脆系统错误
所以这种现象不能第一时间认定成:
1. git 又把模板覆盖了
2. SEO key 又丢了
3. 数据库把引导文清空了
### 4. 这次实际处理方式
已在正式排查中确认:
1. `php-fpm` 运行用户是 `www`
2. `runtime/home/temp` 中存在多份 `root root` 文件
3.`runtime/home` 下属主纠正回 `www:www`
4. 再复测:
- 详情页恢复正常
- 播放页恢复正常
- `guide-detail` / `guide-play` 正常输出
- `canonical` / `og:url` / JSON-LD `url` 恢复到正确页面
### 5. 后续所有 Codex 统一排查顺序
以后再遇到“GPT 模板像突然失忆”时,统一先做这 4 步:
1. 先抓线上实际 HTML不要只凭浏览器体感判断
2. 看是不是 ThinkPHP 错误页,尤其关注 `runtime/home/temp` 写入失败
3. 检查 `runtime/home/temp` 是否混入 `root:root`
4. 只有确认运行时缓存正常后,才继续判断是不是模板 / SEO copy / git 历史问题
## 2026-04-17 凌晨补充:搜索页串页不是模板错,是前端缓存 key 漏了 query string
这也是一个很容易把人带偏的问题,必须单列。
### 1. 实测现象
同一时间分别抓:
1. `/get-index?keyword=爱情`
2. `/get-index?keyword=动作`
结果两次返回:
1. `x-cache-status: HIT`
2. HTML 里的 `title`
3. `canonical`
4. `og:url`
全部都是“爱情”那一页的内容。
也就是说:
1. 不同关键词请求
2. 命中了同一份前端缓存
3. 不是后端模板在实时生成对应 query 的页面
### 2. 结论
这说明当前前端缓存层对搜索页的 cache key 存在高概率配置问题:
1. cache key 没有带上 query string
2. 或搜索页请求被错误归入“只按 URI 缓存”的 location
它会直接造成:
1. 搜索页串页
2. `canonical` / `og:url` / `title` 与真实 query 不一致
3. SEO 表现看起来像“模板或 SEO 数据随机失效”
### 3. 这类问题的判定规则
以后凡是看到:
1. 搜索页关键词 A 打开后像关键词 B
2. `canonical` 看着像随机错乱
3. 源码明明已经修对,但线上输出不稳定
优先先看:
1. 响应头里的 `x-cache-status`
2. 前端缓存 key 是否包含 query string
不要第一时间误判为:
1. 模板回滚
2. seo_copy 丢失
3. 数据库内容被覆盖
### 4. 当前前端 nginx 模板里的直接根因
已对照当前仓库内的前端配置模板:
- [站点伪静态.txt](/www/wwwroot/diff-maccms/前端站群服务器nginx配置/站点伪静态.txt)
问题点在于动态页缓存 key 原来是:
```nginx
proxy_cache_key "$scheme$request_method$host$uri";
```
这意味着:
1. `/get-index?keyword=爱情`
2. `/get-index?keyword=动作`
会共用同一个缓存 key因为它们的 `uri` 都只是 `/get-index`
### 5. 最小修复方案
动态页缓存 key 至少改成:
```nginx
proxy_cache_key "$scheme$request_method$host$uri$is_args$args";
```
这样:
1. 不同 query string 会拆分缓存
2. 搜索页不会再互相串页
3. `canonical` / `og:url` / `title` 不会再被别的关键词页面污染
### 6. 推荐同步修复范围
不要只改搜索页单点 location。
当前建议直接同步到:
1. `location /`
2. `location ~* \.(html|htm)$`
原因是:
1. 搜索页当前命中的是 `location /`
2. 但以后如果某些动态页走 `.html` 风格并带 query也会遇到同类问题
### 7. 上线后复测方法
改完 nginx 并清缓存后,用两组不同关键词直接抓响应头和 HTML
```bash
curl -s -D - 'https://你的域名/get-index?keyword=爱情' -o /tmp/a.html
curl -s -D - 'https://你的域名/get-index?keyword=动作' -o /tmp/b.html
rg '<title>|canonical|og:url' /tmp/a.html
rg '<title>|canonical|og:url' /tmp/b.html
```
通过标准:
1. 两个页面的 `title` 不同
2. `canonical` 分别指向各自关键词
3. `og:url` 分别指向各自关键词
4. 不再出现“动作词页返回爱情 HTML”的现象
## 2026-04-17 继续补充:`chuanjiafeng-net` 已完成一轮多场景恢复
这条是本机继续排查后的新增结论,目的是把“哪些 host 还需要修、哪些已经可以当样板”区分清楚。
### 1. 先看 source / published 差额
本机对比后确认:
1. `code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy/chuanjiafeng-net`
2. `code/data/seo_copy_published/chuanjiafeng-net`
之间之前确实存在明显差额。
最典型的是:
1. `category_index`source 远多于 published
2. `category_list`source 远多于 published
3. `search`source 远多于 published
4. `rank_list`source 有 `daily / weekly / monthly / total`published 原先只有 `daily`
5. `forge`source 比 published 多出多批真实 page-key
也就是说,`chuanjiafeng-net` 在这台机器上虽然已经不是“default-only”但之前仍属于“只恢复了一部分”的状态。
### 2. 本轮采用的恢复策略
为了避免把首页已有主文案冲掉,这轮没有恢复 `home`,只恢复下面这些场景:
```bash
php code/scripts/seo_copy_restore_from_source.php \
--host=chuanjiafeng-net \
--source=code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy \
--scenes=category_index,category_list,search,rank_index,rank_list,detail,forge,play \
--dry-run
php code/scripts/seo_copy_restore_from_source.php \
--host=chuanjiafeng-net \
--source=code/storage/domain_bootstrap_bundles/chuanjiafeng-compact/data/seo_copy \
--scenes=category_index,category_list,search,rank_index,rank_list,detail,forge,play
```
这个策略的好处是:
1. 保住首页现成资产
2. 只补短板场景
3. 恢复面又足够大
### 3. 恢复后的审计结果
恢复后重新审计:
```bash
php code/scripts/seo_copy_published_audit.php --host=chuanjiafeng-net --format=text
```
关键结果已经变成:
1. `category_index: total=6, non_default=6`
2. `category_list: total=32, non_default=31`
3. `search: total=16, non_default=16`
4. `rank_index: total=1, non_default=1`
5. `rank_list: total=4, non_default=4`
6. `detail: total=17, non_default=16`
7. `forge: total=16, non_default=16`
8. `play: total=17, non_default=16`
说明这轮恢复后,`chuanjiafeng-net` 已经不是“局部样本恢复”,而是多场景资产都补齐了一大截。
### 4. 前台验证结果
这轮不是只看文件数量,还做了前台验证:
```bash
php code/scripts/seo_copy_front_verify.php chuanjiafeng.net rank_list weekly --target-root=code/data/seo_copy_published --base-url=https://chuanjiafeng.net --format=text
php code/scripts/seo_copy_front_verify.php chuanjiafeng.net category_list dian-ying dong-zuo-pian --target-root=code/data/seo_copy_published --base-url=https://chuanjiafeng.net --format=text
```
结果都已经:
1. `status: 200`
2. `all_matched: yes`
其中已确认命中的新增场景包括:
1. `rank_list/weekly`
2. `category_list/dian-ying--dong-zuo-pian`
这说明 `chuanjiafeng-net` 这轮新增恢复出来的:
1. 非日榜周期页
2. 细分类列表页
都已经被前台真实读到,不是只停留在离线文件层。
### 5. 后续判断结论
从现在开始,`chuanjiafeng-net` 在这台机器上应视为:
1. 已恢复成功的多场景样板 host
2. 不是当前优先抢修对象
后续如果还要继续扩它,优先考虑:
1. 补更多 `home` 变体
2. 补更大规模的 `detail / play / forge` 样本
但在“先救火、先补漏恢复 host”这个优先级里`chuanjiafeng-net` 已经可以后移。
## 2026-04-17 继续补充:`liangzuan.net` 当前更像“前台部署/回源未命中 GPT 路由”,不是文案文件丢失
这条结论很重要,避免后面把“前台 404”误判成“SEO 文案又没了”。
### 1. 本机已确认 `liangzuan-net` 的发布文件仍然存在
当前本机发布层里,下面这些文件都还在:
1. `code/data/seo_copy_published/liangzuan-net/home/index.json`
2. `code/data/seo_copy_published/liangzuan-net/category_index/dian-ying.json`
3. `code/data/seo_copy_published/liangzuan-net/category_list/dian-ying--xi-ju-pian.json`
4. `code/data/seo_copy_published/liangzuan-net/search/h-c37e405008e4e8c5.json`
5. `code/data/seo_copy_published/liangzuan-net/rank_index/index.json`
6. `code/data/seo_copy_published/liangzuan-net/rank_list/daily.json`
7. `code/data/seo_copy_published/liangzuan-net/detail/154124.json`
8. `code/data/seo_copy_published/liangzuan-net/forge/154124-forge-1.json`
9. `code/data/seo_copy_published/liangzuan-net/play/154124-play-youzhi-1.json`
而且文件内容不是空壳,已经确认存在真实引导文,例如:
1. `rank_list/daily` 有榜单导语与引导卡片
2. `category_list/dian-ying--xi-ju-pian` 有分类导语
3. `search/h-c37e405008e4e8c5` 对应关键词“圣诞不独行”
4. `detail/154124``play/154124-play-youzhi-1` 都有正文引导
所以这一轮不能再把 `liangzuan.net` 判成“发布文件被删了”。
### 2. 当前主题缓存里的 GPT 路由族已经能确定
`code/storage/theme_cache/liangzuan.net.json` 当前记录的 `url_family` 为:
1. 详情页:`film/{strPinyin}/{intVId}`
2. 伪详情页:`film/{strPinyin}/{intVId}-{intVForgeId}`
3. 播放页:`player/{intVId}-{strPlayType}-{intPlayIndex}`
4. 一级分类:`leixing/{strParentCategory}/home`
5. 二级分类:`leixing-{strParentCategory}/{strCategory}/page{intPage}`
6. 榜单首页:`phb/all`
7. 榜单列表:`phb/{strSortType}/home`
8. 搜索:`get/index`
9. 历史:`record/index`
按这套路由推导,理论访问地址应类似:
1. `https://www.liangzuan.net/phb/daily/home`
2. `https://www.liangzuan.net/leixing-dian-ying/xi-ju-pian/page1`
3. `https://www.liangzuan.net/get/index?keyword=圣诞不独行`
4. `https://www.liangzuan.net/film/sheng-dan-bu-du-xing-meng-fei-si-lian-qu/154124`
5. `https://www.liangzuan.net/player/154124-youzhi-1`
### 3. 当前外部访问结果不是“页面文案缺失”,而是整页直接回 nginx 404
实测以上路径时,当前线上直接返回:
1. `HTTP/2 404`
2. `server: nginx`
3. `content-length: 2616`
4. 固定静态错误页特征一致
这说明当前症状更像:
1. 域名没有回源到这套应用
2. 或前台 nginx / 站点发布目录没有接这组 GPT 路由
3. 或线上跑的仍是另一套路由族
总之,**不是单纯 seo_copy 文件缺失导致的 404**。
### 4. 历史验收记录说明这个站点的路由族曾经发生过切换
本机历史运行记录里至少存在两种路径形态:
1. 2026-04-06 早期记录里,成功路径是:
- `https://www.liangzuan.net/detail/pinyin-sheng-dan-bu-du-xing-meng-fei-si-lian-qu`
- `https://www.liangzuan.net/detail/pinyin-sheng-dan-bu-du-xing-meng-fei-si-lian-qu/1`
2. 2026-04-08 后期记录里,成功路径变成:
- `https://www.liangzuan.net/film/sheng-dan-bu-du-xing-meng-fei-si-lian-qu/154124`
- `https://www.liangzuan.net/film/sheng-dan-bu-du-xing-meng-fei-si-lian-qu/154124-1`
这说明:
1. `liangzuan.net` 不是一直固定在单一路由族
2. 历史上至少发生过一次从 `detail/...``film/...` 的切换
3. 如果线上站点还停在旧路由,或 DNS/回源指到了旧发布目录,就会出现“本地文件正常、外部全 404”
### 5. 当前最合理的判断
`liangzuan.net`,现阶段更合理的结论是:
1. 本地 SEO 文案文件仍在
2. 主题缓存里也有当前期望的 GPT 路由定义
3. 但线上域名访问没有命中这套路由
4. 因此当前问题优先看前台部署 / nginx / 回源 / 实际运行版本
5. 不要再优先怀疑“seo_copy 又被删了”
### 6. 后续排查顺序建议
如果后面要继续接手 `liangzuan.net`,建议按这个顺序:
1. 先确认线上域名当前真正回源到哪个项目目录
2. 再确认前台 nginx 是否把 `/film``/player``/phb``/leixing``/get/index` 这组路径交给后端
3. 再确认线上实际 `theme_cache` / 运行缓存是否还是 `A043`
4. 如果线上仍在旧路由族,再决定是:
- 回切旧路由兼容
- 还是统一切到新路由族
在这几步没确认前,不建议继续对 `liangzuan-net` 做大规模文案重建,因为大概率修的不是根因。
## 2026-04-17 继续补充:`detail/play` 引导文退化的一个明确根因已经定位
这条结论直接对应“前面做好的引导文和排版怎么像没了一样”。
### 1. 模板骨架本身没有整体丢失
本轮继续核对 `videoGpt1` 模板历史后,已经确认:
1. 首页导览、`guide-collection`
2. 详情页 `dm-desc-guide`
3. 播放页 `guide-play`
这些核心区块目前代码里都还在。
例如当前文件里仍然能看到:
1. `code/app/home/view/videoGpt1/module/seo_copy/collection.html`
2. `code/app/home/view/videoGpt1/module/seo_copy/detail.html`
3. `code/app/home/view/videoGpt1/module/seo_copy/play.html`
4. `code/app/home/view/videoGpt1/module/detail_main/desc.html`
而且 `detail_main/desc.html``2a905bbf restore gpt seo copy pipeline and stabilize seo tkd output` 这次提交相比,主体结构并没有被后续提交删掉。
所以:
1. 不是“整套引导区块被模板回滚掉了”
2. 更像是“模板还在,但喂进去的数据退回了通用 fallback”
### 2. 明确的代码拐点发生在 `56644e7f`
这次提交:
`56644e7f fix(videoGpt1): normalize seo pages and fallback services`
`code/app/services/VideoService.php` 里加入了一段新逻辑:
1.`detail`
2.`play`
如果当前 host 只有:
1. `default.json`
2. 没有对应 `video_id` / `play_key` 的细粒度 JSON
那就:
1. 不再读取 `default.json`
2. 直接返回空数组
3. 后续走 `SeoCopyFallbackBuilder::build(...)`
这会带来一个非常直接的结果:
1. 模板区块还在
2. 但不再读 host 自己的默认引导文案
3. 而是统一退回通用 fallback 句式
页面体感上就会像:
1. “前面做好的细腻引导文没了”
2. “页面又变成一坨通用说明”
### 3. 这个 suppress 逻辑影响面不小
本机已确认有一批 host 当前 `detail/play` 都只有 `default.json`,例如:
1. `lcdchq-com`
2. `lgyz-net`
3. `oronorent-com`
4. `sdxhtgcl-com`
5. `gz-yxsw-com`
6. `jpjdxs-com`
7. 以及其它多批 host
也就是说,一旦这段 suppress 逻辑开启,这些 host 的详情页与播放页就会:
1. 放弃本域名已有的 `default.json`
2. 强制退回 fallback
### 4. `default.json` 本身并不差,反而通常比 fallback 更像“之前做好的内容”
本轮直接抽查了几个 host 的默认文案,例如:
1. `code/data/seo_copy_published/jpjdxs-com/detail/default.json`
2. `code/data/seo_copy_published/jpjdxs-com/play/default.json`
3. `code/data/seo_copy_published/lcdchq-com/detail/default.json`
4. `code/data/seo_copy_published/lcdchq-com/play/default.json`
确认这些 `default.json` 里本来就包含:
1. `detail_body_lead`
2. `detail_play_link_lead`
3. `play_intro`
4. `play_body_lead`
5. `guide_cards`
并且还是带占位符插值的版本,比如:
1. `{video_name}`
2. `{video_alias}`
3. `{year}`
4. `{play_line}`
这类内容在渲染后,明显比通用 fallback 更接近“前面已经做好的可读引导”。
### 5. 本轮已经做的修复
当前已经把这段 suppress 逻辑撤掉,恢复为:
1. 详情页、播放页仍然优先读 `seo_copy` 发布文件
2. 即使只有 `default.json`,也允许先使用 `default.json`
3. 只有完全读不到可用数据时,才退回 `SeoCopyFallbackBuilder`
这次修复文件:
1. `code/app/services/VideoService.php`
修复后逻辑重新回到更符合直觉的顺序:
1. 优先细粒度 page-key
2. 其次 host 自己的 `default.json`
3. 最后才是通用 fallback
另外,本轮继续往下排查后又确认了一层:
1. 有些 host 虽然存在细粒度 `detail/play` page-key 文件
2. 但这些具体文件本身是旧低配格式
3. 它们没有 `title_template / keywords_template / description_template / guide_cards`
4. 同时文案主体比 `default.json` 更通用
典型样本:
1. `jpjdxs-com/detail/76342.json`
2. `jpjdxs-com/play/76342-play-douban-1.json`
这类文件会继续压住 `default.json`,导致页面仍然表现得像“引导文退化”。
所以这轮又补了一层兼容:
1. 如果 `detail/play` 命中的具体 page-key 文件属于旧低配格式
2. 则自动合并 `default.json` 里的 richer 字段
3. 重点补入:
- `guide_cards`
- `title_template`
- `keywords_template`
- `description_template`
- `detail_body_lead / detail_play_link_lead / detail_body_tail / detail_faq`
- `play_intro / play_meta_note / play_body_lead / play_body_next`
这样可以尽量保留具体 page-key 已有的主题信息,同时恢复默认版更成熟的引导结构。
### 5.1 这一层兼容的实测现象
当前前台实测已经出现分层结果:
1. `jpjdxs.com` 播放页真实页面已出现:
- `当前为色降2之血玫瑰播放页`
- `如果你已在详情页确认...`
- `播放前建议...`
- `先看线路`
2. 同站详情页暂时仍显示旧通用句式
这更像:
1. 代码逻辑已经生效
2. 但详情页前台仍可能被页面缓存 / 反向代理缓存顶住
后续如果继续验证,不要只看一轮 curl就直接下结论说“修复无效”要先区分
1. 代码逻辑未生效
2. 还是前台缓存未刷新
### 5.2 2026-04-17 本轮抽样后的三类状态清单
为了避免后面继续把“代码问题 / 缓存问题 / 部署问题”混在一起,这里先把本轮真实抽样结果按三类归档。
#### A 类:前台已经明确恢复,可视为“代码修复已落地”
这类站点的共性是:
1. 首页 `title/keywords/description` 正常
2. 真实详情页 / 播放页至少有一页已经命中更丰富的引导文
3. 不再只是通用 fallback 话术
已确认样本:
1. `lcdchq.com`
- 详情页:`/movie/76328-shan-zhong-yan-tan`
- 播放页:`/kan/shan-zhong-yan-tan-76328/douban-1`
- 前台已出现:
- `本页为山中艳谭的资料详情页...`
- `先核对资料`
- `当前页面为山中艳谭的播放页...`
- `播放前建议...`
2. `oronorent.com`
- 详情页:`/shipin/76347-se-jie`
- 播放页:`/m3u8/se-jie-76347/youzhi-1`
- 前台已出现:
- `本页汇总...`
- `先核对资料`
- `如果你已经确认是目标内容`
- `先选线路`
- `当前为...`
- `若你已从详情页确认目标内容`
3. `lgyz.net`
- 详情页:`/movie/76332-shang-di-zhi-guo`
- 详情页前台已出现:
- `先核对资料`
- 说明详情页方向已对,文案修复至少已在详情页落地
4. `jpjdxs.com`
- 详情页:`/neirong-76342-se-jiang-zhi-xue-mei-gui`
- 播放页:`/bf-76342-se-jiang-zhi-xue-mei-gui/default-1`
- 2026-04-17 在前端清缓存后再次复测,详情页正文已出现:
- `本页为色降2之血玫瑰的详情资料页...`
- `如果你已确认片名与资料信息...`
- `先核对资料`
- 播放页仍正常输出:
- `当前为色降2之血玫瑰播放页...`
- `播放前建议...`
- 说明这站最终不是代码回退,而是前端整页缓存顶住旧 HTML清缓存后已恢复
#### B 类:代码逻辑大概率已生效,但前台可能仍受缓存影响
这类站点的共性是:
1. 本地 `seo_copy_published` 已有更丰富默认文案
2. 本地逻辑验证已确认 richer 字段可以被合并出来
3. 前台某一类页面已恢复,但另一类页面仍停留在旧通用句式
已确认样本:
1. 当前暂无新的稳定 B 类样本。
- `jpjdxs.com` 原先属于这一类
- 但 2026-04-17 在前端清缓存并切换新版 nginx 动态页缓存策略后,已转入 A 类
- 这次案例可作为“代码没问题,只是前端缓存顶着旧 HTML”的标准样本
当前更合理的判断是:
1. 若再次出现 B 类问题,优先先看前端整页缓存
2. 老配置里动态页 cache key 若只按 path 或只按 URI极容易把旧 HTML 顶很久
3. 加 query 参数不一定能绕过缓存,要结合当前 nginx 的 `proxy_cache_key` 判断
#### C 类:本地文案完整,但线上细页路径/部署仍需单独确认
这类站点的共性是:
1. 本地发布文件存在
2. 但外部访问时,用当前猜测路径会直接 404
3. 更像线上真实路由族、nginx 回源或部署目录与本机认知不完全一致
已确认样本:
1. `chuanjiafeng.net`
- 本地文件:
- `detail/154229.json`
- `play/154229-play-douban-1.json`
- 内容完整
- 2026-04-17 追加抽样:
- 根站首页可正常打开
- 已出现 `首页导览`
- 已出现 `guide-collection`
- 详情页真实路由已确认是:
- `/film/154229-xiang-feng-bu-shi-jiu-shi-ren`
- 播放页真实路由已确认是:
- `/player/xiang-feng-bu-shi-jiu-shi-ren-154229/douban-1`
- `/player/xiang-feng-bu-shi-jiu-shi-ren-154229/youzhi-1`
- 详情页前台已出现:
- `本页整理《相逢不识旧时人》的剧情主线与基础资料...`
- `如果你已经确认作品,可继续查看播放线路页...`
- `先看剧情主线`
- `核对基础资料`
- `再进播放页`
- 说明该站不是模板失效,也不是 seo_copy 丢失,而是前面人工猜的细页路径错误
2. `liangzuan.net`
- 前面已单独确认:
- 线上外部路径直接回 nginx `404`
- 2026-04-17 追加抽样:
- 直接访问 `https://liangzuan.net` 时,证书校验失败
- 使用 `curl -k` 忽略证书后,根站返回 `404`
- `curl -k -I https://liangzuan.net/favicon.ico` 同样返回 `404`
- 说明当前不是“只有深页坏了”,而是域名入口本身没有正确落到站点内容
- 本地 `theme_cache/liangzuan.net.json` 存在,但当前未看到可用 `route_paths`
- 本地 `seo_copy_published/liangzuan-net/` 当前只有 `home/index.json`
- `detail/default.json``play/default.json` 均不存在
- 当前应优先判断:
- 域名证书与站点入口配置异常
- 这域名当前也不像是已完成完整 seo_copy 回灌的站点
- 不是“模板突然丢了”,而是“入口未接通 + 内容资产未完整”
2. `liangzuan.net`
- 前面已单独确认:
- 本地 SEO 文案文件仍在
- 主题缓存里也有 GPT 路由定义
- 但线上外部路径直接回 nginx `404`
- 更像部署 / 回源未命中 GPT 路由
- 2026-04-17 追加抽样:
- 直接访问 `https://liangzuan.net` 时,证书校验失败
- 使用 `curl -k` 忽略证书后,根站返回 `404`
- 当前应优先判断:
- 域名证书与站点入口配置异常
- 不是 seo_copy 或 GPT 模板正文层的问题
3. `lgyz.net`
- 详情页已可直测
- 但本轮手工猜的播放路径 `/bf-76332-shang-di-zhi-guo/youzhi-1` 返回 `404`
- 需要继续按真实播放路由再确认,不宜直接判成文案问题
### 5.3 当前阶段的工作重点建议
到这一步,后续排查优先级应改成:
1. 先用 A 类站点继续验证“default / legacy merge”是否稳定
2. 再对 B 类站点重点清缓存、复测详情页
3. 对 C 类站点先排真实路由 / nginx / 回源,不要急着重写 seo_copy 数据
### 5.4 2026-04-17 前端 nginx 动态页安全缓存方案已验证生效
这轮已经把前端 nginx 新规则真实上线验证通过,当前建议作为长期标准方案使用。
#### 当前建议规则
1. 搜索页 `/get-index`
- `cache key``$args`
2. 详情页 / 播放页 / 分类页 / 榜单页
- `cache key` 不带 `$args`
3. 所有动态页支持 `?__nocache=1`
- 仅用于人工排障
4. 所有动态页返回调试响应头
- `X-Cache-Status`
- `X-Cache-Mode`
- `X-Cache-Bypass`
5. 受管蜘蛛版继续保留
- `X-Managed-Spider`
#### 线上已验证现象
`jpjdxs.com` 为样本2026-04-17 再次验证:
1. 详情页普通访问:
- `X-Cache-Status: STALE`
- `X-Cache-Mode: path-only`
- `X-Cache-Bypass: 0`
- `X-Managed-Spider: normal`
2. 搜索页:
- `X-Cache-Status: MISS`
- `X-Cache-Mode: with-args`
3. 详情页加 `?__nocache=1`
- `X-Cache-Status: BYPASS`
- `X-Cache-Mode: bypass`
- `X-Cache-Bypass: 1`
#### 对后续 Codex 的直接结论
1. 如果前端响应头里已经有:
- `X-Cache-Mode`
- `X-Cache-Bypass`
- `X-Managed-Spider`
说明新版伪静态已经生效
2. 如果页面内容看起来像旧版,但 `?__nocache=1` 正常
- 优先判断为前端缓存问题
- 不要先判断成 git 覆盖或后端模板回退
3. 当前最优模板文件是:
- `前端站群服务器nginx配置/站点伪静态-受管蜘蛛放行版-动态页安全缓存.txt`
### 5.5 2026-04-17 晚间补充:国内蜘蛛有效窗口结论
这轮继续看蜘蛛日志时,发现:
1. `latest/spider-crawl.summary.json` 当前更像最新一轮 `ingest` 基础摘要
2. 它没有展开成适合直接看趋势的聚合视角
3. 所以 latest 看起来像“空壳”,不等于国内蜘蛛完全停抓
#### 手工筛选后的国内蜘蛛窗口
从最近约 180 个 `crawl-logs.summary.json` 中,只筛:
- `baiduspider`
- `sogou`
- `bytespider`
重新轻量聚合后,当前累计大致为:
1. 页面类型:
- `home``144`
- `other``96`
- `robots``87`
- `detail``37`
- `category``34`
- `play``27`
2. 状态码:
- `403``149`
- `301``117`
- `200``113`
- `444``30`
- `404``16`
#### 当前最重要的更新判断
1. 国内蜘蛛最近窗口里,`detail/play` 并没有消失
2. `baiduspider` 深页修复方向仍成立,而且继续出现新的 `301 -> 200 MISS -> 200 HIT` 样本
3. `sogou` 深页当前仍大量是 `403`
4. 所以下一阶段不要把“百度恢复”和“搜狗恢复”混为一谈
#### 最近确认到的百度正向样本
1. `www.codohealth.com`
- `/voddetail/gu-chuan-jin-zhen-qian-jin-jing-shi-feng-jian-lao-zu-zong-73272`
- `200 HIT`
2. `www.codohealth.com`
- `/voddetail/xing-qiu-da-zhan-hei-shi-chuan-shuo-78631`
- `301 -> 200 MISS -> 200 HIT`
3. `sjzyunyang.com`
- `/video-detail/jia-zheng-fu-san-tian-yuan-60513`
- `301 -> 200 MISS -> 200 HIT`
4. `gxhongzhuang.com`
- `/voddetail/xi-xue-gui-ji-nv-184448`
- `301 -> 200 MISS -> 200 HIT`
5. `jingxifa.com`
- `/video-detail/xing-jian-fu-guo-ji-di-wu-ji-107484`
- `301 -> 200 MISS -> 200 HIT`
6. `jingxifa.com`
- `/video-bofang/hei-yi-nv-ren-de-xiang-shui-183894-default-1`
- `301 -> 200 MISS -> 200 HIT`
7. `sjzyunyang.com`
- `/video-bofang/wu-lu-ke-tao-185896-default-1`
- `301 -> 200 MISS -> 200 HIT`
#### 当前新增阻塞点
最近窗口里持续能看到:
1. `www.lgyz.net /vodplay/...`
2. `www.vikau.com /vodplay/...`
3. `www.vikau.com /voddetail/...`
4. `www.jingxifa.com /video-detail/...`
5. `www.jingxifa.com /video-bofang/...`
这些 `sogou` 深页当前大多表现为:
- `403`
- `cache_status = NONE`
因此当前阶段更准确的表述是:
1. 页面恢复层面:成立
2. 百度深页恢复层面:成立
3. `latest` 空壳:只是展示层问题,不代表停抓
4. 当前真正值得继续单独分析的新问题:
- `sogou` 深页 `403`
### 6. 对后续 Codex 的明确提醒
后面如果再看到:
1. 模板还在
2. 但是详情页 / 播放页文案突然变得非常通用
3. 像是“之前的优化白做了”
优先先查:
1. `code/app/services/VideoService.php`
2. 有没有再引入“只剩 default 时不读 default、强制 fallback”的逻辑
不要第一反应就:
1. 怀疑模板被整套回滚
2. 重新重写全部引导文
3. 重新批量生成一轮 seo_copy
这类问题很可能不是生成层丢了,而是读取优先级被改坏了。