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

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.
@@ -38,11 +38,11 @@
38
38
 
39
39
  <script setup lang="ts" name="{{CLASS_NAME}}Form">
40
40
  // 标签页关闭总线
41
- import mittBus from '/@/utils/mitt';
42
41
  // 本地会话存储
43
42
  import { Session } from '/@/utils/storage';
44
43
  // 通用消息提示
45
44
  import { useMessage } from '/@/hooks/message';
45
+ import { useCloseCurrentPage } from '/@/hooks/useCloseCurrentPage';
46
46
  // 表单数据接口
47
47
  import { getObj, addObj, putObj } from '/@/api/{{API_MODULE_PATH}}';
48
48
  // 字典数据加载
@@ -65,6 +65,7 @@ const scFormTable = defineAsyncComponent(() => import('/@/components/FormTable/i
65
65
  const route = useRoute();
66
66
  // 路由跳转能力
67
67
  const router = useRouter();
68
+ const { closeCurrentPage } = useCloseCurrentPage();
68
69
  // 当前页面的国际化命名空间
69
70
  const pageI18nKey = '{{I18N_NAMESPACE}}';
70
71
 
@@ -146,14 +147,9 @@ const initPage = async () => {
146
147
  }
147
148
  };
148
149
 
149
- // 关闭当前标签页
150
- const closeCurrentPage = () => {
151
- mittBus.emit('onCurrentContextmenuClick', { contextMenuClickId: 1, ...route });
152
- };
153
-
154
150
  // 返回上一页
155
151
  const handleBack = () => {
156
- router.back();
152
+ closeCurrentPage();
157
153
  };
158
154
 
159
155
  // 保存、提交和流转共用同一套提交逻辑
@@ -34,11 +34,11 @@
34
34
 
35
35
  <script setup lang="ts" name="{{CLASS_NAME}}Form">
36
36
  // 标签页关闭总线
37
- import mittBus from '/@/utils/mitt';
38
37
  // 本地会话存储
39
38
  import { Session } from '/@/utils/storage';
40
39
  // 通用消息提示
41
40
  import { useMessage } from '/@/hooks/message';
41
+ import { useCloseCurrentPage } from '/@/hooks/useCloseCurrentPage';
42
42
  // 表单数据接口
43
43
  import { getObj, addObj, putObj } from '/@/api/{{API_MODULE_PATH}}';
44
44
  // 字典数据加载
@@ -58,6 +58,7 @@ const { t } = useI18n();
58
58
  const route = useRoute();
59
59
  // 路由跳转能力
60
60
  const router = useRouter();
61
+ const { closeCurrentPage } = useCloseCurrentPage();
61
62
 
62
63
  // 表单引用
63
64
  const dataFormRef = ref();
@@ -128,14 +129,9 @@ const initPage = async () => {
128
129
  }
129
130
  };
130
131
 
131
- // 关闭当前标签页
132
- const closeCurrentPage = () => {
133
- mittBus.emit('onCurrentContextmenuClick', { contextMenuClickId: 1, ...route });
134
- };
135
-
136
132
  // 返回上一页
137
133
  const handleBack = () => {
138
- router.back();
134
+ closeCurrentPage();
139
135
  };
140
136
 
