16 KiB
16 KiB
name, overview, todos
| name | overview | todos | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| module-management-v2-refactor | 将 fms-vue 的 module-management 从旧表结构(category/data/query、s_field_group/s_field_view/s_field_edit/s_field_query 行模型、s_i18n 带 b_id/b_module_id)重构为《FMS新系统核心表结构设计》V2:模块类型 module/data/virtual + 模块树 b_depth/b_path,布局统一存 s_module_schema(view/edit/query) 的 b_schema_json JSON 节点,s_field 精简为 b_source_field/b_type,i18n 主键改 (b_key,b_locale),并同步更新 menu-management 的模块类型过滤。 |
|
产品概述
模块管理页(左树右面板)与 V2 表结构(FMS新系统核心表结构设计.md + sql/fms_core.sql)对齐,并把 开发规范.md 的面板式配置页约定落实到编排层与各面板。界面外观与既有交互(树搜索/右键/拖拽、分节 Tab、字段表格、列表/表单设计器的拖拽与预览、查询条件表、自动编码预览、多语言透视表)保持不变,仅调整底层数据模型、加载与保存逻辑。
用户需求
- 按 V2 重构
fms-vue/src/views/module/module-management/全部代码。 - 布局配置完整迁移为 JSON:列表/表单/查询分别存
s_module_schema的view/edit/query三行b_schema_json,字段分组由独立表变为 JSON 节点。 - 模块类型改为
module / data / virtual(category→module、query→virtual、data 不变),新增/移动节点时维护模块树b_depth / b_path。 - 同步更新
menu-management中对模块类型的过滤条件。 - 不新增
s_relation面板。
核心功能
- 模块树:加载/搜索/展开/右键新增/删除/拖拽排序;节点承载 b_depth、b_path,并随新增与移动同步维护。
- 基础信息:维护新
s_module列(b_view_table/b_save_table/b_key_field/b_order_sql/b_query_sql/b_config_json 等)与类型联动校验。 - 字段定义:维护新
s_field(b_source_field/b_name/b_i18n/b_type/b_canuse/b_xh);按查询表/视图同步字段;表单/列表/查询“参与”勾选改为在对应 JSON 中增删字段节点。 - 界面配置:列表(view JSON,支持分组列/多级表头)、表单(edit JSON,分组+行+字段、栅格/只读/必填)、查询(query JSON,quick + 条件组)。
- 自动编码:单条
s_autocode规则与实时预览(列名已与 V2 一致)。 - 多语言:基于
s_i18n的(b_key, b_locale)复合键维护受管资源键与翻译。 - 保存:
handleSave → beforeSave → buildSaveData → 通用保存接口 → afterSave,按_org基线 diff,无变化不提交;切换模块保留未保存确认。
技术栈
- 前端:Vue 3(Composition API +
<script setup>+defineModel),JavaScript(沿用项目现有.vue/.js,不引入 TS)。 - UI:项目内
@/components/ui(Tabs/Splitter/Modal/Form/FmsTable 等)与@/components/fms-table/FmsTable.vue。 - 数据访问:
@/services/api(loadDataApi/saveObjectApi/describeApi)——写库走{table, key_field|keyFields, inserts, updates, deletes}。 - 变更工具:
@/utils/dataChanges(diffRows/diffRow/tableChange/hasChanges/sanitizeSaveReqs/stripInternalKeys)与@/utils/tree(buildTree/sortTree/findTreeNode/insertTreeNode/removeTreeNode)。 - 依赖:多语言语言清单来自
@/stores/i18n(s_i18n_type)。
实现方案
核心决策
- JSON 节点模型 + 保留未知属性:
view/edit/query以对象形式在编排层持有;面板原地修改已知节点,序列化时保留其余属性(符合规范 1.8「JSON 可扩展新属性」)。顶层带schemaVersion: 1。 - 稳定序列化 + 基线比对防“打开即脏”:新增
stableStringify(对象键递归排序、数组保序)。加载时把库中字符串与新 schema 的默认结构都规范化为基线字符串;保存时用对象序列化结果与基线字符串比较,一致则不插入默认行。 - 配置表用业务键/联合主键,不用雪花临时 ID:
s_field用(b_module_id,b_field);s_module_schema用(b_module_id,b_schema_type);s_autocode用(b_module_id,b_field);s_i18n用(b_key,b_locale)。diffRows传对应keyFields,deletes 仅带主键列。 - 模块树层级维护:
b_parent_id为权威关系,前端新增/移动时按「父路径 + 节点编码」计算b_path(形如/sea/container/,根为/sea/,b_depth根为 0),并同步更新受影响节点及其后代。 - 多语言按资源键前缀加载/清理:
s_i18n无b_module_id,模块的多语言行按资源键匹配加载(b_key = 'module.{id}'或b_key LIKE 'field.{id}.%',分组键取 JSON 节点中的i18n精确值);删除模块时按这些已知键清理。 - 编辑方式切换的处理:V2 已移除
s_module.b_edit_mode且本次不引入s_relation,故表单设计只面向editJSON(保留画布/分组/预览交互),移除依赖b_edit_mode的“主表表单/子表表格”切换。
数据流
graph LR
API[loadDataApi] --> ORCH[index.vue 编排层]
ORCH -->|v-model| BASIC[ModuleBasicPanel]
ORCH -->|v-model fields| FIELDS[ModuleFieldsPanel]
ORCH -->|v-model view_schema| LIST[ModuleListConfigPanel -> TableDesignEditor]
ORCH -->|v-model edit_schema| EDIT[ModuleEditPanel -> FormDesignEditor]
ORCH -->|v-model query_schema| QUERY[ModuleQueryConfigPanel]
ORCH -->|v-model autocode| AUTO[ModuleAutoCodePanel]
ORCH -->|v-model i18n| I18N[ModuleI18nPanel]
ORCH -->|watch 幂等联动| FIELDS
ORCH -->|diff + saveObjectApi| API
性能与可靠性
- 加载时按模块只解析一次 JSON;保存时
stableStringify为 O(n)(n 为节点/字段数),无深层递归热路径。 - 树
b_depth/b_path重算仅在新增/移动的子树范围进行,避免全树反复遍历。 - 保存失败不改写
_org基线,afterSave成功后重新加载为准。
实施要点
- 数据成对命名:
maindata/maindata_org、fields/fields_org、view_schema/view_schema_org、edit_schema/edit_schema_org、query_schema/query_schema_org、autocode/autocode_org、i18n/i18n_org;禁止drafts/originals聚合对象。 - 就绪判据统一
v-if="maindata";整批清空收敛到clearModuleData()。 - 跨面板副作用由编排层幂等
watch承担(删除分组清理 JSON 中分组引用;自动编码字段在表单 JSON 中置只读)。 - 表格/节点编辑采用“就地 patch + 提交换新引用”触发重渲染。
_/v_前缀内部派生字段不参与 diff,提交前经sanitizeSaveReqs统一剥离。- 多语言不做实时响应:加载后 reconcile 一次、保存前再 reconcile 一次;人工翻译不被覆盖。
- 面板范围:基础信息对所有类型;字段/列表/表单/查询对
data与virtual;自动编码仅data;多语言对所有类型。 - 影响面提示(本次不修改):
components/fms-module-list/FmsModuleListPage.vue、components/fms-module-edit/FmsModuleEditModal.vue仍读取旧列/旧布局表,需另立任务迁移到 V2,避免超范围改动。
关键结构
三份 schema(顶层均含 schemaVersion,通过字段编码引用 s_field,不重复定义数据库类型):
// view
{ "schemaVersion": 1, "columns": [
{ "field": "b_no", "visible": true, "width": 140, "fixed": "left" },
{ "type": "group", "title": "费用信息", "i18n": "group.cw_fee.amount",
"children": [ { "field": "mx_amount", "width": 120, "format": "money" } ] } ] }
// edit
{ "schemaVersion": 1, "children": [
{ "type": "group", "title": "基础信息", "i18n": "group.sea_main.basic", "children": [
{ "type": "row", "children": [
{ "field": "b_no", "span": 12, "readonly": true },
{ "field": "b_name", "span": 12, "required": true } ] } ] } ] }
// query
{ "schemaVersion": 1, "quick": ["b_no", "b_name"], "groups": [
{ "logic": "and", "conditions": [ { "field": "b_status", "operator": "eq" } ] } ] }
s_module_schema 保存契约(按联合主键 diff;无变化不提交;不发送审计列):
// 行身份:b_module_id + b_schema_type(view|edit|query)
// 比较值:b_schema_json = stableStringify(草稿对象),基线为库中原串(或缺省 schema)规范化后的串
{ table: 's_module_schema', key_field: 'b_module_id,b_schema_type',
inserts|updates: [ { b_module_id, b_schema_type, b_schema_json, b_canuse } ] }
目录结构
本次重构涉及 fms-vue/src/views/module/module-management/ 与受影响测试;结构沿用现有目录,不新增无意义层级。
fms-vue/
├── src/
│ ├── views/module/
│ │ ├── module-management/
│ │ │ ├── index.vue # [MODIFY] 编排层:持有 maindata/fields/view_schema/edit_schema/query_schema/autocode/i18n 及各自 _org 基线;load→validate→diff 保存→重载主流程;模块树加载/新增/删除/拖拽与 b_depth/b_path 维护;s_module_schema 三行加载与保存;按新表名与新资源键清理删除;跨面板幂等 watch
│ │ │ ├── utils.js # [MODIFY] 纯函数:模块类型映射与图标/新增项、view/edit/query 默认结构、parseSchema、stableStringify、字段节点增删与查找、受管 i18n 键规则与 reconcile、i18n 变更请求((b_key,b_locale))、树 b_depth/b_path 计算与兄弟重排
│ │ │ ├── ModuleTreePanel.vue # [MODIFY] 消费新类型图标/新增项;保留搜索/展开/右键/拖拽交互;未保存节点禁用作为父级
│ │ │ ├── ModuleBasicPanel.vue # [MODIFY] 新类型 module/data/virtual 与新列(b_view_table/b_save_table/b_key_field/b_order_sql/b_query_sql/b_config_json);类型联动清空与校验
│ │ │ ├── ModuleFieldsPanel.vue # [MODIFY] 新 s_field 列(b_field/b_source_field/b_name/b_type/b_i18n/b_canuse/b_xh);describeApi 同步字段写 b_source_field、列序回写 b_xh、库中已删列标记 b_canuse=0;参与勾选改为在 view/edit/query JSON 增删字段节点
│ │ │ ├── ModuleListConfigPanel.vue # [MODIFY] 壳:接收 view_schema 对象,接线 TableDesignEditor(mode=list)
│ │ │ ├── ModuleEditPanel.vue # [MODIFY] 壳:接收 edit_schema 对象,接线 FormDesignEditor(移除 b_edit_mode 切换)
│ │ │ ├── ModuleQueryConfigPanel.vue # [MODIFY] 左字段库 + 右条件表,读写 query_schema.groups[0].conditions(保留 quick 等其余属性)
│ │ │ ├── ModuleAutoCodePanel.vue # [MODIFY] 列名与 V2 一致,随 b_type 取值调整文本字段判定
│ │ │ ├── ModuleI18nPanel.vue # [MODIFY] 透视行改为 (b_key,b_locale) 复合键,row-key 与增删逻辑相应调整
│ │ │ └── components/
│ │ │ ├── fieldDefaults.js # [REWRITE] 字段→view 列节点 / query 条件节点的默认属性与工厂(JSON)
│ │ │ └── design-editor/
│ │ │ ├── TableDesignEditor.vue # [REWRITE] 列表 view JSON 设计器(分组列/多级表头/预览),替换旧行模型
│ │ │ ├── FormDesignEditor.vue # [REWRITE] 表单 edit JSON 设计器(分组/行/栅格/属性/预览)
│ │ │ ├── common/useStructureEditing.js # [REWRITE] JSON 节点模型内核:分组树、多级表头、节点增删移、选中态、属性剪贴板;改造为对 columns/children 节点树操作
│ │ │ ├── common/FieldLibrary.vue # [MODIFY] 字段库数据契约适配(节点存在性判定)
│ │ │ ├── common/EditDataView.vue # [MODIFY] 数据视图适配新节点属性
│ │ │ ├── table/StructureTree.vue # [REWRITE] 分组节点树展示与拖动
│ │ │ ├── table/StructureTreeNode.vue # [REWRITE] 节点渲染/重命名
│ │ │ ├── table/TableInspector.vue # [MODIFY] 选中列/分组节点的属性编辑
│ │ │ ├── table/TablePreview.vue # [MODIFY] 依据 view JSON 渲染表头/列预览
│ │ │ ├── form/FormInspector.vue # [MODIFY] 选中字段/分组节点属性
│ │ │ ├── form/FormPreview.vue # [MODIFY] 依据 edit JSON 渲染表单预览
│ │ │ └── form/useFormGrid.js # [MODIFY] 栅格计算适配 JSON 行/字段节点
│ │ └── menu-management/index.vue # [MODIFY] 模块类型过滤 IN ('data','query') → IN ('data','virtual')
│ └── ...
└── tests/unit/
├── module-list-config-panel-dnd.spec.js # [MODIFY] 适配 view JSON
├── module-table-edit-panel-dnd.spec.js # [MODIFY] 适配 edit JSON
├── module-fields-panel-participation.spec.js# [MODIFY] 适配 JSON 节点参与
├── module-i18n-reconcile.spec.js # [MODIFY] 适配 (b_key,b_locale) 复合键
├── form-edit-panel-mount.spec.js # [MODIFY] 适配新设计器
└── delete-confirm-regression.spec.js # [MODIFY] 适配删除清理逻辑
Agent Extensions
SubAgent
- code-explorer
- Purpose: 在重写设计器内核前,系统梳理
design-editor/下 FormDesignEditor、TableDesignEditor、StructureTree、TableInspector/FormInspector、TablePreview/FormPreview、useFormGrid 之间的数据依赖与事件契约,明确需保留的交互点。 - Expected outcome: 输出设计器内部组件依赖清单与需替换的数据结构映射,作为 JSON 节点模型重写的依据,避免遗漏交互。
Skill
- lsp-code-analysis
- Purpose: 在重构与收尾阶段做全局引用与影响分析,定位
b_viewtable/b_savetable/b_keyfield/b_orderfield/b_delete_policy/b_edit_mode、s_field_view/s_field_edit/s_field_query/s_field_group、旧 i18n 主键等符号的全部引用点,确认引用清理完整。 - Expected outcome: 产出受改符号的完整引用清单,确保无旧路径/旧字段/旧方法名残留,指导受影响的单测与调用点同步更新。