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
|
-
|
|
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
|
-
|
|
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.
|
|
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 !== '
|
|
2188
|
+
if (width !== '100') {
|
|
2120
2189
|
parts.push(`width: '${width}'`);
|
|
2121
2190
|
}
|
|
2122
2191
|
|
package/package.json
CHANGED