Files
workspace/code/fms/.codebuddy/plans/module-management-full-implementation_a1d841b2(未完成).md
T
2026-07-23 17:33:18 +08:00

16 KiB
Raw Blame History

name, overview, todos
name overview todos
module-management-full-implementation 基于新数据库结构.md和开发规范.md完整实现模块管理页面。左侧模块树+右侧7个子Tab(基本信息、字段定义、列表配置、编辑配置、查询配置、权限配置、多语言),子Tab操作按钮靠左。
id content status
create-service 创建 src/services/moduleManagement.js 服务层,封装 loadModuleTree、loadModuleConfig、saveModuleConfig、syncFields、typeFromSqlType 等方法 pending
id content status dependencies
create-main-page 重写 src/views/module-management/index.vue 主页面,实现左侧 FmsTree 模块树 + 右侧 a-tabs 动态Tab布局,集成数据加载与保存流程 pending
create-service
id content status dependencies
create-basic-panel 使用 [skill:antdv-next] 创建 ModuleBasicPanel.vue 基本信息面板,表单编辑 b_module 字段,根据模块类型控制字段可见性 pending
create-main-page
id content status dependencies
create-fields-panel 创建 ModuleFieldsPanel.vue 字段定义面板,FmsTable 展示字段列表,实现「同步字段」功能(调用 describeApi 合并视图列) pending
create-main-page
id content status dependencies
create-list-edit-query-panels 创建 ModuleListConfigPanel.vue、ModuleEditConfigPanel.vue、ModuleQueryConfigPanel.vue 三个配置面板,FmsTable 展示各自数据,操作按钮靠左 pending
create-main-page
id content status dependencies
create-group-manager 创建 FieldGroupManager.vue 共用分组管理组件,弹窗内管理 b_module_field_group 树形分组增删改 pending
create-list-edit-query-panels
id content status dependencies
create-powers-i18n-panels 创建 ModulePowersPanel.vue 权限配置面板和 ModuleI18nPanel.vue 多语言面板,FmsTable 管理 b_module_power 和 b_i18n 数据 pending
create-main-page

用户需求

根据新数据库结构.md和开发规范.md,完整实现模块管理页面。当前模块管理页面只有一个空占位(<el-button>),需要构建完整的左侧模块树+右侧子Tab布局。

核心功能

主页面布局

  • 左侧模块树:以树形结构展示所有模块(directory/page/data),支持选中节点后在右侧加载详情
  • 右侧详情区:使用 a-tabs 展示子Tab,根据选中模块的 b_module_type 动态显示对应Tab

模块类型与Tab对应关系

模块类型 可用Tab
directory 基本信息、权限配置、多语言
page 基本信息、权限配置、多语言
data 基本信息、字段定义、列表配置、编辑配置、查询配置、权限配置、多语言

各子Tab功能

  1. 基本信息:编辑 b_module 的核心字段(b_code、b_name、b_module_type、b_route、b_viewtable、b_savetable、b_keyfield、b_orderfield、b_parent_id、b_canmenu、b_canuse、b_xh),表单保存
  2. 字段定义:展示 b_module_field 列表,不可手工增删。提供「同步字段」按钮,调用 describeApi 获取 b_viewtable 的列结构,与已有字段合并(保留已有配置、追加新列、标记已删列为不可用)。支持编辑 b_name、b_type、b_default_value、b_options、b_canuse
  3. 列表配置:管理 b_module_field_list(字段列配置)和 b_module_field_group(多级表头分组)。表格展示列表配置行,支持新增/删除。分组管理弹窗支持树形分组增删改
  4. 编辑配置:管理 b_module_field_edit(编辑属性)和 b_module_field_group(编辑分组)。表格展示编辑配置行,支持新增/删除。共享分组管理组件
  5. 查询配置:管理 b_module_field_query,表格展示查询条件配置,支持新增/删除
  6. 权限配置:管理 b_module_power,表格展示操作权限(b_code、b_name),支持新增/删除
  7. 多语言:管理 b_i18n,表格展示翻译条目(b_key、b_locale、b_value),支持新增/删除

操作按钮排列

所有子Tab面板内,新增、删除、保存等操作按钮栏靠左对齐显示。

数据保存策略

  • 主表 b_module:选中模块后直接编辑表单并保存,新增模块先调用 nextIdApi 获取雪花ID
  • 子表(b_module_field/b_module_field_list等):新增行使用 createTempId() 生成临时负数ID,调用 saveObjectApi 统一保存变更
  • 保存时:使用 diffRows() 对比草稿与原始数据,通过 tableChange() 构建变更请求,多表变更一次提交到 saveObjectApi

Tech Stack

  • 前端框架:Vue 3(<script setup> SFCs)
  • 状态管理:组件内部 ref/reactive(不引入额外 Pinia store)
  • UI 组件库:antdv-next(自动导入)+ 项目封装组件(FmsTable、FmsTree、FmsSelect)
  • 样式:SCSS scoped + CSS 变量主题(--fms-*)
  • 数据获取:复用现有通用接口 loadDataApi、saveObjectApi、nextIdApi、describeApi
  • 工具函数:createTempId(临时ID)、diffRows/allocateTemporaryIds/remapForeignKeys/tableChange/hasChanges(变更追踪)

