本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:8月13日备份/模板样式与代码质量整改计划.md。
SoSite 整改计划与修复建议 —— 模板样式冗余 & 代码质量
复核日期:2026-08-07 | 依据:《审计20260806.md》第三、四大项
复核方式:全库只读复核(CSS 引用关系、同名类定位、孤儿文件引用、悬空引用、零调用方法抽查、敏感信息、遗留标记)
结论:本次复核未修改任何代码,以下为核实结果、修复建议与分阶段整改计划。
说明:[已核实] = 本次复核已确认;[需执行时再查] = 建议在动手前再确认一次。
〇、复核总览 —— 与原审计报告的差异
| # | 项目 | 原审计(0806) | 本次复核(0807) | 结论 |
|---|
| D1 | assets/css/home.css | 3.2 列为死文件"可删" | 文件已不存在(glob 无此文件) | ✅ 已被删除,无需处理 |
| D2 | 临时文件 tmp_audit_xss.php | 4.5 "审计完成后应删除" | 已不存在 | ✅ 已被清理 |
| D3 | assets/css/blog.css | 3.1 隐含"旧模板遗留" | 全库零引用(css/blog.css 无任何视图/控制器引用,仅备份 SQL 内容含字样) | 🟠 确认为死文件,可删 |
| D4 | protected/rebuild_runtime.php | 4.1 "疑似遗留脚本" | 文件头部注释声称"由 SettingsController 异步调用",但 app/、protected/ 全库 0 引用 | 🟠 确认孤儿,删除前需确认无历史依赖 |
| D5 | plugins/user_profile/FrontController.php:25 悬空引用 | 4.2 🔴 errors/404 视图不存在 | 仍存在:app/Views/errors/ 目录确认不存在 | 🔴 待修复 |
| D6 | admin.css 同名类 | 3.1 列为"三套互覆" | admin.css 中 .badge/.alert 均已加 .admin-content/.admin-container 作用域前缀;但 .stat-card(admin.css:130)仍无前缀,与 components.css:57 冲突 | 🟡 部分已收敛,剩余待处理 |
其余各项(C1–C9 同名类、内联样式、模板冗余、孤儿视图文件、零调用方法、弱口令/固定密钥、TODO 零命中)经复核均与报告一致。
一、模板与样式冗余(原审计第三章)复核明细
1.1 CSS 文件实际引用关系图 [已核实]
| CSS 文件 | 被谁引用 | 状态 |
|---|
modern.css | 所有页面(layouts/main.php:28 统一加载,前台/后台共用基座) | ✅ 基座,保留 |
fontawesome.css | 所有页面(main.php:40) | ✅ 保留 |
editor.css | needsEditor 时(main.php:42) | ✅ 保留 |
style.css | 后台(main.php:21)+ dice/quiz_duel 插件视图(4 个) | ✅ 保留(后台基础层) |
components.css | 后台 + blog/detail + thread/show + post/create + profile/index + dice/quiz_duel | ✅ 保留(前台工具类层) |
admin.css | 仅后台(main.php:23) | ✅ 保留(已作用域化) |
forum.css | blog/detail.php:17、thread/show.php:26、plugins/qa/question/show.php:9 | 🟡 仅 3 个前台页面在用,用后收敛 |
pages.css | 仅 profile/index.php:12(1 个页面) | 🟠 引用面极窄,可收敛合并 |
layout.css | 仅插件视图:dice/index.php:18、quiz_duel/*(create/detail/index/my 共 4 处) | 🟠 引用面极窄,可收敛合并 |
blog.css | 零引用 | 🟠 死文件,可删 |
themes/modern-*.css(5 变体) | main.php:33 按主题热切换 | ✅ 保留 |
关键结论:前台页面级旧 CSS(forum/pages/layout)合计仅 8 个引用点,收敛成本可控;后台已基本完成作用域化改造。
1.2 同名类互覆清单(C1–C9)[已核实]
| # | 选择器 | 位置 | 冲突性质 | 处理建议 |
|---|
| C1 | .badge | forum.css:112(通用徽章)/ layout.css:57,370(navbar 未读数)/ admin.css:240-245,313(后台徽章,已作用域) | 三义同名,加载顺序决定胜负 | 前台以 forum.css 为准或统一到 modern.css;admin 已作用域无需动 |
| C2 | .alert/.alert-* | components.css:166-175 / pages.css:496-516 / admin.css:248-258,401-411 | 三套配色(3px/4px 边框、不同色板) | 统一到 components.css,pages.css 删;admin 已作用域 |
| C3 | .stat-card | components.css:57(邀请码统计卡,无前缀)/ admin.css:130(后台渐变仪表盘,无前缀) | 后台页面同时加载两文件,谁后加载谁赢(main.php 中 modern.css 最后、无 .stat-card,故由 admin.css 生效,components.css 的 flex:1 失效) | admin.css 的 .stat-card 改为 .admin-content .stat-card(或 .admin-stat-card),彻底隔离 |
| C4 | .avatar-placeholder | components.css:144(24px 圆形首字母)/ layout.css:450(100% 父容器 flex 填充) | 同名不同行为 | 统一一个语义(头像占位建议 24px 版),另一处改名 |
| C5 | .btn-danger | components.css:241 / forum.css:370 | 参数拼合互相干扰 | 合并为一份,按需补 -sm 变体 |
| C6 | .category-header-bar/.category-row/.reply-card/.attachment-item/.empty-state/.stat-label | components.css / forum.css / pages.css 多处 | 中低危同名互覆 | 逐一合并进 components.css,删旧 |
| C7 | 侧栏盒子体系 | forum.css:7-8(.forum-sidebar-box)/ blog.css:238-251(.blog-*)/ layout.css:152(.sidebar-box) | 三套"白卡片+标题下划线"仅前缀不同 | 统一为 modern.css 一份(如 .mn-side-box),视图同步改类名 |
| C8 | 搜索表单 | forum.css:9-12 / blog.css:252-275 / pages.css:323-344 / layout.css:187-209 | 4 套实现 | 统一 1 套,类名改 mn- 前缀 |
| C9 | 分页体系 | forum.css:311(.pagination)/ forum.css:316(.forum-pagination)/ components.css:647(.pagination-custom)/ admin.css:261(已作用域)/ modern.css:613(.mn-pagination) | 6 套实现 | 统一用 modern.css 的 .mn-pagination,其余删除/别名过渡 |
1.3 内联样式滥用 [已核实]
| 范围 | 内联 `style=` 命中数 | 建议 |
|---|
app/Views/admin/* | 33 处 | 抽成 admin.css 类 |
app/Views/thread/show.php | 19 处 | 抽成 modern.css 工具类(如 mn-mt-*、mn-text-link 已有部分) |
app/Views/blog/detail.php | 8 处 | 同上 |
| 其他视图 | 若干 | 逐步收敛,非阻塞 |
1.4 模板结构冗余 [已核实]
- 帖子行/评论行结构(作者栏 + 头像 + 用户名 + 时间 + 楼层号 + 操作按钮 + 内容区)在
thread/show.php 与 blog/detail.php 中各实现一遍,结构高度相似(均含 mn-reply-header、mn-row-avatar-*、楼层、删除/引用按钮)。 app/Views/plugins/* 中 dice、quiz_duel、qa 等插件的卡片结构亦重复前台样式。- 建议:抽取
_components/ 公共片段(如 post_row.php / user_bar.php),视图 include 复用。
二、代码质量(原审计第四章)复核明细
2.1 孤儿文件 [已核实,均存在且零引用]
✅ 身份确认结论(2026-08-07 二次深核)
| 文件 | 它到底是什么 | 谁在用/谁替代了它 | 结论 |
|---|
app/Views/admin/settings.php | 旧版"后台站点设置"单一视图:含维护模式、私信开关、站点名/描述、首页设置、论坛/博客分页数、注册/附件开关等全部字段 | 全库无 view('admin/settings') 调用。当前 SettingsController 已拆分为 settings_basic / settings_display / mail_settings / search_settings 四个视图,且 settings_basic.php 已完整覆盖旧视图全部字段(site_closed / message_enabled / site_name / site_description / allow_registration / allow_attachments / threads_per_page / posts_per_page / blogs_per_page / blog_comments_per_page / home_threads_count / home_blogs_count,见 SettingsController.php:23-24,45-46) | 🗑️ 确认为被拆分视图取代的旧文件,可删 |
app/Views/emails/verify_email.txt | 注册邮箱验证邮件的纯文本模板(占位符 $siteName / $username / $verifyLink,1 小时有效链接) | 全库无读取。实际发信逻辑在 AuthController.php:201-207(注册)与 resendVerification(452-455)用 PHP 字符串内联拼装同文内容,Mailer::send() 直接收 body 字符串,从未加载任何 emails/ 模板文件 | 🗑️ 确认为模板化改造前的遗留文件,可删 |
protected/rebuild_runtime.php | 后台重建运行时计数器的独立 CLI 脚本:循环重建 total_users/total_threads/total_posts/total_blogs 四个计数器 + buildCache(),带 PID/锁文件防重入;头部注释声称"由 SettingsController 异步调用" | app/、protected/ 全库 0 引用。实际重建功能已由 MaintenanceController::index() 的 runtime_rebuild 分支内联实现(两步模式:写 .rebuild_pending 标记 → 重定向后同页执行 runtimeBuildSingle + buildCache,逻辑与脚本完全一致) | 🗑️ 确认为被 MaintenanceController 内联替代的遗留脚本,可删(⚠️ 该脚本含 @exec("tasklist ...") 调用,仅作遗留记录,无实际风险) |
protected/database/schema_mysql.sql | V2.x 遗留建库脚本(MySQL 版) | 全库 0 引用,现行建库脚本为 schema.sql | 🗑️ 删除 |
protected/database/schema_sqlite.sql | V2.x 遗留建库脚本(SQLite 版) | 全库 0 引用 | 🗑️ 删除 |
2.2 悬空引用 [已核实,🔴 高]
| 位置 | 问题 | 修复方案 |
|---|
plugins/user_profile/FrontController.php:25 | $this->view('errors/404', [...]),但 app/Views/errors/ 目录不存在 → 用户不存在时渲染异常 | 方案 A(推荐):新建 app/Views/errors/404.php 通用 404 视图(前台/插件均可复用);方案 B:改 $this->redirect('/')。建议 A + B 兜底双保险 |
2.3 零调用方法(原报告 25 个)[抽查一致]
本次抽查了 Settings::getOnlineUsers(已被 getOnlineData 取代,HomeController 实际用 getOnlineData)、Blog::getByCategory(控制器用 getByCategoryPaginated)、Message::getUnreadCount、Points::isReplyToView/getLevelTitle、Permission::getUserGroupId/getUserGroup/isAdminGroup/canReplyToThread 等,定义均在、未见调用,与原报告一致。
| 分组 | 方法 | 建议 |
|---|
| Helpers | RateLimiter::remaining、Points::getLog/getLevelTitle/isReplyToView、Settings::getOnlineUsers/paginate/renderPagination/getAttachment、Search::rebuildFTS、Tag::renderInput、Theme::getInfo/exists/safeTitleColor | 先全库(含 plugins/)再查一次确认无插件引用,加 @deprecated 一个版本后再删;直接删亦可 |
| Permission 遗留 | getUserGroupId/getUserGroup/isAdminGroup/getGroupName/canReplyToThread | 同上 |
| Models | Blog::getByCategory、BlogComment::getByBlog、Post::getLastPage/restore、Thread::getLatest/getLatestPaginated/search、User::onlineCount、Message::getUnreadCount | 同上 |
⚠️ 注意:Thread::restore 有调用(TrashedController.php:29),不在清单内;清单内为 Post::restore,删除时勿混淆。
2.4 硬编码敏感信息 [已核实]
| 位置 | 内容 | 建议 |
|---|
config.php:8-9 | DB 账号 so / 123456 弱默认口令 | 正式部署必须更换;本地开发可暂留 |
config.php:21 | MAIL_PASS_KEY 固定 AES 密钥 SoSite_AES_Key_2026!@#XyZ7890AbCdEf= | 正式部署必须更换;密钥一旦更换,已加密的 SMTP 密码需重新设置(Mailer 用该密钥加解密) |
2.5 遗留标记 [已核实]
- TODO/FIXME/XXX/HACK:零命中 ✅(grep 命中仅来自备份 SQL 内的历史内容,非代码)
- 注释掉的代码块:零命中 ✅
- 临时文件:
tmp_audit_xss.php 已删除 ✅
三、分阶段整改计划(含验证方式)
排序原则:先修复会影响功能/安全的(悬空引用),再清死文件(零风险),再做样式收敛(需逐页回归),最后做可选优化与部署卫生。
阶段 1 —— 修复悬空引用(🔴 高,必须做)
| 步骤 | 内容 | 文件 | 验证 |
|---|
| 1.1 | 新建 app/Views/errors/404.php(复用 modern 布局:mn-section + 提示 + 返回首页链接) | 新文件 | 浏览器访问不存在的用户主页(如 /u/99999)→ 应显示 404 页而非报错 |
| 1.2 | FrontController.php:25 增加兜底:若视图渲染失败则 redirect('/')(或直接改用 redirect + 404 页二选一,实现一个即可) | plugins/user_profile/FrontController.php | 同上回归 |
| 1.3 | 顺手确认 Controller::view() 对不存在的视图有报错提示(日志可见即可,非必改) | app/Core/Controller.php | php -l 语法检查 |
阶段 2 —— 删除孤儿文件与死 CSS(🟠 中,零/低风险)
| 步骤 | 内容 | 文件 | 验证 |
|---|
| 2.1 | 删除孤儿视图/模板文件 | app/Views/admin/settings.php、app/Views/emails/verify_email.txt | 后台"站点设置"各子页(basic/display/mail/search)逐一打开正常 |
| 2.2 | 删除 V2.x 遗留建库脚本 | protected/database/schema_mysql.sql、schema_sqlite.sql | protected/database/schema.sql 仍在;新装环境用 schema.sql 验证建库 |
| 2.3 | 删除 protected/rebuild_runtime.php | 该文件 | 先在 git 历史/交接文档确认无定时任务或外部调用;删除后后台"重建索引"功能正常(该功能由 SettingsController 内部分页处理,不依赖此脚本——删除前请再确认一次) |
| 2.4 | 删除死 CSS assets/css/blog.css | 该文件 | grep 确认无引用后删;前台博客页(列表/详情)样式回归 |
阶段 3 —— CSS 同名类收敛(🟠 中,需逐页回归)
核心策略:以 modern.css + components.css 为唯一基座,admin.css 保持作用域化,逐步下线 forum/pages/layout。
| 步骤 | 内容 | 涉及文件 | 验证 |
|---|
| 3.1 | 盘点 3 个旧 CSS 在 8 个引用点中的实际使用类(用 grep 视图 class= 逐视图统计) | forum.css(3 视图)、pages.css(1 视图)、layout.css(4 插件视图) | 产出"类 → 使用页"清单 |
| 3.2 | 低风险先行:C3 .stat-card(admin.css:130 加 .admin-content 前缀)、C4 .avatar-placeholder(合并为一义)、C5 .btn-danger(合并) | admin.css / components.css / forum.css / layout.css | 后台仪表盘、邀请码页、前台按钮样式回归 |
| 3.3 | 分页统一(C9):视图分页片段改用 .mn-pagination,删除 forum/components 的旧分页类(admin 保留作用域版) | 涉及分页的视图 + modern.css/components.css/forum.css | 前台列表页分页、后台列表分页回归 |
| 3.4 | 侧栏/搜索/徽章统一(C7/C8/C1/C2):统一为 mn- 前缀类,同步改视图类名 | forum.css / layout.css / blog.css(已删) / components.css + 相关视图 | 前台各页侧栏、搜索框、徽章、alert 回归 |
| 3.5 | 收尾:确认 forum.css/pages.css/layout.css 中已无被引用类后,更新 8 个视图的 css 引用(删掉不再需要的 link),最后删除或归档 3 个旧文件 | 8 个引用视图 + 3 个 CSS | 全站前台逐页截图对比 |
| 3.6 | 收敛完成后跑一遍全站页面清单(home/forum/thread/blog/profile/search/tags/登录注册/私信/插件 8 个视图) | — | 无样式回归即通过 |
⚠️ 每步独立提交,可随时回滚;本阶段是工作量最大的部分,建议拆成多次迭代,每次只动一类(先分页,再侧栏,再徽章…)。
阶段 4 —— 内联样式与模板结构收敛(🟡 低,可选优化)
| 步骤 | 内容 | 验证 |
|---|
| 4.1 | thread/show.php(19 处)、blog/detail.php(8 处)内联样式抽为 modern.css 工具类 | 帖子页/博客详情页回归 |
| 4.2 | admin/*(33 处)内联样式抽为 admin.css 类 | 后台各页回归 |
| 4.3 | 抽取 _components/ 公共片段(帖子行/评论行),thread/show.php、blog/detail.php、插件视图复用 | 发帖/回帖/评论/插件页回归 |
| 4.4 | 零调用方法(25 个):全库(含 plugins/)最终确认后加 @deprecated 或删除 | php -l + 功能抽查 |
阶段 5 —— 部署卫生(🟡 低,正式上线前必须做)
| 步骤 | 内容 | 验证 |
|---|
| 5.1 | 更换 config.php DB 口令(改 123456 为强口令,并同步改 MySQL 账号密码) | 站点可正常连接数据库 |
| 5.2 | 更换 MAIL_PASS_KEY 随机密钥(≥32 字符),并重新配置 SMTP 授权码 | 后台发测试邮件成功 |
| 5.3 | (可选)将敏感配置抽到环境变量/外部文件,避免入库 | 部署验证 |
四、风险与注意事项
- 删除前备份:所有删除操作前先
git add -A && git commit(或复制到 protected/backups/),保证可回滚。 - blog.css 删除:虽然零引用,但删除后再全库 grep 一次
css/blog.css 与 blog- 相关类,避免漏网的内联引用。 - rebuild_runtime.php:文件注释声称被 SettingsController 调用,但实际无引用 —— 若曾用旧版本上线,需查 git 历史确认;确认无依赖再删。
- **CSS 收敛期间禁止改
--mn-* 变量**:主题体系依赖该变量名,只收敛类选择器。 - 零调用方法删除:插件可动态加载(plugins/ 目录),删除前必须把 plugins/ 也纳入 grep 范围(本次已含,但动手时再跑一遍最新状态)。
.stat-card 是本轮唯一"后台未作用域化"的冲突点,优先处理(3.2),改动仅 1 处选择器。- 分页类名:前台视图实际用的是哪一套需在 3.3 时逐个视图确认(
.pagination vs .forum-pagination vs .pagination-custom vs .mn-pagination),避免误删在用类。
五、工作量估算(粗)
| 阶段 | 预估 | 说明 |
|---|
| 阶段 1 悬空引用 | 0.5 天 | 新建 404 视图 + 兜底 |
| 阶段 2 孤儿清理 | 0.5 天 | 删 6 个文件 + 回归 |
| 阶段 3 CSS 收敛 | 3–5 天 | 拆 4–5 次迭代,每次独立提交回归 |
| 阶段 4 优化 | 2–3 天 | 内联样式 + 组件抽取 + 零调用清理 |
| 阶段 5 部署卫生 | 0.5 天 | 换口令/密钥 |
本计划基于 2026-08-07 只读复核生成,未修改任何代码。执行时按阶段推进、逐阶段回归、逐阶段提交。