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

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.
@@ -48,6 +48,7 @@ import { fetchList, delObjs{{DICT_API_IMPORTS}} } from '/@/api/{{API_MODULE_PATH
48
48
  import { useMessage, useMessageBox } from '/@/hooks/message';
49
49
  // 字典数据加载
50
50
  import { useDict } from '/@/hooks/dict';
51
+ {{DICT_SEMANTIC_IMPORT_BLOCK}}
51
52
  // 列表页字段元数据能力
52
53
  import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
53
54
  // 列表页查询与分页状态
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.72';
8
+ const SERVER_VERSION = '0.1.77';
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');
@@ -243,6 +243,11 @@ export const DictSemanticValues = {
243
243
  terminated: '3',
244
244
  completed: '4',
245
245
  },
246
+ addStartStop: {
247
+ added: '0',
248
+ started: '1',
249
+ disabled: '2',
250
+ },
246
251
  } as const;
247
252
  `;
248
253
 
@@ -1341,20 +1346,27 @@ function normalizeStructuredLengthAndScale(lengthValue, scaleValue) {
1341
1346
  };
1342
1347
  }
1343
1348
 
1344
- function parseOptionalOrder(value, label) {
1345
- if (value === undefined || value === null || value === '') return undefined;
1346
- const order = Number.parseInt(String(value), 10);
1347
- if (Number.isNaN(order) || order < 0) {
1348
- throw new Error(`${label} must be a positive integer when provided, or 0/empty when unspecified`);
1349
+ function parseOptionalOrder(value, label) {
1350
+ if (value === undefined || value === null || value === '') return undefined;
1351
+ const order = Number.parseInt(String(value), 10);
1352
+ if (Number.isNaN(order) || order < 0) {
1353
+ throw new Error(`${label} must be a positive integer when provided, or 0/empty when unspecified`);
1349
1354
  }
1350
- if (order === 0) return undefined;
1351
- return order;
1352
- }
1353
-
1354
- function sortFieldsForForm(fields) {
1355
- const seenOrders = new Map();
1356
- fields
1357
- .filter((field) => field.formShow !== false && !field.primary)
1355
+ if (order === 0) return undefined;
1356
+ return order;
1357
+ }
1358
+
1359
+ function normalizeOptionWidth(value) {
1360
+ if (value === undefined || value === null) return '';
1361
+ const normalized = String(value).trim();
1362
+ if (!normalized || normalized === '-' || normalized === '/') return '';
1363
+ return normalized.replace(/px$/i, '');
1364
+ }
1365
+
1366
+ function sortFieldsForForm(fields) {
1367
+ const seenOrders = new Map();
1368
+ fields
1369
+ .filter((field) => field.formShow !== false && !field.primary)
1358
1370
  .forEach((field) => {
1359
1371
  if (field.formOrder === undefined) return;
1360
1372
  const existing = seenOrders.get(field.formOrder);
@@ -1398,8 +1410,8 @@ function normalizeStructuredField(inputField, index, contextLabel) {
1398
1410
  }
1399
1411
 
1400
1412
  const { length, scale } = normalizeStructuredLengthAndScale(inputField.length ?? inputField.maxLength, inputField.scale);
1401
- const explicitFormType = normalizeStructuredFormType(inputField.formType || inputField.componentType);
1402
- const formType = type === 'DATE' && explicitFormType === 'datetime' ? 'date' : explicitFormType;
1413
+ const explicitFormType = normalizeStructuredFormType(inputField.formType || inputField.componentType);
1414
+ const formType = explicitFormType;
1403
1415
  const explicitQueryType =
1404
1416
  inputField.queryType === undefined || inputField.queryType === null || inputField.queryType === ''
1405
1417
  ? undefined
@@ -1422,16 +1434,17 @@ function normalizeStructuredField(inputField, index, contextLabel) {
1422
1434
  dictType: normalizeDictType(inputField.dictType),
1423
1435
  notNull: parseBooleanLike(inputField.required, false),
1424
1436
  defaultValue: normalizeDefaultValue(inputField.defaultValue),
1425
- readonly: parseBooleanLike(inputField.readonly ?? inputField.disabled, false),
1437
+ readonly: parseBooleanLike(inputField.readonly, false),
1426
1438
  show,
1427
1439
  listShow,
1428
- formShow,
1429
- formOrder,
1430
- smart: parseBooleanLike(inputField.smart, false),
1431
- queryType: Number.isNaN(explicitQueryType)
1432
- ? undefined
1433
- : explicitQueryType !== undefined
1434
- ? explicitQueryType
1440
+ formShow,
1441
+ formOrder,
1442
+ width: normalizeOptionWidth(inputField.width),
1443
+ smart: parseBooleanLike(inputField.smart, false),
1444
+ queryType: Number.isNaN(explicitQueryType)
1445
+ ? undefined
1446
+ : explicitQueryType !== undefined
1447
+ ? explicitQueryType
1435
1448
  : normalizeDictType(inputField.dictType) && listShow
1436
1449
  ? 30
1437
1450
  : undefined,
@@ -2101,15 +2114,17 @@ function renderFilterType(field) {
2101
2114
  return ` ${field.attrName}: 30,`;
2102
2115
  }
2103
2116
 
2104
- function renderDefaultLine(field) {
2105
- if (field.attrName === 'createUserId') return ` ${field.attrName}: Session.getUserId(),`;
2106
- if (field.attrName === 'createUser') return ` ${field.attrName}: Session.getUsername(),`;
2107
- if (field.attrName === 'billDate') return ` ${field.attrName}: moment(new Date()).format('YYYY-MM-DD'),`;
2108
- if (field.attrName === 'billStateId' || field.fieldName === 'bill_state_id') return ` ${field.attrName}: '0',`;
2109
- if (field.attrName === 'createTime') return ` ${field.attrName}: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),`;
2110
- if (field.formType === 'number' || field.formType === 'microme-operator') return ` ${field.attrName}: 0,`;
2111
- return ` ${field.attrName}: '',`;
2112
- }
2117
+ function renderDefaultLine(field, options = {}) {
2118
+ if (field.attrName === 'createUserId') return ` ${field.attrName}: Session.getUserId(),`;
2119
+ if (field.attrName === 'createUser') return ` ${field.attrName}: Session.getUsername(),`;
2120
+ if (field.attrName === 'billDate') return ` ${field.attrName}: moment(new Date()).format('YYYY-MM-DD'),`;
2121
+ if (field.attrName === 'billStateId' || field.fieldName === 'bill_state_id') {
2122
+ return options.useDictSemantic ? ` ${field.attrName}: DictSemanticValues.billState.editing,` : ` ${field.attrName}: '',`;
2123
+ }
2124
+ if (field.attrName === 'createTime') return ` ${field.attrName}: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),`;
2125
+ if (field.formType === 'number' || field.formType === 'microme-operator') return ` ${field.attrName}: 0,`;
2126
+ return ` ${field.attrName}: '',`;
2127
+ }
2113
2128
 
2114
2129
  function renderFormRulesV2(fields) {
2115
2130
  return fields
@@ -2118,13 +2133,14 @@ function renderFormRulesV2(fields) {
2118
2133
  .join('\n');
2119
2134
  }
2120
2135
 
2121
- function renderFormDefaults(model) {
2122
- const lines = [` ${model.pk.attrName}: '',`];
2123
- for (const field of model.fields.filter((item) => item.fieldName !== model.pk.fieldName && !item.isAudit)) lines.push(renderDefaultLine(field));
2124
- lines.push(` version: 1,`);
2125
- lines.push(` tenantId: Session.getTenant(),`);
2126
- return lines.join('\n');
2127
- }
2136
+ function renderFormDefaults(model) {
2137
+ const lines = [` ${model.pk.attrName}: '',`];
2138
+ const useDictSemantic = hasBusinessBillStateEditControl(model);
2139
+ for (const field of model.fields.filter((item) => item.fieldName !== model.pk.fieldName && !item.isAudit)) lines.push(renderDefaultLine(field, { useDictSemantic }));
2140
+ lines.push(` version: 1,`);
2141
+ lines.push(` tenantId: Session.getTenant(),`);
2142
+ return lines.join('\n');
2143
+ }
2128
2144
 
2129
2145
  function renderChildTempDefaults(childModel) {
2130
2146
  if (!childModel) return '';
@@ -2205,15 +2221,15 @@ function includesAnyLabel(label, values) {
2205
2221
  function getDefaultOptionFieldWidthV2(field) {
2206
2222
  return '100';
2207
2223
  }
2208
- function renderOptionFieldV2(field, labelKey, dictRegistryRefs, indent = ' ') {
2209
- const fallbackLabel = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
2210
- const parts = [`key: '${field.attrName}'`, `labelKey: '${labelKey}'`, `label: '${fallbackLabel}'`];
2211
- const prdWidth = field.width ? field.width.replace('px', '') : null;
2212
- const width = prdWidth || getDefaultOptionFieldWidthV2(field);
2213
-
2214
- if (width !== '100') {
2215
- parts.push(`width: '${width}'`);
2216
- }
2224
+ function renderOptionFieldV2(field, labelKey, dictRegistryRefs, indent = ' ') {
2225
+ const fallbackLabel = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
2226
+ const parts = [`key: '${field.attrName}'`, `labelKey: '${labelKey}'`, `label: '${fallbackLabel}'`];
2227
+ const prdWidth = normalizeOptionWidth(field.width);
2228
+ const width = prdWidth || getDefaultOptionFieldWidthV2(field);
2229
+
2230
+ if (prdWidth || width !== '100') {
2231
+ parts.push(`width: '${width}'`);
2232
+ }
2217
2233
 
2218
2234
  if (field.dictType) {
2219
2235
  parts.push(`dictType: ${getDictRegistryReference(field.dictType, dictRegistryRefs)}`);
@@ -2836,9 +2852,9 @@ function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeMo
2836
2852
  ' <!-- 删除当前字典数据 -->',
2837
2853
  ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
2838
2854
  ' <!-- 启用当前字典数据 -->',
2839
- ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'enable', row)" icon="circle-check" text type="primary" @click="handleEnable(${activeModuleVarName}.key, row)">闁告凹鍨抽弫?/el-button>`,
2855
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'enable', row)" icon="circle-check" text type="primary" @click="handleEnable(${activeModuleVarName}.key, row)">{{ t('common.actions.enable') }}</el-button>`,
2840
2856
  ' <!-- 禁用当前字典数据 -->',
