worsoft-frontend-codegen-local-mcp 0.1.11 → 0.1.12
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/mcp_server.js +50 -94
- package/package.json +1 -1
package/mcp_server.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
|
-
const SERVER_NAME = 'worsoft-codegen-local';
|
|
8
|
-
const SERVER_VERSION = '0.1.
|
|
7
|
+
const SERVER_NAME = 'worsoft-codegen-local';
|
|
8
|
+
const SERVER_VERSION = '0.1.12';
|
|
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');
|
|
@@ -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: {
|
|
@@ -549,7 +549,6 @@ function isAuditField(fieldName) {
|
|
|
549
549
|
|
|
550
550
|
function findDictType(comment) {
|
|
551
551
|
return extractDictType(comment);
|
|
552
|
-
const match = comment.match(/(?:闁诲孩绋掗〃鍛村触閳х憢dict)[闂?\s]*([a-zA-Z0-9_]+)/i);
|
|
553
552
|
}
|
|
554
553
|
|
|
555
554
|
function mapFieldType(field) {
|
|
@@ -588,7 +587,7 @@ function stripDictAnnotation(label) {
|
|
|
588
587
|
return '';
|
|
589
588
|
}
|
|
590
589
|
return text
|
|
591
|
-
.replace(/\s*[\(
|
|
590
|
+
.replace(/\s*[\(\uFF08][^()\uFF08\uFF09]*?(?:\u5B57\u5178|dict)(?:[_\s-]*type)?[^()\uFF08\uFF09]*?[\)\uFF09]\s*/gi, '')
|
|
592
591
|
.replace(/\s+/g, ' ')
|
|
593
592
|
.trim();
|
|
594
593
|
}
|
|
@@ -600,8 +599,8 @@ function extractDictType(text) {
|
|
|
600
599
|
}
|
|
601
600
|
|
|
602
601
|
const patterns = [
|
|
603
|
-
/(
|
|
604
|
-
/[\(
|
|
602
|
+
/(?:\u5B57\u5178|dict)(?:[_\s-]*type)?\s*[:\uFF1A]\s*([a-zA-Z0-9_-]+)/i,
|
|
603
|
+
/[\(\uFF08]\s*(?:\u5B57\u5178|dict)(?:[_\s-]*type)?\s*[:\uFF1A]?\s*([a-zA-Z0-9_-]+)\s*[\)\uFF09]/i,
|
|
605
604
|
];
|
|
606
605
|
|
|
607
606
|
for (const pattern of patterns) {
|
|
@@ -641,7 +640,7 @@ function normalizeDefaultValue(value) {
|
|
|
641
640
|
|
|
642
641
|
function parseRequiredFlag(value) {
|
|
643
642
|
const normalized = String(value || '').trim().toLowerCase();
|
|
644
|
-
return ['
|
|
643
|
+
return ['y', 'yes', '1', 'true', 'required'].includes(normalized);
|
|
645
644
|
}
|
|
646
645
|
|
|
647
646
|
function parseMarkdownRow(line) {
|
|
@@ -667,7 +666,7 @@ function findPrimaryKeyFromText(text, fields) {
|
|
|
667
666
|
return quotedMatch[1];
|
|
668
667
|
}
|
|
669
668
|
|
|
670
|
-
const commentPk = fields.find((field) =>
|
|
669
|
+
const commentPk = fields.find((field) => /主键|primary\s+key|\bpk\b/i.test(field.comment));
|
|
671
670
|
if (commentPk) {
|
|
672
671
|
return commentPk.fieldName;
|
|
673
672
|
}
|
|
@@ -700,14 +699,14 @@ function parseMarkdownTableSection(tableName, tableComment, sectionLines) {
|
|
|
700
699
|
|
|
701
700
|
const headers = rows[0];
|
|
702
701
|
const dataRows = rows.slice(1).filter((cells) => !isMarkdownSeparatorRow(cells));
|
|
703
|
-
const fieldNameIndex = findHeaderIndex(headers, [
|
|
704
|
-
const sqlTypeIndex = findHeaderIndex(headers, [
|
|
705
|
-
const lengthIndex = findHeaderIndex(headers, [
|
|
706
|
-
const requiredIndex = findHeaderIndex(headers, [
|
|
707
|
-
const defaultIndex = findHeaderIndex(headers, [
|
|
708
|
-
const commentIndex = findHeaderIndex(headers, [
|
|
702
|
+
const fieldNameIndex = findHeaderIndex(headers, [/field/i, /\u5B57\u6BB5/i, /\u5B57\u6BB5\u540D/i, /\u5217\u540D/i]);
|
|
703
|
+
const sqlTypeIndex = findHeaderIndex(headers, [/type/i, /\u7C7B\u578B/i, /\u5B57\u6BB5\u7C7B\u578B/i, /\u6570\u636E\u7C7B\u578B/i]);
|
|
704
|
+
const lengthIndex = findHeaderIndex(headers, [/length/i, /\u957F\u5EA6/i, /\u5B57\u6BB5\u957F\u5EA6/i]);
|
|
705
|
+
const requiredIndex = findHeaderIndex(headers, [/required/i, /\u5FC5\u586B/i, /\u662F\u5426\u5FC5\u586B/i, /\u4E0D\u80FD\u4E3A\u7A7A/i]);
|
|
706
|
+
const defaultIndex = findHeaderIndex(headers, [/default/i, /\u9ED8\u8BA4/i, /\u9ED8\u8BA4\u503C/i]);
|
|
707
|
+
const commentIndex = findHeaderIndex(headers, [/comment/i, /\u5907\u6CE8/i, /\u8BF4\u660E/i, /\u5B57\u6BB5\u8BF4\u660E/i]);
|
|
709
708
|
|
|
710
|
-
const dictTypeIndex = findHeaderIndex(headers, [
|
|
709
|
+
const dictTypeIndex = findHeaderIndex(headers, [/dict/i, /dict_?type/i, /\u5B57\u5178/i, /\u5B57\u5178\u7C7B\u578B/i]);
|
|
711
710
|
|
|
712
711
|
if (fieldNameIndex < 0 || sqlTypeIndex < 0) {
|
|
713
712
|
throw new Error('Markdown field table headers are missing required columns for ' + tableName);
|
|
@@ -755,7 +754,7 @@ function parseMarkdownDesignTables(markdownText) {
|
|
|
755
754
|
|
|
756
755
|
for (let index = 0; index < lines.length; index += 1) {
|
|
757
756
|
const heading = lines[index].trim();
|
|
758
|
-
const headingMatch = heading.match(/^###\s+\S+\s+([a-zA-Z0-9_]+)\s*[\(
|
|
757
|
+
const headingMatch = heading.match(/^###\s+\S+\s+([a-zA-Z0-9_]+)\s*[\(\uFF08]([^)\n\uFF09]+)[\)\uFF09]/);
|
|
759
758
|
if (!headingMatch) continue;
|
|
760
759
|
|
|
761
760
|
const tableName = headingMatch[1];
|
|
@@ -785,59 +784,10 @@ function stripMarkdownSyntax(text) {
|
|
|
785
784
|
.replace(/\r\n?/g, '\n');
|
|
786
785
|
}
|
|
787
786
|
|
|
788
|
-
function parseMarkdownRelations(markdownText) {
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
let current = null;
|
|
793
|
-
let match = headingRegex.exec(text);
|
|
794
|
-
|
|
795
|
-
while (match) {
|
|
796
|
-
if (current) {
|
|
797
|
-
current.body = text.slice(current.start, match.index);
|
|
798
|
-
blocks.push(current);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
current = {
|
|
802
|
-
title: match[2].trim(),
|
|
803
|
-
start: headingRegex.lastIndex,
|
|
804
|
-
body: '',
|
|
805
|
-
};
|
|
806
|
-
match = headingRegex.exec(text);
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
if (current) {
|
|
810
|
-
current.body = text.slice(current.start);
|
|
811
|
-
blocks.push(current);
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
const relations = [];
|
|
815
|
-
for (const block of blocks) {
|
|
816
|
-
const lines = block.body.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
817
|
-
const mainLine = lines.find((line) => /(婵炴垶鎸诲Σ鎺楀Υ閸庡嫰鏌i弽銊ュ姸闁?\s*[:闂佹寧绋掗悺?.test(line));
|
|
818
|
-
const childLine = lines.find((line) => /(婵炲濮村锕傚Υ閸庡嫰鎮楀☉娆忓闁?\s*[:闂佹寧绋掗悺?.test(line));
|
|
819
|
-
const fieldLine = lines.find((line) => /闂佺绻愰悿鍥ㄧ閸懇鍋撳☉娆樻畷妞ゆ柨顒竤*[:闂佹寧绋掗悺?.test(line));
|
|
820
|
-
if (!mainLine || !childLine || !fieldLine) continue;
|
|
821
|
-
|
|
822
|
-
const mainIdentifiers = extractIdentifiersFromLine(mainLine);
|
|
823
|
-
const childIdentifiers = extractIdentifiersFromLine(childLine);
|
|
824
|
-
const fieldIdentifiers = extractIdentifiersFromLine(fieldLine);
|
|
825
|
-
if (!mainIdentifiers.length || !childIdentifiers.length || fieldIdentifiers.length < 2) continue;
|
|
826
|
-
|
|
827
|
-
const relationTypeLine = lines.find((line) => /闂佺绻愮壕顓㈡焾鐎靛摜灏甸悹鍥皺閳ь剛锕*[:闂佹寧绋掗悺?.test(line));
|
|
828
|
-
relations.push({
|
|
829
|
-
title: block.title,
|
|
830
|
-
mainTableName: mainIdentifiers[0],
|
|
831
|
-
childTableName: childIdentifiers[0],
|
|
832
|
-
childField: fieldIdentifiers[0],
|
|
833
|
-
mainField: fieldIdentifiers[1],
|
|
834
|
-
relationType: relationTypeLine ? relationTypeLine.split(/[:闂佹寧绋掗悺?).slice(1).join(':').trim() : '',
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
return relations;
|
|
839
|
-
}
|
|
840
|
-
|
|
787
|
+
function parseMarkdownRelations(markdownText) {
|
|
788
|
+
void markdownText;
|
|
789
|
+
return [];
|
|
790
|
+
}
|
|
841
791
|
function parseMarkdownDesignFile(markdownText) {
|
|
842
792
|
return {
|
|
843
793
|
tables: parseMarkdownDesignTables(markdownText),
|
|
@@ -968,13 +918,13 @@ function buildRetryArguments(safeArgs, sourceFile, childTableName) {
|
|
|
968
918
|
function buildRelationCorrectionEntry(safeArgs, sourceFile, candidates, selectedChildTableName) {
|
|
969
919
|
return {
|
|
970
920
|
field: 'childTableName',
|
|
971
|
-
title: '
|
|
921
|
+
title: '请选择子表',
|
|
972
922
|
tableName: safeArgs.tableName,
|
|
973
923
|
style: safeArgs.style,
|
|
974
924
|
designFile: sourceFile,
|
|
975
925
|
description: candidates.length
|
|
976
926
|
? 'If the current child relation is not the one you want, pass childTableName to choose a candidate from the design file.'
|
|
977
|
-
: 'No child relation was found. Check the
|
|
927
|
+
: 'No child relation was found. Check the child relation section in the design file.',
|
|
978
928
|
currentValue: selectedChildTableName || '',
|
|
979
929
|
options: candidates.map((item) => item.childTableName),
|
|
980
930
|
candidates,
|
|
@@ -1182,12 +1132,14 @@ function renderTemplate(templateText, replacements) {
|
|
|
1182
1132
|
function renderFormField(field) {
|
|
1183
1133
|
const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
|
|
1184
1134
|
const prop = field.attrName;
|
|
1135
|
+
const inputPlaceholderExpr = `inputPlaceholder(getMasterFieldLabel('${prop}'))`;
|
|
1136
|
+
const selectPlaceholderExpr = `selectPlaceholder(getMasterFieldLabel('${prop}'))`;
|
|
1185
1137
|
|
|
1186
1138
|
if (field.formType === 'select') {
|
|
1187
1139
|
return [
|
|
1188
1140
|
' <el-col :span="12" class="mb20">',
|
|
1189
1141
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1190
|
-
` <el-select v-model="form.${prop}" placeholder="
|
|
1142
|
+
` <el-select v-model="form.${prop}" :placeholder="${selectPlaceholderExpr}" style="width: 100%">`,
|
|
1191
1143
|
` <el-option v-for="item in ${field.dictType}" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
|
|
1192
1144
|
' </el-select>',
|
|
1193
1145
|
' </el-form-item>',
|
|
@@ -1196,12 +1148,12 @@ function renderFormField(field) {
|
|
|
1196
1148
|
}
|
|
1197
1149
|
|
|
1198
1150
|
if (field.formType === 'number') {
|
|
1199
|
-
const max = field.comment.includes('%') || field.comment
|
|
1151
|
+
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1200
1152
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1201
1153
|
return [
|
|
1202
1154
|
' <el-col :span="12" class="mb20">',
|
|
1203
1155
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1204
|
-
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} placeholder="
|
|
1156
|
+
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} :placeholder="${inputPlaceholderExpr}" style="width: 100%" />`,
|
|
1205
1157
|
' </el-form-item>',
|
|
1206
1158
|
' </el-col>',
|
|
1207
1159
|
].join('\n');
|
|
@@ -1213,7 +1165,7 @@ function renderFormField(field) {
|
|
|
1213
1165
|
return [
|
|
1214
1166
|
' <el-col :span="12" class="mb20">',
|
|
1215
1167
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1216
|
-
` <el-date-picker type="${pickerType}" placeholder="
|
|
1168
|
+
` <el-date-picker type="${pickerType}" :placeholder="${inputPlaceholderExpr}" v-model="form.${prop}" :value-format="${formatName}" style="width: 100%"></el-date-picker>`,
|
|
1217
1169
|
' </el-form-item>',
|
|
1218
1170
|
' </el-col>',
|
|
1219
1171
|
].join('\n');
|
|
@@ -1223,7 +1175,7 @@ function renderFormField(field) {
|
|
|
1223
1175
|
return [
|
|
1224
1176
|
' <el-col :span="24" class="mb20">',
|
|
1225
1177
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1226
|
-
` <el-input type="textarea" v-model="form.${prop}" placeholder="
|
|
1178
|
+
` <el-input type="textarea" v-model="form.${prop}" :placeholder="${inputPlaceholderExpr}" />`,
|
|
1227
1179
|
' </el-form-item>',
|
|
1228
1180
|
' </el-col>',
|
|
1229
1181
|
].join('\n');
|
|
@@ -1232,7 +1184,7 @@ function renderFormField(field) {
|
|
|
1232
1184
|
return [
|
|
1233
1185
|
' <el-col :span="12" class="mb20">',
|
|
1234
1186
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1235
|
-
` <el-input v-model="form.${prop}" placeholder="
|
|
1187
|
+
` <el-input v-model="form.${prop}" :placeholder="${inputPlaceholderExpr}" />`,
|
|
1236
1188
|
' </el-form-item>',
|
|
1237
1189
|
' </el-col>',
|
|
1238
1190
|
].join('\n');
|
|
@@ -1255,16 +1207,18 @@ function renderTableColumn(field) {
|
|
|
1255
1207
|
function renderChildTableColumn(field, childListName) {
|
|
1256
1208
|
const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
|
|
1257
1209
|
const rules = field.notNull ? ` :rules="[{ required: true, trigger: 'blur' }]"` : '';
|
|
1210
|
+
const inputPlaceholderExpr = `inputPlaceholder(getChildFieldLabel('${childListName}', '${field.attrName}'))`;
|
|
1211
|
+
const selectPlaceholderExpr = `selectPlaceholder(getChildFieldLabel('${childListName}', '${field.attrName}'))`;
|
|
1258
1212
|
|
|
1259
|
-
let control = ` <el-input v-model="row.${field.attrName}" />`;
|
|
1213
|
+
let control = ` <el-input v-model="row.${field.attrName}" :placeholder="${inputPlaceholderExpr}" />`;
|
|
1260
1214
|
if (field.formType === 'select' && field.dictType) {
|
|
1261
1215
|
control = [
|
|
1262
|
-
` <el-select v-model="row.${field.attrName}" placeholder="
|
|
1216
|
+
` <el-select v-model="row.${field.attrName}" :placeholder="${selectPlaceholderExpr}" style="width: 100%">`,
|
|
1263
1217
|
` <el-option v-for="item in ${field.dictType}" :key="item.value" :label="item.label" :value="Number(item.value)" />`,
|
|
1264
1218
|
' </el-select>',
|
|
1265
1219
|
].join('\n');
|
|
1266
1220
|
} else if (field.formType === 'number') {
|
|
1267
|
-
const max = field.comment.includes('%') || field.comment
|
|
1221
|
+
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1268
1222
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1269
1223
|
control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} style="width: 100%" />`;
|
|
1270
1224
|
}
|
|
@@ -1417,7 +1371,7 @@ function renderFormFieldV2(field) {
|
|
|
1417
1371
|
}
|
|
1418
1372
|
|
|
1419
1373
|
if (field.formType === 'number') {
|
|
1420
|
-
const max = field.comment.includes('%') || field.comment
|
|
1374
|
+
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1421
1375
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1422
1376
|
return [
|
|
1423
1377
|
` <el-col v-if="${visibilityExpr}" :span="12" class="mb20">`,
|
|
@@ -1434,26 +1388,28 @@ function renderFormFieldV2(field) {
|
|
|
1434
1388
|
return [
|
|
1435
1389
|
` <el-col v-if="${visibilityExpr}" :span="12" class="mb20">`,
|
|
1436
1390
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
1437
|
-
` <el-date-picker type="${pickerType}" :placeholder="
|
|
1391
|
+
` <el-date-picker type="${pickerType}" :placeholder="inputPlaceholder(${labelExpr})" v-model="form.${prop}" :value-format="${formatName}" style="width: 100%"></el-date-picker>`,
|
|
1438
1392
|
' </el-form-item>',
|
|
1439
1393
|
' </el-col>',
|
|
1440
1394
|
].join('\n');
|
|
1441
1395
|
}
|
|
1442
1396
|
|
|
1443
1397
|
if (field.formType === 'textarea') {
|
|
1398
|
+
const textareaAttrs = renderTextareaMaxlengthAttrsV2(field);
|
|
1444
1399
|
return [
|
|
1445
1400
|
` <el-col v-if="${visibilityExpr}" :span="24" class="mb20">`,
|
|
1446
1401
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
1447
|
-
` <el-input type="textarea" v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${
|
|
1402
|
+
` <el-input type="textarea" v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${textareaAttrs} />`,
|
|
1448
1403
|
' </el-form-item>',
|
|
1449
1404
|
' </el-col>',
|
|
1450
1405
|
].join('\n');
|
|
1451
1406
|
}
|
|
1452
1407
|
|
|
1408
|
+
const maxlengthAttr = renderInputMaxlengthAttr(field);
|
|
1453
1409
|
return [
|
|
1454
1410
|
` <el-col v-if="${visibilityExpr}" :span="12" class="mb20">`,
|
|
1455
1411
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
1456
|
-
` <el-input v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${
|
|
1412
|
+
` <el-input v-model="form.${prop}" :placeholder="inputPlaceholder(${labelExpr})"${maxlengthAttr} />`,
|
|
1457
1413
|
' </el-form-item>',
|
|
1458
1414
|
' </el-col>',
|
|
1459
1415
|
].join('\n');
|
|
@@ -1480,7 +1436,7 @@ function renderChildTableColumnV2(field, childListName) {
|
|
|
1480
1436
|
const labelExpr = `getChildFieldLabel('${childListName}', '${field.attrName}')`;
|
|
1481
1437
|
const dictExpr = `getChildFieldMeta('${childListName}', '${field.attrName}')?.dictType`;
|
|
1482
1438
|
|
|
1483
|
-
let control = ` <el-input v-model="row.${field.attrName}"${renderTextMaxlengthAttrV2(field)} />`;
|
|
1439
|
+
let control = ` <el-input v-model="row.${field.attrName}" :placeholder="inputPlaceholder(${labelExpr})"${renderTextMaxlengthAttrV2(field)} />`;
|
|
1484
1440
|
if (field.formType === 'select' && field.dictType) {
|
|
1485
1441
|
control = [
|
|
1486
1442
|
` <el-select v-model="row.${field.attrName}" :placeholder="selectPlaceholder(${labelExpr})" style="width: 100%">`,
|
|
@@ -1488,15 +1444,15 @@ function renderChildTableColumnV2(field, childListName) {
|
|
|
1488
1444
|
' </el-select>',
|
|
1489
1445
|
].join('\n');
|
|
1490
1446
|
} else if (field.formType === 'number') {
|
|
1491
|
-
const max = field.comment.includes('%') || field.comment
|
|
1447
|
+
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1492
1448
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1493
1449
|
control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} style="width: 100%" />`;
|
|
1494
1450
|
} else if (field.formType === 'datetime' || field.formType === 'date') {
|
|
1495
1451
|
const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
|
|
1496
1452
|
const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
|
|
1497
|
-
control = ` <el-date-picker type="${pickerType}" v-model="row.${field.attrName}" :value-format="${formatName}" :placeholder="
|
|
1453
|
+
control = ` <el-date-picker type="${pickerType}" v-model="row.${field.attrName}" :value-format="${formatName}" :placeholder="inputPlaceholder(${labelExpr})" style="width: 100%"></el-date-picker>`;
|
|
1498
1454
|
} else if (field.formType === 'textarea') {
|
|
1499
|
-
control = ` <el-input type="textarea" v-model="row.${field.attrName}"${renderTextareaMaxlengthAttrsV2(field)} />`;
|
|
1455
|
+
control = ` <el-input type="textarea" v-model="row.${field.attrName}" :placeholder="inputPlaceholder(${labelExpr})"${renderTextareaMaxlengthAttrsV2(field)} />`;
|
|
1500
1456
|
}
|
|
1501
1457
|
|
|
1502
1458
|
return [
|
|
@@ -1526,11 +1482,11 @@ function renderChildSectionV2(childModel, childCount) {
|
|
|
1526
1482
|
].join('\n');
|
|
1527
1483
|
}
|
|
1528
1484
|
|
|
1529
|
-
function renderValidationRule(field) {
|
|
1530
|
-
if (!field.notNull) return null;
|
|
1531
|
-
const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
|
|
1532
|
-
return ` ${field.attrName}: [{ required: true, message: '${label}
|
|
1533
|
-
}
|
|
1485
|
+
function renderValidationRule(field) {
|
|
1486
|
+
if (!field.notNull) return null;
|
|
1487
|
+
const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
|
|
1488
|
+
return ` ${field.attrName}: [{ required: true, message: '${label}\u4E0D\u80FD\u4E3A\u7A7A', trigger: 'blur' }],`;
|
|
1489
|
+
}
|
|
1534
1490
|
|
|
1535
1491
|
function renderFormRules(visibleFields) {
|
|
1536
1492
|
const lines = visibleFields.map(renderValidationRule).filter(Boolean);
|
package/package.json
CHANGED