本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:暂存20260913/thread_show旧摘要链路扫描报告.md。
thread/show 旧摘要链路扫描报告
扫描时间:2026-09-12
扫描范围:app/、cli/、update/
本报告阶段只做扫描,没有修改
ThreadController.php、thread/show.php、modern.css、thread.js、sw.js或任何核心运行代码。
一、扫描结论
可以进入方案 B + 方案 A 的实施阶段。
当前运行代码中的旧摘要引用
旧摘要链路只存在于以下两个运行时文件:
app/Controllers/ThreadController.phpapp/Views/thread/show.php
cli/ 中没有旧摘要变量引用。
app/Controllers/ApiController.php 不引用:
_threadExcerpt
_threadNeedsExpand
$threadExcerpt
$threadNeedsExpand
Content::excerpt()Content::excerpt() 函数本身只在当前运行代码的 ThreadController::show() 中被调用。
因此可以:
- 保留
Content::excerpt()函数本身; - 删除
ThreadController::show()中详情页摘要链路调用; - 删除
thread/show.php中摘要变量、摘要判断和 htmx 动态正文分支; - 保留
/api/post/{id}/body接口,但标记为 deprecated,暂不删除、不改接口权限逻辑。
二、旧变量逐项引用位置
1. _threadExcerpt
| 文件 | 行号 | 用途 |
|---|---|---|
app/Views/thread/show.php | 25 | 从视图数据读取 _threadExcerpt,赋给 $threadExcerpt |
app/Controllers/ThreadController.php | 242 | 将摘要 HTML 赋给 $threadExcerpt |
app/Controllers/ThreadController.php | 253 | reply_to_view 锁定时清空 $threadExcerpt |
app/Controllers/ThreadController.php | 263 | 作为 _threadExcerpt 传入视图 |
2. _threadNeedsExpand
| 文件 | 行号 | 用途 |
|---|---|---|
app/Views/thread/show.php | 26 | 从视图数据读取 _threadNeedsExpand |
app/Views/thread/show.php | 120 | 判断是否显示摘要分支 |
app/Controllers/ThreadController.php | 235 | 从 Content::excerpt() 结果读取 truncated |
app/Controllers/ThreadController.php | 239 | 判断是否对纯文本摘要补 nl2br |
app/Controllers/ThreadController.php | 242 | 判断是否赋值 $threadExcerpt |
app/Controllers/ThreadController.php | 252 | reply_to_view 锁定时置为 false |
app/Controllers/ThreadController.php | 263 | 作为 _threadNeedsExpand 传入视图 |
3. $threadExcerpt
| 文件 | 行号 | 用途 |
|---|---|---|
app/Views/thread/show.php | 25 | 视图局部变量声明 |
app/Views/thread/show.php | 121 | 输出摘要 HTML |
app/Controllers/ThreadController.php | 242 | 详情摘要赋值 |
app/Controllers/ThreadController.php | 253 | 锁定帖清空 |
app/Controllers/ThreadController.php | 263 | 传入视图 |
4. $threadNeedsExpand
| 文件 | 行号 | 用途 |
|---|---|---|
app/Views/thread/show.php | 26 | 视图局部变量声明 |
app/Views/thread/show.php | 120 | 控制摘要/全文二选一 |
app/Controllers/ThreadController.php | 235 | 读取截断标记 |
app/Controllers/ThreadController.php | 239 | 控制纯文本摘要处理 |
app/Controllers/ThreadController.php | 242 | 控制摘要变量赋值 |
app/Controllers/ThreadController.php | 252 | 锁定帖关闭展开 |
app/Controllers/ThreadController.php | 263 | 传入视图 |
5. thread/show.php 中相关动态分支
| 文件 | 行号 | 用途 |
|---|---|---|
app/Views/thread/show.php | 120–131 | 摘要/完整正文二选一 |
app/Views/thread/show.php | 124 | hx-get="/api/post/{threadId}/body",按需拉取完整正文 |
app/Views/thread/show.php | 125 | 将接口响应替换到主帖正文容器 |
app/Views/thread/show.php | 126 | hx-swap="innerHTML" |
当前 update/168/app/Views/thread/show.php 是源文件的旧发布副本,仍包含同一旧链路;实施后需要同步更新。
三、Content::excerpt() 使用情况
当前运行代码
| 文件 | 行号 | 用途 |
|---|---|---|
app/Helpers/Content.php | 213 | Content::excerpt() 函数定义:安全 HTML 摘要、截断和 truncated 标记 |
app/Controllers/ThreadController.php | 234 | 详情页主帖生成 500 字摘要 |
其它模块检查结果
在当前 app/ 全量搜索中,除 ThreadController::show() 外没有发现其它 Content::excerpt() 调用:
- 列表页:没有独立调用;列表摘要使用自己的数据/字段逻辑;
- 博客:没有独立调用;
- 搜索:没有独立调用;
- API:没有独立调用;
- CLI:没有调用。
结论:
Content::excerpt() 函数本身保留。
本次只删除 ThreadController::show() 的详情页调用。update/ 中存在若干历史增量包副本,例如:
update/60/app/Controllers/ThreadController.php
update/66/app/Controllers/ThreadController.php
update/125/app/Controllers/ThreadController.php
update/135/app/Controllers/ThreadController.php
update/156/app/Controllers/ThreadController.php
update/160/app/Controllers/ThreadController.php
update/166/app/Controllers/ThreadController.php
update/167/app/Controllers/ThreadController.php这些是历史发布包记录,不是当前运行代码。当前目标发布目录 update/168/ 需要在实施后同步为新版本。
四、/api/post/{id}/body 接口依赖检查
路由
| 文件 | 行号 | 用途 |
|---|---|---|
index.php | 272 | 注册 /post/{id}/body → ApiController::postBody |
实现
| 文件 | 行号 | 用途 |
|---|---|---|
app/Controllers/ApiController.php | 526 | postBody($id) 接口定义 |
app/Controllers/ApiController.php | 528–530 | 设置 HTML、nosniff、no-store 响应头 |
app/Controllers/ApiController.php | 532–536 | 校验帖子 ID |
app/Controllers/ApiController.php | 540 | 接口级 post_body 限流 |
app/Controllers/ApiController.php | 542–545 | 查询主题 |
app/Controllers/ApiController.php | 553–556 | 校验版块浏览权限 |
app/Controllers/ApiController.php | 559–566 | 校验 reply_to_view 回复可见权限 |
app/Controllers/ApiController.php | 569 | 直接 decode + formatPostContent 输出完整正文 |
接口内部没有引用:
_threadExcerpt
_threadNeedsExpand
$threadExcerpt
$threadNeedsExpand
Content::excerpt()结论:
- 接口不依赖详情页摘要变量;
- 接口保留不会影响新折叠逻辑;
thread/show.php删除旧hx-get后,当前页面不再调用接口;- 本次不删除接口,因为它可能被外部客户端、旧缓存页面或未来其它页面使用;
- 仅把接口注释标记为 deprecated,说明详情页已经改为服务端全文直出 + Alpine 本地折叠。
五、reply_to_view 隐私逻辑边界
当前详情控制器在 ThreadController.php 约 248–254 行执行:
reply_to_view且用户未回复时,只替换主帖正文为锁定提示;- 回复列表仍然正常展示;
- 锁定状态关闭旧摘要展开。
实施时必须保留这个逻辑,并改成:
- 未授权用户:继续输出锁定提示,不输出可展开全文;
- 已授权用户:输出完整正文,并允许 CSS 折叠 / Alpine 展开;
- 不能把服务端全文直出误用于绕过
reply_to_view权限。
六、缓存层检查
PageCache
app/Helpers/PageCache.php 只缓存静态 HTML 列表页:
首页 / 版块列表游客缓存其缓存内容是完整渲染后的 HTML 字符串,不序列化控制器 $data,没有针对:
_threadExcerpt
_threadNeedsExpand的特殊处理。
ThreadController
ThreadController::show() 没有调用:
PageCache::serve()
PageCache::render()
serialize()因此帖子详情页不会经过 PageCache,也没有缓存层序列化这两个变量的问题。
全量符号检查
在 app/、cli/、update/ 搜索两个下划线变量后:
- 当前运行代码引用仅为
ThreadController.php+thread/show.php; cli/无引用;update/旧历史包有引用,是历史副本,不是独立运行模块;update/168/有旧发布副本引用,实施后必须同步删除。
七、实施前确认清单
扫描结果满足方案 B 的前置条件:
- [x]
Content::excerpt()没有其它当前运行模块依赖; - [x]
/api/post/{id}/body不依赖旧摘要变量; - [x]
thread/show.php旧变量只有主帖摘要链路使用; - [x] PageCache 不序列化旧变量;
- [x]
reply_to_view逻辑可独立保留; - [x] 列表页摘要不受影响;
- [x] 可删除详情页
Content::excerpt()调用及旧变量传参; - [x] 可把 API 标记为 deprecated 而不删除;
- [x] 可继续按方案 A 增加 CSS + Alpine + htmx 局部翻页。
八、下一步允许的修改范围
用户指定的最终修改范围:
app/Controllers/ThreadController.php
app/Views/thread/show.php
assets/css/modern.css
assets/js/thread.js
sw.js
update/168/ 对应同步副本不修改:
app/Core/
app/Models/
app/Helpers/
SplitDB/
其它插件
数据库结构扫描报告完成。等待用户确认本报告后,才执行方案 B + 方案 A 的代码修改。