2841
- ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'disable', row)" icon="remove" text type="primary" @click="handleDisable(${activeModuleVarName}.key, row)">缂佸倷鑳堕弫?/el-button>`,
2857
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'disable', row)" icon="remove" text type="primary" @click="handleDisable(${activeModuleVarName}.key, row)">{{ t('common.actions.disable') }}</el-button>`,
2842
2858
  ` </template>`,
2843
2859
  ` </SchemaListTable>`,
2844
2860
  ' </div>',
@@ -2981,10 +2997,12 @@ ${formComponents}
2981
2997
  <script setup lang="ts" name="system${model.className}">
2982
2998
  // 通用消息与确认弹窗
2983
2999
  import { useMessage, useMessageBox } from '/@/hooks/message';
2984
- // 字典数据加载
2985
- import { useDict } from '/@/hooks/dict';
2986
- // 多层字典元数据能力
2987
- import { useMultiLevelDictMeta } from '/@/hooks/useMultiLevelDictMeta';
3000
+ // 字典数据加载
3001
+ import { useDict } from '/@/hooks/dict';
3002
+ // 字典语义值
3003
+ import { DictSemanticValues } from '/@/enums/dict-semantic';
3004
+ // 多层字典元数据能力
3005
+ import { useMultiLevelDictMeta } from '/@/hooks/useMultiLevelDictMeta';
2988
3006
  // 多层字典页面状态能力
