worsoft-frontend-codegen-local-mcp 0.1.22 → 0.1.24

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.
Files changed (2) hide show
  1. package/mcp_server.js +142 -104
  2. package/package.json +1 -1
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.22';
8
+ const SERVER_VERSION = '0.1.24';
9
9
  const PROTOCOL_VERSION = '2024-11-05';
10
10
  const TOOL_NAME = 'worsoft_codegen_local_generate_frontend';
11
11
  const TEMPLATE_LIBRARY_ROOT = path.resolve(__dirname, '..', 'template');
@@ -16,25 +16,27 @@ const DEFAULT_DICT_REGISTRY_KEYS = {
16
16
  trade_standard_type: 'TRADE_STANDARD_TYPE',
17
17
  trade_score_standard: 'TRADE_SCORE_STANDARD',
18
18
  };
19
- const DEFAULT_CRUD_SCHEMA_TEMPLATE = `export interface FieldMeta {
20
- show: boolean;
21
- alwaysHide: boolean;
22
- smart: boolean;
23
- labelKey: string;
19
+ const DEFAULT_CRUD_SCHEMA_TEMPLATE = `export interface FieldMeta {
20
+ show: boolean;
21
+ listShow: boolean;
22
+ alwaysHide: boolean;
23
+ smart: boolean;
24
+ labelKey: string;
24
25
  label?: string;
25
26
  width: string;
26
27
  dictType?: string;
27
28
  }
28
29
 