Implementation Approach

整体策略

采用声明式数据驱动模式:每个子Tab面板作为独立组件接收模块ID和完整配置数据,内部维护编辑态草稿(cloneData深拷贝),通过 diffRows 计算变更后交给父组件统一保存。

关键设计决策

  1. 数据加载集中在 Service 层:moduleManagement.js 封装 loadModuleTree()(加载树)、loadModuleConfig(moduleId)(加载单个模块的完整配置)、saveModuleConfig(moduleId, changes)(保存变更),各面板组件调用 Sem 方法获取和回存数据。

  2. 字段同步采用合并策略(与记忆 ID: 93228844 一致):调用 describeApi(b_viewtable) 获取视图列 → 按列名匹配已有 b_module_field → 视图中已存在的保留原配置不覆盖、新增列追加默认行、视图中不存在的已有字段标记 b_canuse=0。

  3. 子Tab操作按钮左对齐:每个面板组件内部在表格上方设置工具栏,使用 justify-content: flex-start 确保按钮靠左排列。

  4. 分组管理复用:列表配置和编辑配置共享 b_module_field_group,通过 FieldGroupManager.vue 组件统一管理分组树增删改。

  5. 保存事务性:所有变更通过 saveObjectApi 一次提交多表变更数组,后端在同一事务内执行,任何表失败整体回滚。

Implementation Notes

  • b_id 全部字符串化:后端返回的 bigint 在 http.js 拦截器中统一转为字符串,前端所有ID比较使用 String() 包裹
  • 布尔字段为 int 0/1:b_canuse、b_visible、b_sortable、b_required、b_readonly、b_disabled、b_canmenu 均使用 0/1
  • b_module_field 同步后不覆盖已有配置:b_name、b_type、b_options 等由管理员手动维护的值在同步时保留
  • 临时ID流转:新增子表行 → createTempId() → 保存时 allocateTemporaryIds() 请求后端真实ID → 保存完成后 loadAll 重建草稿

Architecture Design

flowchart TB
    subgraph 主页面
        A[index.vue<br/>左侧树 + 右侧Tab]
    end

    subgraph Service
        S[moduleManagement.js<br/>loadModuleTree<br/>loadModuleConfig<br/>saveModuleConfig]
    end

    subgraph 组件
        B1[ModuleBasicPanel<br/>基本信息表单]
        B2[ModuleFieldsPanel<br/>字段定义表格+同步]
        B3[ModuleListConfigPanel<br/>列表配置表格]
        B4[ModuleEditConfigPanel<br/>编辑配置表格]
        B5[ModuleQueryConfigPanel<br/>查询配置表格]
        B6[ModulePowersPanel<br/>权限表格]
        B7[ModuleI18nPanel<br/>多语言表格]
        G[FieldGroupManager<br/>共用分组管理]
    end

    subgraph API
        API1[loadDataApi]
        API2[saveObjectApi]
        API3[nextIdApi]
        API4[describeApi]
    end

    A --> S
    S --> API1
    S --> API2
    S --> API3
    S --> API4
    A --> B1
    A --> B2
    A --> B3
    A --> B4
    A --> B5
    A --> B6
    A --> B7
    B3 --> G
    B4 --> G

Directory Structure

