worsoft-frontend-codegen-local-mcp 0.1.42 → 0.1.44

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/README.md CHANGED
@@ -104,6 +104,7 @@ Node:
104
104
  ```bash
105
105
  node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario single
106
106
  node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario single_dialog
107
+ node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario dict_single
107
108
  node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario master
108
109
  node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario dict_multi
109
110
  ```
@@ -38,4 +38,6 @@ export function putObj(obj?: object) {
38
38
  method: 'put',
39
39
  data: obj,
40
40
  });
41
- }
41
+ }
42
+
43
+ {{DICT_API_FUNCTIONS}}
@@ -17,15 +17,14 @@
17
17
  <SchemaListTable
18
18
  v-bind="tableProps"
19
19
  row-id-key="{{PK_ATTR}}"
20
- :action-column-width="180"
20
+ :action-column-width="{{ACTION_COLUMN_WIDTH}}"
21
21
  @selection-change="handleTableSelectionChange"
22
22
  @sort-change="handleTableSortChange"
23
23
  @size-change="handleTableSizeChange"
24
24
  @current-change="handleTableCurrentChange"
25
25
  >
26
26
  <template #actions="{ row }">
27
- <el-button icon="edit-pen" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_edit'" @click="formDialogRef.openDialog(row.{{PK_ATTR}})">{{ t('common.editBtn') }}</el-button>
28
- <el-button icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}])">{{ t('common.delBtn') }}</el-button>
27
+ {{LIST_ACTIONS}}
29
28
  </template>
30
29
  </SchemaListTable>
31
30
  </div>
@@ -36,7 +35,7 @@
36
35
  </template>
37
36
 
38
37
  <script setup lang="ts" name="system{{CLASS_NAME}}">
39
- import { fetchList, delObjs } from '/@/api/{{API_MODULE_PATH}}';
38
+ import { fetchList, delObjs{{DICT_API_IMPORTS}} } from '/@/api/{{API_MODULE_PATH}}';
40
39
  import { useMessage, useMessageBox } from '/@/hooks/message';
41
40
  import { useDict } from '/@/hooks/dict';
42
41
  import { useCrudPageMeta } from '/@/hooks/useCrudPageMeta';
@@ -102,6 +101,8 @@ const tableProps = computed(() => ({
102
101
  tableStyle,
103
102
  }));
104
103
 
104
+ {{DICT_LIST_HELPERS}}
105
+
105
106
  const exportExcel = () => {
106
107
  runExportExcel(selectObjs.value);
107
108
  };
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.42';
8
+ const SERVER_VERSION = '0.1.44';
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');
@@ -1483,22 +1483,23 @@ function buildChildModels(safeArgs, mainFields, mainPk) {
1483
1483
  });
1484
1484
  }
1485
1485
 