2989
3007
  import { useMultiLevelDictPage } from '/@/hooks/useMultiLevelDictPage';
2990
3008
  // 统一列表工具栏组件
@@ -3037,10 +3055,12 @@ const {
3037
3055
  const resolveModuleTitle = (moduleConfig: any) => resolveLabel(moduleConfig?.titleKey, moduleConfig?.key || '');
3038
3056
  // 读取字典选项
3039
3057
  const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
3040
- // 判断状态是否为启用
3041
- const isStatusEnabled = (value: any) => ['1', 1, true, 'true', 'enable', 'enabled'].includes(value);
3042
- const isStatusNew = (value: any) => ['0', 0, false, 'false', 'new', '閺傛澘顤?].includes(value);
3043
- const isStatusNewOrDisabled = (value: any) => ['0', 0, false, 'false', 'new', '閺傛澘顤?, '2', '缁備胶鏁?, 'disabled'].includes(value);
3058
+ // 规范化字典状态值
3059
+ const normalizeStatusValue = (value: any) => String(value ?? '');
3060
+ // 判断状态是否为启用
3061
+ const isStatusEnabled = (value: any) => normalizeStatusValue(value) === DictSemanticValues.addStartStop.started;
3062
+ const isStatusNew = (value: any) => normalizeStatusValue(value) === DictSemanticValues.addStartStop.added;
3063
+ const isStatusNewOrDisabled = (value: any) => [DictSemanticValues.addStartStop.added, DictSemanticValues.addStartStop.disabled].includes(normalizeStatusValue(value));
3044
3064
  // 控制行内动作按钮显隐
3045
3065
  const showModuleAction = (moduleKey: string, action: 'edit' | 'delete' | 'enable' | 'disable', row: any): boolean => {
3046
3066
  const moduleConfig = moduleConfigs[moduleKey];
@@ -3262,14 +3282,16 @@ function renderSingleTableDialogActions(model, permissionPrefix) {
3262
3282
  return lines.join('\n');
3263
3283
  }
3264
3284
 
3265
- function renderSingleTableDialogDictHelpers(model) {
3266
- if (model.pageType !== 'dict' || !model.statusField) return '';
3267
- const statusField = model.statusField;
3268
- return [
3269
- "// 判断状态是否为启用",
3270
- "const isStatusEnabled = (value: any) => ['1', 1, true, 'true', 'enable', 'enabled'].includes(value);",
3271
- "const isStatusNew = (value: any) => ['0', 0, false, 'false', 'new', '閺傛澘顤?].includes(value);",
3272
- "const isStatusNewOrDisabled = (value: any) => ['0', 0, false, 'false', 'new', '閺傛澘顤?, '2', '缁備胶鏁?, 'disabled'].includes(value);",
3285
+ function renderSingleTableDialogDictHelpers(model) {
3286
+ if (model.pageType !== 'dict' || !model.statusField) return '';
3287
+ const statusField = model.statusField;
3288
+ return [
3289
+ "// 规范化字典状态值",
3290
+ "const normalizeStatusValue = (value: any) => String(value ?? '');",
3291
+ "// 判断状态是否为启用",
3292
+ "const isStatusEnabled = (value: any) => normalizeStatusValue(value) === DictSemanticValues.addStartStop.started;",
3293
+ "const isStatusNew = (value: any) => normalizeStatusValue(value) === DictSemanticValues.addStartStop.added;",
3294
+ "const isStatusNewOrDisabled = (value: any) => [DictSemanticValues.addStartStop.added, DictSemanticValues.addStartStop.disabled].includes(normalizeStatusValue(value));",
3273
3295
  '',
3274
3296
  "// 控制字典列表动作按钮显隐",
3275
3297
  "const showDictAction = (action: 'edit' | 'delete' | 'enable' | 'disable', row: any): boolean => {",
@@ -3461,9 +3483,10 @@ function buildReplacements(model, sharedSupport) {
3461
3483
  I18N_NAMESPACE: i18nNamespace,
3462
3484
  PERMISSION_PREFIX: permissionPrefix,
3463
3485
  ACTION_COLUMN_WIDTH: model.pageType === 'dict' && model.statusField ? 300 : 180,
3464
- LIST_ACTIONS: renderSingleTableDialogActions(model, permissionPrefix),
3465
- DICT_API_IMPORTS: model.pageType === 'dict' && model.statusField ? ', enableObj, disableObj' : '',
3466
- DICT_LIST_HELPERS: renderSingleTableDialogDictHelpers(model),
3486
+ LIST_ACTIONS: renderSingleTableDialogActions(model, permissionPrefix),
3487
+ DICT_API_IMPORTS: model.pageType === 'dict' && model.statusField ? ', enableObj, disableObj' : '',
3488
+ DICT_SEMANTIC_IMPORT_BLOCK: model.pageType === 'dict' && model.statusField ? "// 字典语义值\nimport { DictSemanticValues } from '/@/enums/dict-semantic';" : '',
3489
+ DICT_LIST_HELPERS: renderSingleTableDialogDictHelpers(model),
3467
3490
  DICT_API_FUNCTIONS: renderSingleTableDialogDictApiFunctions(model),
3468
3491
  BUSINESS_STATUS_IMPORTS: renderBusinessStatusImports(model),
3469
3492
  BUSINESS_FORM_STATUS_IMPORTS: renderBusinessStatusImports(model),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.72",
3
+ "version": "0.1.77",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",