fms-vue/src/
├── services/
│   └── moduleManagement.js          # [NEW] 模块管理服务层
│                                     # - loadModuleTree(): 加载所有模块并构建树形数据
│                                     # - loadModuleConfig(moduleId): 加载单个模块的完整配置
│                                     #       (b_module + b_module_field + b_module_field_list
│                                     #        + b_module_field_edit + b_module_field_query
│                                     #        + b_module_field_group + b_module_power + b_i18n)
│                                     # - saveModuleConfig(moduleId, changes, oldData): 保存模块配置
│                                     #       对比草稿和原始数据,构建多表变更请求
│                                     # - syncFields(moduleId, viewTable): 同步字段
│                                     #       调用describeApi获取列结构并合并
│                                     # - typeFromSqlType(sqlType): SQL类型到b_type映射
├── views/
│   └── module-management/
│       ├── index.vue                 # [MODIFY] 主页面容器
│       │                             # - 左侧 FmsTree 展示模块树(directory/page/data)
│       │                             # - 右侧 a-tabs 根据 b_module_type 动态显示子Tab
│       │                             # - 选中节点加载完整配置,传递给各子面板
│       │                             # - 统一收集各面板变更并调用保存
│       └── components/
│           ├── ModuleBasicPanel.vue  # [NEW] 基本信息面板
│           │                         # - 表单编辑 b_module 核心字段
│           │                         # - b_code/b_name/b_module_type/b_parent_id 必填
│           │                         # - directory类型隐藏 route/viewtable/savetable
│           │                         # - page类型必须填写 route,data类型必须填写 viewtable
│           │                         # - 新增模块先调用 nextIdApi 获取ID
│           ├── ModuleFieldsPanel.vue # [NEW] 字段定义面板
│           │                         # - FmsTable 展示 b_module_field 列表
│           │                         # - 工具栏「同步字段」按钮 + 保存按钮(靠左)
│           │                         # - 同步逻辑:describeApi获取列 → 合并已有字段
│           │                         # - 不可手工新增/删除行,仅可编辑属性
│           ├── ModuleListConfigPanel.vue # [NEW] 列表配置面板
│           │                         # - FmsTable 展示 b_module_field_list
│           │                         # - 工具栏新增/删除/保存按钮(靠左)
│           │                         # - 可选字段来自 b_module_field(b_canuse=1)
│           │                         # - 分组列可打开 FieldGroupManager 弹窗
│           ├── ModuleEditConfigPanel.vue # [NEW] 编辑配置面板
│           │                         # - FmsTable 展示 b_module_field_edit
│           │                         # - 工具栏新增/删除/保存按钮(靠左)
│           │                         # - 可选字段来自 b_module_field(b_canuse=1)
│           │                         # - 分组列可打开 FieldGroupManager 弹窗
│           ├── ModuleQueryConfigPanel.vue # [NEW] 查询配置面板
│           │                         # - FmsTable 展示 b_module_field_query
│           │                         # - 工具栏新增/删除/保存按钮(靠左)
│           │                         # - b_component和b_operator使用下拉选择
│           ├── ModulePowersPanel.vue # [NEW] 权限配置面板
│           │                         # - FmsTable 展示 b_module_power
│           │                         # - 工具栏新增/删除/保存按钮(靠左)
│           │                         # - b_code 唯一校验
│           ├── ModuleI18nPanel.vue   # [NEW] 多语言面板
│           │                         # - FmsTable 展示 b_i18n
│           │                         # - 工具栏新增/删除/保存按钮(靠左)
│           │                         # - 支持 zh-CN/en-US 等语言切换筛选
│           └── FieldGroupManager.vue # [NEW] 共用分组管理组件
│                                     # - 弹窗内展示分组树(b_module_field_group)
│                                     # - 支持新增/编辑/删除分组节点
│                                     # - 被 ModuleListConfigPanel 和 ModuleEditConfigPanel 引用

Key Code Structures

moduleManagement.js 核心接口

// 加载模块树(用于左侧树展示)
export async function loadModuleTree()

// 加载单个模块的完整配置(所有关联表数据)
export async function loadModuleConfig(moduleId)
// 返回: { module, fields, fieldList, fieldEdit, fieldQuery, groups, powers, i18n }

// 保存模块配置变更
export async function saveModuleConfig(moduleId, draftData, originalData)
// draftData 和 originalData 结构同 loadModuleConfig 返回值
// 内部使用 diffRows 对比各子表,构建 saveObjectApi 请求

// 同步字段:从 b_viewtable 拉取列结构,与已有字段合并
export async function syncFields(moduleId, viewTable, existingFields)

// SQL类型到 b_type 的映射
export function typeFromSqlType(sqlType)
// varchar/char/nvarchar → input, text/ntext → textarea
// int/bigint/decimal/numeric/float → number, money/smallmoney → money
// date → date, datetime/datetime2 → datetime, bit → switch

各面板组件统一 Props/Emits 模式

// 所有面板组件遵循相同的接口约定
defineProps({
  moduleId: { type: String, required: true },       // 当前模块ID
  data: { type: Array, required: true },             // 面板对应的数据行数组
  loading: { type: Boolean, default: false },        // 加载状态
})

const emit = defineEmits(['update'])                 // 数据变更时触发,传递新的行数组

数据流

index.vue 选中模块
  → loadModuleConfig(moduleId) 获取原始数据
  → cloneData 生成 draftData(编辑态草稿)
  → 各面板接收 draftData 对应部分,用户编辑后 emit('update', newRows)
  → index.vue 更新 draftData
  → 用户点击「保存全部」
  → saveModuleConfig(moduleId, draftData, originalData)
    → diffRows 对比各子表变更
    → allocateTemporaryIds 分配临时ID为真实ID
    → 构建 saveObjectApi 请求数组
    → 提交保存
    → 重新 loadModuleConfig 刷新原始数据

Agent Extensions

Skill

  • antdv-next
  • Purpose: 查询 antdv-next 组件库的 API 文档,确认 a-tree、a-tabs、a-form、a-modal、a-select、a-button、a-space 等组件的 props/events/slots 用法
  • Expected outcome: 获取准确的组件属性定义和事件签名,确保模板中使用正确的 API

SubAgent

  • code-explorer
  • Purpose: 在实现过程中需要快速搜索项目中的代码模式(如 FmsTable 使用方式、dataChanges.js 调用示例、现有表单校验模式等)时使用
  • Expected outcome: 获得准确的现有代码引用,确保新代码风格一致