1486
- function buildModel(safeArgs) {
1487
- if (safeArgs.style === 'multi_level_dict') {
1488
- return buildMultiLevelDictModel(safeArgs);
1489
- }
1490
-
1491
- const pkField = findPrimaryKeyFromStructuredFields(safeArgs.fields);
1492
- const fields = normalizeFields({
1493
- fields: safeArgs.fields,
1494
- });
1495
- const optionFields = fields.filter((field) => field.fieldName !== pkField.fieldName && !field.isAudit);
1496
- const visibleFields = optionFields.filter((field) => field.show !== false);
1497
- const listFields = optionFields.filter((field) => field.listShow !== false);
1498
- const gridFields = listFields.slice(0, 8);
1499
- const children = buildChildModels(safeArgs, fields, pkField);
1500
- const childDictTypes = children.flatMap((child) => child.optionFields.map((field) => field.dictType).filter(Boolean));
1501
- const dictTypes = [...new Set([...optionFields.map((field) => field.dictType).filter(Boolean), ...childDictTypes])];
1486
+ function buildModel(safeArgs) {
1487
+ if (safeArgs.style === 'multi_level_dict') {
1488
+ return buildMultiLevelDictModel(safeArgs);
1489
+ }
1490
+
1491
+ const pkField = findPrimaryKeyFromStructuredFields(safeArgs.fields);
1492
+ const fields = normalizeFields({
1493
+ fields: safeArgs.fields,
1494
+ });
1495
+ const optionFields = fields.filter((field) => field.fieldName !== pkField.fieldName && !field.isAudit);
1496
+ const visibleFields = optionFields.filter((field) => field.show !== false);
1497
+ const listFields = optionFields.filter((field) => field.listShow !== false);
1498
+ const gridFields = listFields.slice(0, 8);
1499
+ const statusField = detectStatusField(fields, safeArgs.statusField);
1500
+ const children = buildChildModels(safeArgs, fields, pkField);
1501
+ const childDictTypes = children.flatMap((child) => child.optionFields.map((field) => field.dictType).filter(Boolean));
1502
+ const dictTypes = [...new Set([...optionFields.map((field) => field.dictType).filter(Boolean), ...childDictTypes])];
1502
1503
 
1503
1504
  const derivedFunctionName = toCamelCase(safeArgs.tableName);
1504
1505
  const apiPath = safeArgs.apiPath || derivedFunctionName;
@@ -1525,14 +1526,16 @@ function buildModel(safeArgs) {
1525
1526
  pk: pkField,
1526
1527
  fields,
1527
1528
  optionFields,
1528
- visibleFields,
1529
- listFields,
1530
- gridFields,
1531
- dictTypes,
1532
- frontendPath: normalizeFrontendRootPath(safeArgs.frontendPath),
1533
- style: safeArgs.style,
1534
- children,
1535
- };
1529
+ visibleFields,
1530
+ listFields,
1531
+ gridFields,
1532
+ statusField: statusField ? statusField.fieldName : '',
1533
+ statusDictType: statusField ? statusField.dictType || '' : '',
1534
+ dictTypes,
1535
+ frontendPath: normalizeFrontendRootPath(safeArgs.frontendPath),
1536
+ style: safeArgs.style,
1537
+ children,
1538
+ };
1536
1539
  }
1537
1540
 