141
137
  // 保存、提交和流转共用同一套提交逻辑
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.69';
8
+ const SERVER_VERSION = '0.1.70';
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,6 +204,34 @@ 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';
210
+
211
+ export const closeCurrentRoutePage = (route: RouteLocationNormalizedLoaded) => {
212
+ \tmittBus.emit('onCurrentContextmenuClick', {
213
+ \t\tcontextMenuClickId: 1,
214
+ \t\tpath: route.path,
215
+ \t\tquery: { ...route.query },
216
+ \t\tparams: { ...route.params },
217
+ \t\tmeta: { ...route.meta },
218
+ \t\tname: route.name,
219
+ \t});
220
+ };
221
+
222
+ export function useCloseCurrentPage() {
223
+ \tconst route = useRoute();
224
+
225
+ \tconst closeCurrentPage = () => {
226
+ \t\tcloseCurrentRoutePage(route);
227
+ \t};
228
+
229
+ \treturn {
230
+ \t\tcloseCurrentPage,
231
+ \t};
232
+ }
233
+ `;
234
+
207
235
  const TOOL_SCHEMA = {
208
236
  type: 'object',
209
237
  properties: {
@@ -925,6 +953,21 @@ function ensureCrudFactorySupportFile(frontendPath) {
925
953
  };
926
954
  }
927
955
 
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');
961
+
962
+ return {
963
+ path: hookPath,
964
+ content: DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE,
965
+ exists,
966
+ isCompatible,
967
+ needsWrite: !exists,
968
+ };
969
+ }
970
+
928
971
  function ensureDirectory(filePath) {
929
972
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
930
973
  }
@@ -971,10 +1014,22 @@ function prepareSharedSupport(frontendPath, dictTypes, writeSupportFiles) {
971
1014
  needsWrite: false,
972
1015
  writeEnabled: false,
973
1016
  };
1017
+ 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,
1023
+ exists: fs.existsSync(closeCurrentPagePath),
1024
+ isCompatible: true,
1025
+ needsWrite: false,
1026
+ writeEnabled: false,
1027
+ };
974
1028
  return {
975
1029
  dictRegistry,
976
1030
  crudSchema,
977
1031
  crudFactory,
1032
+ closeCurrentPage,
978
1033
  writeEnabled: Boolean(writeSupportFiles),
979
1034
  };
980
1035
  }
@@ -1005,6 +1060,16 @@ function maybeWriteSharedSupport(sharedSupport, writeToDisk) {
1005
1060
  }
1006
1061
  writeSupportFile(sharedSupport.dictRegistry.path, sharedSupport.dictRegistry.content);
1007
1062
  }
1063
+
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.'
1069
+ );
1070
+ }
1071
+ writeSupportFile(sharedSupport.closeCurrentPage.path, sharedSupport.closeCurrentPage.content);
1072
+ }
1008
1073
  }
1009
1074
 
1010
1075
  function buildSupportNote(sharedSupport, localeZhSupport) {
@@ -1012,7 +1077,7 @@ function buildSupportNote(sharedSupport, localeZhSupport) {
1012
1077
 
1013
1078
  if (!sharedSupport.writeEnabled) {
1014
1079
  notes.push(
1015
- 'Shared support file writing is disabled. Generated code still references src/utils/crudSchema.ts, src/api/common/crudFactory.ts and may reference src/enums/dict-registry.ts, so those helpers must already exist in the target project.'
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.'
1016
1081
  );
1017
1082
  }
1018
1083
 
@@ -1306,7 +1371,7 @@ function normalizeStructuredField(inputField, index, contextLabel) {
1306
1371
  throw new Error(contextLabel + '[' + index + '] is missing required field: type');
1307
1372
  }
1308
1373
 
1309
- const { length, scale } = normalizeStructuredLengthAndScale(inputField.length, inputField.scale);
1374
+ const { length, scale } = normalizeStructuredLengthAndScale(inputField.length ?? inputField.maxLength, inputField.scale);
1310
1375
  const explicitFormType = normalizeStructuredFormType(inputField.formType || inputField.componentType);
1311
1376
  const formType = type === 'DATE' && explicitFormType === 'datetime' ? 'date' : explicitFormType;
1312
1377
  const explicitQueryType =
@@ -1968,9 +2033,13 @@ function renderChildTableColumn(field, childListName) {
1968
2033
  const selectPlaceholderExpr = `formSelectPlaceholder(${labelExpr}, ${renderDisabledBoolV2(field)})`;
1969
2034
  const disabledAttr = renderDisabledAttrV2(field);
1970
2035
 
1971
- let control = ` <el-input v-model="row.${field.attrName}" :placeholder="${inputPlaceholderExpr}"${disabledAttr} />`;
2036
+ let control = ` <el-input v-model="row.${field.attrName}"${renderTextMaxlengthAttrV2(field)} :placeholder="${inputPlaceholderExpr}"${disabledAttr} />`;
1972
2037
  if (field.formType === 'upload') {
1973
2038
  control = ` <UploadFile v-model="row.${field.attrName}"${disabledAttr} />`;
2039
+ } else if (field.formType === 'datetime' || field.formType === 'date') {
2040
+ const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
2041
+ const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
2042
+ control = ` <el-date-picker type="${pickerType}" :placeholder="${inputPlaceholderExpr}" v-model="row.${field.attrName}" :value-format="${formatName}" style="width: 100%"${disabledAttr}></el-date-picker>`;
1974
2043
  } else if (field.formType === 'select' && field.dictType) {
1975
2044
  control = [
1976
2045
  ` <el-select v-model="row.${field.attrName}" :placeholder="${selectPlaceholderExpr}" style="width: 100%"${disabledAttr}>`,
@@ -2116,7 +2185,7 @@ function renderOptionFieldV2(field, labelKey, dictRegistryRefs, indent = ' ')
2116
2185
  const prdWidth = field.width ? field.width.replace('px', '') : null;
2117
2186
  const width = prdWidth || getDefaultOptionFieldWidthV2(field);
2118
2187
 
2119
- if (width !== '120') {
2188
+ if (width !== '100') {
2120
2189
  parts.push(`width: '${width}'`);
2121
2190
  }
2122
2191
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",