29
- export interface FieldConfig {
30
- key: string;
31
- labelKey?: string;
32
- label?: string;
33
- width?: string;
34
- show?: boolean;
35
- alwaysHide?: boolean;
36
- smart?: boolean;
37
- dictType?: string;
30
+ export interface FieldConfig {
31
+ key: string;
32
+ labelKey?: string;
33
+ label?: string;
34
+ width?: string;
35
+ show?: boolean;
36
+ listShow?: boolean;
37
+ alwaysHide?: boolean;
38
+ smart?: boolean;
39
+ dictType?: string;
38
40
  }
39
41
 
40
42
  export interface CrudSchemaDefinition {
@@ -52,11 +54,12 @@ export interface CrudSchema {
52
54
 
53
55
  const DEFAULT_WIDTH = '120';
54
56
 
55
- export const field = (labelKey: string, width = DEFAULT_WIDTH): FieldMeta => ({
56
- show: true,
57
- alwaysHide: false,
58
- smart: false,
59
- labelKey,
57
+ export const field = (labelKey: string, width = DEFAULT_WIDTH): FieldMeta => ({
58
+ show: true,
59
+ listShow: true,
60
+ alwaysHide: false,
61
+ smart: false,
62
+ labelKey,
60
63
  width,
61
64
  });
62
65
 
@@ -79,10 +82,11 @@ export const collectDictTypes = (...groups: Array<Record<string, FieldMeta>>) =>
79
82
  )
80
83
  );
81
84
 
82
- const normalizeField = (item: FieldConfig): FieldMeta => ({
83
- show: item.show ?? true,
84
- alwaysHide: item.alwaysHide ?? false,
85
- smart: item.smart ?? false,
85
+ const normalizeField = (item: FieldConfig): FieldMeta => ({
86
+ show: item.show ?? true,
87
+ listShow: item.listShow ?? item.show ?? true,
88
+ alwaysHide: item.alwaysHide ?? false,
89
+ smart: item.smart ?? false,
86
90
  labelKey: item.labelKey ?? item.label ?? item.key,
87
91
  ...(item.label ? { label: item.label } : {}),
88
92
  width: item.width ?? DEFAULT_WIDTH,
@@ -145,6 +149,7 @@ const TOOL_SCHEMA = {
145
149
  required: { type: ['boolean', 'string'], description: 'Whether the field is required.' },
146
150
  readonly: { type: ['boolean', 'string'], description: 'Whether the field is readonly on the page.' },
147
151
  show: { type: ['boolean', 'string'], description: 'Whether the field is shown on the page.' },
152
+ listShow: { type: ['boolean', 'string'], description: 'Whether the field is shown on the list page.' },
148
153
  dictType: { type: 'string', description: 'Dictionary type code from the API document.' },
149
154
  defaultValue: { type: ['string', 'number', 'boolean'], description: 'Optional default value.' },
150
155
  description: { type: 'string', description: 'Field description or notes.' },
@@ -181,6 +186,7 @@ const TOOL_SCHEMA = {
181
186
  required: { type: ['boolean', 'string'], description: 'Whether the field is required.' },
182
187
  readonly: { type: ['boolean', 'string'], description: 'Whether the field is readonly on the page.' },
183
188
  show: { type: ['boolean', 'string'], description: 'Whether the field is shown on the page.' },
189
+ listShow: { type: ['boolean', 'string'], description: 'Whether the field is shown on the list page.' },
184
190
  dictType: { type: 'string', description: 'Dictionary type code from the API document.' },
185
191
  defaultValue: { type: ['string', 'number', 'boolean'], description: 'Optional default value.' },
186
192
  description: { type: 'string', description: 'Field description or notes.' },
@@ -428,20 +434,20 @@ function buildChildSectionTitleKey(model, childModel) {
428
434
  return `${buildI18nNamespace(model)}.children.${childModel.listName}.title`;
429
435
  }
430
436
 
431
- function buildLocaleLeaf(model) {
432
- const leaf = {
433
- title: model.tableComment,
434
- fields: Object.fromEntries(model.visibleFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
435
- };
437
+ function buildLocaleLeaf(model) {
438
+ const leaf = {
439
+ title: model.tableComment,
440
+ fields: Object.fromEntries(model.optionFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
441
+ };
436
442
 
437
443
  if (model.children.length) {
438
444
  leaf.children = Object.fromEntries(
439
445
  model.children.map((childModel) => [
440
446
  childModel.listName,
441
- {
442
- title: childModel.tableComment,
443
- fields: Object.fromEntries(childModel.visibleFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
444
- },
447
+ {
448
+ title: childModel.tableComment,
449
+ fields: Object.fromEntries(childModel.optionFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
450
+ },
445
451
  ])
446
452
  );
447
453
  }
@@ -778,6 +784,7 @@ function normalizeStructuredField(inputField, index, contextLabel) {
778
784
  defaultValue: normalizeDefaultValue(inputField.defaultValue),
779
785
  readonly: parseBooleanLike(inputField.readonly, false),
780
786
  show: parseBooleanLike(inputField.show, true),
787
+ listShow: parseBooleanLike(inputField.listShow, parseBooleanLike(inputField.show, true)),
781
788
  sourceKind: normalizeStructuredSourceKind(inputField.sourceKind),
782
789
  primary: parseBooleanLike(inputField.primary, fieldName === 'id'),
783
790
  };
@@ -903,9 +910,10 @@ function buildChildModels(safeArgs, mainFields, mainPk) {
903
910
  });
904
911
  const mainRelationField = ensureFieldExists(mainFields, relation.mainField, safeArgs.tableName, 'Main relation');
905
912
  const childRelationField = ensureFieldExists(childFields, relation.childField, relation.childTableName, 'Child relation');
906
- const childVisibleFields = childFields.filter(
907
- (field) => field.fieldName !== childPk.fieldName && !field.isAudit && field.fieldName !== relation.childField && field.show !== false
913
+ const childOptionFields = childFields.filter(
914
+ (field) => field.fieldName !== childPk.fieldName && !field.isAudit && field.fieldName !== relation.childField
908
915
  );
916
+ const childVisibleFields = childOptionFields.filter((field) => field.show !== false);
909
917
  const payloadField = relation.payloadField;
910
918
  const listName = payloadField;
911
919
 
@@ -919,6 +927,7 @@ function buildChildModels(safeArgs, mainFields, mainPk) {
919
927
  payloadFieldSource: 'arguments',
920
928
  pk: childPk,
921
929
  fields: childFields,
930
+ optionFields: childOptionFields,
922
931
  visibleFields: childVisibleFields,
923
932
  mainField: mainRelationField,
924
933
  childField: childRelationField,
@@ -932,11 +941,13 @@ function buildModel(safeArgs) {
932
941
  const fields = normalizeFields({
933
942
  fields: safeArgs.fields,
934
943
  });
935
- const visibleFields = fields.filter((field) => field.fieldName !== pkField.fieldName && !field.isAudit && field.show !== false);
936
- const gridFields = visibleFields.slice(0, 8);
944
+ const optionFields = fields.filter((field) => field.fieldName !== pkField.fieldName && !field.isAudit);
945
+ const visibleFields = optionFields.filter((field) => field.show !== false);
946
+ const listFields = optionFields.filter((field) => field.listShow !== false);
947
+ const gridFields = listFields.slice(0, 8);
937
948
  const children = buildChildModels(safeArgs, fields, pkField);
938
- const childDictTypes = children.flatMap((child) => child.visibleFields.map((field) => field.dictType).filter(Boolean));
939
- const dictTypes = [...new Set([...visibleFields.map((field) => field.dictType).filter(Boolean), ...childDictTypes])];
949
+ const childDictTypes = children.flatMap((child) => child.optionFields.map((field) => field.dictType).filter(Boolean));
950
+ const dictTypes = [...new Set([...optionFields.map((field) => field.dictType).filter(Boolean), ...childDictTypes])];
940
951
 
941
952
  const functionName = toCamelCase(safeArgs.tableName);
942
953
  const apiPath = safeArgs.apiPath || functionName;
@@ -950,7 +961,9 @@ function buildModel(safeArgs) {
950
961
  moduleName: normalizeModulePathForFeature(safeArgs.moduleName, functionName, apiPath),
951
962
  pk: pkField,
952
963
  fields,
964
+ optionFields,
953
965
  visibleFields,
966
+ listFields,
954
967
  gridFields,
955
968
  dictTypes,
956
969
  frontendPath: path.resolve(safeArgs.frontendPath),
@@ -1211,27 +1224,34 @@ function getDefaultOptionFieldWidthV2(field) {
1211
1224
  return '100';
1212
1225
  }
1213
1226
 
1214
- function renderOptionFieldV2(field, labelKey, dictRegistryRefs, indent = ' ') {
1215
- const parts = [`key: '${field.attrName}'`, `labelKey: '${labelKey}'`];
1227
+ function renderOptionFieldV2(field, labelKey, dictRegistryRefs, indent = ' ') {
1228
+ const fallbackLabel = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
1229
+ const parts = [`key: '${field.attrName}'`, `labelKey: '${labelKey}'`, `label: '${fallbackLabel}'`];
1216
1230
  const width = getDefaultOptionFieldWidthV2(field);
1217
1231
 
1218
1232
  if (width !== '120') {
1219
1233
  parts.push(`width: '${width}'`);
1220
1234
  }
1221
1235
 
1222
- if (field.dictType) {
1223
- parts.push(`dictType: ${getDictRegistryReference(field.dictType, dictRegistryRefs)}`);
1224
- }
1225
-
1226
- return `${indent}{ ${parts.join(', ')} },`;
1227
- }
1236
+ if (field.dictType) {
1237
+ parts.push(`dictType: ${getDictRegistryReference(field.dictType, dictRegistryRefs)}`);
1238
+ }
1239
+ if (field.show === false) {
1240
+ parts.push('show: false');
1241
+ }
1242
+ if (field.listShow === false) {
1243
+ parts.push('listShow: false');
1244
+ }
1245
+
1246
+ return `${indent}{ ${parts.join(', ')} },`;
1247
+ }
1228
1248
 
1229
1249
  function renderChildOptionGroupV2(model, childModel, dictRegistryRefs) {
1230
1250
  return [
1231
1251
  ` ${childModel.listName}: [`,
1232
- childModel.visibleFields
1233
- .map((field) => renderOptionFieldV2(field, buildChildFieldLabelKey(model, childModel, field), dictRegistryRefs, ' '))
1234
- .join('\n'),
1252
+ childModel.optionFields
1253
+ .map((field) => renderOptionFieldV2(field, buildChildFieldLabelKey(model, childModel, field), dictRegistryRefs, ' '))
1254
+ .join('\n'),
1235
1255
  ' ],',
1236
1256
  ].join('\n');
1237
1257
  }
@@ -1249,21 +1269,32 @@ function renderTextareaMaxlengthAttrsV2(field) {
1249
1269
  if (!field.length) return '';
1250
1270
  return ` :maxlength="${field.length}" show-word-limit`;
1251
1271
  }
1252
-
1272
+
1273
+ function renderDisabledAttrV2(field) {
1274
+ return field.readonly ? ' disabled' : '';
1275
+ }
1276
+
1277
+ function renderFieldCommentV2(field, indent = ' ') {
1278
+ const label = stripDictAnnotation(field.comment || field.attrName).replace(/-->/g, '').trim() || field.attrName;
1279
+ return `${indent}<!-- 字段:${label} -->`;
1280
+ }
1281
+
1253
1282
  function renderFormFieldV2(field) {
1254
1283
  const prop = field.attrName;
1255
1284
  const labelExpr = `getMasterFieldLabel('${prop}')`;
1256
1285
  const dictExpr = `getMasterFieldMeta('${prop}')?.dictType`;
1286
+ const disabledAttr = renderDisabledAttrV2(field);
1257
1287
 
1258
1288
  if (field.formType === 'select') {
1259
1289
  return [
1290
+ renderFieldCommentV2(field),
1260
1291
  ` <el-col :span="12" class="mb20">`,
1261
1292
  ` <el-form-item :label="${labelExpr}" prop="${prop}">`,
1262
- ` <el-select v-model="form.${prop}" :placeholder="selectPlaceholder(${labelExpr})" style="width: 100%">`,
1293
+ ` <el-select v-model="form.${prop}" :placeholder="selectPlaceholder(${labelExpr})" style="width: 100%"${disabledAttr}>`,
1263
1294
  ` <el-option v-for="item in getDictOptions(${dictExpr})" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
1264
- ' </el-select>',
1265
- ' </el-form-item>',
1266
- ' </el-col>',
1295
+ ' </el-select>',
1296
+ ' </el-form-item>',
1297
+ ' </el-col>',
1267
1298
  ].join('\n');
1268
1299
  }
1269
1300
 
@@ -1271,46 +1302,50 @@ function renderFormFieldV2(field) {
1271
1302
  const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
1272
1303
  const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
1273
1304
  return [
1305
+ renderFieldCommentV2(field),
1274
1306
  ` <el-col :span="12" class="mb20">`,
1275
1307
  ` <el-form-item :label="${labelExpr}" prop="${prop}">`,
1276
- ` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} :placeholder="inputPlaceholder(${labelExpr})" style="width: 100%" />`,
1308
+ ` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} :placeholder="inputPlaceholder(${labelExpr})" style="width: 100%"${disabledAttr} />`,
1277
1309
  ' </el-form-item>',
1278
- ' </el-col>',
1279
- ].join('\n');
1280
- }
1281
-
1310
+ ' </el-col>',
1311
+ ].join('\n');
1312
+ }
1313
+
1282
1314
  if (field.formType === 'datetime' || field.formType === 'date') {
1283
1315
  const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
1284
1316
  const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
1285
1317
  return [
1318
+ renderFieldCommentV2(field),
1286
1319
  ` <el-col :span="12" class="mb20">`,
1287
1320
  ` <el-form-item :label="${labelExpr}" prop="${prop}">`,
1288
- ` <el-date-picker type="${pickerType}" :placeholder="inputPlaceholder(${labelExpr})" v-model="form.${prop}" :value-format="${formatName}" style="width: 100%"></el-date-picker>`,
1321
+ ` <el-date-picker type="${pickerType}" :placeholder="inputPlaceholder(${labelExpr})" v-model="form.${prop}" :value-format="${formatName}" style="width: 100%"${disabledAttr}></el-date-picker>`,
1289
1322
  ' </el-form-item>',
1290
- ' </el-col>',
1291
- ].join('\n');
1292
- }
1293
-
1323
+ ' </el-col>',
1324
+ ].join('\n');
1325
+ }
1326
+
1294
1327
  if (field.formType === 'textarea') {
1295
1328
  const textareaAttrs = renderTextareaMaxlengthAttrsV2(field);
1296
1329
  return [
1330
+ renderFieldCommentV2(field),
1297
1331
  ` <el-col :span="24" class="mb20">`,
1298
1332
  ` <el-form-item :label="${labelExpr}" prop="${prop}">`,
1299
- ` <el-input type="textarea" v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${textareaAttrs} />`,
1333
+ ` <el-input type="textarea" v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${textareaAttrs}${disabledAttr} />`,
1300
1334
  ' </el-form-item>',
1301
- ' </el-col>',
1302
- ].join('\n');
1303
- }
1304
-
1335
+ ' </el-col>',
1336
+ ].join('\n');
1337
+ }
1338
+
1305
1339
  const maxlengthAttr = renderInputMaxlengthAttr(field);
1306
1340
  return [
1341
+ renderFieldCommentV2(field),
1307
1342
  ` <el-col :span="12" class="mb20">`,
1308
1343
  ` <el-form-item :label="${labelExpr}" prop="${prop}">`,
1309
- ` <el-input v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${maxlengthAttr} />`,
1344
+ ` <el-input v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${maxlengthAttr}${disabledAttr} />`,
1310
1345
  ' </el-form-item>',
1311
- ' </el-col>',
1312
- ].join('\n');
1313
- }
1346
+ ' </el-col>',
1347
+ ].join('\n');
1348
+ }
1314
1349
 
1315
1350
  function renderTableColumnV2(field, dictRegistryRefs) {
1316
1351
  const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
@@ -1328,34 +1363,36 @@ function renderTableColumnV2(field, dictRegistryRefs) {
1328
1363
  return ` { ${parts.join(', ')} },`;
1329
1364
  }
1330
1365
 
1331
- function renderChildTableColumnV2(field, childListName) {
1332
- const rules = field.notNull ? ` :rules="[{ required: true, trigger: 'blur' }]"` : '';
1333
- const labelExpr = `getChildFieldLabel('${childListName}', '${field.attrName}')`;
1334
- const dictExpr = `getChildFieldMeta('${childListName}', '${field.attrName}')?.dictType`;
1335
-
1336
- let control = ` <el-input v-model="row.${field.attrName}" :placeholder="inputPlaceholder(${labelExpr})"${renderTextMaxlengthAttrV2(field)} />`;
1337
- if (field.formType === 'select' && field.dictType) {
1338
- control = [
1339
- ` <el-select v-model="row.${field.attrName}" :placeholder="selectPlaceholder(${labelExpr})" style="width: 100%">`,
1340
- ` <el-option v-for="item in getDictOptions(${dictExpr})" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
1341
- ' </el-select>',
1342
- ].join('\n');
1343
- } else if (field.formType === 'number') {
1344
- const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
1345
- const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
1346
- control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} style="width: 100%" />`;
1347
- } else if (field.formType === 'datetime' || field.formType === 'date') {
1348
- const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
1349
- const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
1350
- control = ` <el-date-picker type="${pickerType}" v-model="row.${field.attrName}" :value-format="${formatName}" :placeholder="inputPlaceholder(${labelExpr})" style="width: 100%"></el-date-picker>`;
1351
- } else if (field.formType === 'textarea') {
1352
- control = ` <el-input type="textarea" v-model="row.${field.attrName}" :placeholder="inputPlaceholder(${labelExpr})"${renderTextareaMaxlengthAttrsV2(field)} />`;
1353
- }
1354
-
1355
- return [
1356
- ` <el-table-column :label="${labelExpr}" prop="${field.attrName}">`,
1357
- ' <template #default="{ row, $index }">',
1358
- ` <el-form-item :prop="\`${childListName}.\${$index}.${field.attrName}\`"${rules}>`,
1366
+ function renderChildTableColumnV2(field, childListName) {
1367
+ const rules = field.notNull ? ` :rules="[{ required: true, trigger: 'blur' }]"` : '';
1368
+ const labelExpr = `getChildFieldLabel('${childListName}', '${field.attrName}')`;
1369
+ const dictExpr = `getChildFieldMeta('${childListName}', '${field.attrName}')?.dictType`;
1370
+ const disabledAttr = renderDisabledAttrV2(field);
1371
+
1372
+ let control = ` <el-input v-model="row.${field.attrName}" :placeholder="inputPlaceholder(${labelExpr})"${renderTextMaxlengthAttrV2(field)}${disabledAttr} />`;
1373
+ if (field.formType === 'select' && field.dictType) {
1374
+ control = [
1375
+ ` <el-select v-model="row.${field.attrName}" :placeholder="selectPlaceholder(${labelExpr})" style="width: 100%"${disabledAttr}>`,
1376
+ ` <el-option v-for="item in getDictOptions(${dictExpr})" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
1377
+ ' </el-select>',
1378
+ ].join('\n');
1379
+ } else if (field.formType === 'number') {
1380
+ const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
1381
+ const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
1382
+ control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} style="width: 100%"${disabledAttr} />`;
1383
+ } else if (field.formType === 'datetime' || field.formType === 'date') {
1384
+ const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
1385
+ const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
1386
+ control = ` <el-date-picker type="${pickerType}" v-model="row.${field.attrName}" :value-format="${formatName}" :placeholder="inputPlaceholder(${labelExpr})" style="width: 100%"${disabledAttr}></el-date-picker>`;
1387
+ } else if (field.formType === 'textarea') {
1388
+ control = ` <el-input type="textarea" v-model="row.${field.attrName}" :placeholder="inputPlaceholder(${labelExpr})"${renderTextareaMaxlengthAttrsV2(field)}${disabledAttr} />`;
1389
+ }
1390
+
1391
+ return [
1392
+ renderFieldCommentV2(field, ' '),
1393
+ ` <el-table-column :label="${labelExpr}" prop="${field.attrName}">`,
1394
+ ' <template #default="{ row, $index }">',
1395
+ ` <el-form-item :prop="\`${childListName}.\${$index}.${field.attrName}\`"${rules}>`,
1359
1396
  control,
1360
1397
  ' </el-form-item>',
1361
1398
  ' </template>',
@@ -1426,7 +1463,7 @@ function buildReplacements(model, sharedSupport) {
1426
1463
  TABLE_COLUMNS: model.gridFields.map((field) => renderTableColumnV2(field, dictRegistryRefs)).join('\n'),
1427
1464
  FORM_DEFAULTS: renderFormDefaults(model),
1428
1465
  DICT_REGISTRY_IMPORT_BLOCK: model.dictTypes.length ? "import { DictRegistry } from '/@/enums/dict-registry';" : '',
1429
- MASTER_OPTION_FIELDS: model.visibleFields.map((field) => renderOptionFieldV2(field, buildFieldLabelKey(model, field), dictRegistryRefs)).join('\n'),
1466
+ MASTER_OPTION_FIELDS: model.optionFields.map((field) => renderOptionFieldV2(field, buildFieldLabelKey(model, field), dictRegistryRefs)).join('\n'),
1430
1467
  CHILD_OPTION_GROUPS: model.children.map((childModel) => renderChildOptionGroupV2(model, childModel, dictRegistryRefs)).join('\n'),
1431
1468
  FORM_RULES: renderFormRulesV2(model.visibleFields),
1432
1469
  CHILD_FORM_LIST_DEFAULTS: renderChildFormListDefaults(model.children),
@@ -1565,7 +1602,8 @@ function buildManifest(model, safeArgs, stylePreset, sharedTemplates, files, not
1565
1602
  summary: {
1566
1603
  totalFields: model.fields.length,
1567
1604
  visibleFields: model.visibleFields.length,
1568
- dictFields: model.visibleFields.filter((field) => field.dictType).map((field) => field.attrName),
1605
+ listVisibleFields: model.listFields.length,
1606
+ dictFields: model.optionFields.filter((field) => field.dictType).map((field) => field.attrName),
1569
1607
  skippedAuditFields: model.fields.filter((field) => field.isAudit).map((field) => field.fieldName),
1570
1608
  childCount: model.children.length,
1571
1609
  childTables: model.children.map((childModel) => childModel.tableName),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",