技能|业务模块闭环构建SOP
适用场景
数据层已落地、要为一个业务模块跑通业务闭环时触发。本项目已落地七模块(M1~M7 全闭环),四层结构一致、可直接克隆:
- M5 安防/安全查验/门禁台账(scripts/m5_ledger/):asset + ledger 两表 CRUD + 枚举守护(cat∈监控/安全查验/门禁/UPS,status∈在用/停用/待修),覆盖资产与巡检/盲区/UPS更新/门禁权限台账。
- M7 隐患治理闭环台账(scripts/m7_hazard/):hazard 表 + 状态机正向推进(登记→整改中→已闭环),advanceState 仅允许正向、逆向直接 throw。
- M4 统计分析报告(scripts/m4_report/):只读跨表聚合 asset/ledger/hazard/schedule,产出周简报 + 综合统计报告;空表返回空数组与 total=0、渲染"暂无数据"而非报错,绝不写库。
- M1 活动安防方案与报批(scripts/m1_plan/):D1 按需生成不落库——调 docx-helper 出活动安防方案/应急预案/报批包三种 docx;报批包"预算测算""合规审查"占位章节由 M2/M3 接入后顶替,活动安防方案"岗位配置"章节由 M6 接入后顶替(见下);仅以只读方式取 asset 概览/预算/合规/岗位作背景、不写任何表、不触发设计升版。
- M2 费用预算核算(scripts/m2_budget/):基于 budget_subject 科目表做科目×数量×单价测算,产出预算测算表,回填 M1 报批包预算章节。
- M3 智能合规审查(scripts/m3_compliance/):报批材料齐备性核查(安全许可/交通管制备案/消防预案报备三类),产出审查意见,回填 M1 报批包合规章节。
- M6 岗位与人员管理(scripts/m6_post/):混合模块——岗位侧(post 表)为生成型(genPostConfig/genPostDesc 出配置清单/说明书 docx,错误码 E1601 岗位数为零/E1602 职责空);人员侧(personnel/schedule_record/training_record/assessment_record)为写入型,排班/培训/考核引用 personnel 并守护 E1603 人员不存在,产出人员台账 docx。
一次只做一个模块,跑通再复制模式到其余模块。M5→M7 验证"台账闭环可复制",M7→M4/M1 验证"读聚合"与"纯生成不落库"两种变体,M2/M3/M6 验证"写入模块回填 M1 报批包"的联动也已跑通。
操作步骤
- 确认依赖现状:优先用运行时内置能力——Node 22 内置
node:sqlite(require('node:sqlite'),实验特性会打 warning,功能正常),不必装 better-sqlite3(需本地编译);文档导出复用既有docx-helper,不重复造轮子。 - 设运行环境:
SKILL_PATH指向含docx/scripts/docx-helper的目录(本项目程序源代码\runtime);把路径写进set_env.bat一键生效,并写进相关技能说明。 - 分四层写(本项目落
程序源代码\scripts\<模块>\):
-db.js连接层(库缺失时给出「先跑 init_db.py」的明确提示,支持环境变量覆盖路径)
-<模块>.js数据访问层:CRUD + 枚举守护(契约枚举外的值直接 throw)
-export_docx.js导出层:调 docx-helper 组表 → 输出
-cli.js命令行入口:list / add / stats / export - 导出注意:
docx-helper.build()固定写到process.argv[1]同名 docx(调用脚本同目录),拿不到自定义路径 → 要么 build 返回后copyFileSync到目标再unlinkSync中间文件(v1.1 前唯一办法),要么用 v1.2 的h.buildTo(doc, 绝对路径)直接输出到目标(异步、返回 Promise,须 await)。导出后确认调用目录无 docx 残留。 - 版式出口二选一:交付物是内部技术材料(说明书/台账/统计)→ 图文版(
h.cover()+h.toc()+h.image()+h.caption(),封面+目录+页码,首页不显示页码);交付物是给上级/主办的正式文件(报告/请示)→ 公文版h.gw()(GB/T 9704,无封面目录、页码「— X —」、落款+成文日期+附件另面,文种不得混用)。细则见《程序文档图文排版标准SOP》。 - 冒烟自测
selftest.js:复制库到临时副本再跑完整闭环(写→读→join→导出→断言),测完删除——真实库零污染。断言项:基线可读、过滤正确、写入回读一致、非法枚举被拒、导出文件存在且 >3KB、统计接口可用。 - 第二轮回读校验:导出产物用 python-docx 打开,确认标题、表头、行数与库内一致(M5 资产 101 行、M7 隐患表为闭环台账)。
- 移交说明:把命令清单(set_env → node cli.js …)写进技能与项目日志。
注意边界
- TypeScript 不是必选项:技术路线写 TS 但本机未装 tsc、装它需联网。可先用 CommonJS + JSDoc 跑通,TS 迁移需用户明确同意再装包。
- 枚举写在代码里并与设计说明书同步:设计升版后必须同步代码枚举,否则守护的是过期契约。
- 中间产物:注意 docx-helper 会在调用脚本目录留同名 docx,自测后确认无残留。
- 落点:模块代码放
程序源代码\scripts\<模块>\(不新造一级目录,遵循 V1.5 存储规则——scripts 三层:db 数据层 / <模块> 业务闭环 / 根 06 生成器)。 - 闭环状态机:对带生命周期的台账(如 M7 隐患),在数据访问层加
advanceState仅允许正向推进(登记→整改中→已闭环),逆向直接 throw,避免状态回退破坏闭环语义。 - 空表健壮性:统计/聚合类模块(如 M4)面对尚未补录的空表,必须返回空数组与 total=0 并渲染"暂无数据",绝不因 COUNT=0 抛错或除零;占比计算前先判分母。
- D1 不落库模式:纯文档生成模块(如 M1)只调 docx-helper 产出 docx,不 INSERT/UPDATE 任何业务表;如需背景数据,仅以只读方式取 asset 概览等,真实库零污染、不触发设计升版。
反例避雷
- ❌ 一上来就装 better-sqlite3/express 全家桶:本机能用内置
node:sqlite,装包既联网又要编译。 - ❌ 自测直接跑真实库:会把测试数据写进业务库,101 条资产变 102 条。
- ❌ 直接 require 相对路径找 docx-helper:
SKILL_PATH未设时报「找不到模块」,应先跑 set_env。 - ❌ 一次做多个模块:接口风格没稳定就复制,返工成本高。
- ❌ 导出后不回读校验:docx 能生成不代表表格行数正确。