@lambo-design/variant-form 2.2.9-beta.0 → 2.2.9-beta.1

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 (66) hide show
  1. package/README.md +201 -0
  2. package/babel.config.js +5 -0
  3. package/dist/lib/VFormDesigner.common-report.html +53 -0
  4. package/dist/lib/VFormDesigner.common.js +123773 -0
  5. package/dist/lib/VFormDesigner.common.js.map +1 -0
  6. package/dist/lib/VFormDesigner.css +1 -0
  7. package/dist/lib/VFormDesigner.umd-report.html +53 -0
  8. package/dist/lib/VFormDesigner.umd.js +123783 -0
  9. package/dist/lib/VFormDesigner.umd.js.map +1 -0
  10. package/dist/lib/VFormDesigner.umd.min-report.html +53 -0
  11. package/dist/lib/VFormDesigner.umd.min.js +222 -0
  12. package/dist/lib/demo.html +10 -0
  13. package/dist/lib/img/indicator-card-header.7291bcc9.png +0 -0
  14. package/dist/lib/img/lan_navigator.53090c9d.png +0 -0
  15. package/dist/lib/img/layout-header-bg-canglan.b1d97e4e.png +0 -0
  16. package/dist/lib/img/layout-header-bg-cuiwei.67019b6d.png +0 -0
  17. package/dist/lib/img/lv_navigator.f07fb393.png +0 -0
  18. package/index_template/index_dev.html +19 -0
  19. package/index_template/index_prod.html +28 -0
  20. package/install-render.js +29 -0
  21. package/install.js +41 -0
  22. package/jsconfig.json +10 -0
  23. package/license.txt +8 -0
  24. package/package.json +10 -4
  25. package/public/favicon.ico +0 -0
  26. package/public/index.html +19 -0
  27. package/src/App.vue +45 -0
  28. package/src/components/form-designer/designer.js +1 -0
  29. package/src/components/form-designer/form-widget/field-widget/organ-select-widget.vue +254 -0
  30. package/src/components/form-designer/form-widget/field-widget/relation-form-widget.vue +397 -0
  31. package/src/components/form-designer/form-widget/field-widget/sub-form-widget.vue +660 -0
  32. package/src/components/form-designer/form-widget/field-widget/user-select-widget.vue +333 -0
  33. package/src/components/form-designer/form-widget/index.vue +1 -1
  34. package/src/components/form-designer/index.vue +14 -12
  35. package/src/components/form-designer/setting-panel/form-setting.vue +59 -60
  36. package/src/components/form-designer/setting-panel/index.vue +2 -0
  37. package/src/components/form-designer/setting-panel/property-editor/allowMultiple-editor.vue +24 -0
  38. package/src/components/form-designer/setting-panel/property-editor/border-editor.vue +1 -1
  39. package/src/components/form-designer/setting-panel/property-editor/buttonStyle-editor.vue +1 -1
  40. package/src/components/form-designer/setting-panel/property-editor/clearable-editor.vue +1 -1
  41. package/src/components/form-designer/setting-panel/property-editor/displayFields-editor.vue +91 -0
  42. package/src/components/form-designer/setting-panel/property-editor/displayStyle-editor.vue +1 -1
  43. package/src/components/form-designer/setting-panel/property-editor/field-relation-form/relation-form-defaultValue-editor.vue +18 -0
  44. package/src/components/form-designer/setting-panel/property-editor/filterable-editor.vue +1 -1
  45. package/src/components/form-designer/setting-panel/property-editor/multipleLimit-editor.vue +1 -1
  46. package/src/components/form-designer/setting-panel/property-editor/name-editor.vue +2 -2
  47. package/src/components/form-designer/setting-panel/property-editor/operList-editor.vue +64 -0
  48. package/src/components/form-designer/setting-panel/property-editor/placeholder-editor.vue +1 -1
  49. package/src/components/form-designer/setting-panel/property-editor/relationForm-editor.vue +74 -0
  50. package/src/components/form-designer/setting-panel/property-editor/relationItems-editor.vue +91 -0
  51. package/src/components/form-designer/setting-panel/property-editor/relationType-editor.vue +67 -0
  52. package/src/components/form-designer/setting-panel/property-editor/rootOrgan-editor.vue +248 -0
  53. package/src/components/form-designer/setting-panel/property-editor/size-editor.vue +5 -5
  54. package/src/components/form-designer/setting-panel/property-editor/subFormId-editor.vue +74 -0
  55. package/src/components/form-designer/setting-panel/propertyRegister.js +144 -133
  56. package/src/components/form-designer/toolbar-panel/index.vue +11 -10
  57. package/src/components/form-designer/widget-panel/index.vue +11 -11
  58. package/src/components/form-designer/widget-panel/widgetsConfig.js +425 -297
  59. package/src/extension/extension-loader.js +1 -1
  60. package/src/icons/svg/relation-form-field.svg +1 -0
  61. package/src/lang/en-US.js +39 -0
  62. package/src/lang/zh-CN.js +42 -3
  63. package/src/main.js +29 -0
  64. package/src/utils/config.js +1 -1
  65. package/src/utils/util.js +35 -1
  66. package/vue.config.js +93 -0
