№ · 工程规范
CH.06.22
代码结构拆分规则 v1
目标:把“静态数据、运行逻辑、UI 渲染、持久化读写”拆成不同责任面,避免把表、规则、界面混进同一个脚本里。
1. 总原则
- 静态数据优先进入
src/data/。 - 业务逻辑优先进入
src/utils/或独立的纯逻辑模块。 - UI 渲染优先进入
src/components/。 src/App.tsx只保留组合、状态连接、页面切换和少量协调逻辑。- 一个文件如果同时承担“数据定义 + 规则判断 + UI 生成”三件事,必须拆。
2. 责任边界
| 责任 | 放置位置 | 典型内容 |
| --- | --- | --- |
| 静态数据 | src/data/ | 事件表、剧情表、角色表、配置表、文案表、预设列表 |
| 纯逻辑 | src/utils/ | 抽样、权重、条件判定、状态机、时间推演、终局推进 |
| UI | src/components/ | 弹窗、面板、列表、表格、卡片、按钮、视图容器 |
| 编排层 | src/App.tsx 或页面壳 | state 挂接、组件组合、数据注入、页面路由 |
| 持久化 | src/endgame/、src/components/endgame/、src/utils/ | 存档、读档、快照、回放、恢复入口 |
3. 具体规则
3.1 静态数据必须独立
- 事件、终局链、简报模板、角色节点、表格索引,优先放
src/data/。 - 不要把大量静态常量塞进
App.tsx。 - 不要在数据文件里直接写 React 组件。
- 不要让数据文件依赖浏览器状态或组件状态。
3.2 逻辑和 UI 必须分离
- 条件判断、权重计算、状态推进、结果结算,不能和 JSX 混在一起。
- UI 文件只负责展示,不负责决定事件是否触发。
- 如果一个组件开始承担状态机判断,就先把判断抽到
utils。
3.3 endgame 必须三层拆分
| 层 | 说明 |
| --- | --- |
| 内容层 | 终局链、阶段、失败种子、文案、预警表,优先放 src/data/ |
| 逻辑层 | 触发、推进、回滚、条件检查、结局判定,放 src/utils/ |
| 表现层 | 复盘页、终局弹窗、恢复面板、历史展示,放 src/components/ |
- 终局内容不要和终局页面渲染写在一个文件。
- 终局逻辑不要和存档 UI 混写。
- 复盘界面只消费结构化数据,不反向承载规则。
3.4 App 只做编排
App.tsx中允许存在:状态初始化、数据聚合、页面切换、事件分发入口。App.tsx中不鼓励存在:大段静态表、长链条件判断、复杂 JSX 弹窗、深层业务状态机。- 当
App.tsx里某一段超过“只看这一段就知道全模块怎么工作”的体量时,说明该段该拆了。
4. 拆分判断标准
满足任意一条,就建议拆文件:
- 文件里既有静态表,又有计算规则。
- 文件里既有逻辑,又有渲染。
- 文件需要同时被“数据维护者”和“UI 维护者”修改。
- 一个文件要让人理解三种事情:它是什么、它怎么跑、它长什么样。
- 以后新增同类功能时,必须先改这个大文件再继续开发。
5. 推荐目录约定
src/data/
eventTables/
endgame/
briefing/
characters/
src/utils/
eventSelection.ts
failureEndgame.ts
gameTime.ts
briefing.ts
src/components/
endgame/
events/
briefing/
6. 落地顺序
- 先拆静态数据到
src/data/。 - 再拆纯逻辑到
src/utils/。 - 最后拆 UI 到
src/components/。 App.tsx只保留编排,不再承载新业务。
7. 结论
以后如果看到“数据、逻辑、UI、存档”都挤在一个脚本里,默认就是要拆,不是继续往里加。