worsoft-frontend-codegen-local-mcp 0.1.7 → 0.1.9
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.
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
6
6
|
<span style="font-size: 16px; font-weight: bold;">{{ form.{{PK_ATTR}} ? (detail ? t('common.viewBtn') : t('common.editBtn')) : t('common.addBtn') }}</span>
|
|
7
7
|
<div v-if="!detail">
|
|
8
|
-
<el-button @click="onSubmit('save')" :disabled="loading" icon="document">{{
|
|
9
|
-
<el-button @click="onSubmit('flow')" :disabled="loading" plain type="success" icon="position">{{
|
|
10
|
-
<el-button @click="onSubmit('submit')" :disabled="loading" type="primary" icon="check">{{
|
|
8
|
+
<el-button @click="onSubmit('save')" :disabled="loading" icon="document">{{ commonActionLabel('save') }}</el-button>
|
|
9
|
+
<el-button @click="onSubmit('flow')" :disabled="loading" plain type="success" icon="position">{{ commonActionLabel('flow') }}</el-button>
|
|
10
|
+
<el-button @click="onSubmit('submit')" :disabled="loading" type="primary" icon="check">{{ commonActionLabel('submit') }}</el-button>
|
|
11
11
|
<el-divider direction="vertical" />
|
|
12
12
|
<el-button @click="handleBack" icon="close">{{ t('common.cancelButtonText') }}</el-button>
|
|
13
13
|
</div>
|
|
14
14
|
<div v-else>
|
|
15
|
-
<el-button @click="handleBack" icon="back">{{
|
|
15
|
+
<el-button @click="handleBack" icon="back">{{ commonActionLabel('back') }}</el-button>
|
|
16
16
|
</div>
|
|
17
17
|
</div>
|
|
18
18
|
</template>
|
|
@@ -71,10 +71,10 @@ const getChildFieldLabel = (groupName: string, prop: string) => {
|
|
|
71
71
|
};
|
|
72
72
|
const childSectionTitle = (groupName: string) => t(`${pageI18nKey}.children.${groupName}.title`);
|
|
73
73
|
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
74
|
-
const inputPlaceholder = (label: string) => t(
|
|
75
|
-
const selectPlaceholder = (label: string) => t(
|
|
76
|
-
const fieldRequiredMessage = (prop: string) => t(
|
|
77
|
-
const
|
|
74
|
+
const inputPlaceholder = (label: string) => t('common.placeholders.input', { label });
|
|
75
|
+
const selectPlaceholder = (label: string) => t('common.placeholders.select', { label });
|
|
76
|
+
const fieldRequiredMessage = (prop: string) => t('common.messages.required', { label: getMasterFieldLabel(prop) });
|
|
77
|
+
const commonActionLabel = (action: string) => t('common.actions.' + action);
|
|
78
78
|
|
|
79
79
|
const form = reactive({
|
|
80
80
|
{{FORM_DEFAULTS}}
|
|
@@ -93,7 +93,7 @@ const get{{CLASS_NAME}}Data = async (id: string) => {
|
|
|
93
93
|
const { data } = await getObj({ {{PK_ATTR}}: id });
|
|
94
94
|
Object.assign(form, data[0] || {});
|
|
95
95
|
} catch (error) {
|
|
96
|
-
useMessage().error(t(
|
|
96
|
+
useMessage().error(t('common.messages.fetchError'));
|
|
97
97
|
} finally {
|
|
98
98
|
loading.value = false;
|
|
99
99
|
}
|
|
@@ -143,14 +143,14 @@ const onSubmit = async (actionType?: string) => {
|
|
|
143
143
|
try {
|
|
144
144
|
form.{{PK_ATTR}} ? await putObj(form) : await addObj(form);
|
|
145
145
|
|
|
146
|
-
let msg = form.{{PK_ATTR}} ? t(
|
|
147
|
-
if (actionType === 'submit') msg = t(
|
|
148
|
-
if (actionType === 'flow') msg = t(
|
|
146
|
+
let msg = form.{{PK_ATTR}} ? t('common.editSuccessText') : t('common.addSuccessText');
|
|
147
|
+
if (actionType === 'submit') msg = t('common.messages.quickSubmitSuccess');
|
|
148
|
+
if (actionType === 'flow') msg = t('common.messages.quickFlowSuccess');
|
|
149
149
|
|
|
150
150
|
useMessage().success(msg);
|
|
151
151
|
closeCurrentPage();
|
|
152
152
|
} catch (err: any) {
|
|
153
|
-
useMessage().error(err.msg || t(
|
|
153
|
+
useMessage().error(err.msg || t('common.messages.submitError'));
|
|
154
154
|
} finally {
|
|
155
155
|
loading.value = false;
|
|
156
156
|
}
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
<template #default="scope">
|
|
40
40
|
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(scope.row.id)">{{ t('common.viewBtn') }}</el-button>
|
|
41
41
|
<el-button icon="edit-pen" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_edit'" @click="handleEdit(scope.row.id)">{{ t('common.editBtn') }}</el-button>
|
|
42
|
-
<el-button text type="primary" icon="check" @click="handleQuickAction(scope.row, 'submit')">{{
|
|
43
|
-
<el-button text type="success" icon="position" @click="handleQuickAction(scope.row, 'flow')">{{
|
|
42
|
+
<el-button text type="primary" icon="check" @click="handleQuickAction(scope.row, 'submit')">{{ commonActionLabel('submit') }}</el-button>
|
|
43
|
+
<el-button text type="success" icon="position" @click="handleQuickAction(scope.row, 'flow')">{{ commonActionLabel('flow') }}</el-button>
|
|
44
44
|
<el-button icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([scope.row.id])">{{ t('common.delBtn') }}</el-button>
|
|
45
45
|
</template>
|
|
46
46
|
</el-table-column>
|
|
@@ -67,7 +67,6 @@ import { allDictTypes, dataMasterEntity } from './options';
|
|
|
67
67
|
const dictRefs = useDict(...allDictTypes);
|
|
68
68
|
const { t } = useI18n();
|
|
69
69
|
const router = useRouter();
|
|
70
|
-
const pageI18nKey = '{{I18N_NAMESPACE}}';
|
|
71
70
|
|
|
72
71
|
const excelUploadRef = ref();
|
|
73
72
|
const showSearch = ref(true);
|
|
@@ -85,7 +84,7 @@ const resolveLabel = (labelKey?: string, fallback = '') => {
|
|
|
85
84
|
return translated === labelKey ? fallback : translated;
|
|
86
85
|
};
|
|
87
86
|
|
|
88
|
-
const
|
|
87
|
+
const commonActionLabel = (action: string) => t('common.actions.' + action);
|
|
89
88
|
|
|
90
89
|
const visibleTableColumns = computed(() =>
|
|
91
90
|
Object.entries(dataMasterEntity)
|
|
@@ -118,13 +117,13 @@ const handleEdit = (id: string) => {
|
|
|
118
117
|
};
|
|
119
118
|
|
|
120
119
|
const handleQuickAction = async (row: any, actionType: string) => {
|
|
121
|
-
const actionName =
|
|
120
|
+
const actionName = commonActionLabel(actionType);
|
|
122
121
|
try {
|
|
123
|
-
await useMessageBox().confirm(t(
|
|
122
|
+
await useMessageBox().confirm(t('common.messages.quickActionConfirm', { action: actionName }));
|
|
124
123
|
useMessage().success(
|
|
125
124
|
actionType === 'submit'
|
|
126
|
-
? t(
|
|
127
|
-
: t(
|
|
125
|
+
? t('common.messages.quickSubmitSuccess')
|
|
126
|
+
: t('common.messages.quickFlowSuccess')
|
|
128
127
|
);
|
|
129
128
|
getDataList();
|
|
130
129
|
} catch {}
|
|
@@ -23,7 +23,6 @@ import { allDictTypes, dataMasterEntity } from './options';
|
|
|
23
23
|
|
|
24
24
|
const dictRefs = useDict(...allDictTypes);
|
|
25
25
|
const { t } = useI18n();
|
|
26
|
-
const pageI18nKey = '{{I18N_NAMESPACE}}';
|
|
27
26
|
const emit = defineEmits(['refresh']);
|
|
28
27
|
|
|
29
28
|
const dataFormRef = ref();
|
|
@@ -47,9 +46,9 @@ const getMasterFieldLabel = (prop: string) => {
|
|
|
47
46
|
return resolveLabel(config?.labelKey, config?.label || prop);
|
|
48
47
|
};
|
|
49
48
|
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
50
|
-
const inputPlaceholder = (label: string) => t(
|
|
51
|
-
const selectPlaceholder = (label: string) => t(
|
|
52
|
-
const fieldRequiredMessage = (prop: string) => t(
|
|
49
|
+
const inputPlaceholder = (label: string) => t('common.placeholders.input', { label });
|
|
50
|
+
const selectPlaceholder = (label: string) => t('common.placeholders.select', { label });
|
|
51
|
+
const fieldRequiredMessage = (prop: string) => t('common.messages.required', { label: getMasterFieldLabel(prop) });
|
|
53
52
|
|
|
54
53
|
const form = reactive({
|
|
55
54
|
{{FORM_DEFAULTS}}
|
|
@@ -65,7 +64,7 @@ const get{{CLASS_NAME}}Data = async (id: string) => {
|
|
|
65
64
|
const { data } = await getObj({ {{PK_ATTR}}: id });
|
|
66
65
|
Object.assign(form, data[0] || {});
|
|
67
66
|
} catch (error) {
|
|
68
|
-
useMessage().error(t(
|
|
67
|
+
useMessage().error(t('common.messages.fetchError'));
|
|
69
68
|
} finally {
|
|
70
69
|
loading.value = false;
|
|
71
70
|
}
|
|
@@ -101,11 +100,11 @@ const onSubmit = async () => {
|
|
|
101
100
|
|
|
102
101
|
try {
|
|
103
102
|
form.{{PK_ATTR}} ? await putObj(form) : await addObj(form);
|
|
104
|
-
useMessage().success(form.{{PK_ATTR}} ? t(
|
|
103
|
+
useMessage().success(form.{{PK_ATTR}} ? t('common.editSuccessText') : t('common.addSuccessText'));
|
|
105
104
|
visible.value = false;
|
|
106
105
|
emit('refresh');
|
|
107
106
|
} catch (err: any) {
|
|
108
|
-
useMessage().error(err.msg || t(
|
|
107
|
+
useMessage().error(err.msg || t('common.messages.submitError'));
|
|
109
108
|
} finally {
|
|
110
109
|
loading.value = false;
|
|
111
110
|
}
|
|
@@ -29,7 +29,6 @@ const dictRefs = useDict(...allDictTypes);
|
|
|
29
29
|
const { t } = useI18n();
|
|
30
30
|
const route = useRoute();
|
|
31
31
|
const router = useRouter();
|
|
32
|
-
const pageI18nKey = '{{I18N_NAMESPACE}}';
|
|
33
32
|
|
|
34
33
|
const dataFormRef = ref();
|
|
35
34
|
const loading = ref(false);
|
|
@@ -52,9 +51,9 @@ const getMasterFieldLabel = (prop: string) => {
|
|
|
52
51
|
return resolveLabel(config?.labelKey, config?.label || prop);
|
|
53
52
|
};
|
|
54
53
|
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
55
|
-
const inputPlaceholder = (label: string) => t(
|
|
56
|
-
const selectPlaceholder = (label: string) => t(
|
|
57
|
-
const fieldRequiredMessage = (prop: string) => t(
|
|
54
|
+
const inputPlaceholder = (label: string) => t('common.placeholders.input', { label });
|
|
55
|
+
const selectPlaceholder = (label: string) => t('common.placeholders.select', { label });
|
|
56
|
+
const fieldRequiredMessage = (prop: string) => t('common.messages.required', { label: getMasterFieldLabel(prop) });
|
|
58
57
|
|
|
59
58
|
const form = reactive({
|
|
60
59
|
{{FORM_DEFAULTS}}
|
|
@@ -70,7 +69,7 @@ const get{{CLASS_NAME}}Data = async (id: string) => {
|
|
|
70
69
|
const { data } = await getObj({ {{PK_ATTR}}: id });
|
|
71
70
|
Object.assign(form, data[0] || {});
|
|
72
71
|
} catch (error) {
|
|
73
|
-
useMessage().error(t(
|
|
72
|
+
useMessage().error(t('common.messages.fetchError'));
|
|
74
73
|
} finally {
|
|
75
74
|
loading.value = false;
|
|
76
75
|
}
|
|
@@ -117,10 +116,10 @@ const onSubmit = async () => {
|
|
|
117
116
|
|
|
118
117
|
try {
|
|
119
118
|
form.{{PK_ATTR}} ? await putObj(form) : await addObj(form);
|
|
120
|
-
useMessage().success(form.{{PK_ATTR}} ? t(
|
|
119
|
+
useMessage().success(form.{{PK_ATTR}} ? t('common.editSuccessText') : t('common.addSuccessText'));
|
|
121
120
|
closeCurrentPage();
|
|
122
121
|
} catch (err: any) {
|
|
123
|
-
useMessage().error(err.msg || t(
|
|
122
|
+
useMessage().error(err.msg || t('common.messages.submitError'));
|
|
124
123
|
} finally {
|
|
125
124
|
loading.value = false;
|
|
126
125
|
}
|
package/mcp_server.js
CHANGED
|
@@ -5,12 +5,12 @@ 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.9';
|
|
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');
|
|
12
12
|
const STYLE_CATALOG_PATH = path.join(__dirname, 'assets', 'style-catalog.json');
|
|
13
|
-
const DEFAULT_DESIGN_FILE = path.resolve(__dirname, '..', 'sql', 'SQL
|
|
13
|
+
const DEFAULT_DESIGN_FILE = path.resolve(__dirname, '..', 'sql', 'SQL 璁捐璇存槑.md');
|
|
14
14
|
const STYLE_CATALOG = loadStyleCatalog();
|
|
15
15
|
const DEFAULT_DICT_REGISTRY_KEYS = {
|
|
16
16
|
add_start_stop: 'COMMON_STATUS',
|
|
@@ -127,7 +127,7 @@ export function createCrudSchema(
|
|
|
127
127
|
const TOOL_SCHEMA = {
|
|
128
128
|
type: 'object',
|
|
129
129
|
properties: {
|
|
130
|
-
designFile: { type: 'string', description: 'Absolute or relative Markdown design file path. Defaults to ../sql/SQL
|
|
130
|
+
designFile: { type: 'string', description: 'Absolute or relative Markdown design file path. Defaults to ../sql/SQL 璁捐璇存槑.md when omitted.' },
|
|
131
131
|
tableName: { type: 'string', description: 'Target main table name from the design file.' },
|
|
132
132
|
style: { type: 'string', enum: Object.keys(STYLE_CATALOG), description: 'Style id from assets/style-catalog.json.' },
|
|
133
133
|
children: {
|
|
@@ -324,6 +324,30 @@ function buildI18nNamespace(model) {
|
|
|
324
324
|
return buildI18nNamespaceSegments(model).join('.');
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
function removeFeatureCommonLocaleSections(localeObject, model) {
|
|
328
|
+
if (!isPlainObject(localeObject)) {
|
|
329
|
+
return localeObject;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const segments = buildI18nNamespaceSegments(model);
|
|
333
|
+
let cursor = localeObject;
|
|
334
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
335
|
+
const segment = segments[index];
|
|
336
|
+
if (!isPlainObject(cursor[segment])) {
|
|
337
|
+
return localeObject;
|
|
338
|
+
}
|
|
339
|
+
if (index === segments.length - 1) {
|
|
340
|
+
delete cursor[segment].placeholders;
|
|
341
|
+
delete cursor[segment].actions;
|
|
342
|
+
delete cursor[segment].messages;
|
|
343
|
+
return localeObject;
|
|
344
|
+
}
|
|
345
|
+
cursor = cursor[segment];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return localeObject;
|
|
349
|
+
}
|
|
350
|
+
|
|
327
351
|
function buildFieldLabelKey(model, field) {
|
|
328
352
|
return `${buildI18nNamespace(model)}.fields.${field.attrName}`;
|
|
329
353
|
}
|
|
@@ -340,26 +364,6 @@ function buildLocaleLeaf(model) {
|
|
|
340
364
|
const leaf = {
|
|
341
365
|
title: model.tableComment,
|
|
342
366
|
fields: Object.fromEntries(model.visibleFields.map((field) => [field.attrName, stripDictAnnotation(field.comment)])),
|
|
343
|
-
placeholders: {
|
|
344
|
-
input: '请输入{label}',
|
|
345
|
-
select: '请选择{label}',
|
|
346
|
-
},
|
|
347
|
-
actions: {
|
|
348
|
-
save: '保存',
|
|
349
|
-
submit: '提交',
|
|
350
|
-
flow: '流转',
|
|
351
|
-
back: '返回',
|
|
352
|
-
},
|
|
353
|
-
messages: {
|
|
354
|
-
required: '{label}不能为空',
|
|
355
|
-
fetchError: '获取数据失败',
|
|
356
|
-
submitError: '提交失败',
|
|
357
|
-
createSuccess: '添加成功',
|
|
358
|
-
updateSuccess: '修改成功',
|
|
359
|
-
quickSubmitSuccess: '提交操作成功',
|
|
360
|
-
quickFlowSuccess: '流转操作成功',
|
|
361
|
-
quickActionConfirm: '确定要{action}该记录吗?',
|
|
362
|
-
},
|
|
363
367
|
};
|
|
364
368
|
|
|
365
369
|
if (model.children.length) {
|
|
@@ -399,7 +403,8 @@ function prepareZhCnLocaleFile(model) {
|
|
|
399
403
|
const currentObject = exists ? parseExportDefaultObject(currentContent) : null;
|
|
400
404
|
const generatedObject = buildZhCnLocaleObject(model);
|
|
401
405
|
const isCompatible = !exists || isPlainObject(currentObject);
|
|
402
|
-
const
|
|
406
|
+
const sanitizedCurrentObject = isCompatible ? removeFeatureCommonLocaleSections(currentObject || {}, model) : null;
|
|
407
|
+
const mergedObject = isCompatible ? deepMergeMissing(sanitizedCurrentObject || {}, generatedObject) : null;
|
|
403
408
|
|
|
404
409
|
return {
|
|
405
410
|
path: localePath,
|
|
@@ -544,7 +549,7 @@ function isAuditField(fieldName) {
|
|
|
544
549
|
|
|
545
550
|
function findDictType(comment) {
|
|
546
551
|
return extractDictType(comment);
|
|
547
|
-
const match = comment.match(/(
|
|
552
|
+
const match = comment.match(/(?:瀛楀吀|dict)[锛?\s]*([a-zA-Z0-9_]+)/i);
|
|
548
553
|
}
|
|
549
554
|
|
|
550
555
|
function mapFieldType(field) {
|
|
@@ -583,7 +588,7 @@ function stripDictAnnotation(label) {
|
|
|
583
588
|
return '';
|
|
584
589
|
}
|
|
585
590
|
return text
|
|
586
|
-
.replace(/\s*[
|
|
591
|
+
.replace(/\s*[锛?]\s*(?:瀛楀吀|dict)(?:绫诲瀷|type)?\s*[:锛?]?\s*[a-zA-Z0-9_-]+\s*[锛?]\s*/gi, '')
|
|
587
592
|
.replace(/\s+/g, ' ')
|
|
588
593
|
.trim();
|
|
589
594
|
}
|
|
@@ -595,9 +600,9 @@ function extractDictType(text) {
|
|
|
595
600
|
}
|
|
596
601
|
|
|
597
602
|
const patterns = [
|
|
598
|
-
/(
|
|
599
|
-
/(
|
|
600
|
-
/[
|
|
603
|
+
/(?:瀛楀吀|dict)(?:绫诲瀷|type)?\s*[:锛?]\s*([a-zA-Z0-9_-]+)/i,
|
|
604
|
+
/(?:瀛楀吀|dict)(?:绫诲瀷|type)?\s*[锛?]\s*([a-zA-Z0-9_-]+)\s*[锛?]/i,
|
|
605
|
+
/[锛?]\s*(?:瀛楀吀|dict)(?:绫诲瀷|type)?\s*[:锛?]?\s*([a-zA-Z0-9_-]+)\s*[锛?]/i,
|
|
601
606
|
];
|
|
602
607
|
|
|
603
608
|
for (const pattern of patterns) {
|
|
@@ -616,7 +621,7 @@ function resolveDictType(comment, explicitDictType) {
|
|
|
616
621
|
|
|
617
622
|
function detectDictType(comment) {
|
|
618
623
|
return extractDictType(comment);
|
|
619
|
-
return findDictType(comment) || ((comment.match(/(
|
|
624
|
+
return findDictType(comment) || ((comment.match(/(?:瀛楀吀|dict)\s*[:锛歕(锛圿?\s*([a-zA-Z0-9_]+)/i) || [])[1] ?? null);
|
|
620
625
|
}
|
|
621
626
|
|
|
622
627
|
function splitLength(value) {
|
|
@@ -638,7 +643,7 @@ function normalizeDefaultValue(value) {
|
|
|
638
643
|
|
|
639
644
|
function parseRequiredFlag(value) {
|
|
640
645
|
const normalized = String(value || '').trim().toLowerCase();
|
|
641
|
-
return ['
|
|
646
|
+
return ['鏄?, 'y', 'yes', '1', 'true', '蹇呭~'].includes(normalized);
|
|
642
647
|
}
|
|
643
648
|
|
|
644
649
|
function parseMarkdownRow(line) {
|
|
@@ -664,7 +669,7 @@ function findPrimaryKeyFromText(text, fields) {
|
|
|
664
669
|
return quotedMatch[1];
|
|
665
670
|
}
|
|
666
671
|
|
|
667
|
-
const commentPk = fields.find((field) =>
|
|
672
|
+
const commentPk = fields.find((field) => /涓婚敭/i.test(field.comment));
|
|
668
673
|
if (commentPk) {
|
|
669
674
|
return commentPk.fieldName;
|
|
670
675
|
}
|
|
@@ -697,14 +702,14 @@ function parseMarkdownTableSection(tableName, tableComment, sectionLines) {
|
|
|
697
702
|
|
|
698
703
|
const headers = rows[0];
|
|
699
704
|
const dataRows = rows.slice(1).filter((cells) => !isMarkdownSeparatorRow(cells));
|
|
700
|
-
const fieldNameIndex = findHeaderIndex(headers, [
|
|
701
|
-
const sqlTypeIndex = findHeaderIndex(headers, [
|
|
702
|
-
const lengthIndex = findHeaderIndex(headers, [
|
|
703
|
-
const requiredIndex = findHeaderIndex(headers, [
|
|
704
|
-
const defaultIndex = findHeaderIndex(headers, [
|
|
705
|
-
const commentIndex = findHeaderIndex(headers, [
|
|
705
|
+
const fieldNameIndex = findHeaderIndex(headers, [/瀛楁鍚?, /鍒楀悕/i, /field/i]);
|
|
706
|
+
const sqlTypeIndex = findHeaderIndex(headers, [/绫诲瀷/, /鏁版嵁绫诲瀷/, /type/i]);
|
|
707
|
+
const lengthIndex = findHeaderIndex(headers, [/闀垮害/, /绮惧害/, /length/i]);
|
|
708
|
+
const requiredIndex = findHeaderIndex(headers, [/蹇呭~/, /蹇呰緭/, /required/i]);
|
|
709
|
+
const defaultIndex = findHeaderIndex(headers, [/榛樿/, /default/i]);
|
|
710
|
+
const commentIndex = findHeaderIndex(headers, [/璇存槑/, /澶囨敞/, /comment/i]);
|
|
706
711
|
|
|
707
|
-
const dictTypeIndex = findHeaderIndex(headers, [
|
|
712
|
+
const dictTypeIndex = findHeaderIndex(headers, [/瀛楀吀/, /dict/i, /dict_?type/i]);
|
|
708
713
|
|
|
709
714
|
if (fieldNameIndex < 0 || sqlTypeIndex < 0) {
|
|
710
715
|
throw new Error('Markdown field table headers are missing required columns for ' + tableName);
|
|
@@ -752,7 +757,7 @@ function parseMarkdownDesignTables(markdownText) {
|
|
|
752
757
|
|
|
753
758
|
for (let index = 0; index < lines.length; index += 1) {
|
|
754
759
|
const heading = lines[index].trim();
|
|
755
|
-
const headingMatch = heading.match(/^###\s+\S+\s+([a-zA-Z0-9_]+)\s*[\(
|
|
760
|
+
const headingMatch = heading.match(/^###\s+\S+\s+([a-zA-Z0-9_]+)\s*[\(锛圿([^)\n锛塢+)[\)锛塢/);
|
|
756
761
|
if (!headingMatch) continue;
|
|
757
762
|
|
|
758
763
|
const tableName = headingMatch[1];
|
|
@@ -811,9 +816,9 @@ function parseMarkdownRelations(markdownText) {
|
|
|
811
816
|
const relations = [];
|
|
812
817
|
for (const block of blocks) {
|
|
813
818
|
const lines = block.body.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
814
|
-
const mainLine = lines.find((line) => /(
|
|
815
|
-
const childLine = lines.find((line) => /(
|
|
816
|
-
const fieldLine = lines.find((line) =>
|
|
819
|
+
const mainLine = lines.find((line) => /(涓昏〃|鐖惰〃)\s*[:锛歖/.test(line));
|
|
820
|
+
const childLine = lines.find((line) => /(浠庤〃|瀛愯〃)\s*[:锛歖/.test(line));
|
|
821
|
+
const fieldLine = lines.find((line) => /鍏宠仈瀛楁\s*[:锛歖/.test(line));
|
|
817
822
|
if (!mainLine || !childLine || !fieldLine) continue;
|
|
818
823
|
|
|
819
824
|
const mainIdentifiers = extractIdentifiersFromLine(mainLine);
|
|
@@ -821,14 +826,14 @@ function parseMarkdownRelations(markdownText) {
|
|
|
821
826
|
const fieldIdentifiers = extractIdentifiersFromLine(fieldLine);
|
|
822
827
|
if (!mainIdentifiers.length || !childIdentifiers.length || fieldIdentifiers.length < 2) continue;
|
|
823
828
|
|
|
824
|
-
const relationTypeLine = lines.find((line) =>
|
|
829
|
+
const relationTypeLine = lines.find((line) => /鍏崇郴绫诲瀷\s*[:锛歖/.test(line));
|
|
825
830
|
relations.push({
|
|
826
831
|
title: block.title,
|
|
827
832
|
mainTableName: mainIdentifiers[0],
|
|
828
833
|
childTableName: childIdentifiers[0],
|
|
829
834
|
childField: fieldIdentifiers[0],
|
|
830
835
|
mainField: fieldIdentifiers[1],
|
|
831
|
-
relationType: relationTypeLine ? relationTypeLine.split(/[
|
|
836
|
+
relationType: relationTypeLine ? relationTypeLine.split(/[:锛歖/).slice(1).join(':').trim() : '',
|
|
832
837
|
});
|
|
833
838
|
}
|
|
834
839
|
|
|
@@ -965,13 +970,13 @@ function buildRetryArguments(safeArgs, sourceFile, childTableName) {
|
|
|
965
970
|
function buildRelationCorrectionEntry(safeArgs, sourceFile, candidates, selectedChildTableName) {
|
|
966
971
|
return {
|
|
967
972
|
field: 'childTableName',
|
|
968
|
-
title: '
|
|
973
|
+
title: '涓诲瓙琛ㄥ叧鑱斾慨姝e叆鍙?,
|
|
969
974
|
tableName: safeArgs.tableName,
|
|
970
975
|
style: safeArgs.style,
|
|
971
976
|
designFile: sourceFile,
|
|
972
977
|
description: candidates.length
|
|
973
978
|
? 'If the current child relation is not the one you want, pass childTableName to choose a candidate from the design file.'
|
|
974
|
-
: 'No child relation was found. Check the
|
|
979
|
+
: 'No child relation was found. Check the 涓讳粠琛ㄥ叧鑱旇鏄?section in the design file.',
|
|
975
980
|
currentValue: selectedChildTableName || '',
|
|
976
981
|
options: candidates.map((item) => item.childTableName),
|
|
977
982
|
candidates,
|
|
@@ -1184,7 +1189,7 @@ function renderFormField(field) {
|
|
|
1184
1189
|
return [
|
|
1185
1190
|
' <el-col :span="12" class="mb20">',
|
|
1186
1191
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1187
|
-
` <el-select v-model="form.${prop}" placeholder="
|
|
1192
|
+
` <el-select v-model="form.${prop}" placeholder="璇烽€夋嫨${label}" style="width: 100%">`,
|
|
1188
1193
|
` <el-option v-for="item in ${field.dictType}" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
|
|
1189
1194
|
' </el-select>',
|
|
1190
1195
|
' </el-form-item>',
|
|
@@ -1193,12 +1198,12 @@ function renderFormField(field) {
|
|
|
1193
1198
|
}
|
|
1194
1199
|
|
|
1195
1200
|
if (field.formType === 'number') {
|
|
1196
|
-
const max = field.comment.includes('%') || field.comment.includes('
|
|
1201
|
+
const max = field.comment.includes('%') || field.comment.includes('姣斾緥') ? ' :max="100"' : '';
|
|
1197
1202
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1198
1203
|
return [
|
|
1199
1204
|
' <el-col :span="12" class="mb20">',
|
|
1200
1205
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1201
|
-
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} placeholder="
|
|
1206
|
+
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} placeholder="璇疯緭鍏?{label}" style="width: 100%" />`,
|
|
1202
1207
|
' </el-form-item>',
|
|
1203
1208
|
' </el-col>',
|
|
1204
1209
|
].join('\n');
|
|
@@ -1210,7 +1215,7 @@ function renderFormField(field) {
|
|
|
1210
1215
|
return [
|
|
1211
1216
|
' <el-col :span="12" class="mb20">',
|
|
1212
1217
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1213
|
-
` <el-date-picker type="${pickerType}" placeholder="
|
|
1218
|
+
` <el-date-picker type="${pickerType}" placeholder="璇烽€夋嫨${label}" v-model="form.${prop}" :value-format="${formatName}" style="width: 100%"></el-date-picker>`,
|
|
1214
1219
|
' </el-form-item>',
|
|
1215
1220
|
' </el-col>',
|
|
1216
1221
|
].join('\n');
|
|
@@ -1220,7 +1225,7 @@ function renderFormField(field) {
|
|
|
1220
1225
|
return [
|
|
1221
1226
|
' <el-col :span="24" class="mb20">',
|
|
1222
1227
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1223
|
-
` <el-input type="textarea" v-model="form.${prop}" placeholder="
|
|
1228
|
+
` <el-input type="textarea" v-model="form.${prop}" placeholder="璇疯緭鍏?{label}" />`,
|
|
1224
1229
|
' </el-form-item>',
|
|
1225
1230
|
' </el-col>',
|
|
1226
1231
|
].join('\n');
|
|
@@ -1229,7 +1234,7 @@ function renderFormField(field) {
|
|
|
1229
1234
|
return [
|
|
1230
1235
|
' <el-col :span="12" class="mb20">',
|
|
1231
1236
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1232
|
-
` <el-input v-model="form.${prop}" placeholder="
|
|
1237
|
+
` <el-input v-model="form.${prop}" placeholder="璇疯緭鍏?{label}" />`,
|
|
1233
1238
|
' </el-form-item>',
|
|
1234
1239
|
' </el-col>',
|
|
1235
1240
|
].join('\n');
|
|
@@ -1256,12 +1261,12 @@ function renderChildTableColumn(field, childListName) {
|
|
|
1256
1261
|
let control = ` <el-input v-model="row.${field.attrName}" />`;
|
|
1257
1262
|
if (field.formType === 'select' && field.dictType) {
|
|
1258
1263
|
control = [
|
|
1259
|
-
` <el-select v-model="row.${field.attrName}" placeholder="
|
|
1264
|
+
` <el-select v-model="row.${field.attrName}" placeholder="璇烽€夋嫨${label}" style="width: 100%">`,
|
|
1260
1265
|
` <el-option v-for="item in ${field.dictType}" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
|
|
1261
1266
|
' </el-select>',
|
|
1262
1267
|
].join('\n');
|
|
1263
1268
|
} else if (field.formType === 'number') {
|
|
1264
|
-
const max = field.comment.includes('%') || field.comment.includes('
|
|
1269
|
+
const max = field.comment.includes('%') || field.comment.includes('姣斾緥') ? ' :max="100"' : '';
|
|
1265
1270
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1266
1271
|
control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} style="width: 100%" />`;
|
|
1267
1272
|
}
|
|
@@ -1325,7 +1330,7 @@ function renderChildSection(childModel, childCount) {
|
|
|
1325
1330
|
return [
|
|
1326
1331
|
' <el-col :span="24" class="mb20">',
|
|
1327
1332
|
` <div class="mb10" style="font-weight: 600;">${title}</div>`,
|
|
1328
|
-
` <sc-form-table v-model="form.${childModel.listName}" :addTemplate="childTemp${childModel.className}" @delete="(obj) => ${deleteExpression}" placeholder="
|
|
1333
|
+
` <sc-form-table v-model="form.${childModel.listName}" :addTemplate="childTemp${childModel.className}" @delete="(obj) => ${deleteExpression}" :placeholder="t('common.noData')">`,
|
|
1329
1334
|
childModel.visibleFields.map((field) => renderChildTableColumn(field, childModel.listName)).join('\n'),
|
|
1330
1335
|
' </sc-form-table>',
|
|
1331
1336
|
' </el-col>',
|
|
@@ -1414,7 +1419,7 @@ function renderFormFieldV2(field) {
|
|
|
1414
1419
|
}
|
|
1415
1420
|
|
|
1416
1421
|
if (field.formType === 'number') {
|
|
1417
|
-
const max = field.comment.includes('%') || field.comment.includes('
|
|
1422
|
+
const max = field.comment.includes('%') || field.comment.includes('濮f柧绶?) ? ' :max="100"' : '';
|
|
1418
1423
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1419
1424
|
return [
|
|
1420
1425
|
` <el-col v-if="${visibilityExpr}" :span="12" class="mb20">`,
|
|
@@ -1485,7 +1490,7 @@ function renderChildTableColumnV2(field, childListName) {
|
|
|
1485
1490
|
' </el-select>',
|
|
1486
1491
|
].join('\n');
|
|
1487
1492
|
} else if (field.formType === 'number') {
|
|
1488
|
-
const max = field.comment.includes('%') || field.comment.includes('
|
|
1493
|
+
const max = field.comment.includes('%') || field.comment.includes('濮f柧绶?) ? ' :max="100"' : '';
|
|
1489
1494
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1490
1495
|
control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} style="width: 100%" />`;
|
|
1491
1496
|
} else if (field.formType === 'datetime' || field.formType === 'date') {
|
|
@@ -1516,7 +1521,7 @@ function renderChildSectionV2(childModel, childCount) {
|
|
|
1516
1521
|
return [
|
|
1517
1522
|
' <el-col :span="24" class="mb20">',
|
|
1518
1523
|
` <div class="mb10" style="font-weight: 600;">{{ childSectionTitle('${childModel.listName}') }}</div>`,
|
|
1519
|
-
` <sc-form-table v-model="form.${childModel.listName}" :addTemplate="childTemp${childModel.className}" @delete="(obj) => ${deleteExpression}" placeholder="
|
|
1524
|
+
` <sc-form-table v-model="form.${childModel.listName}" :addTemplate="childTemp${childModel.className}" @delete="(obj) => ${deleteExpression}" :placeholder="t('common.noData')">`,
|
|
1520
1525
|
childModel.visibleFields.map((field) => renderChildTableColumnV2(field, childModel.listName)).join('\n'),
|
|
1521
1526
|
' </sc-form-table>',
|
|
1522
1527
|
' </el-col>',
|
|
@@ -1526,7 +1531,7 @@ function renderChildSectionV2(childModel, childCount) {
|
|
|
1526
1531
|
function renderValidationRule(field) {
|
|
1527
1532
|
if (!field.notNull) return null;
|
|
1528
1533
|
const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
|
|
1529
|
-
return ` ${field.attrName}: [{ required: true, message: '${label}
|
|
1534
|
+
return ` ${field.attrName}: [{ required: true, message: '${label}涓嶈兘涓虹┖', trigger: 'blur' }],`;
|
|
1530
1535
|
}
|
|
1531
1536
|
|
|
1532
1537
|
function renderFormRules(visibleFields) {
|
|
@@ -1810,3 +1815,4 @@ function start() {
|
|
|
1810
1815
|
}
|
|
1811
1816
|
|
|
1812
1817
|
start();
|
|
1818
|
+
|
package/package.json
CHANGED