1538
1541
  function renderTemplate(templateText, replacements) {
@@ -2377,36 +2380,90 @@ const handleCurrentChange = (row: any) => {
2377
2380
  `;
2378
2381
  }
2379
2382
 
2380
- function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
2381
- return [
2382
- ` <div class="multi-level-slot" v-if="${levelVarName}">`,
2383
- ' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
2384
- ` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
2385
- ' </el-tabs>',
2386
- ' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
2387
- ` <LevelPanel`,
2388
- ` :columns="getListFields(${activeModuleVarName}.key)"`,
2389
- ` :dict-types="${activeModuleVarName}.dictTypes"`,
2390
- ` :data-list="moduleStateMap[${activeModuleVarName}.key].dataList"`,
2391
- ` :loading="moduleStateMap[${activeModuleVarName}.key].loading"`,
2392
- ` :add-disabled="isAddDisabled(${activeModuleVarName}.key)"`,
2393
- ` :status-field="${activeModuleVarName}.statusField"`,
2394
- ` :current-page="moduleStateMap[${activeModuleVarName}.key].currentPage"`,
2395
- ` :page-size="moduleStateMap[${activeModuleVarName}.key].pageSize"`,
2396
- ` :total="moduleStateMap[${activeModuleVarName}.key].total"`,
2397
- ` @add="openCreate(${activeModuleVarName}.key)"`,
2398
- ` @edit="openEdit(${activeModuleVarName}.key, $event)"`,
2399
- ` @delete="handleDelete(${activeModuleVarName}.key, $event)"`,
2400
- ` @enable="handleEnable(${activeModuleVarName}.key, $event)"`,
2401
- ` @disable="handleDisable(${activeModuleVarName}.key, $event)"`,
2402
- ` @current-change="handleCurrentPageChange(${activeModuleVarName}.key, $event)"`,
2403
- ` @size-change="handlePageSizeChange(${activeModuleVarName}.key, $event)"`,
2404
- ` @select-row="handleSelectRow(${activeModuleVarName}.key, $event)"`,
2405
- ' />',
2406
- ' </div>',
2407
- ` </div>`,
2408
- ].join('\n');
2409
- }
2383
+ function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
2384
+ return [
2385
+ ` <div class="multi-level-slot" v-if="${levelVarName}">`,
2386
+ ' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
2387
+ ` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
2388
+ ' </el-tabs>',
2389
+ ' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
2390
+ ' <div class="layout-padding-auto layout-padding-view flex h-full flex-col">',
2391
+ ` <SchemaListToolbar v-bind="getPanelToolbarProps(${activeModuleVarName}.key)" @add="openCreate(${activeModuleVarName}.key)" />`,
2392
+ ` <SchemaListTable`,
2393
+ ` v-bind="getPanelTableProps(${activeModuleVarName}.key)"`,
2394
+ ` @row-current-change="handlePanelCurrentChange(${activeModuleVarName}.key, $event.row)"`,
2395
+ ` @current-change="handleCurrentPageChange(${activeModuleVarName}.key, $event.current)"`,
2396
+ ` @size-change="handlePageSizeChange(${activeModuleVarName}.key, $event.size)"`,
2397
+ ` >`,
2398
+ ` <template #actions="{ row }">`,
2399
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'edit', row)" icon="edit-pen" text type="primary" @click="openEdit(${activeModuleVarName}.key, row)">{{ t('common.editBtn') }}</el-button>`,
2400
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
2401
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'enable', row)" icon="circle-check" text type="primary" @click="handleEnable(${activeModuleVarName}.key, row)">鍚敤</el-button>`,
2402
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'disable', row)" icon="remove" text type="primary" @click="handleDisable(${activeModuleVarName}.key, row)">绂佺敤</el-button>`,
2403
+ ` </template>`,
2404
+ ` </SchemaListTable>`,
2405
+ ' </div>',
2406
+ ' </div>',
2407
+ ` </div>`,
2408
+ ].join('\n');
2409
+ }
2410
+
2411
+ function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
2412
+ return [
2413
+ ` <div class="multi-level-slot" v-if="${levelVarName}">`,
2414
+ ' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
2415
+ ` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
2416
+ ' </el-tabs>',
2417
+ ' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
2418
+ ' <div class="layout-padding-auto layout-padding-view flex h-full flex-col">',
2419
+ ' <div class="mb8" style="width: 100%">',
2420
+ ` <el-button icon="folder-add" type="primary" class="ml10" :disabled="isAddDisabled(${activeModuleVarName}.key)" @click="openCreate(${activeModuleVarName}.key)">{{ t('common.addBtn') }}</el-button>`,
2421
+ ' </div>',
2422
+ ' <el-table',
2423
+ ` :data="moduleStateMap[${activeModuleVarName}.key].dataList"`,
2424
+ ` v-loading="moduleStateMap[${activeModuleVarName}.key].loading"`,
2425
+ ' border',
2426
+ ' height="100%"',
2427
+ ' highlight-current-row',
2428
+ ` @current-change="handlePanelCurrentChange(${activeModuleVarName}.key, $event)"`,
2429
+ ' >',
2430
+ ` <el-table-column type="index" :label="t('common.serial')" width="60" />`,
2431
+ ` <el-table-column`,
2432
+ ` v-for="column in getListFields(${activeModuleVarName}.key)"`,
2433
+ ' :key="column.key"',
2434
+ ' :prop="column.key"',
2435
+ ` :label="resolveLabel(column.labelKey, column.key || '')"`,
2436
+ ` :min-width="column.width || '120'"`,
2437
+ ' show-overflow-tooltip',
2438
+ ' >',
2439
+ ' <template #default="scope">',
2440
+ ' <dict-tag v-if="column.dictType" :options="getDictOptions(column.dictType)" :value="scope.row[column.key]" />',
2441
+ ' <span v-else>{{ scope.row[column.key] }}</span>',
2442
+ ' </template>',
2443
+ ' </el-table-column>',
2444
+ ` <el-table-column :label="t('common.action')" width="260">`,
2445
+ ' <template #default="{ row }">',
2446
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'edit', row)" icon="edit-pen" text type="primary" @click="openEdit(${activeModuleVarName}.key, row)">{{ t('common.editBtn') }}</el-button>`,
2447
+ ` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
2448
+ ` <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>`,
2449
+ ` <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>`,
2450
+ ' </template>',
2451
+ ' </el-table-column>',
2452
+ ' </el-table>',
2453
+ ' <div class="mt-2.5 flex shrink-0 justify-end">',
2454
+ ' <pagination',
2455
+ ` :current-page="moduleStateMap[${activeModuleVarName}.key].currentPage"`,
2456
+ ` :page-size="moduleStateMap[${activeModuleVarName}.key].pageSize"`,
2457
+ ` :total="moduleStateMap[${activeModuleVarName}.key].total"`,
2458
+ ` @current-change="handleCurrentPageChange(${activeModuleVarName}.key, $event)"`,
2459
+ ` @size-change="handlePageSizeChange(${activeModuleVarName}.key, $event)"`,
2460
+ ' />',
2461
+ ' </div>',
2462
+ ' </div>',
2463
+ ' </div>',
2464
+ ` </div>`,
2465
+ ].join('\n');
2466
+ }
2410
2467
 
2411
2468
  function renderMultiLevelIndexVue(model) {
2412
2469
  const level2 = model.levels.find((level) => level.levelIndex === 2);
@@ -2447,14 +2504,14 @@ function renderMultiLevelIndexVue(model) {
2447
2504
  <!-- \u529f\u80fd\u540d\u79f0\uFF1A${model.featureTitle.replace(/--/g, '')} -->
2448
2505
  <div class="multi-level-dict-layout">
2449
2506
  <div class="multi-level-left">
2450
- ${renderMultiLevelLevelSlot('level1Config', 'activeLevel1Key', 'activeLevel1Module')}
2507
+ ${renderMultiLevelSchemaListSlot('level1Config', 'activeLevel1Key', 'activeLevel1Module')}
2451
2508
  </div>
2452
2509
  <div class="multi-level-right">
2453
2510
  <div class="multi-level-right-top">
2454
- ${level2 ? renderMultiLevelLevelSlot('level2Config', 'activeLevel2Key', 'activeLevel2Module') : ''}
2511
+ ${level2 ? renderMultiLevelSchemaListSlot('level2Config', 'activeLevel2Key', 'activeLevel2Module') : ''}
2455
2512
  </div>
2456
2513
  <div v-if="level3Config" class="multi-level-right-bottom">
2457
- ${level3 ? renderMultiLevelLevelSlot('level3Config', 'activeLevel3Key', 'activeLevel3Module') : ''}
2514
+ ${level3 ? renderMultiLevelSchemaListSlot('level3Config', 'activeLevel3Key', 'activeLevel3Module') : ''}
2458
2515
  </div>
2459
2516
  </div>
2460
2517
  </div>
@@ -2463,14 +2520,16 @@ ${formComponents}
2463
2520
  </div>
2464
2521
  </template>
2465
2522
 
2466
- <script setup lang="ts" name="system${model.className}">
2467
- import { useMessage, useMessageBox } from '/@/hooks/message';
2468
- import { useMultiLevelDictMeta } from '/@/hooks/useMultiLevelDictMeta';
2469
- import { useMultiLevelDictPage } from '/@/hooks/useMultiLevelDictPage';
2470
- import { useI18n } from 'vue-i18n';
2471
- import LevelPanel from '/@/components/DictLevelPanel/index.vue';
2472
- import { levelConfigs, moduleConfigs } from './options';
2473
- import { ${apiImports} } from '/@/api/${model.moduleName}/${model.functionName}';
2523
+ <script setup lang="ts" name="system${model.className}">
2524
+ import { useMessage, useMessageBox } from '/@/hooks/message';
2525
+ import { useDict } from '/@/hooks/dict';
2526
+ import { useMultiLevelDictMeta } from '/@/hooks/useMultiLevelDictMeta';
2527
+ import { useMultiLevelDictPage } from '/@/hooks/useMultiLevelDictPage';
2528
+ import SchemaListToolbar from '/@/components/schema-list/SchemaListToolbar.vue';
2529
+ import SchemaListTable from '/@/components/schema-list/SchemaListTable.vue';
2530
+ import { useI18n } from 'vue-i18n';
2531
+ import { allDictTypes, levelConfigs, moduleConfigs } from './options';
2532
+ import { ${apiImports} } from '/@/api/${model.moduleName}/${model.functionName}';
2474
2533
 
2475
2534
  ${asyncImports}
2476
2535
 
@@ -2478,10 +2537,11 @@ ${formRefs}
2478
2537
  ${formRefMap}
2479
2538
  ${apiHandlerMap}
2480
2539
 
2481
- const { t } = useI18n();
2482
-
2483
- const {
2484
- level1Config,
2540
+ const { t } = useI18n();
2541
+ const dictRefs = useDict(...allDictTypes);
2542
+
2543
+ const {
2544
+ level1Config,
2485
2545
  level2Config,
2486
2546
  level3Config,
2487
2547
  activeLevel1Key,
@@ -2497,14 +2557,28 @@ const resolveLabel = (labelKey?: string, fallback = '') => {
2497
2557
  if (!labelKey) return fallback;
2498
2558
  const translated = t(labelKey);
2499
2559
  return translated === labelKey ? fallback : translated;
2500
- };
2501
-
2502
- const resolveModuleTitle = (moduleConfig: any) => resolveLabel(moduleConfig?.titleKey, moduleConfig?.key || '');
2503
-
2504
- const {
2505
- moduleStateMap,
2506
- getParentIdForModule,
2507
- getListFields,
2560
+ };
2561
+
2562
+ const resolveModuleTitle = (moduleConfig: any) => resolveLabel(moduleConfig?.titleKey, moduleConfig?.key || '');
2563
+ const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
2564
+ const isStatusEnabled = (value: any) => ['1', 1, true, 'true', 'enable', 'enabled'].includes(value);
2565
+ const isStatusNew = (value: any) => ['0', 0, false, 'false', 'new', '新增'].includes(value);
2566
+ const isStatusNewOrDisabled = (value: any) => ['0', 0, false, 'false', 'new', '新增', '2', '禁用', 'disabled'].includes(value);
2567
+ const showModuleAction = (moduleKey: string, action: 'edit' | 'delete' | 'enable' | 'disable', row: any): boolean => {
2568
+ const moduleConfig = moduleConfigs[moduleKey];
2569
+ const statusValue = moduleConfig?.statusField ? row?.[moduleConfig.statusField] : undefined;
2570
+ if (action === 'edit') return statusValue === undefined || isStatusNewOrDisabled(statusValue);
2571
+ if (action === 'delete') return statusValue === undefined || isStatusNew(statusValue);
2572
+ if (action === 'enable') return !!moduleConfig?.statusField && isStatusNewOrDisabled(statusValue);
2573
+ if (action === 'disable') return !!moduleConfig?.statusField && isStatusEnabled(statusValue);
2574
+ return false;
2575
+ };
2576
+
2577
+ const {
2578
+ moduleStateMap,
2579
+ tableStyle,
2580
+ getParentIdForModule,
2581
+ getListFields,
2508
2582
  isAddDisabled,
2509
2583
  loadModuleData,
2510
2584
  handleSelectRow,
@@ -2521,19 +2595,61 @@ const {
2521
2595
  activeLevel2Module,
2522
2596
  activeLevel3Module,
2523
2597
  getModuleLevel,
2524
- apiHandlerMap
2525
- );
2598
+ apiHandlerMap
2599
+ );
2600
+
2601
+ const getPanelColumns = (moduleKey: string) =>
2602
+ getListFields(moduleKey).map((column: any) => ({
2603
+ prop: column.key,
2604
+ label: resolveLabel(column.labelKey, column.key || ''),
2605
+ width: column.width || '120',
2606
+ dictType: column.dictType,
2607
+ options: column.dictType ? getDictOptions(column.dictType) : [],
2608
+ }));
2609
+
2610
+ const getPanelToolbarProps = (moduleKey: string) => ({
2611
+ keyword: '',
2612
+ searchPlaceholder: '',
2613
+ queryModel: {},
2614
+ selectedIds: [],
2615
+ showImport: false,
2616
+ showDelete: false,
2617
+ showQueryTools: false,
2618
+ showRightTools: false,
2619
+ deleteDisabled: true,
2620
+ addText: t('common.addBtn'),
2621
+ });
2622
+
2623
+ const getPanelTableProps = (moduleKey: string) => ({
2624
+ data: moduleStateMap[moduleKey].dataList,
2625
+ loading: !!moduleStateMap[moduleKey].loading,
2626
+ columns: getPanelColumns(moduleKey),
2627
+ pagination: {
2628
+ current: moduleStateMap[moduleKey].currentPage,
2629
+ size: moduleStateMap[moduleKey].pageSize,
2630
+ total: moduleStateMap[moduleKey].total,
2631
+ },
2632
+ tableStyle,
2633
+ rowIdKey: moduleConfigs[moduleKey].primaryKey,
2634
+ showSelection: false,
2635
+ highlightCurrentRow: true,
2636
+ actionColumnWidth: 260,
2637
+ });
2526
2638
 
2527
2639
  const openCreate = (moduleKey: string) => {
2528
2640
  formRefMap[moduleKey]?.value?.openDialog(undefined, getParentIdForModule(moduleKey));
2529
2641
  };
2530
2642
 
2531
- const openEdit = (moduleKey: string, row: any) => {
2532
- const primaryKey = moduleConfigs[moduleKey].primaryKey;
2533
- formRefMap[moduleKey]?.value?.openDialog(row?.[primaryKey], getParentIdForModule(moduleKey));
2534
- };
2535
-
2536
- const handleDelete = async (moduleKey: string, row: any) => {
2643
+ const openEdit = (moduleKey: string, row: any) => {
2644
+ const primaryKey = moduleConfigs[moduleKey].primaryKey;
2645
+ formRefMap[moduleKey]?.value?.openDialog(row?.[primaryKey], getParentIdForModule(moduleKey));
2646
+ };
2647
+
2648
+ const handlePanelCurrentChange = (moduleKey: string, row: any) => {
2649
+ if (row) handleSelectRow(moduleKey, row);
2650
+ };
2651
+
2652
+ const handleDelete = async (moduleKey: string, row: any) => {
2537
2653
  try {
2538
2654
  await useMessageBox().confirm(t('common.delConfirmText'));
2539
2655
  } catch {
@@ -2584,10 +2700,10 @@ function renderMultiLevelMenuSql(model) {
2584
2700
  ].join('\n');
2585
2701
  }
2586
2702
 
2587
- function renderMultiLevelFiles(model, sharedSupport, localeZhSupport) {
2588
- const dictRegistryRefs = sharedSupport.dictRegistry.keyByValue;
2589
- const viewRoot = buildViewRoot(model);
2590
- const apiFilePath = buildApiFilePath(model);
2703
+ function renderMultiLevelFiles(model, sharedSupport, localeZhSupport) {
2704
+ const dictRegistryRefs = sharedSupport.dictRegistry.keyByValue;
2705
+ const viewRoot = buildViewRoot(model);
2706
+ const apiFilePath = buildApiFilePath(model);
2591
2707
  const menuRoot = path.join(model.frontendPath, 'menu');
2592
2708
  const files = [
2593
2709
  { type: 'list', path: path.join(viewRoot, 'index.vue'), content: renderMultiLevelIndexVue(model) },
@@ -2610,15 +2726,90 @@ function renderMultiLevelFiles(model, sharedSupport, localeZhSupport) {
2610
2726
  content: renderMultiLevelFormVue(model, moduleModel),
2611
2727
  });
2612
2728
  });
2613
-
2614
- return files;
2615
- }
2616
-
2617
- function buildReplacements(model, sharedSupport) {
2618
- const menuBaseId = Date.now();
2619
- const apiModulePath = model.targetApiModule || `${model.moduleName}/${model.functionName}`;
2620
- const apiRoutePath = buildApiRoutePath(model.moduleName, model.apiPath || model.functionName).replace(/^\/+/, '');
2621
- const routePath = `${model.moduleName}/${model.functionName}`;
2729
+
2730
+ return files;
2731
+ }
2732
+
2733
+ function renderSingleTableDialogActions(model, permissionPrefix) {
2734
+ const pkAttr = model.pk.attrName;
2735
+ const isDictWithStatus = model.pageType === 'dict' && model.statusField;
2736
+ const lines = [
2737
+ ` <el-button${isDictWithStatus ? ` v-if="showDictAction('edit', row)"` : ''} icon="edit-pen" text type="primary" v-auth="'${permissionPrefix}_edit'" @click="formDialogRef.openDialog(row.${pkAttr})">{{ t('common.editBtn') }}</el-button>`,
2738
+ ` <el-button${isDictWithStatus ? ` v-if="showDictAction('delete', row)"` : ''} icon="delete" text type="primary" v-auth="'${permissionPrefix}_del'" @click="handleDelete([row.${pkAttr}])">{{ t('common.delBtn') }}</el-button>`,
2739
+ ];
2740
+ if (isDictWithStatus) {
2741
+ lines.push(` <el-button v-if="showDictAction('enable', row)" icon="circle-check" text type="primary" @click="handleEnable(row.${pkAttr})">{{ t('common.actions.enable') }}</el-button>`);
2742
+ lines.push(` <el-button v-if="showDictAction('disable', row)" icon="remove" text type="primary" @click="handleDisable(row.${pkAttr})">{{ t('common.actions.disable') }}</el-button>`);
2743
+ }
2744
+ return lines.join('\n');
2745
+ }
2746
+
2747
+ function renderSingleTableDialogDictHelpers(model) {
2748
+ if (model.pageType !== 'dict' || !model.statusField) return '';
2749
+ const statusField = model.statusField;
2750
+ return [
2751
+ "const isStatusEnabled = (value: any) => ['1', 1, true, 'true', 'enable', 'enabled'].includes(value);",
2752
+ "const isStatusNew = (value: any) => ['0', 0, false, 'false', 'new', '新增'].includes(value);",
2753
+ "const isStatusNewOrDisabled = (value: any) => ['0', 0, false, 'false', 'new', '新增', '2', '禁用', 'disabled'].includes(value);",
2754
+ '',
2755
+ "const showDictAction = (action: 'edit' | 'delete' | 'enable' | 'disable', row: any): boolean => {",
2756
+ ` const status = row?.${statusField};`,
2757
+ " if (action === 'edit') return isStatusNewOrDisabled(status);",
2758
+ " if (action === 'delete') return isStatusNew(status);",
2759
+ " if (action === 'enable') return isStatusNewOrDisabled(status);",
2760
+ " if (action === 'disable') return isStatusEnabled(status);",
2761
+ ' return false;',
2762
+ '};',
2763
+ '',
2764
+ 'const handleEnable = async (id: string | number) => {',
2765
+ ' try {',
2766
+ ' await enableObj(id);',
2767
+ ' getDataList();',
2768
+ " useMessage().success(t('common.messages.enableSuccess'));",
2769
+ ' } catch (err: any) {',
2770
+ " useMessage().error(err.msg || t('common.messages.enableError'));",
2771
+ ' }',
2772
+ '};',
2773
+ '',
2774
+ 'const handleDisable = async (id: string | number) => {',
2775
+ ' try {',
2776
+ ' await disableObj(id);',
2777
+ ' getDataList();',
2778
+ " useMessage().success(t('common.messages.disableSuccess'));",
2779
+ ' } catch (err: any) {',
2780
+ " useMessage().error(err.msg || t('common.messages.disableError'));",
2781
+ ' }',
2782
+ '};',
2783
+ ].join('\n');
2784
+ }
2785
+
2786
+ function renderSingleTableDialogDictApiFunctions(model) {
2787
+ if (model.pageType !== 'dict' || !model.statusField) return '';
2788
+ const apiRoutePath = buildApiRoutePath(model.moduleName, model.apiPath || model.functionName).replace(/^\/+/, '');
2789
+ return [
2790
+ "export function enableObj(id: string | number) {",
2791
+ ' return request({',
2792
+ ` url: '/${apiRoutePath}/enable',`,
2793
+ " method: 'post',",
2794
+ ' params: { id },',
2795
+ ' });',
2796
+ '}',
2797
+ '',
2798
+ "export function disableObj(id: string | number) {",
2799
+ ' return request({',
2800
+ ` url: '/${apiRoutePath}/disable',`,
2801
+ " method: 'post',",
2802
+ ' params: { id },',
2803
+ ' });',
2804
+ '}',
2805
+ ].join('\n');
2806
+ }
2807
+
2808
+ function buildReplacements(model, sharedSupport) {
2809
+ const menuBaseId = Date.now();
2810
+ const apiModulePath = model.targetApiModule || `${model.moduleName}/${model.functionName}`;
2811
+ const apiRoutePath = buildApiRoutePath(model.moduleName, model.apiPath || model.functionName).replace(/^\/+/, '');
2812
+ const routePath = `${model.moduleName}/${model.functionName}`;
2622
2813
  const permissionPrefix = `${model.moduleName}/${model.functionName}`.replace(/\//g, '_');
2623
2814
  const dictRegistryRefs = sharedSupport.dictRegistry.keyByValue;
2624
2815
  const i18nNamespace = buildI18nNamespace(model);
@@ -2633,12 +2824,17 @@ function buildReplacements(model, sharedSupport) {
2633
2824
  API_MODULE_PATH: apiModulePath,
2634
2825
  API_PATH: apiRoutePath,
2635
2826
  VIEW_MODULE_PATH: routePath,
2636
- MENU_ROUTE_PATH: routePath,
2637
- I18N_NAMESPACE: i18nNamespace,
2638
- PERMISSION_PREFIX: permissionPrefix,
2639
- MENU_BASE_ID: menuBaseId,
2640
- MENU_BASE_ID_PLUS_1: menuBaseId + 1,
2641
- MENU_BASE_ID_PLUS_2: menuBaseId + 2,
2827
+ MENU_ROUTE_PATH: routePath,
2828
+ I18N_NAMESPACE: i18nNamespace,
2829
+ PERMISSION_PREFIX: permissionPrefix,
2830
+ ACTION_COLUMN_WIDTH: model.pageType === 'dict' && model.statusField ? 300 : 180,
2831
+ LIST_ACTIONS: renderSingleTableDialogActions(model, permissionPrefix),
2832
+ DICT_API_IMPORTS: model.pageType === 'dict' && model.statusField ? ', enableObj, disableObj' : '',
2833
+ DICT_LIST_HELPERS: renderSingleTableDialogDictHelpers(model),
2834
+ DICT_API_FUNCTIONS: renderSingleTableDialogDictApiFunctions(model),
2835
+ MENU_BASE_ID: menuBaseId,
2836
+ MENU_BASE_ID_PLUS_1: menuBaseId + 1,
2837
+ MENU_BASE_ID_PLUS_2: menuBaseId + 2,
2642
2838
  MENU_BASE_ID_PLUS_3: menuBaseId + 3,
2643
2839
  MENU_BASE_ID_PLUS_4: menuBaseId + 4,
2644
2840
  MENU_BASE_ID_PLUS_5: menuBaseId + 5,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",