mcp-vue-codegen 1.0.0

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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/build/generators/api.d.ts +3 -0
  4. package/build/generators/api.d.ts.map +1 -0
  5. package/build/generators/api.js +8 -0
  6. package/build/generators/api.js.map +1 -0
  7. package/build/generators/form-vue.d.ts +3 -0
  8. package/build/generators/form-vue.d.ts.map +1 -0
  9. package/build/generators/form-vue.js +8 -0
  10. package/build/generators/form-vue.js.map +1 -0
  11. package/build/generators/index-vue.d.ts +3 -0
  12. package/build/generators/index-vue.d.ts.map +1 -0
  13. package/build/generators/index-vue.js +8 -0
  14. package/build/generators/index-vue.js.map +1 -0
  15. package/build/generators/options.d.ts +3 -0
  16. package/build/generators/options.d.ts.map +1 -0
  17. package/build/generators/options.js +8 -0
  18. package/build/generators/options.js.map +1 -0
  19. package/build/index.d.ts +3 -0
  20. package/build/index.d.ts.map +1 -0
  21. package/build/index.js +74 -0
  22. package/build/index.js.map +1 -0
  23. package/build/templates/api.tpl.d.ts +3 -0
  24. package/build/templates/api.tpl.d.ts.map +1 -0
  25. package/build/templates/api.tpl.js +53 -0
  26. package/build/templates/api.tpl.js.map +1 -0
  27. package/build/templates/form-vue.tpl.d.ts +3 -0
  28. package/build/templates/form-vue.tpl.d.ts.map +1 -0
  29. package/build/templates/form-vue.tpl.js +862 -0
  30. package/build/templates/form-vue.tpl.js.map +1 -0
  31. package/build/templates/index-vue.tpl.d.ts +3 -0
  32. package/build/templates/index-vue.tpl.d.ts.map +1 -0
  33. package/build/templates/index-vue.tpl.js +591 -0
  34. package/build/templates/index-vue.tpl.js.map +1 -0
  35. package/build/templates/options.tpl.d.ts +3 -0
  36. package/build/templates/options.tpl.d.ts.map +1 -0
  37. package/build/templates/options.tpl.js +48 -0
  38. package/build/templates/options.tpl.js.map +1 -0
  39. package/build/tools/generate.d.ts +11 -0
  40. package/build/tools/generate.d.ts.map +1 -0
  41. package/build/tools/generate.js +95 -0
  42. package/build/tools/generate.js.map +1 -0
  43. package/build/tools/validate.d.ts +1051 -0
  44. package/build/tools/validate.d.ts.map +1 -0
  45. package/build/tools/validate.js +147 -0
  46. package/build/tools/validate.js.map +1 -0
  47. package/build/types/schema.d.ts +124 -0
  48. package/build/types/schema.d.ts.map +1 -0
  49. package/build/types/schema.js +7 -0
  50. package/build/types/schema.js.map +1 -0
  51. package/package.json +34 -0
