项目:html5-examples | 版本:v1.1 | 生成日期:2026-10-06 | 依据:源码分析
技术债务在本项目里有两个来源:一是拆分战略的伴生品——2026 年三次板块拆分(html5-dataviz/html5-games/devtools)遵循"前端先行、后端滞后清理"的节奏,留下了成体系的冻结资产;二是文档与实现的时间差——README/AGENTS.md 成文于"数据在 PostgreSQL"的第二阶段,第三阶段(本地 JSON)迁移后未回写。本篇把实地核实过的债务逐条登记为"位置/证据/影响/建议"四要素格式,条目按风险与清理收益排序;每条都给出可执行的处置,但不建议"顺手清理"——第 10 节的路线图把债务处置编排为三次专项任务,理由在各条目内阐述(核心顾虑:/admin 后台的隐藏消费方无法静态排除,清理必须带运行时验证)。
README.md 第 107 行("数据通过 src/api/* 从 NestJS 后端 /api/* 接口获取,持久化在 PostgreSQL")与第 196 行("核心数据不再使用静态 JSON,而是通过 src/api/* …持久化在 PostgreSQL 数据库中");AGENTS.md 第 196 行同文,另有第 968 行("示例数据存储在 PostgreSQL 数据库中,通过 /api/examples 接口提供")、第 990 行("在 PostgreSQL 数据库的 topics 表中添加主题记录")、第 1024-1035 行(导入示例到数据库的 SOP)。src/api/examples.ts 文件头注释明确"示例内容自 2026-10-05 起从 PostgreSQL 迁移至 src/content/examples/*.json(8 个分组文件,按需懒加载并模块级缓存)";前端 11 个消费方零改动;本套文档 00/04 篇已还原三阶段迁移史。/admin 静态页产物):
server/src/modules/examples/:前端 src/api/examples.ts 已切本地 JSON,SPA 前端零调用;但 /admin 后台静态页是现存消费方——server/admin/js/examples.js 以 ${API_BASE}/examples 做列表/CRUD(2026-10-06 静态 grep 核实),删除决策前必须先迁移或废弃该管理页;server/src/modules/chart-examples/:前端无 api 文件,仅存测试目录残留 src/components/chart-examples/__tests__/;server/src/modules/visual-demos/:前端仅保留单函数 getVisualDemoById(src/api/visual-demos.ts 头注释:"历史深链专用 /visual-demo/:id 详情仍走后端")——注意该模块不是完全冻结,列表类端点冻结、单条详情端点仍被 SVG 课程深链消费;server/src/modules/knowledge/(7 子模块、15+2 实体、约 70 端点,2026-10-06 复核一致):html5-examples 前端、devtools/html5-dataviz/html5-games 三姊妹项目与 /admin 静态页均无引用(grep 核实);server/src/modules/oss/:路径挂 /api/knowledge/oss,是 knowledge 域配套设施,同样无任何前端与 /admin 引用;server/src/modules/run/:admin-token.guard.ts 注释称消费方是"前端(devtools)…见 getRunAdminToken",但 devtools 现源码中不存在 getRunAdminToken,也无 api/run 引用——注释描述的调用方在当前源码中找不到(2026-10-06 已复核 devtools/dataviz/games 三项目与 /admin 均无 /api/run 调用,⚠️ 待确认 仅剩"是否存在于未开源分支")。/admin 隐藏消费方——已完成静态 grep(2026-10-06):server/admin/js/ 五个脚本仅调 /api/topics、/api/categories、/api/examples 三者,knowledge/oss/run 连 /admin 消费也可排除;但注意 examples 模块因此有 /admin 这一存量消费方(见上),瘦身时须同步处置该管理页;第二步按"确认零消费 → 删模块目录 → 移除 app.module 登记 → 生成 DROP 迁移"四步一次完成;第三步 DB_SYNC=false 下跑迁移并验证 /admin 与 /visual-demo/:id 深链。run 模块在确认消费方死亡前不要删(它带 fail-closed 守卫,留着无害),但应在部署清单标注"必配 RUN_ADMIN_TOKEN 或明确弃用"。| 口径出处 | 数值 | 统计对象 |
|---|---|---|
src/router/routes/css-lab.ts 65 行注释 | 61 | "61 项子生成器共用一个动态路由" |
src/config/css-lab/catalog.ts 内注释 | 64 | "64 项子生成器(拆分自原 /tools/generate/css 单页)" |
generators/BaseGenerator.vue 头注释 | 61 | "61 个生成器通过 props/sections/presets 接入" |
generators/ 目录实况 | 63 | 64 个 *Generator.vue 含 BaseGenerator 基类,具体生成器 63 个 |
generators/routes.ts generatorComponents | 64 个 kind | 63 组件 + card→slanted-card 别名 |
generators/index.ts | 61 个导出(60 具体组件)+ generatorList 60 条 | "自动生成,请勿手动编辑"已滞后 |
catalog.ts cssTools 实况 | 52 条(51 个 css-gen-*) | 目录清单比组件映射少 12+ 条 |
routes.ts TOOL_ROUTE_PATHS | 66 键(65 个 gen-*) | 路由常量比目录清单多 14 条 |
generatorComponents(路由可达性)为准清单,回填 catalog 缺失条目、重生成 index.ts,然后把三处注释统一改为引用"计数以 generatorComponents 键数为准";更长期的做法是写一个 20 行的校验脚本(比对四个注册表键集)挂进 extract 或 CI,把口径漂移变成红灯。src/components/examples/ExampleCodeSnapshot.vue 渲染示例源码前 12 行(previewCode computed 截断 + CodeBlock/Shiki + 底部渐隐 mask),被 ExampleCard.vue 与 ExampleListItem.vue 引用。server/data-source.ts entities 数组(26 项)缺少 CanvasExample 与 SnippetVersion(app.module.ts 为 28 项)。data-source.ts 是 migration:generate/run/revert 的连接配置——实体登记不全时,generate 基于的元数据不完整,可能生成错误或遗漏的迁移;这是"平时无感、生成迁移时踩坑"型债务。RefreshToken、CaptchaChallenge 两实体定义在 modules/knowledge/entities/(auth.service.ts 与 app.module.ts 均从 knowledge 路径导入)——知识库全家桶迁移时把认证实体一并带了过去。POST /api/auth/me 标注 @Public() 导致 checkMe() 恒得 { user: null }(证据链见《08-安全与权限设计》§7 第 1 条,⚠️ 待确认 是否存在依赖 cookie 通道的存量用户)。modules/auth/entities/(import 路径三处同步改,无行为变更);POST /auth/me 的处置需要先决策语义——若 cookie 通道要保留,去掉 @Public 并利用宽容模式守卫(无凭证时 req.user 为 undefined,端点已兼容);若决定放弃 cookie 通道,删端点并同步删 checkMe()。决策依据是线上是否还有仅 cookie 的会话,无法静态判断,⚠️ 待确认。guards/rate-limit.guard.ts 进程内 Map 按 IP 计数,仅挂在 auth 三端点。eslint.config.js ignores 含 src/chart-examples/**、src/views/data-visualization/bigscreen/**、src/transform/**、scripts/.chart-src/** 等——均为已拆分板块或生成物的目录引用;src/components/chart-examples/__tests__/VueSfcRenderer.test.ts 仍被执行(匹配 vitest include);env.d.ts 里 vue-virtual-scroller、keli-heatmap.js、aplayer 等模块声明经全 src grep 核实(2026-10-06)零使用,属已卸载依赖的声明残留,可安全删除;package.json 同时依赖 playwright 与 puppeteer 两套浏览器自动化。src/api/index.ts 桶导出缺 canvas-examples/ui-elements/visual-demos 三模块(《11-扩展开发指南》场景五易错点已提示新模块回归桶导出)——纯一致性债,五分钟修复。localStorage 覆盖层无容量管理:examples-overrides-v1 随用户编辑无限增长(单键上限 5MB 量级),溢出时 persistOverrides 静默失败——可在覆盖数超阈值时提示清理,优先级低。server/package.json 的 lint script 是 --fix 形态(无纯 check),CI 即使接入也会"静默改文件"而非报错——第 10 节后端 CI 化时一并改。docs/ 知识库中《数据可视化能力增强方案》等篇目已被拆分事实推翻——需要一轮"文档考古归档"(标注失效篇目),与第 1 条文档漂移同批处理。专项一:文档与配置对齐(0.5-1 天,零风险)。README/AGENTS.md 数据来源段落改写(第 1 条);data-source.ts 实体补齐(第 5 条);api 桶导出补齐(第 9 条);lint ignores 与残留测试清理(第 8 条);生成器口径对齐 + 校验脚本(第 3 条)。这批改动全部可静态验证,做完后文档集与源码进入互信状态。
专项二:后端瘦身与 CI 化(2-3 天,需运行时验证)。消费方审计(含 /admin 产物 grep)→ 冻结模块删除 + DROP 迁移(第 2 条)→ 认证实体归位(第 6 条前半)→ server 接入 vitest + CI 第四步(呼应《09-测试与质量保障》§4 第一优先)→ auth.service 补测。验证锚点:迁移 up/down 幂等、/visual-demo/:id 深链、/admin 关键操作、登录收藏全链路。
专项三:通道决策与加固(1 天决策 + 按需实施)。cookie 回退通道去留决策(第 6 条后半,依赖线上数据确认);限流升级评估(第 7 条);为"未来开放用户提交"预置的三项前置条件(CSP、独立子域、入库校验器)立项评审(《08-安全与权限设计》§6)——这三项平时不阻塞任何需求,但应作为架构决策记录(ADR)先写下来,避免届时在压力下临时拍板。
路线图之外,给出两条不设期限的演进原则作为收尾:其一,凡"拆分/迁移"类变更,回写文档与清理冻结物应作为验收标准的一部分(本次三处漂移的根因都是验收缺了这一环);其二,凡"两处以上手工同步的清单"(实体数组、generator 注册表、文档计数)都值得一个校验脚本——本项目已经用 TOOL_ROUTE_PATHS + toolPath 证明了"单一事实源 + 类型派生"的价值,把这个模式推广到其余注册表,就是最便宜的架构投资。
本篇完。下一篇:14-配置与环境详解.md