From f019a1c1acf627004652cbd0c2baf7237116ea56 Mon Sep 17 00:00:00 2001 From: oneao Date: Sun, 30 Aug 2026 21:05:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(module-management):=20=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E9=9D=A2=E6=9D=BF=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E8=A1=A8=E5=8D=95/=E5=88=97=E8=A1=A8/=E6=9F=A5=E8=AF=A2=20?= =?UTF-8?q?=E5=8F=82=E4=B8=8E=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 跨 tab 的「字段参与了哪些界面」在字段定义一行内表达并可就地切换, tab 结构不变。「参与是选择不是缺失」——不引入任何完整性提示。 - 语义沿用 fieldAreaDefaults 既有约定:行存在=已配置,行内开关=是否参与 (表单/列表 b_visible、查询 b_canuse);关=置 0 不删行,保留画布布局与既有查询配置 - fieldParticipation.js(纯逻辑):判定与切换;行不存在时按默认工厂生成且强制参与 (显式意愿覆盖大文本默认 参与=0),表单新行 b_colspan=24 追加到末尾序号 - fieldAreaDefaults 增加列表/查询默认行工厂,useModuleConfig.buildMissingDefaultConfigs 改用工厂——「同步字段自动补全」与「手动打开开关」生成的行结构同源 - ParticipationCell(h 渲染 ui Switch)接 FmsTable customCell;表单列仅 data 模块展示 - 新 spec field-participation 9 用例:判定/两路切换/大文本强制参与/不变性 --- .../components/ModuleFieldsPanel.vue | 132 ++++++++++++++---- .../components/ParticipationCell.js | 29 ++++ .../components/participation-cell.scss | 7 + .../composables/useModuleConfig.js | 28 +--- .../module-management/fieldAreaDefaults.js | 50 ++++++- .../module-management/fieldParticipation.js | 80 +++++++++++ .../views/system/module-management/index.vue | 7 + .../tests/unit/field-participation.spec.js | 112 +++++++++++++++ 8 files changed, 391 insertions(+), 54 deletions(-) create mode 100644 code/fms/fms-vue/src/views/system/module-management/components/ParticipationCell.js create mode 100644 code/fms/fms-vue/src/views/system/module-management/components/participation-cell.scss create mode 100644 code/fms/fms-vue/src/views/system/module-management/fieldParticipation.js create mode 100644 code/fms/fms-vue/tests/unit/field-participation.spec.js diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue index 83fbc8e7..4a20366f 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue @@ -2,21 +2,45 @@ /** * 字段定义面板(s_field):可编辑表格维护模块字段。 * i18n 键按 field.{moduleCode}.{fieldName} 自动同步。 + * 表单/列表/查询三列为「参与开关」:在一行内表达该字段参与了哪些界面, + * 开关即改即生效(生成/隐藏默认配置行);布局细节仍在对应设计器调整。 + * 语义见 fieldParticipation.js(沿用 fieldAreaDefaults 的行内开关约定)。 */ import { ref, shallowRef, watch } from 'vue' import FmsTable from '@/components/fms-table/FmsTable.vue' import { buildModuleItemI18nKey, syncModuleItemI18nKeys } from '@/utils/i18n' import I18nQuickSetModal from './I18nQuickSetModal.vue' import { createI18nKeyCell } from './I18nKeyCell' +import { createParticipationCell } from './ParticipationCell' +import { + isFormOn, + isListOn, + isQueryOn, + toggleForm, + toggleList, + toggleQuery, +} from '../fieldParticipation' const props = defineProps({ moduleId: { type: String, required: true }, moduleCode: { type: String, default: '' }, fields: { type: Array, default: () => [] }, + /** 参与开关所需的三个配置草稿(由 index.vue 传入,切换后事件回写) */ + editConfig: { type: Array, default: () => [] }, + listConfig: { type: Array, default: () => [] }, + queryConfig: { type: Array, default: () => [] }, + /** 模块类型:表单参与列仅 data 模块展示(查询模块无表单设计) */ + moduleType: { type: String, default: null }, loading: { type: Boolean, default: false }, }) -const emit = defineEmits(['update', 'i18nSaved']) +const emit = defineEmits([ + 'update', + 'i18nSaved', + 'updateEditConfig', + 'updateListConfig', + 'updateQueryConfig', +]) const FIELD_TYPES = [ { label: '输入框', value: 'input' }, @@ -74,37 +98,83 @@ function openI18n(row) { const I18nKeyCell = createI18nKeyCell({ onOpen: openI18n }) -const columns = shallowRef([ - { dataIndex: 'b_field', title: '字段名', width: 150 }, - { dataIndex: 'b_name', title: '字段名称', width: 140, editor: { type: 'input' } }, - { - dataIndex: 'b_type', - title: '控件类型', - width: 130, - editor: { type: 'select', options: FIELD_TYPES }, +/* ---------- 参与开关(表单/列表/查询) ---------- */ +/* 字段行 → 配置行:字段定义行的 b_id 与配置行的 b_field_id 对应; + 字段本身未启用时开关禁用(停用字段运行时不显示,参与无意义) */ + +function onToggleForm(field) { + if (props.loading) return + emit('updateEditConfig', toggleForm(props.editConfig, field, props.moduleId)) +} + +function onToggleList(field) { + if (props.loading) return + emit('updateListConfig', toggleList(props.listConfig, field, props.moduleId)) +} + +function onToggleQuery(field) { + if (props.loading) return + emit('updateQueryConfig', toggleQuery(props.queryConfig, field, props.moduleId)) +} + +const FormCell = createParticipationCell({ isOn: (f) => isFormOn(props.editConfig, f), onToggle: onToggleForm, title: '参与表单' }) +const ListCell = createParticipationCell({ isOn: (f) => isListOn(props.listConfig, f), onToggle: onToggleList, title: '参与列表显示' }) +const QueryCell = createParticipationCell({ isOn: (f) => isQueryOn(props.queryConfig, f), onToggle: onToggleQuery, title: '作为查询条件' }) + +const columns = shallowRef(buildColumns()) + +// 列宽拖拽结果随 v-model 写回 columns,仅在模块类型变化时重建 +watch( + () => props.moduleType, + () => { + columns.value = buildColumns() }, - { - dataIndex: 'b_dbtype', - title: '数据库类型', - width: 130, - editor: { type: 'select', options: DB_TYPES }, - }, - { - dataIndex: 'b_length', - title: '长度', - width: 80, - editor: { type: 'input', inputType: 'number' }, - }, - { dataIndex: 'b_default_value', title: '默认值', width: 120, editor: { type: 'input' } }, - { dataIndex: 'b_i18n', title: '多语言键', width: 220, customCell: I18nKeyCell }, - { - dataIndex: 'b_canuse', - title: '启用', - width: 70, - align: 'center', - editor: { type: 'checkbox' }, - }, -]) +) + +function buildColumns() { + const baseColumns = [ + { dataIndex: 'b_field', title: '字段名', width: 150 }, + { dataIndex: 'b_name', title: '字段名称', width: 140, editor: { type: 'input' } }, + { + dataIndex: 'b_type', + title: '控件类型', + width: 130, + editor: { type: 'select', options: FIELD_TYPES }, + }, + { + dataIndex: 'b_dbtype', + title: '数据库类型', + width: 130, + editor: { type: 'select', options: DB_TYPES }, + }, + { + dataIndex: 'b_length', + title: '长度', + width: 80, + editor: { type: 'input', inputType: 'number' }, + }, + { dataIndex: 'b_default_value', title: '默认值', width: 120, editor: { type: 'input' } }, + { dataIndex: 'b_i18n', title: '多语言键', width: 220, customCell: I18nKeyCell }, + ] + // 表单参与列仅数据模块展示(查询模块无表单设计) + const participationColumns = [ + ...(props.moduleType === 'data' + ? [{ dataIndex: '__form', title: '表单', width: 64, align: 'center', customCell: FormCell }] + : []), + { dataIndex: '__list', title: '列表', width: 64, align: 'center', customCell: ListCell }, + { dataIndex: '__query', title: '查询', width: 64, align: 'center', customCell: QueryCell }, + ] + const tailColumns = [ + { + dataIndex: 'b_canuse', + title: '启用', + width: 70, + align: 'center', + editor: { type: 'checkbox' }, + }, + ] + return [...baseColumns, ...participationColumns, ...tailColumns] +}