@@ -0,0 +1,862 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFormVueTemplate = generateFormVueTemplate;
4
+ /**
5
+ * Group fields by formSection and formRow
6
+ */
7
+ function getFormFieldsBySection(fields, sectionName) {
8
+ const rows = new Map();
9
+ fields
10
+ .filter(f => f.showInForm && f.formSection === sectionName && f.inputType !== 'hidden')
11
+ .sort((a, b) => (a.formRow || 0) - (b.formRow || 0))
12
+ .forEach(f => {
13
+ const row = f.formRow || 0;
14
+ if (!rows.has(row))
15
+ rows.set(row, []);
16
+ rows.get(row).push(f);
17
+ });
18
+ return rows;
19
+ }
20
+ /**
21
+ * Generate a form field template based on inputType
22
+ */
23
+ function generateFieldTemplate(field, processDefKey, entityPrefix) {
24
+ const labelExpr = `t(\`column.\${processDefKey}.${entityPrefix}.${field.fieldName}\`)`;
25
+ const prop = field.fieldName;
26
+ const colSpan = field.formColSpan || 6;
27
+ let inputContent = '';
28
+ switch (field.inputType) {
29
+ case 'date':
30
+ inputContent = ` <el-date-picker
31
+ v-model="dataForm.${prop}"
32
+ type="dateTime"
33
+ :placeholder="\`\${t('message.pleaseSelect')}\${${labelExpr}}\`"
34
+ value-format="${field.dateFormat || 'YYYY-MM-DD'}"
35
+ format="${field.dateFormat || 'YYYY-MM-DD'}"
36
+ />`;
37
+ break;
38
+ case 'textarea':
39
+ inputContent = ` <el-input
40
+ type="textarea"
41
+ rows="${field.textareaRows || 3}"${field.maxLength ? `\n maxlength="${field.maxLength}"` : ''}${field.showWordLimit ? `\n show-word-limit` : ''}
42
+ v-model="dataForm.${prop}"
43
+ :placeholder="\`\${t('message.pleaseEnter')}\${${labelExpr}}\`"
44
+ ></el-input>`;
45
+ break;
46
+ case 'file':
47
+ inputContent = ` <upload-file v-model:modelValue="dataForm.${prop}"> </upload-file>`;
48
+ break;
49
+ case 'userRef':
50
+ case 'personRef': {
51
+ const ref = field.refConfig;
52
+ const clickFn = field.inputType === 'userRef'
53
+ ? `${prop}MasterSelect${capitalizeRef(ref.refComponent)}Click`
54
+ : `${prop}MasterSelect${capitalizeRef(ref.refComponent)}Click`;
55
+ inputContent = ` <el-input
56
+ v-model="dataForm.${prop}"
57
+ ${field.disabled ? 'disabled' : 'readonly'}
58
+ :placeholder="\`\${t('message.pleaseSelect')}\${${labelExpr}}\`"
59
+ >
60
+ <template #append>
61
+ <el-button @click="${clickFn}()" icon="Search"></el-button>
62
+ </template>
63
+ </el-input>`;
64
+ break;
65
+ }
66
+ default: {
67
+ // Regular input
68
+ const disabledAttr = field.disabled ? ' disabled' : '';
69
+ const maxLengthAttr = field.maxLength ? ` maxlength="${field.maxLength}"` : '';
70
+ if (field.disabled) {
71
+ inputContent = ` <el-input${maxLengthAttr} v-model="dataForm.${prop}"${disabledAttr}></el-input>`;
72
+ }
73
+ else {
74
+ inputContent = ` <el-input${maxLengthAttr} v-model="dataForm.${prop}"${disabledAttr}
75
+ :placeholder="\`\${t('message.pleaseEnter')}\${${labelExpr}}\`"
76
+ ></el-input>`;
77
+ }
78
+ break;
79
+ }
80
+ }
81
+ return ` <!-- 字段:${field.label} -->
82
+ <el-col :span="${colSpan}">
83
+ <el-form-item :label="${labelExpr}" prop="${prop}">
84
+ ${inputContent}
85
+ </el-form-item>
86
+ </el-col>`;
87
+ }
88
+ function capitalizeRef(name) {
89
+ return name.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
90
+ }
91
+ /**
92
+ * Generate the detail table columns (from table visible fields)
93
+ */
94
+ function generateDetailTableColumns(schema) {
95
+ if (!schema.detail)
96
+ return '';
97
+ const detail = schema.detail;
98
+ const visibleFields = detail.fields.filter(f => f.showInTable && !f.alwaysHide);
99
+ const editableFields = detail.fields.filter(f => f.editableInTable);
100
+ return visibleFields.map(f => {
101
+ const editable = editableFields.find(ef => ef.fieldName === f.fieldName);
102
+ if (editable) {
103
+ return generateEditableDetailColumn(f, schema);
104
+ }
105
+ return ` <!-- 字段:${f.label} -->
106
+ <el-table-column
107
+ prop="${f.fieldName}"
108
+ show-overflow-tooltip
109
+ :label="t(\`column.\${processDefKey}.detail.${f.fieldName}\`)"
110
+ header-align="center"
111
+ :min-width="detailColumns.filter((c) => c.key === '${f.fieldName}')[0]?.width"
112
+ align="center"
113
+ >
114
+ </el-table-column>`;
115
+ }).join('\n');
116
+ }
117
+ function generateEditableDetailColumn(field, schema) {
118
+ const editType = field.editInputType || field.inputType;
119
+ const ruleProp = field.editRuleProp || field.fieldName;
120
+ const bindField = field.editBindField || field.fieldName;
121
+ let innerTemplate = '';
122
+ if (editType === 'select') {
123
+ const dictCode = field.dictCode || '';
124
+ innerTemplate = ` <el-form-item
125
+ label-width="0"
126
+ :rules="dataDetailRules.${ruleProp}"
127
+ :prop="\`details.\${$index}.${bindField}\`"
128
+ >
129
+ <el-select
130
+ v-model="row.${bindField}"
131
+ style="width: 99%"
132
+ :placeholder="\`\${t('message.pleaseSelect')}\${t(\`column.\${processDefKey}.detail.${field.fieldName}\`)}\`"
133
+ >
134
+ <el-option
135
+ v-for="item in ${field.fieldName}Options"
136
+ :key="item.value"
137
+ :label="item.label"
138
+ :value="item.value"
139
+ >
140
+ </el-option>
141
+ </el-select>
142
+ </el-form-item>`;
143
+ }
144
+ else if (editType === 'date') {
145
+ innerTemplate = ` <el-form-item
146
+ label-width="0"
147
+ :rules="dataDetailRules.${ruleProp}"
148
+ :prop="\`details.\${$index}.${field.fieldName}\`"
149
+ >
150
+ <el-date-picker
151
+ type="date"
152
+ v-model="row.${field.fieldName}"
153
+ :placeholder="\`\${t('message.pleaseSelect')}\${t(\`column.\${processDefKey}.detail.${field.fieldName}\`)}\`"
154
+ format="${field.dateFormat || 'YYYY-MM-DD'}"
155
+ value-format="${field.dateFormat || 'YYYY-MM-DD'}"
156
+ style="width: 99%"
157
+ />
158
+ </el-form-item>`;
159
+ }
160
+ else {
161
+ innerTemplate = ` <el-form-item
162
+ label-width="0"
163
+ :rules="dataDetailRules.${ruleProp}"
164
+ :prop="\`details.\${$index}.${field.fieldName}\`"
165
+ >
166
+ <el-input v-model="row.${field.fieldName}" style="width: 99%" />
167
+ </el-form-item>`;
168
+ }
169
+ return ` <!-- 字段:${field.label} -->
170
+ <el-table-column
171
+ prop="${field.fieldName}"
172
+ show-overflow-tooltip
173
+ :label="t(\`column.\${processDefKey}.detail.${field.fieldName}\`)"
174
+ header-align="center"
175
+ :min-width="detailColumns.filter((c) => c.key === '${field.fieldName}')[0]?.width"
176
+ align="center"
177
+ >
178
+ <template v-slot="{ $index, row }">
179
+ ${innerTemplate}
180
+ </template>
181
+ </el-table-column>`;
182
+ }
183
+ function generateFormVueTemplate(schema) {
184
+ const m = schema.module;
185
+ const master = schema.master;
186
+ const detail = schema.detail;
187
+ const hasDetail = !!detail;
188
+ const perm = m.permissionPrefix;
189
+ // Find ref fields in master
190
+ const refFields = master.fields.filter(f => f.refConfig && (f.inputType === 'userRef' || f.inputType === 'personRef'));
191
+ // Collect all form sections
192
+ const sections = master.formSections;
193
+ // Fields with defaultValue
194
+ const allFormFields = master.fields;
195
+ // Detail editable fields with dict
196
+ const detailEditableSelectFields = hasDetail
197
+ ? detail.fields.filter(f => f.editableInTable && f.editInputType === 'select' && f.dictCode)
198
+ : [];
199
+ // Required master fields (for validation rules)
200
+ const requiredMasterFields = master.fields.filter(f => f.required && f.showInForm && f.inputType !== 'hidden');
201
+ // Required detail fields (for validation rules)
202
+ const requiredDetailFields = hasDetail
203
+ ? detail.fields.filter(f => f.required && (f.showInTable || f.editableInTable) && f.inputType !== 'hidden')
204
+ : [];
205
+ // Build collapse items
206
+ const collapseItems = [];
207
+ const collapseIndices = [];
208
+ sections.forEach(section => {
209
+ collapseIndices.push(section.collapseIndex);
210
+ if (section.name === 'detail' && hasDetail) {
211
+ // Detail section - generate table
212
+ const detailRowKey = detail.detailRowKey;
213
+ collapseItems.push(generateDetailSection(schema, section));
214
+ }
215
+ else {
216
+ // Regular form section
217
+ const rows = getFormFieldsBySection(master.fields, section.name);
218
+ let sectionContent = '';
219
+ rows.forEach((fields, rowNum) => {
220
+ const fieldTemplates = fields.map(f => generateFieldTemplate(f, 'processDefKey', 'master')).join('\n');
221
+ sectionContent += ` <!-- 行内:第${rowNum}行 -->
222
+ <el-row>
223
+ ${fieldTemplates}
224
+ </el-row>\n`;
225
+ });
226
+ // Determine the title expression
227
+ let titleExpr;
228
+ if (section.name === 'basic') {
229
+ titleExpr = `t(\`column.\${processDefKey}.master.${master.collapseTitle}\`)`;
230
+ }
231
+ else if (section.name === 'createInfo') {
232
+ titleExpr = `t(\`column.\${processDefKey}.master.${master.createInfoTitle}\`)`;
233
+ }
234
+ else {
235
+ titleExpr = `t(\`column.\${processDefKey}.master.${section.title}\`)`;
236
+ }
237
+ collapseItems.push(` <!-- 内容容器:${section.title} -->
238
+ <div class="basic">
239
+ <basic-container>
240
+ <el-collapse-item :title="${titleExpr}" name="${section.collapseIndex}">
241
+ ${sectionContent} </el-collapse-item>
242
+ </basic-container>
243
+ </div>`);
244
+ }
245
+ });
246
+ // Build ref dialog components
247
+ const refDialogs = refFields.map(f => {
248
+ const ref = f.refConfig;
249
+ const componentTag = ref.refComponent;
250
+ const refName = getRefComponentVarName(f);
251
+ const rootIdVar = `${refName}RootId`;
252
+ const titleExpr = `t(\`column.\${processDefKey}.master.${ref.refTitle}\`)`;
253
+ const containParent = ref.containParentFlag ? `\n containParentFlag="${ref.containParentFlag}"` : '';
254
+ return ` <!-- ${f.label} 引用选择弹窗 -->
255
+ <${componentTag}
256
+ ref="${capitalizeFirst(refName)}"
257
+ :title="${titleExpr}"
258
+ :rootId="${rootIdVar}"${containParent}
259
+ @okHandle="${refName}OkHandle"
260
+ ></${componentTag}>`;
261
+ }).join('\n');
262
+ // Detail ref dialog
263
+ const detailRefDialog = hasDetail && detail.detailRefConfig ? (() => {
264
+ const drc = detail.detailRefConfig;
265
+ const componentTag = drc.component;
266
+ // import path is just the component name
267
+ return `
268
+ <!-- 选择${detail.detailTitle}弹窗 -->
269
+ <${componentTag} ref="registeRef" @okHandle="detailRegisteOkHandle"></${componentTag}>`;
270
+ })() : '';
271
+ // Build dataForm initialization
272
+ const dataFormFields = allFormFields.map(f => {
273
+ return ` ${f.fieldName}: ${f.defaultValue || 'null'}, //${f.label}`;
274
+ }).join('\n');
275
+ // Build master validation rules
276
+ const masterRulesEntries = requiredMasterFields.map(f => {
277
+ return ` ${f.fieldName}: [
278
+ {
279
+ required: true,
280
+ message: t(\`column.\${processDefKey}.master.${f.fieldName}\`) + t('message.not_empty'),
281
+ trigger: ['blur', 'change']
282
+ }
283
+ ]`;
284
+ }).join(',\n');
285
+ // Build detail validation rules
286
+ const detailRulesEntries = requiredDetailFields.map(f => {
287
+ const ruleProp = f.editRuleProp || f.fieldName;
288
+ const labelEntity = 'detail';
289
+ return ` ${ruleProp}: [
290
+ {
291
+ required: true,
292
+ message: t(\`column.\${processDefKey}.${labelEntity}.${f.fieldName}\`) + t('message.not_empty'),
293
+ trigger: ['blur', 'change']
294
+ }
295
+ ]`;
296
+ }).join(',\n');
297
+ // Build ref component click handlers and ok handlers
298
+ const refHandlers = refFields.map(f => {
299
+ const ref = f.refConfig;
300
+ const refVarName = getRefComponentVarName(f);
301
+ const capitalRefName = capitalizeFirst(refVarName);
302
+ // Click handler
303
+ const clickFn = `const ${f.fieldName}MasterSelect${capitalizeRef(ref.refComponent)}Click = () => {
304
+ ${capitalRefName}.value.data.visible = true
305
+ ${capitalRefName}.value.getTreeInclude()
306
+ }`;
307
+ // Ok handler - map extraMappings
308
+ const mappings = ref.extraMappings.map(em => {
309
+ return ` dataForm.${em.target} = data.${em.source}`;
310
+ }).join('\n');
311
+ const okFn = `const ${refVarName}OkHandle = (data) => {
312
+ ${mappings}
313
+ }`;
314
+ return `${clickFn}\n\n${okFn}`;
315
+ }).join('\n\n');
316
+ // Ref component declarations
317
+ const refComponentDecls = refFields.map(f => {
318
+ const refVarName = getRefComponentVarName(f);
319
+ const capitalRefName = capitalizeFirst(refVarName);
320
+ return `const ${capitalRefName} = ref()
321
+ const ${refVarName}RootId = getCurrPsmInfo() ? getCurrPsmInfo().ognId : '0'`;
322
+ }).join('\n');
323
+ // Detail select options for editable fields
324
+ const detailSelectImports = detailEditableSelectFields.map(f => f.dictCode).filter((v, i, a) => a.indexOf(v) === i);
325
+ const detailSelectImportLine = detailSelectImports.length > 0
326
+ ? `import { ${detailSelectImports.join(', ')} } from '/@/enums/dict'`
327
+ : '';
328
+ const detailSelectOptionInits = detailEditableSelectFields.map(f => {
329
+ return `let ${f.fieldName}Options: any = reactive([])`;
330
+ }).join('\n');
331
+ // Collapse item names
332
+ const collapseNames = collapseIndices.map(i => `'${i}'`).join(', ');
333
+ // Print button
334
+ const printBtn = m.hasPrint ? `
335
+ <!-- 打印按钮 -->
336
+ <pdf-upload
337
+ :current-row="dataForm"
338
+ :fileName="\`\${getStore({ name: 'currentMenu' })}—\${dataForm ? dataForm.${m.printFileNameField || 'id'} : ' '}\`"
339
+ ></pdf-upload>` : '';
340
+ // getStore import
341
+ const getStoreImport = m.hasPrint ? `\nimport { getStore } from '/@/utils/store'` : '';
342
+ // Detail section handlers
343
+ const detailHandlers = hasDetail ? generateDetailHandlers(schema) : '';
344
+ // Detail async component import
345
+ const detailAsyncImport = hasDetail && detail.detailRefConfig
346
+ ? `const selectRegiste = defineAsyncComponent(() => import('${detail.detailRefConfig.componentPath}'))`
347
+ : '';
348
+ // Detail useTypeOptions init in show()
349
+ const detailOptionsInitInShow = detailEditableSelectFields.map(f => {
350
+ return ` ${f.fieldName}Options = ${f.dictCode}(operateType != 'view' ? '1' : '')`;
351
+ }).join('\n');
352
+ // Detail imports
353
+ const detailImportLine = hasDetail
354
+ ? `import { dataDetailEntity } from './options'
355
+ import { useDynamicsShowColumn } from '../../../hooks/table'`
356
+ : '';
357
+ // Detail dynamic columns
358
+ const detailDynColumns = hasDetail
359
+ ? `// 使用表格列动态显示
360
+ useDynamicsShowColumn(detailColumns, dataDetailEntity)`
361
+ : '';
362
+ // Workflow related
363
+ const workflowProcessComp = m.hasWorkflow ? `
364
+ <!-- 流程组件,仅在流程类状态时显示 -->
365
+ <process
366
+ v-if="isProcessState"
367
+ :operateType="showOperateType"
368
+ :beforeFlow="beforeFlow"
369
+ :currentRow="dataForm"
370
+ @workflowPopClose="workflowPopClose"
371
+ @afterFlowHandle="afterFlowHandle"
372
+ />` : '';
373
+ const workflowSubmitBtn = m.hasWorkflow ? `
374
+ <!-- 提交按钮,仅在非查看模式且非流程类状态时显示 -->
375
+ <el-button v-if="isSubmitShow" icon="Select" type="primary" @click="submitHandle(true)">
376
+ {{ t('common.submit') }}
377
+ </el-button>` : '';
378
+ const workflowImports = m.hasWorkflow
379
+ ? `import { getCurrPsmInfo, getMainPosPsmInfo, getMenuObjByMenuPath, getProcessFunction, getIsProcessByBusinessId } from '/@/util/util'`
380
+ : `import { getCurrPsmInfo, getMenuObjByMenuPath } from '/@/util/util'`;
381
+ const workflowRefs = m.hasWorkflow ? `
382
+ const isProcessFunction = ref(false)` : '';
383
+ const workflowComputed = m.hasWorkflow ? `
384
+ const isSubmitShow = computed(() => {
385
+ return !isProcessState.value && showOperateType.value !== 'view'
386
+ })
387
+
388
+ const isProcessState = computed(() => {
389
+ if (!dataForm) return
390
+ if (dataForm.billStateId == '0') return isProcessFunction.value
391
+ if (dataForm.billStateId != '4') return true
392
+ return dataForm.isProcessData
393
+ })` : '';
394
+ const workflowBeforeFlow = m.hasWorkflow ? `
395
+ const beforeFlow = async () => {
396
+ const isNext = await checkData(false, 'process')
397
+ if (isNext) {
398
+ if (oldValue.value === JSON.stringify(dataForm)) {
399
+ return { cancel: false, data: dataForm }
400
+ }
401
+ return postData({}, false).then((d) => {
402
+ return { cancel: false, data: d }
403
+ })
404
+ }
405
+ return { cancel: true }
406
+ }
407
+
408
+ const refreshDataForm = () => {
409
+ getObj(dataForm.id).then((res) => {
410
+ Object.assign(dataForm, res.data)
411
+ oldValue.value = showOperateType.value === 'view' ? null : JSON.stringify(dataForm)
412
+ })
413
+ }
414
+
415
+ const workflowPopClose = () => {
416
+ refreshDataForm()
417
+ emit('refresh')
418
+ }
419
+
420
+ const afterFlowHandle = () => {
421
+ refreshDataForm()
422
+ gobackClick()
423
+ emit('refresh')
424
+ }` : '';
425
+ const workflowOnMounted = m.hasWorkflow ? `
426
+ onMounted(() => {
427
+ getProcessFunction(route.path).then((res) => {
428
+ isProcessFunction.value = res === '0'
429
+ })
430
+ })` : '';
431
+ const workflowSubmitHandle = m.hasWorkflow ? `
432
+ const submitHandle = async (isBtn, isList?) => {
433
+ if (!(await checkData(isList, 'submit'))) return
434
+ useMessageBox()
435
+ .confirm(t('message.form_submit'))
436
+ .then(() => {
437
+ Object.assign(dataForm, { tempProp: moment().format() })
438
+ postData({ billStateId: '4', billState: '已完成' }, true)
439
+ })
440
+ }` : '';
441
+ const workflowFormDisabled = m.hasWorkflow ? `
442
+ const FormDisabled = computed(() => {
443
+ return (
444
+ showOperateType.value === 'view' ||
445
+ (!route.query.nodeKey && dataForm.billStateId !== '0') ||
446
+ (route.query.nodeKey && route.query.nodeKey !== startNodeKey.value) ||
447
+ (route.query.nodeKey && !route.query.psmId) ||
448
+ (route.query.mode && route.query.mode == 'view')
449
+ )
450
+ })` : `
451
+ const FormDisabled = computed(() => {
452
+ return showOperateType.value === 'view'
453
+ })`;
454
+ const workflowStartNode = m.hasWorkflow ? `
455
+ const startNodeKey = ref('userTask1')` : '';
456
+ const workflowIsProcessDataField = m.hasWorkflow ? ` isProcessData: '' // 当前数据是否流转类` : '';
457
+ const workflowShowExtra = m.hasWorkflow ? `
458
+ if (dataForm.billStateId == '4' && isProcessFunction == undefined)
459
+ dataForm.isProcessData = await getIsProcessByBusinessId(id)
460
+ else dataForm.isProcessData = isProcessFunction` : '';
461
+ // Detail validate in checkData
462
+ const detailValidateConfig = hasDetail ? `,
463
+ detailsName: [
464
+ {
465
+ listName: '${detail.detailListName}',
466
+ rowNameType: '${detail.detailValidateConfig.rowNameType}',
467
+ rowName: '${detail.detailValidateConfig.rowName}'
468
+ }
469
+ ]` : '';
470
+ const detailCheckList = hasDetail ? `
471
+ isNext = isNext && (await detailCheckOneList())` : '';
472
+ const detailCheckOneListFn = hasDetail ? `
473
+ const detailCheckOneList = () => {
474
+ if (dataForm.${detail.detailListName}.length < 1) {
475
+ useMessage().error(t(\`column.\${processDefKey}.detail.checkOneList\`))
476
+ return false
477
+ }
478
+ return true
479
+ }` : '';
480
+ const detailListField = hasDetail ? ` ${detail.detailListName}: [] as any,` : '';
481
+ // Detail refs
482
+ const detailRefDecls = hasDetail ? `
483
+ const detailCurrentRow = reactive({})
484
+ const detailSelectRows = ref<any>([])
485
+ const detailTable = ref()
486
+ const detailColumns = ref([] as any[])
487
+ const registeRef = ref()` : '';
488
+ return `<template>
489
+ <div class="layout-padding-auto layout-padding-view bg-info" v-show="visible" v-loading="loading" :key="componentKey">
490
+ <!-- 按钮区域 -->
491
+ <div class="menu_boxs">
492
+ <div class="avue-crud__menu">
493
+ <div class="avue-crud__left">
494
+ <!-- 保存按钮,仅在非查看模式下显示 -->
495
+ <el-button
496
+ v-if="showOperateType !== 'view'"
497
+ :disabled="!saveBtn"
498
+ icon="DocumentChecked"
499
+ type="primary"
500
+ @click="saveClick(true)"
501
+ >
502
+ {{ t('common.saveBtn') }}
503
+ </el-button>
504
+ <!-- 返回按钮 -->
505
+ <el-button icon="Close" @click="gobackClick" v-if="!route.query.taskId">
506
+ {{ t('common.gobackBtn') }}
507
+ </el-button>${workflowSubmitBtn}${workflowProcessComp}
508
+ <!-- 一键展开收起按钮 -->
509
+ <el-button type="primary" @click="handleToggleCollapseExpand()">
510
+ {{ t('common.retract_expand') }}
511
+ </el-button>
512
+ <!-- 分享按钮 -->
513
+ <el-button type="primary" circle icon="Share" style="position: absolute; right: 20px" @click="gobackClick">
514
+ </el-button>${printBtn}
515
+ </div>
516
+ </div>
517
+ </div>
518
+
519
+ <!-- 表单区域 -->
520
+ <el-row class="rounded-1 form_h">
521
+ <el-collapse v-model="activeNames">
522
+ <el-form
523
+ ref="dataFormRef"
524
+ :model="dataForm"
525
+ :rules="dataMasterRules"
526
+ formDialogRef
527
+ :label-width="cfg.labelWidth"
528
+ :disabled="FormDisabled"
529
+ >
530
+ ${collapseItems.join('\n')}
531
+ </el-form>
532
+ </el-collapse>
533
+ </el-row>
534
+ ${refDialogs}${detailRefDialog}
535
+ </div>
536
+ </template>
537
+ <script setup lang="ts" name="${m.componentName}Dialog">
538
+ import { useMessage, useMessageBox } from '/@/hooks/message'
539
+ import { getObj, addObj, putObj } from '/@/${m.apiFilePath}'
540
+ import { useI18n } from 'vue-i18n'
541
+ import { formValidate } from '/@/utils/verify'
542
+ import { unique } from '/@/utils/common'
543
+ import moment from 'moment'
544
+ ${detailImportLine}
545
+ ${workflowImports}
546
+ ${detailSelectImportLine}${getStoreImport}
547
+ ${detailAsyncImport}
548
+
549
+ const componentKey = ref(0)
550
+ const emit = defineEmits(['goback', 'refresh'])
551
+ const { t } = useI18n()
552
+ const dataFormRef = ref()
553
+ const saveBtn = ref(false)
554
+
555
+ const oldValue = ref<any>()
556
+ const visible = ref(false)
557
+ const loading = ref(false)
558
+ const showOperateType = ref('view')
559
+ const route = useRoute()
560
+ const processDefKey = getMenuObjByMenuPath(route.path).modelId${workflowRefs}
561
+ const activeFlag = ref(true)
562
+ const activeNames = ref([${collapseNames}])
563
+ const collapseItemName: Array<string> = [${collapseNames}]${detailRefDecls}
564
+ ${refComponentDecls}
565
+ ${detailSelectOptionInits}
566
+ const cfg = reactive({
567
+ gutter: 16,
568
+ span: 12,
569
+ labelWidth: '${m.labelWidth}'
570
+ })${workflowStartNode}
571
+ // 初始化数据表单
572
+ const dataForm = reactive({
573
+ ${dataFormFields}
574
+ ${detailListField}
575
+ ${workflowIsProcessDataField}
576
+ })
577
+ const initForm = Object.assign({}, dataForm)
578
+ // 定义主表数据验证规则
579
+ const dataMasterRules = ref({
580
+ ${masterRulesEntries}
581
+ })
582
+ ${hasDetail ? `
583
+ // 定义从表数据验证规则
584
+ const dataDetailRules = ref({
585
+ ${detailRulesEntries}
586
+ })` : ''}
587
+
588
+ ${detailDynColumns}
589
+
590
+ ${refHandlers}
591
+ ${detailHandlers}
592
+ ${workflowFormDisabled}
593
+
594
+ const show = async (operateType: string, id?: string, data?: any, isProcessFunction?: any) => {
595
+ showOperateType.value = operateType
596
+ ${detailOptionsInitInShow}
597
+ visible.value = true
598
+ await nextTick(() => {
599
+ dataFormRef.value?.resetFields()
600
+ componentKey.value += 1
601
+ })
602
+ Object.assign(dataForm, initForm)
603
+ loading.value = true
604
+ try {
605
+ if (id) {
606
+ getObj(id).then(async (res) => {
607
+ Object.assign(dataForm, res.data)${workflowShowExtra}
608
+ oldValue.value = operateType === 'view' ? null : JSON.stringify(dataForm)${hasDetail ? `
609
+ if (dataForm.${detail.detailListName}.length > 0) {
610
+ nextTick(() => {
611
+ detailTable.value.toggleRowSelection(dataForm.${detail.detailListName}[0], true)
612
+ })
613
+ }` : ''}
614
+ })
615
+ } else {
616
+ dataForm.version = '0'
617
+ }
618
+ } finally {
619
+ loading.value = false
620
+ }
621
+ }
622
+ ${workflowComputed}
623
+
624
+ const gobackClick = () => {
625
+ visible.value = false
626
+ emit('goback', 'cancel')
627
+ }
628
+
629
+ const handleToggleCollapseExpand = () => {
630
+ if (activeFlag.value) {
631
+ if (activeNames.value.length > 0) {
632
+ activeNames.value = []
633
+ activeFlag.value = false
634
+ } else {
635
+ activeNames.value = collapseItemName
636
+ }
637
+ } else {
638
+ if (activeNames.value.length === 0 || activeNames.value.length !== collapseItemName.length) {
639
+ activeNames.value = collapseItemName
640
+ activeFlag.value = true
641
+ } else {
642
+ activeNames.value = []
643
+ }
644
+ }
645
+ }
646
+ ${workflowBeforeFlow}
647
+ ${detailCheckOneListFn}
648
+
649
+ const checkData = async (isList = false, btnType = 'save') => {
650
+ let isNext = true
651
+ if (btnType === 'submit' || btnType === 'process') {
652
+ isNext = await formValidate(
653
+ [
654
+ {
655
+ dataFormName: dataForm,
656
+ name: dataFormRef${detailValidateConfig}
657
+ }
658
+ ],
659
+ isList
660
+ )${detailCheckList}
661
+ }
662
+ return isNext
663
+ }
664
+
665
+ const postData = async (extVals = {}, isSave = false) => {
666
+ loading.value = true
667
+ try {
668
+ let res = dataForm.id
669
+ ? await putObj(Object.assign({}, dataForm, extVals))
670
+ : await addObj(Object.assign({}, dataForm, extVals))
671
+ useMessage().success(dataForm.id ? t('common.editSuccessText') : t('common.addSuccessText'))
672
+ Object.assign(dataForm, res.data)
673
+ const query = route.query
674
+ if (isSave && !query.taskId) {
675
+ visible.value = false
676
+ emit('goback')
677
+ emit('refresh', 'save', dataForm)
678
+ }
679
+ return dataForm
680
+ } finally {
681
+ loading.value = false
682
+ }
683
+ }
684
+
685
+ const saveClick = async (isSave = true, extVals = {}) => {
686
+ let isNext = await checkData(false, 'save')
687
+ if (!isNext) return false
688
+ if (oldValue.value === JSON.stringify(dataForm)) {
689
+ useMessage().info(t('message.no_changed_cannot_save'))
690
+ return
691
+ }
692
+ postData(extVals, isSave)
693
+ }
694
+ ${workflowSubmitHandle}
695
+ ${workflowOnMounted}
696
+
697
+ watch(
698
+ () => dataForm,
699
+ () => {
700
+ saveBtn.value = false
701
+ if (JSON.stringify(initForm) != JSON.stringify(dataForm) && oldValue.value != JSON.stringify(dataForm)) {
702
+ saveBtn.value = true
703
+ }
704
+ },
705
+ { deep: true, immediate: true }
706
+ )
707
+
708
+ defineExpose({
709
+ show,
710
+ oldValue,
711
+ showOperateType,
712
+ dataFormRef,
713
+ dataForm,${m.hasWorkflow ? `
714
+ submitHandle,
715
+ beforeFlow,` : ''}
716
+ checkData
717
+ })
718
+ </script>
719
+ `;
720
+ }
721
+ function getRefComponentVarName(field) {
722
+ const ref = field.refConfig;
723
+ const componentParts = ref.refComponent.split('-');
724
+ const capitalizedParts = componentParts.map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
725
+ return `${field.fieldName}Master${capitalizedParts}`;
726
+ }
727
+ function capitalizeFirst(s) {
728
+ return s.charAt(0).toUpperCase() + s.slice(1);
729
+ }
730
+ function generateDetailSection(schema, section) {
731
+ const detail = schema.detail;
732
+ const detailRowKey = detail.detailRowKey;
733
+ const columns = generateDetailTableColumns(schema);
734
+ return ` <!-- 内容容器:${detail.detailTitle} -->
735
+ <div class="basic">
736
+ <basic-container>
737
+ <el-collapse-item :title="t(\`column.\${processDefKey}.master.${detail.detailCollapseTitle}\`)" name="${section.collapseIndex}">
738
+ <!-- 按钮区域 -->
739
+ <div class="btn">
740
+ <!-- 新增 -->
741
+ <el-button icon="Plus" type="primary" @click="addDetailClick()">
742
+ {{ t('common.addBtn') }}
743
+ </el-button>
744
+ <!-- 删除 -->
745
+ <el-button
746
+ type="primary"
747
+ icon="el-icon-delete"
748
+ :disabled="isDelDisabled"
749
+ @click="deleteDetailClick()"
750
+ >
751
+ {{ t('common.delBtn') }}
752
+ </el-button>
753
+ </div>
754
+ <!-- 表格区域 -->
755
+ <el-table
756
+ :data="dataForm.${detail.detailListName}"
757
+ :row-class-name="
758
+ ({ row }) =>
759
+ detailSelectRows.find((item) => item.${detailRowKey} === row.${detailRowKey})
760
+ ? 'selectRowColor'
761
+ : ''
762
+ "
763
+ ref="detailTable"
764
+ @selection-change="detailSelectChangeHandle"
765
+ @current-change="detailCurrentRowChangeHandle"
766
+ >
767
+ <el-table-column type="selection" width="40" align="center"> </el-table-column>
768
+ <el-table-column type="index" align="center" width="70" label="序号"> </el-table-column>
769
+ ${columns}
770
+ </el-table>
771
+ </el-collapse-item>
772
+ </basic-container>
773
+ </div>`;
774
+ }
775
+ function generateDetailHandlers(schema) {
776
+ const detail = schema.detail;
777
+ const drc = detail.detailRefConfig;
778
+ const detailRowKey = detail.detailRowKey;
779
+ const listName = detail.detailListName;
780
+ // Build add detail click handler
781
+ const addMappings = [
782
+ ` id: x.${drc.idMapping.target},`,
783
+ ` name: x.${drc.nameMapping.target},`,
784
+ ];
785
+ if (drc.codeMapping) {
786
+ addMappings.push(` code: x.${drc.codeMapping.target},`);
787
+ }
788
+ drc.extraMappings.forEach(em => {
789
+ addMappings.push(` ${em.source}: x.${em.target},`);
790
+ });
791
+ // Build ok handle mappings
792
+ const okMappings = [
793
+ ` ${drc.idMapping.target}: x.${drc.idMapping.source},`,
794
+ ` ${drc.nameMapping.target}: x.${drc.nameMapping.source},`,
795
+ ];
796
+ if (drc.codeMapping) {
797
+ okMappings.push(` code: x.${drc.codeMapping.source},`);
798
+ }
799
+ drc.extraMappings.forEach(em => {
800
+ okMappings.push(` ${em.target}: x.${em.source},`);
801
+ });
802
+ if (drc.codeMapping) {
803
+ okMappings.push(` ${drc.codeMapping.target}: x.${drc.codeMapping.source}`);
804
+ }
805
+ return `
806
+ const addDetailClick = () => {
807
+ let arr = dataForm.${listName}.map((x) => {
808
+ return {
809
+ ${addMappings.join('\n')}
810
+ }
811
+ })
812
+ registeRef.value.openDialog(arr)
813
+ }
814
+ const detailRegisteOkHandle = (data) => {
815
+ dataForm.${listName} = data.map((x) => {
816
+ return {
817
+ ${okMappings.join('\n')}
818
+ }
819
+ })
820
+ nextTick(() => {
821
+ if (dataForm.${listName}.length > 0) {
822
+ detailTable.value.toggleRowSelection(dataForm.${listName}[0], true)
823
+ }
824
+ })
825
+ }
826
+ const isDelDisabled = computed(() => {
827
+ return detailSelectRows.value.length === 0 || dataForm.${listName}.length === 0
828
+ })
829
+
830
+ const deleteDetailClick = () => {
831
+ dataForm.${listName} = dataForm.${listName}.filter(
832
+ (item: any) => !detailSelectRows.value.some((ele: any) => ele.${detailRowKey} === item.${detailRowKey})
833
+ )
834
+ if (dataForm.${listName}.length > 0) {
835
+ nextTick(() => {
836
+ detailTable.value.toggleRowSelection(dataForm.${listName}[0], true)
837
+ })
838
+ } else {
839
+ Object.assign(detailCurrentRow, {})
840
+ }
841
+ }
842
+
843
+ const detailSelectChangeHandle = (rows: any) => {
844
+ Object.assign(detailCurrentRow, rows[0])
845
+ detailSelectRows.value = rows
846
+ }
847
+
848
+ const detailCurrentRowChangeHandle = (row) => {
849
+ detailSelectRows.value = []
850
+ if (row) {
851
+ Object.assign(detailCurrentRow, row)
852
+ detailTable.value.clearSelection()
853
+ detailSelectRows.value.push(row)
854
+ detailTable.value.toggleRowSelection(row, true)
855
+ }
856
+ }
857
+
858
+ const detailFormat = (row, column, cellValue, index) => {
859
+ return cellValue
860
+ }`;
861
+ }
862
+ //# sourceMappingURL=form-vue.tpl.js.map