worsoft-frontend-codegen-local-mcp 0.1.70 → 0.1.72

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.
@@ -51,6 +51,7 @@ import { useDict } from '/@/hooks/dict';
51
51
  import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
52
52
  // 国际化能力
53
53
  import { useI18n } from 'vue-i18n';
54
+ {{BUSINESS_FORM_STATUS_IMPORTS}}
54
55
  // 当前页面的字段配置
55
56
  import { allDictTypes, childFieldGroups, dataMasterEntity } from './options';
56
57
 
@@ -165,7 +166,8 @@ const onSubmit = async (actionType?: string) => {
165
166
  }
166
167
 
167
168
  try {
168
- form.{{PK_ATTR}} ? await putObj(form) : await addObj(form);
169
+ const submitData = Object.assign({}, form{{BUSINESS_SUBMIT_STATUS_ASSIGNMENT}});
170
+ form.{{PK_ATTR}} ? await putObj(submitData) : await addObj(submitData);
169
171
 
170
172
  let msg = form.{{PK_ATTR}} ? t('common.editSuccessText') : t('common.addSuccessText');
171
173
  if (actionType === 'submit') msg = t('common.messages.quickSubmitSuccess');
@@ -37,7 +37,7 @@
37
37
  <!-- 流转{{FEATURE_TITLE}} -->
38
38
  <el-button text type="success" icon="position" @click="handleQuickAction(row, 'flow')">{{ commonActionLabel('flow') }}</el-button>
39
39
  <!-- 删除{{FEATURE_TITLE}} -->
40
- <el-button icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}])">{{ t('common.delBtn') }}</el-button>
40
+ <el-button{{BUSINESS_DELETE_IF}} icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}]{{BUSINESS_DELETE_ROW_ARG}})">{{ t('common.delBtn') }}</el-button>
41
41
  </template>
42
42
  </SchemaListTable>
43
43
  </div>
@@ -80,6 +80,7 @@ const router = useRouter();
80
80
  const excelUploadRef = ref();
81
81
  // 列表勾选主键集合
82
82
  const selectObjs = ref<string[]>([]);
83
+ {{BUSINESS_SELECTED_ROWS_DECLARATION}}
83
84
  // 批量删除按钮状态
84
85
  const multiple = ref(true);
85
86
 
@@ -120,7 +121,7 @@ const toolbarProps = computed(() => ({
120
121
  queryModel: state.queryForm,
121
122
  customQueryFields: queryableDictOptions.value,
122
123
  selectedIds: selectObjs.value,
123
- deleteDisabled: multiple.value,
124
+ deleteDisabled: multiple.value{{BUSINESS_DELETE_DISABLED_EXPR}},
124
125
  exportPermission: '{{PERMISSION_PREFIX}}_export',
125
126
  }));
126
127
 
@@ -195,7 +196,8 @@ const resetQuery = () => {
195
196
  };
196
197
 
197
198
  // 删除列表数据
