worsoft-frontend-codegen-local-mcp 0.1.80 → 0.1.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/templates/ledger_master_child_jump/api.tpl +7 -0
- package/assets/templates/ledger_master_child_jump/form.tpl +135 -0
- package/assets/templates/ledger_master_child_jump/index.tpl +172 -0
- package/assets/templates/ledger_master_child_jump/menu.sql.tpl +15 -0
- package/assets/templates/ledger_master_child_jump/options.tpl +35 -0
- package/assets/templates/ledger_single_table_jump/api.tpl +7 -0
- package/assets/templates/ledger_single_table_jump/form.tpl +121 -0
- package/assets/templates/ledger_single_table_jump/index.tpl +172 -0
- package/assets/templates/ledger_single_table_jump/menu.sql.tpl +15 -0
- package/assets/templates/ledger_single_table_jump/options.tpl +35 -0
- package/mcp_server.js +64 -39
- package/package.json +1 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 页面布局:{{FEATURE_TITLE}}主子表台账详情页,只读展示主表和子表明细 -->
|
|
3
|
+
<div class="layout-padding-auto layout-padding-view">
|
|
4
|
+
<!-- 详情卡片:承载标题、返回按钮、只读主表字段和只读子表明细 -->
|
|
5
|
+
<el-card shadow="never" class="w100">
|
|
6
|
+
<template #header>
|
|
7
|
+
<!-- 详情页头部:台账只显示查看标题和返回按钮 -->
|
|
8
|
+
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
9
|
+
<span style="font-size: 16px; font-weight: bold;">{{ t('common.viewBtn') }}</span>
|
|
10
|
+
<el-button @click="handleBack" icon="back">{{ commonActionLabel('back') }}</el-button>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
<!-- 只读主子表表单:字段由 MCP 根据 PRD 表单显隐和顺序渲染 -->
|
|
14
|
+
<el-form ref="dataFormRef" :model="form" disabled v-loading="loading">
|
|
15
|
+
<!-- 主表字段区域 -->
|
|
16
|
+
<el-row :gutter="24">
|
|
17
|
+
{{FORM_FIELDS}}
|
|
18
|
+
</el-row>
|
|
19
|
+
<!-- 子表明细区域:隐藏新增行和删除行入口 -->
|
|
20
|
+
<el-row :gutter="24">
|
|
21
|
+
{{LEDGER_CHILD_SECTIONS}}
|
|
22
|
+
</el-row>
|
|
23
|
+
</el-form>
|
|
24
|
+
</el-card>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup lang="ts" name="{{CLASS_NAME}}Form">
|
|
29
|
+
// 本地会话存储:用于表单默认值生成兼容公共模板
|
|
30
|
+
import { Session } from '/@/utils/storage';
|
|
31
|
+
// 通用消息提示
|
|
32
|
+
import { useMessage } from '/@/hooks/message';
|
|
33
|
+
// 标签页关闭能力
|
|
34
|
+
import { useCloseCurrentPage } from '/@/hooks/useCloseCurrentPage';
|
|
35
|
+
// 台账详情接口:只消费 getObj
|
|
36
|
+
import { getObj } from '/@/api/{{API_MODULE_PATH}}';
|
|
37
|
+
// 字典数据加载
|
|
38
|
+
import { useDict } from '/@/hooks/dict';
|
|
39
|
+
// 表单字段元数据能力
|
|
40
|
+
import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
|
|
41
|
+
// 国际化能力
|
|
42
|
+
import { useI18n } from 'vue-i18n';
|
|
43
|
+
// 当前页面字段配置
|
|
44
|
+
import { allDictTypes, childFieldGroups, dataMasterEntity } from './options';
|
|
45
|
+
|
|
46
|
+
// 页面所需字典引用
|
|
47
|
+
const dictRefs = useDict(...allDictTypes);
|
|
48
|
+
// 国际化方法
|
|
49
|
+
const { t } = useI18n();
|
|
50
|
+
// 子表表格组件:仅用于只读展示,模板中 hide-add/hide-delete 固定启用
|
|
51
|
+
const scFormTable = defineAsyncComponent(() => import('/@/components/FormTable/index.vue'));
|
|
52
|
+
// 当前路由信息
|
|
53
|
+
const route = useRoute();
|
|
54
|
+
const { closeCurrentPage } = useCloseCurrentPage();
|
|
55
|
+
// 当前页面的国际化命名空间
|
|
56
|
+
const pageI18nKey = '{{I18N_NAMESPACE}}';
|
|
57
|
+
|
|
58
|
+
// 表单引用
|
|
59
|
+
const dataFormRef = ref();
|
|
60
|
+
// 页面加载状态
|
|
61
|
+
const loading = ref(false);
|
|
62
|
+
// 台账详情固定为只读模式
|
|
63
|
+
const detail = ref(true);
|
|
64
|
+
|
|
65
|
+
// 主表和子表字段的双语、字典和提示文案由公共 hook 提供
|
|
66
|
+
const {
|
|
67
|
+
getFieldMeta: getMasterFieldMeta,
|
|
68
|
+
getFieldLabel: getMasterFieldLabel,
|
|
69
|
+
getChildFieldLabel,
|
|
70
|
+
getDictOptions,
|
|
71
|
+
inputPlaceholder,
|
|
72
|
+
selectPlaceholder,
|
|
73
|
+
fieldRequiredMessage,
|
|
74
|
+
commonActionLabel,
|
|
75
|
+
} = useCrudPageMeta(dataMasterEntity, dictRefs, childFieldGroups);
|
|
76
|
+
|
|
77
|
+
// 台账详情只读,不显示输入占位提示
|
|
78
|
+
const formInputPlaceholder = () => '';
|
|
79
|
+
const formSelectPlaceholder = () => '';
|
|
80
|
+
// 子表分组标题从功能级词条中读取
|
|
81
|
+
const childSectionTitle = (groupName: string) => t(`${pageI18nKey}.children.${groupName}.title`);
|
|
82
|
+
|
|
83
|
+
// 统一维护表单默认值和子表列表默认值
|
|
84
|
+
const createDefaultFormState = () => ({
|
|
85
|
+
{{FORM_DEFAULTS}}
|
|
86
|
+
{{CHILD_FORM_LIST_DEFAULTS}}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 表单响应式数据
|
|
90
|
+
const form = reactive(createDefaultFormState());
|
|
91
|
+
|
|
92
|
+
// 根据主键加载台账详情数据
|
|
93
|
+
const get{{CLASS_NAME}}Data = async (id: string) => {
|
|
94
|
+
try {
|
|
95
|
+
loading.value = true;
|
|
96
|
+
const { data } = await getObj({ {{PK_ATTR}}: id });
|
|
97
|
+
Object.assign(form, Array.isArray(data) ? data[0] || {} : data || {});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
useMessage().error(t('common.messages.fetchError'));
|
|
100
|
+
} finally {
|
|
101
|
+
loading.value = false;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// 重置表单为初始状态,并清空子表列表
|
|
106
|
+
const resetFormState = () => {
|
|
107
|
+
Object.assign(form, createDefaultFormState());
|
|
108
|
+
nextTick(() => {
|
|
109
|
+
dataFormRef.value?.resetFields();
|
|
110
|
+
{{CHILD_RESET_LISTS}}
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// 根据路由参数初始化详情页
|
|
115
|
+
const initPage = async () => {
|
|
116
|
+
const id = route.query.id as string;
|
|
117
|
+
detail.value = true;
|
|
118
|
+
resetFormState();
|
|
119
|
+
|
|
120
|
+
if (id) {
|
|
121
|
+
form.{{PK_ATTR}} = id;
|
|
122
|
+
await get{{CLASS_NAME}}Data(id);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// 返回上一页并关闭当前标签
|
|
127
|
+
const handleBack = () => {
|
|
128
|
+
closeCurrentPage();
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// 页面挂载后初始化详情数据
|
|
132
|
+
onMounted(() => {
|
|
133
|
+
initPage();
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 页面布局:{{FEATURE_TITLE}}主子表台账列表页,只提供查询和查看能力 -->
|
|
3
|
+
<div class="layout-padding">
|
|
4
|
+
<div class="layout-padding-auto layout-padding-view flex h-full flex-col">
|
|
5
|
+
<!-- 台账工具栏:保留关键字查询、重置、高级查询和刷新,隐藏新增、导入、删除、导出 -->
|
|
6
|
+
<SchemaListToolbar
|
|
7
|
+
v-bind="toolbarProps"
|
|
8
|
+
@update:keyword="state.queryForm.smartVal = $event"
|
|
9
|
+
@query="handleToolbarQuery"
|
|
10
|
+
@reset="handleToolbarReset"
|
|
11
|
+
@custom-query-confirm="handleToolbarCustomQueryConfirm"
|
|
12
|
+
@refresh="handleToolbarRefresh"
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
<!-- 台账列表表格:展示主表列表数据和行内查看按钮,不提供勾选批量操作 -->
|
|
16
|
+
<SchemaListTable
|
|
17
|
+
v-bind="tableProps"
|
|
18
|
+
row-id-key="{{PK_ATTR}}"
|
|
19
|
+
:action-column-width="100"
|
|
20
|
+
@sort-change="handleTableSortChange"
|
|
21
|
+
@size-change="handleTableSizeChange"
|
|
22
|
+
@current-change="handleTableCurrentChange"
|
|
23
|
+
>
|
|
24
|
+
<!-- 行操作按钮:主子表台账只允许查看详情 -->
|
|
25
|
+
<template #actions="{ row }">
|
|
26
|
+
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(row.{{PK_ATTR}})">{{ t('common.viewBtn') }}</el-button>
|
|
27
|
+
</template>
|
|
28
|
+
</SchemaListTable>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts" name="system{{CLASS_NAME}}">
|
|
34
|
+
// 台账列表接口:只消费分页查询能力
|
|
35
|
+
import { fetchList } from '/@/api/{{API_MODULE_PATH}}';
|
|
36
|
+
// 字典数据加载
|
|
37
|
+
import { useDict } from '/@/hooks/dict';
|
|
38
|
+
// 列表字段元数据能力
|
|
39
|
+
import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
|
|
40
|
+
// 列表页查询、分页、排序状态管理
|
|
41
|
+
import { useSchemaListQuery } from '/@/hooks/useSchemaListQuery';
|
|
42
|
+
// 统一列表工具栏组件
|
|
43
|
+
import SchemaListToolbar from '/@/components/schema-list/SchemaListToolbar.vue';
|
|
44
|
+
// 统一列表表格组件
|
|
45
|
+
import SchemaListTable from '/@/components/schema-list/SchemaListTable.vue';
|
|
46
|
+
// 国际化能力
|
|
47
|
+
import { useI18n } from 'vue-i18n';
|
|
48
|
+
// 当前页面 schema 与字段配置
|
|
49
|
+
import { allDictTypes, crudSchema, dataMasterEntity } from './options';
|
|
50
|
+
|
|
51
|
+
// 页面所需字典引用
|
|
52
|
+
const dictRefs = useDict(...allDictTypes);
|
|
53
|
+
// 国际化方法
|
|
54
|
+
const { t } = useI18n();
|
|
55
|
+
// 路由跳转能力
|
|
56
|
+
const router = useRouter();
|
|
57
|
+
|
|
58
|
+
// 统一管理台账列表查询、分页和排序
|
|
59
|
+
const { state, getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, tableStyle, resetQueryForm } = useSchemaListQuery({
|
|
60
|
+
schema: crudSchema,
|
|
61
|
+
pageList: fetchList,
|
|
62
|
+
exportUrl: '/{{API_PATH}}/export',
|
|
63
|
+
exportFileName: '{{FUNCTION_NAME}}.xlsx',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 提供字段标签、字典选项和查询区描述
|
|
67
|
+
const { resolveLabel, getDictOptions, visibleTableColumns, searchKeywordTooltip, queryableDictFields } = useCrudPageMeta(dataMasterEntity, dictRefs);
|
|
68
|
+
|
|
69
|
+
// 高级查询字典字段配置
|
|
70
|
+
const queryableDictOptions = computed(() =>
|
|
71
|
+
queryableDictFields.value.map((field) => ({
|
|
72
|
+
...field,
|
|
73
|
+
options: getDictOptions(field.dictType),
|
|
74
|
+
}))
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// 列表表格列配置
|
|
78
|
+
const tableColumns = computed(() =>
|
|
79
|
+
visibleTableColumns.value.map((column) => ({
|
|
80
|
+
prop: column.prop,
|
|
81
|
+
label: resolveLabel(column.labelKey, column.fallbackLabel),
|
|
82
|
+
width: column.width,
|
|
83
|
+
dictType: column.dictType,
|
|
84
|
+
options: column.dictType ? getDictOptions(column.dictType) : [],
|
|
85
|
+
}))
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// 台账工具栏透传属性:显式关闭新增、导入、删除和导出入口
|
|
89
|
+
const toolbarProps = computed(() => ({
|
|
90
|
+
keyword: state.queryForm.smartVal,
|
|
91
|
+
searchPlaceholder: searchKeywordTooltip.value,
|
|
92
|
+
queryModel: state.queryForm,
|
|
93
|
+
customQueryFields: queryableDictOptions.value,
|
|
94
|
+
selectedIds: [],
|
|
95
|
+
showAdd: false,
|
|
96
|
+
showImport: false,
|
|
97
|
+
showDelete: false,
|
|
98
|
+
exportPermission: false,
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
// 台账表格透传属性:关闭勾选列,仅保留查看操作列
|
|
102
|
+
const tableProps = computed(() => ({
|
|
103
|
+
data: state.dataList,
|
|
104
|
+
loading: !!state.loading,
|
|
105
|
+
columns: tableColumns.value,
|
|
106
|
+
pagination: state.pagination,
|
|
107
|
+
tableStyle,
|
|
108
|
+
showSelection: false,
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
// 详情页路由路径
|
|
112
|
+
const getFormPath = () => '/{{VIEW_MODULE_PATH}}/form';
|
|
113
|
+
|
|
114
|
+
// 跳转台账详情页,固定 detail=1
|
|
115
|
+
const handleDetail = (id: string) => {
|
|
116
|
+
router.push({ path: getFormPath(), query: { id, detail: '1', tagsViewName: t('common.viewBtn') } });
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// 应用高级查询条件
|
|
120
|
+
const handleQueryFilterConfirm = (values: Record<string, any>) => {
|
|
121
|
+
queryableDictFields.value.forEach((field) => {
|
|
122
|
+
const nextValue = values[field.prop];
|
|
123
|
+
if (Array.isArray(nextValue) && nextValue.length) {
|
|
124
|
+
state.queryForm[field.prop] = nextValue;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
delete state.queryForm[field.prop];
|
|
128
|
+
});
|
|
129
|
+
getDataList();
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// 重置查询条件并刷新列表
|
|
133
|
+
const resetQuery = () => {
|
|
134
|
+
resetQueryForm();
|
|
135
|
+
getDataList();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// 工具栏查询事件
|
|
139
|
+
const handleToolbarQuery = () => {
|
|
140
|
+
getDataList();
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// 工具栏重置事件
|
|
144
|
+
const handleToolbarReset = () => {
|
|
145
|
+
resetQuery();
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// 工具栏高级查询确认事件
|
|
149
|
+
const handleToolbarCustomQueryConfirm = (payload: { values: Record<string, any> }) => {
|
|
150
|
+
handleQueryFilterConfirm(payload.values);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// 工具栏刷新事件
|
|
154
|
+
const handleToolbarRefresh = () => {
|
|
155
|
+
getDataList();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// 表格排序事件
|
|
159
|
+
const handleTableSortChange = (payload: { raw: any }) => {
|
|
160
|
+
sortChangeHandle(payload.raw);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// 分页大小变化事件
|
|
164
|
+
const handleTableSizeChange = (payload: { size: number }) => {
|
|
165
|
+
sizeChangeHandle(payload.size);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// 当前页变化事件
|
|
169
|
+
const handleTableCurrentChange = (payload: { current: number }) => {
|
|
170
|
+
currentChangeHandle(payload.current);
|
|
171
|
+
};
|
|
172
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Do not execute directly. Review parent menu id and tenant settings before import.
|
|
2
|
+
-- Suggested default parent_id: -1
|
|
3
|
+
-- Generated by worsoft-codegen-local on {{GENERATED_AT}}
|
|
4
|
+
|
|
5
|
+
-- 主子表台账列表菜单:只读台账入口
|
|
6
|
+
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
7
|
+
values ({{MENU_BASE_ID}}, '-1', '/{{MENU_ROUTE_PATH}}/index', '', '0', 'icon-bangzhushouji', '0', null, '8', null, '{{TABLE_COMMENT}}管理', 1);
|
|
8
|
+
|
|
9
|
+
-- 主子表台账详情路由:隐藏菜单,用于列表页查看跳转
|
|
10
|
+
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, visible, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
11
|
+
values ({{MENU_BASE_ID_PLUS_6}}, '-1', '/{{MENU_ROUTE_PATH}}/form', '', '0', 'icon-biaodan', '0', '0', null, '9', null, '{{TABLE_COMMENT}}详情', 1);
|
|
12
|
+
|
|
13
|
+
-- 台账查看权限:不生成新增、编辑、删除等操作权限
|
|
14
|
+
insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
15
|
+
values ({{MENU_BASE_ID_PLUS_1}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_view', '1', null, '1', '0', null, '0', null, '{{TABLE_COMMENT}}查看', 1);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// 字典注册表
|
|
2
|
+
{{DICT_REGISTRY_IMPORT_BLOCK}}
|
|
3
|
+
// schema 构建工具
|
|
4
|
+
import { createCrudSchema } from '/@/utils/crudSchema';
|
|
5
|
+
// schema 类型定义
|
|
6
|
+
import type { CrudSchemaDefinition } from '/@/utils/crudSchema';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* {{TABLE_NAME}} 主子表台账页面字段声明
|
|
10
|
+
* 这里维护主表和子表字段 key、双语 key、字典类型和显示元数据。
|
|
11
|
+
*/
|
|
12
|
+
const definition: CrudSchemaDefinition = {
|
|
13
|
+
master: [
|
|
14
|
+
{{MASTER_OPTION_FIELDS}}
|
|
15
|
+
],
|
|
16
|
+
children: {
|
|
17
|
+
{{CHILD_OPTION_GROUPS}}
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// 将页面字段声明转换为 index/form 共用的 schema 结果
|
|
22
|
+
const schema = createCrudSchema(definition);
|
|
23
|
+
|
|
24
|
+
// 完整 CRUD schema
|
|
25
|
+
export const crudSchema = schema;
|
|
26
|
+
// 主表字段配置,供列表页和详情页使用
|
|
27
|
+
export const dataMasterEntity = schema.master;
|
|
28
|
+
// 子表字段配置,供详情页子表区域使用
|
|
29
|
+
export const childFieldGroups = schema.children;
|
|
30
|
+
// 列表/查询使用的主表字段类型映射
|
|
31
|
+
export const filterTypes = schema.filterTypes;
|
|
32
|
+
// 子表字段类型映射
|
|
33
|
+
export const childFilterTypes = schema.childFilterTypes;
|
|
34
|
+
// 当前页面需要一次性加载的全部字典类型
|
|
35
|
+
export const allDictTypes = schema.allDictTypes;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 页面布局:{{FEATURE_TITLE}}台账详情页,只读展示主表字段 -->
|
|
3
|
+
<div class="layout-padding-auto layout-padding-view">
|
|
4
|
+
<!-- 详情卡片:承载标题、返回按钮和只读表单 -->
|
|
5
|
+
<el-card shadow="never" class="w100">
|
|
6
|
+
<template #header>
|
|
7
|
+
<!-- 详情页头部:台账只显示查看标题和返回按钮 -->
|
|
8
|
+
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
9
|
+
<span style="font-size: 16px; font-weight: bold;">{{ t('common.viewBtn') }}</span>
|
|
10
|
+
<el-button @click="handleBack" icon="back">{{ commonActionLabel('back') }}</el-button>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
<!-- 只读主表表单:字段由 MCP 根据 PRD 表单显隐和顺序渲染 -->
|
|
14
|
+
<el-form ref="dataFormRef" :model="form" disabled v-loading="loading">
|
|
15
|
+
<el-row :gutter="24">
|
|
16
|
+
{{FORM_FIELDS}}
|
|
17
|
+
</el-row>
|
|
18
|
+
</el-form>
|
|
19
|
+
</el-card>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts" name="{{CLASS_NAME}}Form">
|
|
24
|
+
// 本地会话存储:用于表单默认值生成兼容公共模板
|
|
25
|
+
import { Session } from '/@/utils/storage';
|
|
26
|
+
// 通用消息提示
|
|
27
|
+
import { useMessage } from '/@/hooks/message';
|
|
28
|
+
// 标签页关闭能力
|
|
29
|
+
import { useCloseCurrentPage } from '/@/hooks/useCloseCurrentPage';
|
|
30
|
+
// 台账详情接口:只消费 getObj
|
|
31
|
+
import { getObj } from '/@/api/{{API_MODULE_PATH}}';
|
|
32
|
+
// 字典数据加载
|
|
33
|
+
import { useDict } from '/@/hooks/dict';
|
|
34
|
+
// 表单字段元数据能力
|
|
35
|
+
import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
|
|
36
|
+
// 国际化能力
|
|
37
|
+
import { useI18n } from 'vue-i18n';
|
|
38
|
+
// 当前页面字段配置
|
|
39
|
+
import { allDictTypes, dataMasterEntity } from './options';
|
|
40
|
+
|
|
41
|
+
// 页面所需字典引用
|
|
42
|
+
const dictRefs = useDict(...allDictTypes);
|
|
43
|
+
// 国际化方法
|
|
44
|
+
const { t } = useI18n();
|
|
45
|
+
// 当前路由信息
|
|
46
|
+
const route = useRoute();
|
|
47
|
+
const { closeCurrentPage } = useCloseCurrentPage();
|
|
48
|
+
|
|
49
|
+
// 表单引用
|
|
50
|
+
const dataFormRef = ref();
|
|
51
|
+
// 页面加载状态
|
|
52
|
+
const loading = ref(false);
|
|
53
|
+
// 台账详情固定为只读模式
|
|
54
|
+
const detail = ref(true);
|
|
55
|
+
|
|
56
|
+
// 主表字段的双语、字典和提示文案由公共 hook 提供
|
|
57
|
+
const {
|
|
58
|
+
getFieldMeta: getMasterFieldMeta,
|
|
59
|
+
getFieldLabel: getMasterFieldLabel,
|
|
60
|
+
getDictOptions,
|
|
61
|
+
inputPlaceholder,
|
|
62
|
+
selectPlaceholder,
|
|
63
|
+
fieldRequiredMessage,
|
|
64
|
+
commonActionLabel,
|
|
65
|
+
} = useCrudPageMeta(dataMasterEntity, dictRefs);
|
|
66
|
+
|
|
67
|
+
// 台账详情只读,不显示输入占位提示
|
|
68
|
+
const formInputPlaceholder = () => '';
|
|
69
|
+
const formSelectPlaceholder = () => '';
|
|
70
|
+
|
|
71
|
+
// 统一维护表单默认值
|
|
72
|
+
const createDefaultFormState = () => ({
|
|
73
|
+
{{FORM_DEFAULTS}}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 表单响应式数据
|
|
77
|
+
const form = reactive(createDefaultFormState());
|
|
78
|
+
|
|
79
|
+
// 根据主键加载台账详情数据
|
|
80
|
+
const get{{CLASS_NAME}}Data = async (id: string) => {
|
|
81
|
+
try {
|
|
82
|
+
loading.value = true;
|
|
83
|
+
const { data } = await getObj({ {{PK_ATTR}}: id });
|
|
84
|
+
Object.assign(form, Array.isArray(data) ? data[0] || {} : data || {});
|
|
85
|
+
} catch (error) {
|
|
86
|
+
useMessage().error(t('common.messages.fetchError'));
|
|
87
|
+
} finally {
|
|
88
|
+
loading.value = false;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// 重置表单为初始状态
|
|
93
|
+
const resetFormState = () => {
|
|
94
|
+
Object.assign(form, createDefaultFormState());
|
|
95
|
+
nextTick(() => {
|
|
96
|
+
dataFormRef.value?.resetFields();
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// 根据路由参数初始化详情页
|
|
101
|
+
const initPage = async () => {
|
|
102
|
+
const id = route.query.id as string;
|
|
103
|
+
detail.value = true;
|
|
104
|
+
resetFormState();
|
|
105
|
+
|
|
106
|
+
if (id) {
|
|
107
|
+
form.{{PK_ATTR}} = id;
|
|
108
|
+
await get{{CLASS_NAME}}Data(id);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// 返回上一页并关闭当前标签
|
|
113
|
+
const handleBack = () => {
|
|
114
|
+
closeCurrentPage();
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// 页面挂载后初始化详情数据
|
|
118
|
+
onMounted(() => {
|
|
119
|
+
initPage();
|
|
120
|
+
});
|
|
121
|
+
</script>
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 页面布局:{{FEATURE_TITLE}}台账列表页,只提供查询和查看能力 -->
|
|
3
|
+
<div class="layout-padding">
|
|
4
|
+
<div class="layout-padding-auto layout-padding-view flex h-full flex-col">
|
|
5
|
+
<!-- 台账工具栏:保留关键字查询、重置、高级查询和刷新,隐藏新增、导入、删除、导出 -->
|
|
6
|
+
<SchemaListToolbar
|
|
7
|
+
v-bind="toolbarProps"
|
|
8
|
+
@update:keyword="state.queryForm.smartVal = $event"
|
|
9
|
+
@query="handleToolbarQuery"
|
|
10
|
+
@reset="handleToolbarReset"
|
|
11
|
+
@custom-query-confirm="handleToolbarCustomQueryConfirm"
|
|
12
|
+
@refresh="handleToolbarRefresh"
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
<!-- 台账列表表格:展示列表数据和行内查看按钮,不提供勾选批量操作 -->
|
|
16
|
+
<SchemaListTable
|
|
17
|
+
v-bind="tableProps"
|
|
18
|
+
row-id-key="{{PK_ATTR}}"
|
|
19
|
+
:action-column-width="100"
|
|
20
|
+
@sort-change="handleTableSortChange"
|
|
21
|
+
@size-change="handleTableSizeChange"
|
|
22
|
+
@current-change="handleTableCurrentChange"
|
|
23
|
+
>
|
|
24
|
+
<!-- 行操作按钮:台账只允许查看详情 -->
|
|
25
|
+
<template #actions="{ row }">
|
|
26
|
+
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(row.{{PK_ATTR}})">{{ t('common.viewBtn') }}</el-button>
|
|
27
|
+
</template>
|
|
28
|
+
</SchemaListTable>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts" name="system{{CLASS_NAME}}">
|
|
34
|
+
// 台账列表接口:只消费分页查询能力
|
|
35
|
+
import { fetchList } from '/@/api/{{API_MODULE_PATH}}';
|
|
36
|
+
// 字典数据加载
|
|
37
|
+
import { useDict } from '/@/hooks/dict';
|
|
38
|
+
// 列表字段元数据能力
|
|
39
|
+
import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
|
|
40
|
+
// 列表页查询、分页、排序状态管理
|
|
41
|
+
import { useSchemaListQuery } from '/@/hooks/useSchemaListQuery';
|
|
42
|
+
// 统一列表工具栏组件
|
|
43
|
+
import SchemaListToolbar from '/@/components/schema-list/SchemaListToolbar.vue';
|
|
44
|
+
// 统一列表表格组件
|
|
45
|
+
import SchemaListTable from '/@/components/schema-list/SchemaListTable.vue';
|
|
46
|
+
// 国际化能力
|
|
47
|
+
import { useI18n } from 'vue-i18n';
|
|
48
|
+
// 当前页面 schema 与字段配置
|
|
49
|
+
import { allDictTypes, crudSchema, dataMasterEntity } from './options';
|
|
50
|
+
|
|
51
|
+
// 页面所需字典引用
|
|
52
|
+
const dictRefs = useDict(...allDictTypes);
|
|
53
|
+
// 国际化方法
|
|
54
|
+
const { t } = useI18n();
|
|
55
|
+
// 路由跳转能力
|
|
56
|
+
const router = useRouter();
|
|
57
|
+
|
|
58
|
+
// 统一管理台账列表查询、分页和排序
|
|
59
|
+
const { state, getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, tableStyle, resetQueryForm } = useSchemaListQuery({
|
|
60
|
+
schema: crudSchema,
|
|
61
|
+
pageList: fetchList,
|
|
62
|
+
exportUrl: '/{{API_PATH}}/export',
|
|
63
|
+
exportFileName: '{{FUNCTION_NAME}}.xlsx',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 提供字段标签、字典选项和查询区描述
|
|
67
|
+
const { resolveLabel, getDictOptions, visibleTableColumns, searchKeywordTooltip, queryableDictFields } = useCrudPageMeta(dataMasterEntity, dictRefs);
|
|
68
|
+
|
|
69
|
+
// 高级查询字典字段配置
|
|
70
|
+
const queryableDictOptions = computed(() =>
|
|
71
|
+
queryableDictFields.value.map((field) => ({
|
|
72
|
+
...field,
|
|
73
|
+
options: getDictOptions(field.dictType),
|
|
74
|
+
}))
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// 列表表格列配置
|
|
78
|
+
const tableColumns = computed(() =>
|
|
79
|
+
visibleTableColumns.value.map((column) => ({
|
|
80
|
+
prop: column.prop,
|
|
81
|
+
label: resolveLabel(column.labelKey, column.fallbackLabel),
|
|
82
|
+
width: column.width,
|
|
83
|
+
dictType: column.dictType,
|
|
84
|
+
options: column.dictType ? getDictOptions(column.dictType) : [],
|
|
85
|
+
}))
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// 台账工具栏透传属性:显式关闭新增、导入、删除和导出入口
|
|
89
|
+
const toolbarProps = computed(() => ({
|
|
90
|
+
keyword: state.queryForm.smartVal,
|
|
91
|
+
searchPlaceholder: searchKeywordTooltip.value,
|
|
92
|
+
queryModel: state.queryForm,
|
|
93
|
+
customQueryFields: queryableDictOptions.value,
|
|
94
|
+
selectedIds: [],
|
|
95
|
+
showAdd: false,
|
|
96
|
+
showImport: false,
|
|
97
|
+
showDelete: false,
|
|
98
|
+
exportPermission: false,
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
// 台账表格透传属性:关闭勾选列,仅保留查看操作列
|
|
102
|
+
const tableProps = computed(() => ({
|
|
103
|
+
data: state.dataList,
|
|
104
|
+
loading: !!state.loading,
|
|
105
|
+
columns: tableColumns.value,
|
|
106
|
+
pagination: state.pagination,
|
|
107
|
+
tableStyle,
|
|
108
|
+
showSelection: false,
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
// 详情页路由路径
|
|
112
|
+
const getFormPath = () => '/{{VIEW_MODULE_PATH}}/form';
|
|
113
|
+
|
|
114
|
+
// 跳转台账详情页,固定 detail=1
|
|
115
|
+
const handleDetail = (id: string) => {
|
|
116
|
+
router.push({ path: getFormPath(), query: { id, detail: '1', tagsViewName: t('common.viewBtn') } });
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// 应用高级查询条件
|
|
120
|
+
const handleQueryFilterConfirm = (values: Record<string, any>) => {
|
|
121
|
+
queryableDictFields.value.forEach((field) => {
|
|
122
|
+
const nextValue = values[field.prop];
|
|
123
|
+
if (Array.isArray(nextValue) && nextValue.length) {
|
|
124
|
+
state.queryForm[field.prop] = nextValue;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
delete state.queryForm[field.prop];
|
|
128
|
+
});
|
|
129
|
+
getDataList();
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// 重置查询条件并刷新列表
|
|
133
|
+
const resetQuery = () => {
|
|
134
|
+
resetQueryForm();
|
|
135
|
+
getDataList();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// 工具栏查询事件
|
|
139
|
+
const handleToolbarQuery = () => {
|
|
140
|
+
getDataList();
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// 工具栏重置事件
|
|
144
|
+
const handleToolbarReset = () => {
|
|
145
|
+
resetQuery();
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// 工具栏高级查询确认事件
|
|
149
|
+
const handleToolbarCustomQueryConfirm = (payload: { values: Record<string, any> }) => {
|
|
150
|
+
handleQueryFilterConfirm(payload.values);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// 工具栏刷新事件
|
|
154
|
+
const handleToolbarRefresh = () => {
|
|
155
|
+
getDataList();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// 表格排序事件
|
|
159
|
+
const handleTableSortChange = (payload: { raw: any }) => {
|
|
160
|
+
sortChangeHandle(payload.raw);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// 分页大小变化事件
|
|
164
|
+
const handleTableSizeChange = (payload: { size: number }) => {
|
|
165
|
+
sizeChangeHandle(payload.size);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// 当前页变化事件
|
|
169
|
+
const handleTableCurrentChange = (payload: { current: number }) => {
|
|
170
|
+
currentChangeHandle(payload.current);
|
|
171
|
+
};
|
|
172
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Do not execute directly. Review parent menu id and tenant settings before import.
|
|
2
|
+
-- Suggested default parent_id: -1
|
|
3
|
+
-- Generated by worsoft-codegen-local on {{GENERATED_AT}}
|
|
4
|
+
|
|
5
|
+
-- 台账列表菜单:只读台账入口
|
|
6
|
+
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
7
|
+
values ({{MENU_BASE_ID}}, '-1', '/{{MENU_ROUTE_PATH}}/index', '', '0', 'icon-bangzhushouji', '0', null, '8', null, '{{TABLE_COMMENT}}管理', 1);
|
|
8
|
+
|
|
9
|
+
-- 台账详情路由:隐藏菜单,用于列表页查看跳转
|
|
10
|
+
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, visible, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
11
|
+
values ({{MENU_BASE_ID_PLUS_6}}, '-1', '/{{MENU_ROUTE_PATH}}/form', '', '0', 'icon-biaodan', '0', '0', null, '9', null, '{{TABLE_COMMENT}}详情', 1);
|
|
12
|
+
|
|
13
|
+
-- 台账查看权限:不生成新增、编辑、删除等操作权限
|
|
14
|
+
insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
15
|
+
values ({{MENU_BASE_ID_PLUS_1}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_view', '1', null, '1', '0', null, '0', null, '{{TABLE_COMMENT}}查看', 1);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// 字典注册表
|
|
2
|
+
{{DICT_REGISTRY_IMPORT_BLOCK}}
|
|
3
|
+
// schema 构建工具
|
|
4
|
+
import { createCrudSchema } from '/@/utils/crudSchema';
|
|
5
|
+
// schema 类型定义
|
|
6
|
+
import type { CrudSchemaDefinition } from '/@/utils/crudSchema';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* {{TABLE_NAME}} 台账页面字段声明
|
|
10
|
+
* 这里维护字段 key、双语 key、字典类型和显示元数据。
|
|
11
|
+
*/
|
|
12
|
+
const definition: CrudSchemaDefinition = {
|
|
13
|
+
master: [
|
|
14
|
+
{{MASTER_OPTION_FIELDS}}
|
|
15
|
+
],
|
|
16
|
+
children: {
|
|
17
|
+
{{CHILD_OPTION_GROUPS}}
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// 将页面字段声明转换为 index/form 共用的 schema 结果
|
|
22
|
+
const schema = createCrudSchema(definition);
|
|
23
|
+
|
|
24
|
+
// 完整 CRUD schema
|
|
25
|
+
export const crudSchema = schema;
|
|
26
|
+
// 主表字段配置,供列表页和详情页使用
|
|
27
|
+
export const dataMasterEntity = schema.master;
|
|
28
|
+
// 子表字段配置,单表台账保留统一出口
|
|
29
|
+
export const childFieldGroups = schema.children;
|
|
30
|
+
// 列表/查询使用的主表字段类型映射
|
|
31
|
+
export const filterTypes = schema.filterTypes;
|
|
32
|
+
// 子表字段类型映射
|
|
33
|
+
export const childFilterTypes = schema.childFilterTypes;
|
|
34
|
+
// 当前页面需要一次性加载的全部字典类型
|
|
35
|
+
export const allDictTypes = schema.allDictTypes;
|
package/mcp_server.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require('fs');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
7
|
const SERVER_NAME = 'worsoft-codegen-local';
|
|
8
|
-
const SERVER_VERSION = '0.1.
|
|
8
|
+
const SERVER_VERSION = '0.1.82';
|
|
9
9
|
const PROTOCOL_VERSION = '2024-11-05';
|
|
10
10
|
const TOOL_NAME = 'worsoft_codegen_local_generate_frontend';
|
|
11
11
|
const STYLE_CATALOG_PATH = path.join(__dirname, 'assets', 'style-catalog.json');
|
|
@@ -267,10 +267,10 @@ const TOOL_SCHEMA = {
|
|
|
267
267
|
tableName: { type: 'string', description: 'Canonical main table name from PRD-aligned structured metadata.' },
|
|
268
268
|
tableComment: { type: 'string', description: 'Canonical main table comment or feature label from PRD-aligned structured metadata.' },
|
|
269
269
|
apiPath: { type: 'string', description: 'Backend API base path from pre-parsed structured metadata, for example iwmEmpOutsourcePerson.' },
|
|
270
|
-
pageType: {
|
|
271
|
-
type: 'string',
|
|
272
|
-
enum: ['business', 'dict', 'non_standard'],
|
|
273
|
-
description: 'Structured page type from parseResult. MCP consumes this value but does not derive it. Dict pages are restricted to dialog-based templates.',
|
|
270
|
+
pageType: {
|
|
271
|
+
type: 'string',
|
|
272
|
+
enum: ['business', 'dict', 'ledger', 'non_standard'],
|
|
273
|
+
description: 'Structured page type from parseResult. MCP consumes this value but does not derive it. Dict pages are restricted to dialog-based templates. Ledger pages are read-only jump-based templates.',
|
|
274
274
|
},
|
|
275
275
|
style: { type: 'string', enum: Object.keys(STYLE_CATALOG), description: 'Final style id from parseResult or translated mcpPayload. MCP validates it but does not infer it.' },
|
|
276
276
|
fields: {
|
|
@@ -1641,12 +1641,12 @@ function getStylePreset(styleId) {
|
|
|
1641
1641
|
return preset;
|
|
1642
1642
|
}
|
|
1643
1643
|
|
|
1644
|
-
function normalizePageTypeInput(pageType) {
|
|
1645
|
-
if (pageType === undefined || pageType === null || pageType === '') return '';
|
|
1646
|
-
const normalized = String(pageType).trim();
|
|
1647
|
-
if (['business', 'dict', 'non_standard'].includes(normalized)) return normalized;
|
|
1648
|
-
throw new Error(`Unsupported pageType: ${normalized}. Allowed values are dict, business, non_standard.`);
|
|
1649
|
-
}
|
|
1644
|
+
function normalizePageTypeInput(pageType) {
|
|
1645
|
+
if (pageType === undefined || pageType === null || pageType === '') return '';
|
|
1646
|
+
const normalized = String(pageType).trim();
|
|
1647
|
+
if (['business', 'dict', 'ledger', 'non_standard'].includes(normalized)) return normalized;
|
|
1648
|
+
throw new Error(`Unsupported pageType: ${normalized}. Allowed values are dict, business, ledger, non_standard.`);
|
|
1649
|
+
}
|
|
1650
1650
|
|
|
1651
1651
|
function rejectSemanticStageInputs(input) {
|
|
1652
1652
|
const forbiddenKeys = [
|
|
@@ -1669,17 +1669,23 @@ function validatePageTypeAndStyle(pageType, style) {
|
|
|
1669
1669
|
if (pageType === 'non_standard') {
|
|
1670
1670
|
throw new Error('non_standard pages are not supported by worsoft_codegen_local_generate_frontend');
|
|
1671
1671
|
}
|
|
1672
|
-
if (pageType === 'business') {
|
|
1673
|
-
if (style === 'single_table_dialog') {
|
|
1674
|
-
throw new Error('Business pages must use jump-based styles. pageType=business does not support style=single_table_dialog; use single_table_jump for single-table business pages or master_child_jump for master-child business pages.');
|
|
1675
|
-
}
|
|
1676
|
-
return;
|
|
1677
|
-
}
|
|
1678
|
-
if (pageType
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1672
|
+
if (pageType === 'business') {
|
|
1673
|
+
if (style === 'single_table_dialog') {
|
|
1674
|
+
throw new Error('Business pages must use jump-based styles. pageType=business does not support style=single_table_dialog; use single_table_jump for single-table business pages or master_child_jump for master-child business pages.');
|
|
1675
|
+
}
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
if (pageType === 'ledger') {
|
|
1679
|
+
if (style !== 'single_table_jump' && style !== 'master_child_jump') {
|
|
1680
|
+
throw new Error('Ledger pages must use jump-based styles. pageType=ledger supports single_table_jump or master_child_jump only.');
|
|
1681
|
+
}
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
if (pageType !== 'dict') return;
|
|
1685
|
+
if (style === 'single_table_jump' || style === 'master_child_jump') {
|
|
1686
|
+
throw new Error(`Dict pages must use dialog-based styles. pageType=dict does not support style=${style}`);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1683
1689
|
|
|
1684
1690
|
function hasRuntimeSupport(stylePreset) {
|
|
1685
1691
|
return Boolean(stylePreset.runtime && stylePreset.runtime.supported && stylePreset.runtime.templateDir);
|
|
@@ -2181,8 +2187,8 @@ function renderChildTempDeclaration(childModel) {
|
|
|
2181
2187
|
].join('\n');
|
|
2182
2188
|
}
|
|
2183
2189
|
|
|
2184
|
-
function renderChildSection(childModel, childCount) {
|
|
2185
|
-
const deleteExpression = `deleteChild(obj, '${childModel.pk.attrName}')`;
|
|
2190
|
+
function renderChildSection(childModel, childCount) {
|
|
2191
|
+
const deleteExpression = `deleteChild(obj, '${childModel.pk.attrName}')`;
|
|
2186
2192
|
|
|
2187
2193
|
return [
|
|
2188
2194
|
' <el-col :span="24" class="mb20">',
|
|
@@ -3413,6 +3419,21 @@ function renderBusinessDeleteGuard(model) {
|
|
|
3413
3419
|
].join('\n');
|
|
3414
3420
|
}
|
|
3415
3421
|
|
|
3422
|
+
function asReadonlyField(field) {
|
|
3423
|
+
return { ...field, readonly: true };
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
function renderLedgerChildSection(childModel) {
|
|
3427
|
+
return [
|
|
3428
|
+
' <el-col :span="24" class="mb20">',
|
|
3429
|
+
` <div class="mb10" style="font-weight: 600;">{{ childSectionTitle('${childModel.listName}') }}</div>`,
|
|
3430
|
+
` <sc-form-table v-model="form.${childModel.listName}" hide-add hide-delete :placeholder="t('common.noData')">`,
|
|
3431
|
+
childModel.visibleFields.map((field) => renderChildTableColumn(asReadonlyField(field), childModel.listName)).join('\n'),
|
|
3432
|
+
' </sc-form-table>',
|
|
3433
|
+
' </el-col>',
|
|
3434
|
+
].join('\n');
|
|
3435
|
+
}
|
|
3436
|
+
|
|
3416
3437
|
function renderBusinessSubmitStatusAssignment(model) {
|
|
3417
3438
|
if (!hasBusinessBillStateEditControl(model)) return '';
|
|
3418
3439
|
const statusAttr = toCamelCase(model.statusField);
|
|
@@ -3541,7 +3562,7 @@ function buildReplacements(model, sharedSupport) {
|
|
|
3541
3562
|
MENU_BASE_ID_PLUS_5: menuBaseId + 5,
|
|
3542
3563
|
MENU_BASE_ID_PLUS_6: menuBaseId + 6,
|
|
3543
3564
|
GENERATED_AT: new Date().toISOString(),
|
|
3544
|
-
FORM_FIELDS: model.visibleFields.map(renderFormFieldV2).join('\n'),
|
|
3565
|
+
FORM_FIELDS: (model.pageType === 'ledger' ? model.visibleFields.map(asReadonlyField) : model.visibleFields).map(renderFormFieldV2).join('\n'),
|
|
3545
3566
|
TABLE_COLUMNS: model.gridFields.map((field) => renderTableColumn(field, dictRegistryRefs)).join('\n'),
|
|
3546
3567
|
FORM_DEFAULTS: renderFormDefaults(model),
|
|
3547
3568
|
DICT_REGISTRY_IMPORT_BLOCK: model.dictTypes.length ? "import { DictRegistry } from '/@/enums/dict-registry';" : '',
|
|
@@ -3549,21 +3570,25 @@ function buildReplacements(model, sharedSupport) {
|
|
|
3549
3570
|
CHILD_OPTION_GROUPS: model.children.map((childModel) => renderChildOptionGroupV2(model, childModel, dictRegistryRefs)).join('\n'),
|
|
3550
3571
|
FORM_RULES: renderFormRulesV2(model.visibleFields),
|
|
3551
3572
|
CHILD_FORM_LIST_DEFAULTS: renderChildFormListDefaults(model.children),
|
|
3552
|
-
CHILD_TEMP_DECLARATIONS: renderChildTempDeclarations(model.children),
|
|
3553
|
-
CHILD_RESET_LISTS: renderChildResetListLines(model.children),
|
|
3554
|
-
CHILD_SECTIONS: model.children.map((childModel) => renderChildSection(childModel, model.children.length)).join('\n'),
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
function renderFiles(model, stylePreset, sharedSupport, localeZhSupport) {
|
|
3559
|
-
if (!hasRuntimeSupport(stylePreset)) throw new Error('Runtime templates are not implemented for style: ' + model.style);
|
|
3560
|
-
if (model.style === 'multi_level_dict') {
|
|
3561
|
-
return renderMultiLevelFiles(model, sharedSupport, localeZhSupport);
|
|
3562
|
-
}
|
|
3573
|
+
CHILD_TEMP_DECLARATIONS: renderChildTempDeclarations(model.children),
|
|
3574
|
+
CHILD_RESET_LISTS: renderChildResetListLines(model.children),
|
|
3575
|
+
CHILD_SECTIONS: model.children.map((childModel) => renderChildSection(childModel, model.children.length)).join('\n'),
|
|
3576
|
+
LEDGER_CHILD_SECTIONS: model.children.map((childModel) => renderLedgerChildSection(childModel)).join('\n'),
|
|
3577
|
+
};
|
|
3578
|
+
}
|
|
3563
3579
|
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3580
|
+
function renderFiles(model, stylePreset, sharedSupport, localeZhSupport) {
|
|
3581
|
+
if (!hasRuntimeSupport(stylePreset)) throw new Error('Runtime templates are not implemented for style: ' + model.style);
|
|
3582
|
+
if (model.style === 'multi_level_dict') {
|
|
3583
|
+
return renderMultiLevelFiles(model, sharedSupport, localeZhSupport);
|
|
3584
|
+
}
|
|
3585
|
+
|
|
3586
|
+
const runtime = stylePreset.runtime;
|
|
3587
|
+
const templateDir =
|
|
3588
|
+
model.pageType === 'ledger'
|
|
3589
|
+
? path.resolve(__dirname, 'assets/templates/ledger_' + model.style)
|
|
3590
|
+
: path.resolve(__dirname, runtime.templateDir);
|
|
3591
|
+
const replacements = buildReplacements(model, sharedSupport);
|
|
3567
3592
|
const formTemplate = fs.readFileSync(path.join(templateDir, runtime.files.form), 'utf8');
|
|
3568
3593
|
const listTemplate = fs.readFileSync(path.join(templateDir, runtime.files.list), 'utf8');
|
|
3569
3594
|
const optionsTemplate = fs.readFileSync(path.join(templateDir, runtime.files.options), 'utf8');
|
package/package.json
CHANGED