@@ -0,0 +1,660 @@
1
+ <template>
2
+ <form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
3
+ :parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
4
+ :sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
5
+ <div>
6
+ <div class="sub-form-table-button">
7
+ <el-button v-if="operList.includes('insert')" size="medium" type="primary" @click="openDialog('insert')">{{ i18nt('designer.setting.actions.insert') }}</el-button>
8
+ <el-button v-if="operList.includes('batchDelete')" size="medium" @click="batchDelete">{{ i18nt('designer.setting.actions.batchDelete') }}</el-button>
9
+ </div>
10
+ <el-table ref="draggableTable" sortable="true" :data="tableData" stripe border style="width: 100%" @selection-change="handleSelectionChange">
11
+ <el-table-column type="selection" fixed="left" width="60"></el-table-column>
12
+ <el-table-column v-for="(item, index) in tableColumns" :key="index" :prop="item.columnName" :label="item.columnLabel" width="200">
13
+ <template slot-scope="scope">
14
+ {{ formatField(scope.row[item.columnName], item.widgetType) }}
15
+ </template>
16
+ </el-table-column>
17
+ <el-table-column prop="operation" label="操作" fixed="right" min-width="200px">
18
+ <template slot-scope="scope">
19
+ <el-button v-if="operList.includes('edit')" type="text" size="small" @click="openDialog('edit', scope.$index, scope.row)">{{ i18nt('designer.setting.actions.edit') }}</el-button>
20
+ <el-button v-if="operList.includes('copy')" type="text" size="small" @click="openDialog('copy', scope.$index, scope.row)">{{ i18nt('designer.setting.actions.copy') }}</el-button>
21
+ <el-button v-if="operList.includes('delete')" type="text" size="small" @click="deleteItem(scope.$index)">{{ i18nt('designer.setting.actions.delete') }}</el-button>
22
+ <el-button type="text" size="small" @click="openDialog('detail', scope.$index, scope.row)">{{ i18nt('designer.setting.actions.detail') }}</el-button>
23
+ </template>
24
+ </el-table-column>
25
+ </el-table>
26
+ <Draggable
27
+ v-model="tableData"
28
+ :animation="150"
29
+ :force-fallback="true"
30
+ fallback-class="dragging-fallback"
31
+ @end="onDragEnd"
32
+ style="display: none"
33
+ >
34
+ <transition-group>
35
+ <div v-for="(item, index) in tableData" :key="item.id" :data-index="index"></div>
36
+ </transition-group>
37
+ </Draggable>
38
+ </div>
39
+ <el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible">
40
+ <el-form label-width="120px">
41
+ <el-form-item v-for="(item, index) in tableColumns" class="edit-form-item" :key="index" :label="item.columnLabel">
42
+ <el-input v-if="item.widgetType === 'textarea'" type="textarea" v-model="rowData[item.columnName]"></el-input>
43
+ <el-input-number v-else-if="item.widgetType === 'number'" v-model="rowData[item.columnName]"></el-input-number>
44
+ <div v-else-if="item.widgetType === 'radio'">
45
+ <el-radio v-model="rowData[item.columnName]" label="单选1">单选1</el-radio>
46
+ <el-radio v-model="rowData[item.columnName]" label="单选2">单选2</el-radio>
47
+ <el-radio v-model="rowData[item.columnName]" label="单选3">单选3</el-radio>
48
+ </div>
49
+ <el-checkbox-group v-else-if="item.widgetType === 'checkbox'" v-model="rowData[item.columnName]">
50
+ <el-checkbox label="复选框1"></el-checkbox>
51
+ <el-checkbox label="复选框2"></el-checkbox>
52
+ <el-checkbox label="复选框3"></el-checkbox>
53
+ </el-checkbox-group>
54
+ <el-select v-else-if="item.widgetType === 'select'" v-model="rowData[item.columnName]">
55
+ <el-option key="选项1" label="选项1" value="选项1"></el-option>
56
+ <el-option key="选项2" label="选项2" value="选项2"></el-option>
57
+ <el-option key="选项3" label="选项3" value="选项3"></el-option>
58
+ </el-select>
59
+ <el-time-select v-else-if="item.widgetType === 'time'"
60
+ v-model="rowData[item.columnName]"
61
+ :picker-options="{start: '08:30',step: '00:15',end: '18:30'}"
62
+ placeholder="选择时间"></el-time-select>
63
+ <el-time-picker v-else-if="item.widgetType === 'time-range'"
64
+ is-range
65
+ v-model="rowData[item.columnName]"
66
+ range-separator="至"
67
+ start-placeholder="开始时间"
68
+ end-placeholder="结束时间"
69
+ placeholder="选择时间范围">
70
+ </el-time-picker>
71
+ <el-date-picker v-else-if="item.widgetType === 'date'"
72
+ v-model="rowData[item.columnName]"
73
+ type="date"
74
+ placeholder="选择日期">
75
+ </el-date-picker>
76
+ <el-date-picker v-else-if="item.widgetType === 'date-range'"
77
+ v-model="rowData[item.columnName]"
78
+ type="daterange"
79
+ range-separator="至"
80
+ start-placeholder="开始日期"
81
+ end-placeholder="结束日期">
82
+ </el-date-picker>
83
+ <el-switch v-else-if="item.widgetType === 'switch'" v-model="rowData[item.columnName]" active-value="开" inactive-value="关" active-text="开" inactive-text="关"></el-switch>
84
+ <el-input v-else v-model="rowData[item.columnName]"></el-input>
85
+ </el-form-item>
86
+ </el-form>
87
+ <div slot="footer" class="dialog-footer">
88
+ <el-button @click="dialogTableClose">取 消</el-button>
89
+ <el-button type="primary" @click="onOk">确 定</el-button>
90
+ </div>
91
+ </el-dialog>
92
+ </form-item-wrapper>
93
+ </template>
94
+
95
+ <script>
96
+ import FormItemWrapper from './form-item-wrapper'
97
+ import emitter from '@/utils/emitter'
98
+ import i18n, { translate } from "@/utils/i18n";
99
+ import Draggable from "vuedraggable";
100
+ import ajax from "@lambo-design/shared/utils/ajax";
101
+ import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
102
+
103
+ export default {
104
+ name: "sub-form-widget",
105
+ componentName: 'FieldWidget',
106
+ mixins: [emitter, fieldMixin, i18n],
107
+ props: {
108
+ field: Object,
109
+ parentWidget: Object,
110
+ parentList: Array,
111
+ indexOfParentList: Number,
112
+ designer: Object,
113
+
114
+ designState: {
115
+ type: Boolean,
116
+ default: false
117
+ },
118
+
119
+ subFormRowIndex: {
120
+ type: Number,
121
+ default: -1
122
+ },
123
+ subFormColIndex: {
124
+ type: Number,
125
+ default: -1
126
+ },
127
+ subFormRowId: {
128
+ type: String,
129
+ default: ''
130
+ },
131
+ },
132
+ components: {
133
+ FormItemWrapper,
134
+ Draggable
135
+ },
136
+ inject: ['refList', 'formConfig', 'globalOptionData', 'globalModel', 'getDesignerConfig'],
137
+ data() {
138
+ return {
139
+ operList: this.field.options.operList,
140
+ oldFieldValue: null,
141
+ fieldModel: null,
142
+ fieldModelName: null,
143
+ rules: [],
144
+ dialogFormVisible: false,
145
+
146
+ allColumns: [],
147
+ tableColumns: [],
148
+ tableData: [],
149
+ rowData: {},
150
+ curActionType: '',
151
+ currentRow: -1,
152
+ dialogTitle: '',
153
+ draggingIndex: -1,
154
+ isDragging: false,
155
+ displayFields: [],
156
+ // 存储事件处理函数的引用,便于后续移除
157
+ eventHandlers: {}
158
+ };
159
+ },
160
+ created() {
161
+ this.initFieldModel();
162
+ this.registerToRefList();
163
+ this.initEventHandler();
164
+ this.buildFieldRules();
165
+ this.handleOnCreated();
166
+ this.getDefaultDisplayFields();
167
+ },
168
+ mounted() {
169
+ this.handleOnMounted();
170
+ this.initDisplayFields(this.field.options.subFormId);
171
+ this.$nextTick(() => {
172
+ this.initRowDraggable();
173
+ });
174
+ },
175
+ beforeDestroy() {
176
+ this.unregisterFromRefList();
177
+ this.removeRowDragEvents();
178
+ },
179
+ methods: {
180
+ // 清除所有行的拖拽事件
181
+ removeRowDragEvents() {
182
+ const table = this.$refs.draggableTable;
183
+ if (!table) return;
184
+
185
+ const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');
186
+ if (!tbody) return;
187
+
188
+ const rows = tbody.querySelectorAll('.el-table__row');
189
+ rows.forEach((row, index) => {
190
+ // 移除所有事件监听
191
+ if (this.eventHandlers[`dragstart-${index}`]) {
192
+ row.removeEventListener('dragstart', this.eventHandlers[`dragstart-${index}`]);
193
+ }
194
+ if (this.eventHandlers[`dragend-${index}`]) {
195
+ row.removeEventListener('dragend', this.eventHandlers[`dragend-${index}`]);
196
+ }
197
+ if (this.eventHandlers[`dragover-${index}`]) {
198
+ row.removeEventListener('dragover', this.eventHandlers[`dragover-${index}`]);
199
+ }
200
+ if (this.eventHandlers[`dragleave-${index}`]) {
201
+ row.removeEventListener('dragleave', this.eventHandlers[`dragleave-${index}`]);
202
+ }
203
+ if (this.eventHandlers[`drop-${index}`]) {
204
+ row.removeEventListener('drop', this.eventHandlers[`drop-${index}`]);
205
+ }
206
+
207
+ row.removeAttribute('draggable');
208
+ row.classList.remove('dragging', 'drag-over');
209
+ row.style.cursor = '';
210
+ });
211
+
212
+ // 清空事件处理函数引用
213
+ this.eventHandlers = {};
214
+ },
215
+
216
+ // 初始化行拖拽功能
217
+ initRowDraggable() {
218
+ this.removeRowDragEvents();
219
+ if (!this.operList.includes('draggable')) return;
220
+
221
+ const table = this.$refs.draggableTable;
222
+ if (!table) return;
223
+
224
+ const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');
225
+ if (!tbody) return;
226
+
227
+ const rows = tbody.querySelectorAll('.el-table__row');
228
+ rows.forEach((row, index) => {
229
+ // 为每行创建独立的事件处理函数,确保正确的索引绑定
230
+ this.eventHandlers[`dragstart-${index}`] = (e) => this.handleDragStart(e, index);
231
+ this.eventHandlers[`dragend-${index}`] = (e) => this.handleDragEnd(e);
232
+ this.eventHandlers[`dragover-${index}`] = (e) => this.handleDragOver(e);
233
+ this.eventHandlers[`dragleave-${index}`] = (e) => this.handleDragLeave(e);
234
+ this.eventHandlers[`drop-${index}`] = (e) => this.handleDrop(e, index);
235
+
236
+ // 绑定事件
237
+ row.setAttribute('draggable', 'true');
238
+ row.style.cursor = 'move';
239
+ row.addEventListener('dragstart', this.eventHandlers[`dragstart-${index}`]);
240
+ row.addEventListener('dragend', this.eventHandlers[`dragend-${index}`]);
241
+ row.addEventListener('dragover', this.eventHandlers[`dragover-${index}`]);
242
+ row.addEventListener('dragleave', this.eventHandlers[`dragleave-${index}`]);
243
+ row.addEventListener('drop', this.eventHandlers[`drop-${index}`]);
244
+ });
245
+ },
246
+
247
+ // 拖拽开始处理
248
+ handleDragStart(e, index) {
249
+ if (this.isDragging) return;
250
+ this.isDragging = true;
251
+ this.draggingIndex = index;
252
+ const row = e.currentTarget;
253
+ row.classList.add('dragging');
254
+
255
+ // 设置拖拽数据
256
+ e.dataTransfer.setData('text/plain', index.toString());
257
+
258
+ // 创建自定义拖拽图像
259
+ // const dragImage = document.createElement('div');
260
+ // dragImage.textContent = `移动行 ${index + 1}`;
261
+ // dragImage.style.position = 'absolute';
262
+ // dragImage.style.left = '-9999px';
263
+ // dragImage.dataset.dragImage = 'true';
264
+ // document.body.appendChild(dragImage);
265
+ // e.dataTransfer.setDragImage(dragImage, 0, 0);
266
+ },
267
+
268
+ // 拖拽结束处理
269
+ handleDragEnd(e) {
270
+ this.isDragging = false;
271
+ this.draggingIndex = -1;
272
+ const row = e.currentTarget;
273
+ row.classList.remove('dragging');
274
+
275
+ // 清理拖拽图像
276
+ // const dragImages = document.querySelectorAll('[data-drag-image="true"]');
277
+ // dragImages.forEach(img => img.remove());
278
+ },
279
+
280
+ // 拖拽经过处理
281
+ handleDragOver(e) {
282
+ e.preventDefault();
283
+ if (this.isDragging) {
284
+ const row = e.currentTarget;
285
+ row.classList.add('drag-over');
286
+ }
287
+ },
288
+
289
+ // 拖拽离开处理
290
+ handleDragLeave(e) {
291
+ const row = e.currentTarget;
292
+ row.classList.remove('drag-over');
293
+ },
294
+
295
+ // 放置处理
296
+ handleDrop(e, toIndex) {
297
+ e.preventDefault();
298
+ const row = e.currentTarget;
299
+ row.classList.remove('drag-over');
300
+
301
+ if (!this.isDragging) return;
302
+
303
+ const fromIndex = parseInt(e.dataTransfer.getData('text/plain'));
304
+
305
+ if (fromIndex !== toIndex && !isNaN(fromIndex)) {
306
+ // 执行数据移动
307
+ const [movedItem] = this.tableData.splice(fromIndex, 1);
308
+ this.tableData.splice(toIndex, 0, movedItem);
309
+
310
+ // 触发Vue数据更新
311
+ this.tableData = [...this.tableData];
312
+
313
+ // 重新初始化拖拽,确保所有行(包括新位置的行)都能正常拖拽
314
+ this.$nextTick(() => {
315
+ this.initRowDraggable();
316
+ });
317
+ }
318
+
319
+ this.isDragging = false;
320
+ },
321
+
322
+ // 拖拽结束后重新初始化
323
+ onDragEnd() {
324
+ this.$nextTick(() => {
325
+ this.initRowDraggable();
326
+ });
327
+ },
328
+ openDialog(actionType, index, row) {
329
+ this.curActionType = actionType;
330
+ this.currentRow = index;
331
+ this.dialogTitle = translate(`designer.setting.actions.${actionType}`);
332
+ console.log(`点击了${this.dialogTitle}`);
333
+ // if (actionType === 'insert') {
334
+ // this.rowData = this.tableColumns.reduce((acc, cur) => {
335
+ // switch (cur.widgetType) {
336
+ // case 'checkbox':
337
+ // acc[cur.columnName] = [];
338
+ // break;
339
+ // case 'time':
340
+ // acc[cur.columnName] = '';
341
+ // break;
342
+ // case 'time-range':
343
+ // acc[cur.columnName] = [new Date(2025, 9, 10, 8, 40), new Date(2025, 9, 10, 9, 40)];
344
+ // break;
345
+ // case 'date':
346
+ // acc[cur.columnName] = '';
347
+ // break;
348
+ // case 'date-range':
349
+ // acc[cur.columnName] = [];
350
+ // break;
351
+ // default:
352
+ // acc[cur.columnName] = '';
353
+ // break;
354
+ // }
355
+ // return acc;
356
+ // }, {});
357
+ // } else {
358
+ // this.rowData = JSON.parse(JSON.stringify(row));
359
+ // this.tableColumns.forEach(cur => {
360
+ // if (cur.widgetType === 'date' && typeof this.rowData[cur.columnName] === 'string') {
361
+ // this.rowData[cur.columnName] = new Date(this.rowData[cur.columnName]);
362
+ // }
363
+ // });
364
+ // }
365
+ //
366
+ // this.dialogFormVisible = true;
367
+ },
368
+ deleteItem(index) {
369
+ console.log('点击了删除');
370
+ // this.tableData.splice(index, 1);
371
+ // this.$nextTick(() => {
372
+ // this.initRowDraggable();
373
+ // });
374
+ },
375
+
376
+ // 批量删除
377
+ batchDelete() {
378
+ console.log('点击了批量删除');
379
+ // if (this.multipleSelection && this.multipleSelection.length > 0) {
380
+ // this.$alert(translate('designer.setting.batchDeleteConfirm'), translate('designer.setting.actions.batchDelete'), {
381
+ // confirmButtonText: translate('designer.hint.confirm'),
382
+ // callback: action => {
383
+ // const idsToDelete = this.multipleSelection.map(item => item.id);
384
+ // this.tableData = this.tableData.filter(item => !idsToDelete.includes(item.id));
385
+ // this.$nextTick(() => {
386
+ // this.initRowDraggable(); // 批量删除后重新初始化拖拽
387
+ // });
388
+ // }
389
+ // });
390
+ // }
391
+ },
392
+
393
+ // 处理选择变化
394
+ handleSelectionChange(val) {
395
+ this.multipleSelection = val;
396
+ },
397
+
398
+ // 关闭对话框
399
+ dialogTableClose() {
400
+ this.dialogFormVisible = false;
401
+ },
402
+
403
+ // 格式化字段显示
404
+ formatField(value, type) {
405
+ if (!value) return '';
406
+
407
+ if (type === 'time') {
408
+ if (typeof value === 'string') return value;
409
+ const date = new Date(value);
410
+ return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
411
+ }
412
+
413
+ if (type === 'time-range') {
414
+ if (!Array.isArray(value) || value.length !== 2) return '';
415
+
416
+ const formatSingleTime = (time) => {
417
+ if (typeof time === 'string') {
418
+ return time;
419
+ }
420
+ const date = new Date(time);
421
+ return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
422
+ };
423
+
424
+ const formattedTimes = value.map(formatSingleTime);
425
+ return `[${formattedTimes[0]}, ${formattedTimes[1]}]`;
426
+ }
427
+
428
+ return value;
429
+ },
430
+
431
+ onOk() {
432
+ const submitData = JSON.parse(JSON.stringify(this.rowData));
433
+
434
+ this.tableColumns.forEach(column => {
435
+ if (column.widgetType === 'date' && submitData[column.columnName]) {
436
+ const date = new Date(submitData[column.columnName]);
437
+ submitData[column.columnName] = date.toISOString().split('T')[0];
438
+ }
439
+
440
+ if (column.widgetType === 'time-range' && submitData[column.columnName]) {
441
+ if (Array.isArray(submitData[column.columnName]) && submitData[column.columnName].length === 2) {
442
+ submitData[column.columnName] = submitData[column.columnName].map(time => {
443
+ return new Date(time);
444
+ });
445
+ }
446
+ }
447
+
448
+ if (column.widgetType === 'date-range' && submitData[column.columnName]) {
449
+ if (Array.isArray(submitData[column.columnName]) && submitData[column.columnName].length === 2) {
450
+ submitData[column.columnName] = submitData[column.columnName].map(time => {
451
+ const date = new Date(time);
452
+ const year = date.getFullYear();
453
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
454
+ const day = date.getDate().toString().padStart(2, '0');
455
+ return `${year}-${month}-${day}`;
456
+ });
457
+ }
458
+ }
459
+ });
460
+
461
+ switch (this.curActionType) {
462
+ case 'insert':
463
+ submitData.id = Date.now();
464
+ this.tableData.push(submitData);
465
+ break;
466
+ case 'edit':
467
+ this.tableData.splice(this.currentRow, 1, submitData);
468
+ break;
469
+ case 'copy':
470
+ submitData.id = Date.now() + Math.floor(Math.random() * 1000);
471
+ this.tableData.push(submitData);
472
+ break;
473
+ case 'detail':
474
+ this.dialogFormVisible = false;
475
+ return;
476
+ }
477
+
478
+ this.dialogFormVisible = false;
479
+
480
+ this.$nextTick(() => {
481
+ this.initRowDraggable();
482
+ });
483
+ },
484
+
485
+ // 获取默认显示字段
486
+ getDefaultDisplayFields() {
487
+ this.tableColumns = [
488
+ {
489
+ columnLabel: '展示字段一',
490
+ columnName: 'example1',
491
+ widgetType: 'textarea'
492
+ },
493
+ {
494
+ columnLabel: '展示字段二',
495
+ columnName: 'example2',
496
+ widgetType: 'number'
497
+ },
498
+ {
499
+ columnLabel: '展示字段三',
500
+ columnName: 'example3',
501
+ widgetType: 'radio'
502
+ },
503
+ ];
504
+
505
+ this.tableData = [
506
+ {
507
+ id: 1,
508
+ example1: '示例数据1',
509
+ example2: 100,
510
+ example3: '单选1'
511
+ },
512
+ {
513
+ id: 2,
514
+ example1: '示例数据2',
515
+ example2: 200,
516
+ example3: '单选2'
517
+ },
518
+ {
519
+ id: 3,
520
+ example1: '示例数据3',
521
+ example2: 300,
522
+ example3: '单选3'
523
+ },
524
+ ];
525
+
526
+ this.$nextTick(() => {
527
+ this.initRowDraggable();
528
+ });
529
+ },
530
+
531
+ // 获取默认数据
532
+ getDefaultData(tableColumns) {
533
+ this.tableData = [];
534
+ for (let i = 1; i < 4; i++) {
535
+ const data = { id: i };
536
+ tableColumns.forEach(cur => {
537
+ switch (cur.widgetType) {
538
+ case 'number':
539
+ data[cur.columnName] = i;
540
+ break;
541
+ case 'radio':
542
+ data[cur.columnName] = `单选${i}`;
543
+ break;
544
+ case 'checkbox':
545
+ data[cur.columnName] = [`复选框${i}`];
546
+ break;
547
+ case 'select':
548
+ data[cur.columnName] = `选项${i}`;
549
+ break;
550
+ case 'time':
551
+ data[cur.columnName] = '18:40';
552
+ break;
553
+ case 'time-range':
554
+ data[cur.columnName] = [new Date(2025, 9, 29, 8, 40), new Date(2025, 9, 29, 9, 40)];
555
+ break;
556
+ case 'date':
557
+ data[cur.columnName] = '2025-09-29';
558
+ break;
559
+ case 'date-range':
560
+ data[cur.columnName] = ['2025-09-29', '2025-10-07'];
561
+ break;
562
+ case 'switch':
563
+ data[cur.columnName] = i % 2 === 0 ? '开' : '关';
564
+ break;
565
+ default:
566
+ data[cur.columnName] = `示例数据${i}`;
567
+ break;
568
+ }
569
+ });
570
+ this.tableData.push(data);
571
+ }
572
+ },
573
+
574
+ // 初始化显示字段
575
+ initDisplayFields(subFormId) {
576
+ const self = this;
577
+ if(this.field.options.subFormId) {
578
+ let url = "/dida-manage-server/manage/form-materialization-table-meta-info/getSpecificTypeMetaInfos?formId="+subFormId;
579
+ ajax.get(url)
580
+ .then(resp => {
581
+ if (resp.data && (resp.data.code == 1 || resp.data.code == 200)) {
582
+ self.allColumns = resp.data.data;
583
+ self.tableColumns = self.allColumns.filter(column => self.displayFields.includes(column.columnName)).map(item =>{
584
+ return {
585
+ columnName: item.columnName,
586
+ columnLabel: item.columnLabel,
587
+ widgetType: item.widgetType
588
+ }
589
+ });
590
+ self.tableColumns.length > 0 ? self.getDefaultData(self.tableColumns) : self.getDefaultDisplayFields();
591
+ } else {
592
+ self.getDefaultDisplayFields();
593
+ console.error(resp.data.message);
594
+ }
595
+ })
596
+ .catch(err => {
597
+ self.getDefaultDisplayFields();
598
+ console.error(err);
599
+ });
600
+ } else {
601
+ this.getDefaultDisplayFields();
602
+ }
603
+ this.$nextTick(() => {
604
+ this.initRowDraggable();
605
+ });
606
+ },
607
+ },
608
+ watch: {
609
+ 'field.options.operList'(newValue) {
610
+ this.operList = newValue;
611
+ this.initRowDraggable();
612
+ },
613
+ 'field.options.displayFields'(newValue) {
614
+ const self = this;
615
+ self.displayFields = newValue;
616
+ if (self.field.options.displayFields && !self.allColumns){
617
+ this.initDisplayFields(self.field.options.subFormId);
618
+ return
619
+ }
620
+ self.tableColumns = self.allColumns.filter(column => self.displayFields.includes(column.columnName)).map(item =>{
621
+ return {
622
+ columnName: item.columnName,
623
+ columnLabel: item.columnLabel,
624
+ widgetType: item.widgetType
625
+ }
626
+ });
627
+ self.tableColumns.length > 0 ? self.getDefaultData(self.tableColumns) : self.getDefaultDisplayFields();
628
+ },
629
+ 'field.options.subFormId'(newValue) {
630
+ this.initDisplayFields(newValue);
631
+ },
632
+ // 监听表格数据变化,确保新数据行能被正确初始化拖拽
633
+ 'tableData': {
634
+ handler() {
635
+ this.$nextTick(() => {
636
+ this.initRowDraggable();
637
+ });
638
+ },
639
+ deep: true
640
+ }
641
+ }
642
+ };
643
+ </script>
644
+
645
+ <style lang="scss" scoped>
646
+ @import "../../../../styles/global.scss"; //* form-item-wrapper已引入,还需要重复引入吗? *//
647
+
648
+ .full-width-input {
649
+ width: 100% !important;
650
+ }
651
+
652
+ .sub-form-table-button {
653
+ float: right;
654
+ margin: 8px;
655
+ }
656
+ .edit-form-item{
657
+ margin-top: 16px;
658
+ }
659
+
660
+ </style>