198
- const handleDelete = async (ids: string[]) => {
199
+ const handleDelete = async (ids: string[]{{BUSINESS_DELETE_ROWS_PARAM}}) => {
200
+ {{BUSINESS_DELETE_GUARD}}
199
201
  try {
200
202
  await useMessageBox().confirm(t('common.delConfirmText'));
201
203
  } catch {
@@ -223,7 +225,7 @@ const handleToolbarImport = () => {
223
225
 
224
226
  // 工具栏批量删除事件
225
227
  const handleToolbarDelete = () => {
226
- handleDelete(selectObjs.value);
228
+ handleDelete(selectObjs.value{{BUSINESS_SELECTED_ROWS_ARG}});
227
229
  };
228
230
 
229
231
  // 工具栏查询事件
@@ -252,7 +254,8 @@ const handleToolbarRefresh = () => {
252
254
  };
253
255
 
254
256
  // 表格勾选变化事件
255
- const handleTableSelectionChange = (payload: { ids: Array<string | number> }) => {
257
+ const handleTableSelectionChange = (payload: { rows: any[]; ids: Array<string | number> }) => {
258
+ {{BUSINESS_SELECTED_ROWS_ASSIGNMENT}}
256
259
  selectObjs.value = payload.ids.map((id) => String(id));
257
260
  multiple.value = !payload.ids.length;
258
261
  };
@@ -47,6 +47,7 @@ import { useDict } from '/@/hooks/dict';
47
47
  import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
48
48
  // 国际化能力
49
49
  import { useI18n } from 'vue-i18n';
50
+ {{BUSINESS_FORM_STATUS_IMPORTS}}
50
51
  // 当前页面的字段配置
51
52
  import { allDictTypes, dataMasterEntity } from './options';
52
53
 
@@ -147,7 +148,8 @@ const onSubmit = async (actionType?: string) => {
147
148
  }
148
149
 
149
150
  try {
150
- form.{{PK_ATTR}} ? await putObj(form) : await addObj(form);
151
+ const submitData = Object.assign({}, form{{BUSINESS_SUBMIT_STATUS_ASSIGNMENT}});
152
+ form.{{PK_ATTR}} ? await putObj(submitData) : await addObj(submitData);
151
153
 
152
154
  let msg = form.{{PK_ATTR}} ? t('common.editSuccessText') : t('common.addSuccessText');
153
155
  if (actionType === 'submit') msg = t('common.messages.quickSubmitSuccess');
@@ -34,7 +34,7 @@
34
34
  <!-- 编辑{{FEATURE_TITLE}}:业务单据编辑态控制按需生效 -->
35
35
  <el-button{{BUSINESS_EDIT_IF}} icon="edit-pen" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_edit'" @click="handleEdit(row.{{PK_ATTR}})">{{ t('common.editBtn') }}</el-button>
36
36
  <!-- 删除{{FEATURE_TITLE}} -->
37
- <el-button icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}])">{{ t('common.delBtn') }}</el-button>
37
+ <el-button{{BUSINESS_DELETE_IF}} icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}]{{BUSINESS_DELETE_ROW_ARG}})">{{ t('common.delBtn') }}</el-button>
38
38
  </template>
39
39
  </SchemaListTable>
40
40
  </div>
@@ -77,6 +77,7 @@ const router = useRouter();
77
77
  const excelUploadRef = ref();
78
78
  // 列表勾选主键集合
79
79
  const selectObjs = ref<string[]>([]);
80
+ {{BUSINESS_SELECTED_ROWS_DECLARATION}}
80
81
  // 批量删除按钮状态
81
82
  const multiple = ref(true);
82
83
 
