chore(fms-vue): WIP 基线快照——收编工作区未提交的前端改动
不含 fms-api Java 侧改动与后续导航状态化阶段提交。主要内容: - ui 组件库:date/dropdown/form/input/popover/select/tooltip 调整, 新增 Segmented 组件;fms-table 可编辑单元格渲染器与 FileCard 更新 - 模块管理:列表配置加载自动补全、查询缺配徽标与一键补充、 结构编辑内核 useStructureEditing/useBandLayout、子表表格编辑方式、 分组标题多语言、I18nKeyCell 等(含配套 spec) - 布局/主题/仪表盘/演示页小幅更新
This commit is contained in:
1 parent
a1079a7150
commit
05d0c7f304
58 files changed
+3698
-1343
No files matched your search
@@ -19,7 +19,6 @@ import {
|
||||
List,
|
||||
Pencil,
|
||||
Hash,
|
||||
RefreshCw,
|
||||
Shield,
|
||||
Globe,
|
||||
Info,
|
||||
@@ -94,7 +93,6 @@ const isQueryModule = computed(() => moduleType.value === 'query')
|
||||
|
||||
/* ================= 编辑方式 / 导航 / i18n 展示(面板编排) ================= */
|
||||
const editMode = computed(() => drafts.value?.module?.b_edit_mode || 'form')
|
||||
const editNavLabel = computed(() => (editMode.value === 'table' ? '表格设计' : '表单设计'))
|
||||
|
||||
const finalI18nItems = computed(() => {
|
||||
const module = drafts.value?.module
|
||||
@@ -117,6 +115,11 @@ const finalI18nItems = computed(() => {
|
||||
const key = buildModuleItemI18nKey('power', module.b_code, power.b_code)
|
||||
if (key) items.push({ key, managed: true, defaultValue: power.b_name || '', id: `power:${key}` })
|
||||
}
|
||||
// 分组标题多语言:b_i18n 为用户手填 key(空则运行时直接用标题原文,不纳入受管)
|
||||
for (const group of drafts.value?.groups || []) {
|
||||
const key = String(group.b_i18n || '').trim()
|
||||
if (key) items.push({ key, managed: true, defaultValue: group.b_title || '', id: `group:${group.b_id}` })
|
||||
}
|
||||
return items
|
||||
})
|
||||
|
||||
@@ -137,30 +140,18 @@ const configGroups = computed(() => {
|
||||
items: [{ key: 'fields', label: '字段定义', icon: Table2 }],
|
||||
})
|
||||
|
||||
// 界面配置:表单设计(数据模块)→ 列表配置 → 查询配置
|
||||
// 界面配置:表单设计(数据模块,含主表表单/子表表格两种编辑方式)→ 列表配置 → 查询配置
|
||||
const uiItems = []
|
||||
if (isDataModule.value) {
|
||||
const editLen = drafts.value?.editConfig?.length ?? 0
|
||||
uiItems.push({
|
||||
key: 'edit',
|
||||
label: editNavLabel.value,
|
||||
icon: Pencil,
|
||||
badge: editLen ? '已配置' : '',
|
||||
})
|
||||
uiItems.push({ key: 'edit', label: '表单设计', icon: Pencil })
|
||||
}
|
||||
const listLen = drafts.value?.listConfig?.length ?? 0
|
||||
uiItems.push({
|
||||
key: 'list',
|
||||
label: '列表配置',
|
||||
icon: List,
|
||||
badge: listLen ? '已配置' : '',
|
||||
})
|
||||
const queryLen = drafts.value?.queryConfig?.length ?? 0
|
||||
// 列表配置行在加载时自动补全全部启用字段,无「缺失」概念,不带徽标
|
||||
uiItems.push({ key: 'list', label: '列表配置', icon: List })
|
||||
uiItems.push({
|
||||
key: 'query',
|
||||
label: '查询配置',
|
||||
icon: Search,
|
||||
badge: queryLen ? '已配置' : '',
|
||||
badge: missingQueryCount.value ? `缺 ${missingQueryCount.value}` : '',
|
||||
})
|
||||
groups.push({ key: 'display', label: '界面配置', items: uiItems })
|
||||
|
||||
@@ -195,6 +186,9 @@ const configNavItems = computed(() =>
|
||||
configGroups.value.flatMap((group) => group.items.map((item) => ({ ...item }))),
|
||||
)
|
||||
|
||||
/* 编辑设计器:form/table 两面板 props/emits 契约一致,用动态组件消除模板重复 */
|
||||
const activeEditPanel = computed(() => (editMode.value === 'table' ? ModuleTableEditPanel : ModuleFormEditPanel))
|
||||
|
||||
/* ================= composables ================= */
|
||||
const { saveModule } = useModuleSave({
|
||||
selectedModule,
|
||||
@@ -298,11 +292,12 @@ const {
|
||||
})
|
||||
|
||||
const {
|
||||
reloadModule,
|
||||
onModuleSelect,
|
||||
onFieldsUpdate,
|
||||
onAutoCodeUpdate,
|
||||
syncFields,
|
||||
missingQueryCount,
|
||||
fillMissingConfigs,
|
||||
} = useModuleConfig({
|
||||
moduleSelectedId,
|
||||
moduleTreeData,
|
||||
@@ -337,6 +332,19 @@ function onModuleUpdate(section, newData) {
|
||||
if (drafts.value) drafts.value[section] = newData
|
||||
}
|
||||
|
||||
/* 分组管理弹层提交:写回分组草稿,并清理被删分组在列表/编辑配置中的引用 */
|
||||
function onGroupsUpdate(groups, removedGroupIds) {
|
||||
if (!drafts.value) return
|
||||
drafts.value.groups = groups
|
||||
const removed = new Set((removedGroupIds || []).map(String))
|
||||
if (!removed.size) return
|
||||
for (const section of ['listConfig', 'editConfig']) {
|
||||
drafts.value[section] = (drafts.value[section] || []).map((row) =>
|
||||
removed.has(String(row.b_group_id)) ? { ...row, b_group_id: null } : row,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function onModuleI18nSaved() {
|
||||
i18nPanelRef.value?.refreshKey?.()
|
||||
}
|
||||
@@ -408,6 +416,27 @@ loadModuleTree()
|
||||
<SplitterPanel>
|
||||
<main class="mm-main">
|
||||
<template v-if="selectedModule">
|
||||
<!-- 顶部通栏操作:保存 / 同步字段(全 tab 生效,不随内容区切换) -->
|
||||
<div class="mm-main-toolbar">
|
||||
<Button
|
||||
type="primary"
|
||||
:loading="configSaving"
|
||||
:disabled="configLoading || !drafts"
|
||||
@click="saveModule"
|
||||
>
|
||||
<Save :size="14" /> 保存
|
||||
</Button>
|
||||
<Button
|
||||
v-if="isDataModule || isQueryModule"
|
||||
type="outline"
|
||||
:disabled="busy"
|
||||
title="按数据库视图结构对齐字段定义"
|
||||
@click="syncFields"
|
||||
>
|
||||
同步字段
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Tabs
|
||||
v-if="drafts"
|
||||
v-model="activeSection"
|
||||
@@ -421,21 +450,6 @@ loadModuleTree()
|
||||
<span class="mm-config-nav__label">{{ item.label }}</span>
|
||||
<span v-if="item.badge" class="mm-config-nav__badge">{{ item.badge }}</span>
|
||||
</template>
|
||||
<template #rightExtra>
|
||||
<div class="mm-header__actions">
|
||||
<Button type="outline" :disabled="busy || !selectedModule" @click="reloadModule">
|
||||
<RefreshCw :size="14" /> 重载
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
:loading="configSaving"
|
||||
:disabled="configLoading"
|
||||
@click="saveModule"
|
||||
>
|
||||
<Save :size="14" /> 保存
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</Tabs>
|
||||
|
||||
<div class="mm-body__inner">
|
||||
@@ -456,9 +470,6 @@ loadModuleTree()
|
||||
v-show="activeSection === 'fields'"
|
||||
class="mm-config-pane"
|
||||
>
|
||||
<div class="mm-section-toolbar">
|
||||
<Button type="outline" :disabled="busy" @click="syncFields">同步字段</Button>
|
||||
</div>
|
||||
<ModuleFieldsPanel
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:module-code="drafts?.module?.b_code || ''"
|
||||
@@ -466,7 +477,6 @@ loadModuleTree()
|
||||
:loading="busy"
|
||||
@update="onFieldsUpdate"
|
||||
@i18n-saved="onModuleI18nSaved"
|
||||
@sync-fields="syncFields"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -477,25 +487,23 @@ loadModuleTree()
|
||||
>
|
||||
<ModuleListConfigPanel
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:module-code="drafts?.module?.b_code || ''"
|
||||
:list-config="drafts?.listConfig"
|
||||
:edit-config="drafts?.editConfig"
|
||||
:query-config="drafts?.queryConfig"
|
||||
:fields="drafts?.fields"
|
||||
:groups="drafts?.groups"
|
||||
:loading="busy"
|
||||
@update="(v) => onModuleUpdate('listConfig', v)"
|
||||
@sync-edit="(v) => onModuleUpdate('editConfig', v)"
|
||||
@sync-query="(v) => onModuleUpdate('queryConfig', v)"
|
||||
@update-groups="onGroupsUpdate"
|
||||
@i18n-saved="onModuleI18nSaved"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="isDataModule" v-show="activeSection === 'edit'" class="mm-config-pane">
|
||||
<ModuleTableEditPanel
|
||||
v-if="editMode === 'table'"
|
||||
<component
|
||||
:is="activeEditPanel"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:edit-config="drafts?.editConfig"
|
||||
:list-config="drafts?.listConfig"
|
||||
:query-config="drafts?.queryConfig"
|
||||
:fields="drafts?.fields"
|
||||
:groups="drafts?.groups"
|
||||
:edit-mode="editMode"
|
||||
@@ -505,28 +513,8 @@ loadModuleTree()
|
||||
@update:edit-mode="
|
||||
(v) => onModuleUpdate('module', { ...(drafts?.module || {}), b_edit_mode: v })
|
||||
"
|
||||
@update-groups="(v) => onModuleUpdate('groups', v)"
|
||||
@sync-list="(v) => onModuleUpdate('listConfig', v)"
|
||||
@sync-query="(v) => onModuleUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleFormEditPanel
|
||||
v-else
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:edit-config="drafts?.editConfig"
|
||||
:list-config="drafts?.listConfig"
|
||||
:query-config="drafts?.queryConfig"
|
||||
:fields="drafts?.fields"
|
||||
:groups="drafts?.groups"
|
||||
:edit-mode="editMode"
|
||||
:active="activeSection === 'edit'"
|
||||
:loading="busy"
|
||||
@update="(v) => onModuleUpdate('editConfig', v)"
|
||||
@update:edit-mode="
|
||||
(v) => onModuleUpdate('module', { ...(drafts?.module || {}), b_edit_mode: v })
|
||||
"
|
||||
@update-groups="(v) => onModuleUpdate('groups', v)"
|
||||
@sync-list="(v) => onModuleUpdate('listConfig', v)"
|
||||
@sync-query="(v) => onModuleUpdate('queryConfig', v)"
|
||||
@update-groups="onGroupsUpdate"
|
||||
@update-list-config="(v) => onModuleUpdate('listConfig', v)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -540,7 +528,9 @@ loadModuleTree()
|
||||
:query-config="drafts?.queryConfig"
|
||||
:fields="drafts?.fields"
|
||||
:loading="busy"
|
||||
:missing-count="missingQueryCount"
|
||||
@update="(v) => onModuleUpdate('queryConfig', v)"
|
||||
@fill-missing="() => fillMissingConfigs(['queryConfig'])"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -803,12 +793,13 @@ loadModuleTree()
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 操作按钮组(Tabs 的 rightExtra 插槽内) */
|
||||
.mm-header__actions {
|
||||
/* 顶部通栏操作条:保存 / 同步字段(位于 tabs 之上,全 tab 生效) */
|
||||
.mm-main-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
gap: 8px;
|
||||
flex: none;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
/* ---- 右侧:配置工作区 ---- */
|
||||
@@ -897,11 +888,4 @@ loadModuleTree()
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.mm-section-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user