@@ -117,7 +118,7 @@ const toolbarProps = computed(() => ({
117
118
  queryModel: state.queryForm,
118
119
  customQueryFields: queryableDictOptions.value,
119
120
  selectedIds: selectObjs.value,
120
- deleteDisabled: multiple.value,
121
+ deleteDisabled: multiple.value{{BUSINESS_DELETE_DISABLED_EXPR}},
121
122
  addPermission: '{{PERMISSION_PREFIX}}_add',
122
123
  importPermission: '{{PERMISSION_PREFIX}}_add',
123
124
  deletePermission: '{{PERMISSION_PREFIX}}_del',
@@ -179,7 +180,8 @@ const resetQuery = () => {
179
180
  };
180
181
 
181
182
  // 删除列表数据
182
- const handleDelete = async (ids: string[]) => {
183
+ const handleDelete = async (ids: string[]{{BUSINESS_DELETE_ROWS_PARAM}}) => {
184
+ {{BUSINESS_DELETE_GUARD}}
183
185
  try {
184
186
  await useMessageBox().confirm(t('common.delConfirmText'));
185
187
  } catch {
@@ -207,7 +209,7 @@ const handleToolbarImport = () => {
207
209
 
208
210
  // 工具栏批量删除事件
209
211
  const handleToolbarDelete = () => {
210
- handleDelete(selectObjs.value);
212
+ handleDelete(selectObjs.value{{BUSINESS_SELECTED_ROWS_ARG}});
211
213
  };
212
214
 
213
215
  // 工具栏查询事件
@@ -236,7 +238,8 @@ const handleToolbarRefresh = () => {
236
238
  };
237
239
 
238
240
  // 表格勾选变化事件
239
- const handleTableSelectionChange = (payload: { ids: Array<string | number> }) => {
241
+ const handleTableSelectionChange = (payload: { rows: any[]; ids: Array<string | number> }) => {
242
+ {{BUSINESS_SELECTED_ROWS_ASSIGNMENT}}
240
243
  selectObjs.value = payload.ids.map((id) => String(id));
241
244
  multiple.value = !payload.ids.length;
242
245
  };
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.70';
8
+ const SERVER_VERSION = '0.1.72';
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');
@@ -204,9 +204,9 @@ export const createCrudApi = (baseUrl: string, overrides: CrudApiPathOverrides =
204
204
  });
205
205
  `;
206
206
 
207
- const DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE = `import type { RouteLocationNormalizedLoaded } from 'vue-router';
208
- import { useRoute } from 'vue-router';
209
- import mittBus from '/@/utils/mitt';
207
+ const DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE = `import type { RouteLocationNormalizedLoaded } from 'vue-router';
208
+ import { useRoute } from 'vue-router';
209
+ import mittBus from '/@/utils/mitt';
210
210
 
211
211
  export const closeCurrentRoutePage = (route: RouteLocationNormalizedLoaded) => {
212
212
  \tmittBus.emit('onCurrentContextmenuClick', {
@@ -229,8 +229,22 @@ export function useCloseCurrentPage() {
229
229
  \treturn {
230
230
  \t\tcloseCurrentPage,
231
231
  \t};
232
- }
233
- `;
232
+ }
233
+ `;
234
+
235
+ const DEFAULT_DICT_SEMANTIC_TEMPLATE = `// This file is hand-maintained. Do NOT overwrite during dict-registry sync.
236
+ // Add semantic keys here for dictionaries that have meaningful state values.
237
+
238
+ export const DictSemanticValues = {
239
+ billState: {
240
+ editing: '0',
241
+ processing: '1',
242
+ paused: '2',
243
+ terminated: '3',
244
+ completed: '4',
245
+ },
246
+ } as const;
247
+ `;
234
248
 
235
249
  const TOOL_SCHEMA = {
236
250
  type: 'object',
@@ -590,22 +604,9 @@ function renderDictRegistryContent(entries) {
590
604
  '',
591
605
  'export type DictRegistryKey = keyof typeof DictRegistry;',
592
606
  'export type DictType = (typeof DictRegistry)[DictRegistryKey];',
593
- '',
594
- 'export const DictSemanticValues = {',
595
- ' billState: {',
596
- " editing: '0',",
597
- " processing: '1',",
598
- " paused: '2',",
599
- " terminated: '3',",
600
- " completed: '4',",
601
- ' },',
602
- '} as const;',
603
- '',
604
- 'export const isBillStateEditing = (value: unknown): boolean =>',
605
- " String(value ?? '') === DictSemanticValues.billState.editing;",
606
- '',
607
- ].join('\n');
608
- }
607
+ '',
608
+ ].join('\n');
609
+ }
609
610
 
610
611
  function patchDictRegistryContent(fileContent, entriesToAdd) {
611
612
  const source = String(fileContent || '');
@@ -626,28 +627,9 @@ function patchDictRegistryContent(fileContent, entriesToAdd) {
626
627
  return source.replace(block, nextBlock);
627
628
  }
628
629
 
629
- const DICT_REGISTRY_SEMANTIC_HELPERS = [
630
- '',
631
- 'export const DictSemanticValues = {',
632
- ' billState: {',
633
- " editing: '0',",
634
- " processing: '1',",
635
- " paused: '2',",
636
- " terminated: '3',",
637
- " completed: '4',",
638
- ' },',
639
- '} as const;',
640
- '',
641
- 'export const isBillStateEditing = (value: unknown): boolean =>',
642
- " String(value ?? '') === DictSemanticValues.billState.editing;",
643
- '',
644
- ].join('\n');
645
-
646
- function ensureDictRegistrySemanticHelpers(fileContent) {
647
- const source = String(fileContent || '').replace(/\s*$/, '\n');
648
- if (source.includes('export const isBillStateEditing')) return source;
649
- return `${source}${DICT_REGISTRY_SEMANTIC_HELPERS}`;
650
- }
630
+ function ensureDictRegistrySemanticHelpers(fileContent) {
631
+ return String(fileContent || '').replace(/\s*$/, '\n');
632
+ }
651
633
 
652
634
  function isPlainObject(value) {
653
635
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
@@ -807,12 +789,12 @@ function buildLocaleLeaf(model) {
807
789
  };
808
790
  }
809
791
 
810
- const leaf = {
811
- title: model.tableComment,
812
- fields: Object.fromEntries(model.optionFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
813
- };
814
-
815
- if (model.children.length) {
792
+ const leaf = {
793
+ title: model.tableComment,
794
+ fields: Object.fromEntries(model.optionFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
795
+ };
796
+
797
+ if (model.children.length) {
816
798
  leaf.children = Object.fromEntries(
817
799
  model.children.map((childModel) => [
818
800
  childModel.listName,
@@ -953,24 +935,39 @@ function ensureCrudFactorySupportFile(frontendPath) {
953
935
  };
954
936
  }
955
937
 
956
- function ensureCloseCurrentPageSupportFile(frontendPath) {
957
- const hookPath = path.join(frontendPath, 'src', 'hooks', 'useCloseCurrentPage.ts');
958
- const exists = fs.existsSync(hookPath);
959
- const currentContent = exists ? readUtf8File(hookPath) : '';
960
- const isCompatible = !exists || currentContent.includes('export function useCloseCurrentPage');
938
+ function ensureCloseCurrentPageSupportFile(frontendPath) {
939
+ const hookPath = path.join(frontendPath, 'src', 'hooks', 'useCloseCurrentPage.ts');
940
+ const exists = fs.existsSync(hookPath);
941
+ const currentContent = exists ? readUtf8File(hookPath) : '';
942
+ const isCompatible = !exists || currentContent.includes('export function useCloseCurrentPage');
961
943
 
962
944
  return {
963
945
  path: hookPath,
964
946
  content: DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE,
965
947
  exists,
966
948
  isCompatible,
967
- needsWrite: !exists,
968
- };
969
- }
970
-
971
- function ensureDirectory(filePath) {
972
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
973
- }
949
+ needsWrite: !exists,
950
+ };
951
+ }
952
+
953
+ function ensureDictSemanticSupportFile(frontendPath) {
954
+ const semanticPath = path.join(frontendPath, 'src', 'enums', 'dict-semantic.ts');
955
+ const exists = fs.existsSync(semanticPath);
956
+ const currentContent = exists ? readUtf8File(semanticPath) : '';
957
+ const isCompatible = !exists || currentContent.includes('export const DictSemanticValues');
958
+
959
+ return {
960
+ path: semanticPath,
961
+ content: DEFAULT_DICT_SEMANTIC_TEMPLATE,
962
+ exists,
963
+ isCompatible,
964
+ needsWrite: !exists,
965
+ };
966
+ }
967
+
968
+ function ensureDirectory(filePath) {
969
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
970
+ }
974
971
 
975
972
  function writeSupportFile(filePath, content) {
976
973
  ensureDirectory(filePath);
@@ -1015,24 +1012,36 @@ function prepareSharedSupport(frontendPath, dictTypes, writeSupportFiles) {
1015
1012
  writeEnabled: false,
1016
1013
  };
1017
1014
  const closeCurrentPagePath = path.join(frontendPath, 'src', 'hooks', 'useCloseCurrentPage.ts');
1018
- const closeCurrentPage = writeSupportFiles
1019
- ? ensureCloseCurrentPageSupportFile(frontendPath)
1020
- : {
1021
- path: closeCurrentPagePath,
1022
- content: DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE,
1015
+ const closeCurrentPage = writeSupportFiles
1016
+ ? ensureCloseCurrentPageSupportFile(frontendPath)
1017
+ : {
1018
+ path: closeCurrentPagePath,
1019
+ content: DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE,
1023
1020
  exists: fs.existsSync(closeCurrentPagePath),
1024
1021
  isCompatible: true,
1025
- needsWrite: false,
1026
- writeEnabled: false,
1027
- };
1028
- return {
1029
- dictRegistry,
1030
- crudSchema,
1031
- crudFactory,
1032
- closeCurrentPage,
1033
- writeEnabled: Boolean(writeSupportFiles),
1034
- };
1035
- }
1022
+ needsWrite: false,
1023
+ writeEnabled: false,
1024
+ };
1025
+ const dictSemanticPath = path.join(frontendPath, 'src', 'enums', 'dict-semantic.ts');
1026
+ const dictSemantic = writeSupportFiles
1027
+ ? ensureDictSemanticSupportFile(frontendPath)
1028
+ : {
1029
+ path: dictSemanticPath,
1030
+ content: DEFAULT_DICT_SEMANTIC_TEMPLATE,
1031
+ exists: fs.existsSync(dictSemanticPath),
1032
+ isCompatible: true,
1033
+ needsWrite: false,
1034
+ writeEnabled: false,
1035
+ };
1036
+ return {
1037
+ dictRegistry,
1038
+ crudSchema,
1039
+ crudFactory,
1040
+ closeCurrentPage,
1041
+ dictSemantic,
1042
+ writeEnabled: Boolean(writeSupportFiles),
1043
+ };
1044
+ }
1036
1045
 
1037
1046
  function maybeWriteSharedSupport(sharedSupport, writeToDisk) {
1038
1047
  if (!writeToDisk || !sharedSupport.writeEnabled) return;
@@ -1061,25 +1070,35 @@ function maybeWriteSharedSupport(sharedSupport, writeToDisk) {
1061
1070
  writeSupportFile(sharedSupport.dictRegistry.path, sharedSupport.dictRegistry.content);
1062
1071
  }
1063
1072
 
1064
- if (sharedSupport.closeCurrentPage.needsWrite) {
1065
- if (!sharedSupport.closeCurrentPage.isCompatible) {
1066
- throw new Error(
1067
- 'Detected an existing src/hooks/useCloseCurrentPage.ts that MCP could not merge safely. ' +
1068
- 'Please align the useCloseCurrentPage export manually before enabling writeSupportFiles.'
1073
+ if (sharedSupport.closeCurrentPage.needsWrite) {
1074
+ if (!sharedSupport.closeCurrentPage.isCompatible) {
1075
+ throw new Error(
1076
+ 'Detected an existing src/hooks/useCloseCurrentPage.ts that MCP could not merge safely. ' +
1077
+ 'Please align the useCloseCurrentPage export manually before enabling writeSupportFiles.'
1069
1078
  );
1070
- }
1071
- writeSupportFile(sharedSupport.closeCurrentPage.path, sharedSupport.closeCurrentPage.content);
1072
- }
1073
- }
1079
+ }
1080
+ writeSupportFile(sharedSupport.closeCurrentPage.path, sharedSupport.closeCurrentPage.content);
1081
+ }
1082
+
1083
+ if (sharedSupport.dictSemantic.needsWrite) {
1084
+ if (!sharedSupport.dictSemantic.isCompatible) {
1085
+ throw new Error(
1086
+ 'Detected an existing src/enums/dict-semantic.ts that MCP could not merge safely. ' +
1087
+ 'Please align the DictSemanticValues export manually before enabling writeSupportFiles.'
1088
+ );
1089
+ }
1090
+ writeSupportFile(sharedSupport.dictSemantic.path, sharedSupport.dictSemantic.content);
1091
+ }
1092
+ }
1074
1093
 
1075
1094
  function buildSupportNote(sharedSupport, localeZhSupport) {
1076
1095
  const notes = [];
1077
1096
 
1078
- if (!sharedSupport.writeEnabled) {
1079
- notes.push(
1080
- 'Shared support file writing is disabled. Generated code still references src/utils/crudSchema.ts, src/api/common/crudFactory.ts, src/hooks/useCloseCurrentPage.ts and may reference src/enums/dict-registry.ts, so those helpers must already exist in the target project.'
1081
- );
1082
- }
1097
+ if (!sharedSupport.writeEnabled) {
1098
+ notes.push(
1099
+ 'Shared support file writing is disabled. Generated code still references src/utils/crudSchema.ts, src/api/common/crudFactory.ts, src/hooks/useCloseCurrentPage.ts, src/enums/dict-semantic.ts and may reference src/enums/dict-registry.ts, so those helpers must already exist in the target project.'
1100
+ );
1101
+ }
1083
1102
 
1084
1103
  if (sharedSupport.crudSchema.exists && !sharedSupport.crudSchema.isCompatible) {
1085
1104
  notes.push(
@@ -1095,12 +1114,19 @@ function buildSupportNote(sharedSupport, localeZhSupport) {
1095
1114
  );
1096
1115
  }
1097
1116
 
1098
- if (sharedSupport.dictRegistry.exists && !sharedSupport.dictRegistry.isCompatible) {
1099
- notes.push(
1100
- 'Detected an existing src/enums/dict-registry.ts that MCP could not merge safely. ' +
1101
- 'MCP preserved the existing file and did not overwrite it.'
1102
- );
1103
- }
1117
+ if (sharedSupport.dictRegistry.exists && !sharedSupport.dictRegistry.isCompatible) {
1118
+ notes.push(
1119
+ 'Detected an existing src/enums/dict-registry.ts that MCP could not merge safely. ' +
1120
+ 'MCP preserved the existing file and did not overwrite it.'
1121
+ );
1122
+ }
1123
+
1124
+ if (sharedSupport.dictSemantic.exists && !sharedSupport.dictSemantic.isCompatible) {
1125
+ notes.push(
1126
+ 'Detected an existing src/enums/dict-semantic.ts that does not expose DictSemanticValues. ' +
1127
+ 'MCP preserved the existing file and did not overwrite it.'
1128
+ );
1129
+ }
1104
1130
 
1105
1131
  if (localeZhSupport.exists && !localeZhSupport.isCompatible) {
1106
1132
  notes.push(
@@ -3303,24 +3329,45 @@ function renderSingleTableDialogDictApiFunctions(model) {
3303
3329
  ].join('\n');
3304
3330
  }
3305
3331
 
3306
- function hasBusinessBillStateEditControl(model) {
3307
- return model.pageType === 'business' && !!model.statusField && model.statusDictType === 'bill_state';
3308
- }
3309
-
3310
- function renderBusinessStatusImports(model) {
3311
- return hasBusinessBillStateEditControl(model)
3312
- ? "// 业务单据编辑态判断\nimport { isBillStateEditing } from '/@/enums/dict-registry';"
3313
- : '';
3314
- }
3315
-
3316
- function renderBusinessStatusHelpers(model) {
3317
- if (!hasBusinessBillStateEditControl(model)) return '';
3318
- const statusAttr = toCamelCase(model.statusField);
3319
- return [
3320
- '// 控制业务单据编辑按钮显隐',
3321
- `const showEditAction = (row: any): boolean => isBillStateEditing(row?.${statusAttr});`,
3322
- ].join('\n');
3323
- }
3332
+ function hasBusinessBillStateEditControl(model) {
3333
+ return model.pageType === 'business' && !!model.statusField && model.statusDictType === 'bill_state';
3334
+ }
3335
+
3336
+ function renderBusinessStatusImports(model) {
3337
+ return hasBusinessBillStateEditControl(model)
3338
+ ? "// 业务单据状态枚举\nimport { DictSemanticValues } from '/@/enums/dict-semantic';"
3339
+ : '';
3340
+ }
3341
+
3342
+ function renderBusinessStatusHelpers(model) {
3343
+ if (!hasBusinessBillStateEditControl(model)) return '';
3344
+ const statusAttr = toCamelCase(model.statusField);
3345
+ return [
3346
+ '// 控制业务单据编辑按钮显隐:仅编辑中允许编辑',
3347
+ `const showEditAction = (row: any): boolean => String(row?.${statusAttr} ?? '') === DictSemanticValues.billState.editing;`,
3348
+ '',
3349
+ '// 控制业务单据删除按钮显隐:已完成不允许删除',
3350
+ `const showDeleteAction = (row: any): boolean => String(row?.${statusAttr} ?? '') !== DictSemanticValues.billState.completed;`,
3351
+ ].join('\n');
3352
+ }
3353
+
3354
+ function renderBusinessDeleteGuard(model) {
3355
+ if (!hasBusinessBillStateEditControl(model)) return '';
3356
+ const i18nNamespace = buildI18nNamespace(model);
3357
+ return [
3358
+ ' if (rows.some((row) => !showDeleteAction(row))) {',
3359
+ " useMessage().warning(t('common.messages.completedBillCannotDelete'));",
3360
+ ' return;',
3361
+ ' }',
3362
+ '',
3363
+ ].join('\n');
3364
+ }
3365
+
3366
+ function renderBusinessSubmitStatusAssignment(model) {
3367
+ if (!hasBusinessBillStateEditControl(model)) return '';
3368
+ const statusAttr = toCamelCase(model.statusField);
3369
+ return `, actionType === 'submit' ? { ${statusAttr}: DictSemanticValues.billState.completed } : {}`;
3370
+ }
3324
3371
 
3325
3372
  function sanitizeComment(value) {
3326
3373
  return String(value || '').replace(/\*\//g, '* /').replace(/\r?\n/g, ' ').trim();
@@ -3417,11 +3464,21 @@ function buildReplacements(model, sharedSupport) {
3417
3464
  LIST_ACTIONS: renderSingleTableDialogActions(model, permissionPrefix),
3418
3465
  DICT_API_IMPORTS: model.pageType === 'dict' && model.statusField ? ', enableObj, disableObj' : '',
3419
3466
  DICT_LIST_HELPERS: renderSingleTableDialogDictHelpers(model),
3420
- DICT_API_FUNCTIONS: renderSingleTableDialogDictApiFunctions(model),
3421
- BUSINESS_STATUS_IMPORTS: renderBusinessStatusImports(model),
3422
- BUSINESS_EDIT_IF: hasBusinessBillStateEditControl(model) ? ' v-if="showEditAction(row)"' : '',
3423
- BUSINESS_STATUS_HELPERS: renderBusinessStatusHelpers(model),
3424
- API_REQUEST_IMPORT: renderApiRequestImport(model),
3467
+ DICT_API_FUNCTIONS: renderSingleTableDialogDictApiFunctions(model),
3468
+ BUSINESS_STATUS_IMPORTS: renderBusinessStatusImports(model),
3469
+ BUSINESS_FORM_STATUS_IMPORTS: renderBusinessStatusImports(model),
3470
+ BUSINESS_EDIT_IF: hasBusinessBillStateEditControl(model) ? ' v-if="showEditAction(row)"' : '',
3471
+ BUSINESS_DELETE_IF: hasBusinessBillStateEditControl(model) ? ' v-if="showDeleteAction(row)"' : '',
3472
+ BUSINESS_DELETE_ROW_ARG: hasBusinessBillStateEditControl(model) ? ', [row]' : '',
3473
+ BUSINESS_SELECTED_ROWS_DECLARATION: hasBusinessBillStateEditControl(model) ? 'const selectedRows = ref<any[]>([]);' : '',
3474
+ BUSINESS_DELETE_DISABLED_EXPR: hasBusinessBillStateEditControl(model) ? ' || selectedRows.value.some((row) => !showDeleteAction(row))' : '',
3475
+ BUSINESS_DELETE_ROWS_PARAM: hasBusinessBillStateEditControl(model) ? ', rows: any[] = []' : '',
3476
+ BUSINESS_DELETE_GUARD: renderBusinessDeleteGuard(model),
3477
+ BUSINESS_SELECTED_ROWS_ARG: hasBusinessBillStateEditControl(model) ? ', selectedRows.value' : '',
3478
+ BUSINESS_SELECTED_ROWS_ASSIGNMENT: hasBusinessBillStateEditControl(model) ? ' selectedRows.value = payload.rows;' : '',
3479
+ BUSINESS_STATUS_HELPERS: renderBusinessStatusHelpers(model),
3480
+ BUSINESS_SUBMIT_STATUS_ASSIGNMENT: renderBusinessSubmitStatusAssignment(model),
3481
+ API_REQUEST_IMPORT: renderApiRequestImport(model),
3425
3482
  EXTRA_API_FUNCTIONS: renderExtraApiFunctionsV2(model),
3426
3483
  CUSTOM_QUERY_FIELDS_EXPR: model.pageType === 'dict' ? '[]' : 'queryableDictOptions.value',
3427
3484
  SHOW_RIGHT_TOOLS: model.pageType === 'dict' ? 'false' : 'true',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.70",
3
+ "version": "0.1.72",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",