@tmagic/form 1.1.6 → 1.2.0-beta.10

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 (76) hide show
  1. package/dist/tmagic-form.mjs +2318 -2632
  2. package/dist/tmagic-form.mjs.map +1 -1
  3. package/dist/tmagic-form.umd.js +2341 -2656
  4. package/dist/tmagic-form.umd.js.map +1 -1
  5. package/package.json +5 -5
  6. package/src/Form.vue +123 -158
  7. package/src/FormDialog.vue +140 -158
  8. package/src/containers/Col.vue +22 -38
  9. package/src/containers/Container.vue +138 -171
  10. package/src/containers/Fieldset.vue +12 -8
  11. package/src/containers/GroupList.vue +80 -112
  12. package/src/containers/GroupListItem.vue +87 -124
  13. package/src/containers/Panel.vue +26 -49
  14. package/src/containers/Row.vue +18 -40
  15. package/src/containers/Step.vue +36 -48
  16. package/src/containers/Table.vue +449 -479
  17. package/src/containers/Tabs.vue +92 -118
  18. package/src/fields/Cascader.vue +88 -136
  19. package/src/fields/Checkbox.vue +46 -50
  20. package/src/fields/CheckboxGroup.vue +39 -35
  21. package/src/fields/ColorPicker.vue +5 -3
  22. package/src/fields/Date.vue +20 -26
  23. package/src/fields/DateTime.vue +31 -39
  24. package/src/fields/Daterange.vue +4 -3
  25. package/src/fields/Display.vue +1 -1
  26. package/src/fields/DynamicField.vue +63 -77
  27. package/src/fields/Hidden.vue +1 -1
  28. package/src/fields/Link.vue +65 -86
  29. package/src/fields/Number.vue +32 -34
  30. package/src/fields/RadioGroup.vue +23 -23
  31. package/src/fields/Select.vue +294 -321
  32. package/src/fields/SelectOptionGroups.vue +11 -6
  33. package/src/fields/SelectOptions.vue +5 -3
  34. package/src/fields/Switch.vue +46 -49
  35. package/src/fields/Text.vue +99 -107
  36. package/src/fields/Textarea.vue +32 -44
  37. package/src/fields/Time.vue +19 -30
  38. package/src/index.ts +22 -23
  39. package/src/schema.ts +46 -12
  40. package/src/utils/form.ts +4 -0
  41. package/types/Form.vue.d.ts +211 -111
  42. package/types/FormDialog.vue.d.ts +809 -154
  43. package/types/containers/Col.vue.d.ts +92 -40
  44. package/types/containers/Container.vue.d.ts +122 -65
  45. package/types/containers/Fieldset.vue.d.ts +1 -3
  46. package/types/containers/GroupList.vue.d.ts +86 -53
  47. package/types/containers/GroupListItem.vue.d.ts +97 -67
  48. package/types/containers/Panel.vue.d.ts +92 -39
  49. package/types/containers/Row.vue.d.ts +92 -39
  50. package/types/containers/Step.vue.d.ts +102 -42
  51. package/types/containers/Table.vue.d.ts +157 -130
  52. package/types/containers/Tabs.vue.d.ts +93 -50
  53. package/types/fields/Cascader.vue.d.ts +95 -71
  54. package/types/fields/Checkbox.vue.d.ts +95 -56
  55. package/types/fields/CheckboxGroup.vue.d.ts +95 -53
  56. package/types/fields/ColorPicker.vue.d.ts +1 -3
  57. package/types/fields/Date.vue.d.ts +95 -54
  58. package/types/fields/DateTime.vue.d.ts +95 -54
  59. package/types/fields/Daterange.vue.d.ts +1 -3
  60. package/types/fields/Display.vue.d.ts +1 -3
  61. package/types/fields/DynamicField.vue.d.ts +95 -64
  62. package/types/fields/Hidden.vue.d.ts +1 -3
  63. package/types/fields/Link.vue.d.ts +60 -657
  64. package/types/fields/Number.vue.d.ts +99 -56
  65. package/types/fields/RadioGroup.vue.d.ts +96 -52
  66. package/types/fields/Select.vue.d.ts +97 -65
  67. package/types/fields/SelectOptionGroups.vue.d.ts +1 -3
  68. package/types/fields/SelectOptions.vue.d.ts +1 -3
  69. package/types/fields/Switch.vue.d.ts +95 -56
  70. package/types/fields/Text.vue.d.ts +98 -57
  71. package/types/fields/Textarea.vue.d.ts +100 -60
  72. package/types/fields/Time.vue.d.ts +95 -55
  73. package/types/index.d.ts +0 -1
  74. package/types/schema.d.ts +38 -9
  75. package/src/utils/fieldProps.ts +0 -39
  76. package/types/utils/fieldProps.d.ts +0 -21
@@ -2,12 +2,12 @@
2
2
  <div ref="mTable" class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
3
3
  <span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
4
4
  <div class="el-form-item__content">
5
- <el-tooltip content="拖拽可排序" placement="left-start" :disabled="config.dropSort !== true">
6
- <el-table
5
+ <TMagicTooltip content="拖拽可排序" placement="left-start" :disabled="config.dropSort !== true">
6
+ <TMagicTable
7
7
  v-if="model[modelName]"
8
- ref="elTable"
8
+ ref="tMagicTable"
9
9
  style="width: 100%"
10
- :data="model[modelName]"
10
+ :data="data"
11
11
  :border="config.border"
12
12
  :max-height="config.maxHeight"
13
13
  :default-expand-all="true"
@@ -15,31 +15,36 @@
15
15
  @select="selectHandle"
16
16
  @sort-change="sortChange"
17
17
  >
18
- <el-table-column v-if="config.itemExtra" :fixed="'left'" width="30" type="expand">
18
+ <TMagicTableColumn v-if="config.itemExtra" :fixed="'left'" width="30" type="expand">
19
19
  <template v-slot="scope">
20
20
  <span v-html="itemExtra(config.itemExtra, scope.$index)" class="m-form-tip"></span>
21
21
  </template>
22
- </el-table-column>
22
+ </TMagicTableColumn>
23
23
 
24
- <el-table-column label="操作" width="55" align="center" :fixed="config.fixed === false ? undefined : 'left'">
24
+ <TMagicTableColumn
25
+ label="操作"
26
+ width="55"
27
+ align="center"
28
+ :fixed="config.fixed === false ? undefined : 'left'"
29
+ >
25
30
  <template v-slot="scope">
26
- <el-icon
31
+ <TMagicIcon
27
32
  v-show="showDelete(scope.$index + 1 + pagecontext * pagesize - 1)"
28
33
  class="m-table-delete-icon"
29
34
  @click="removeHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
30
35
  ><Delete
31
- /></el-icon>
36
+ /></TMagicIcon>
32
37
  </template>
33
- </el-table-column>
38
+ </TMagicTableColumn>
34
39
 
35
- <el-table-column v-if="sort && model[modelName] && model[modelName].length > 1" label="排序" width="60">
40
+ <TMagicTableColumn v-if="sort && model[modelName] && model[modelName].length > 1" label="排序" width="60">
36
41
  <template v-slot="scope">
37
- <el-tooltip
42
+ <TMagicTooltip
43
+ v-if="scope.$index + 1 + pagecontext * pagesize - 1 !== 0"
38
44
  content="点击上移,双击置顶"
39
45
  placement="top"
40
- v-if="scope.$index + 1 + pagecontext * pagesize - 1 !== 0"
41
46
  >
42
- <el-button
47
+ <TMagicButton
43
48
  plain
44
49
  size="small"
45
50
  type="primary"
@@ -47,14 +52,14 @@
47
52
  text
48
53
  @click="upHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
49
54
  @dblclick="topHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
50
- ></el-button>
51
- </el-tooltip>
52
- <el-tooltip
55
+ ></TMagicButton>
56
+ </TMagicTooltip>
57
+ <TMagicTooltip
58
+ v-if="scope.$index + 1 + pagecontext * pagesize - 1 !== model[modelName].length - 1"
53
59
  content="点击下移,双击置底"
54
60
  placement="top"
55
- v-if="scope.$index + 1 + pagecontext * pagesize - 1 !== model[modelName].length - 1"
56
61
  >
57
- <el-button
62
+ <TMagicButton
58
63
  plain
59
64
  size="small"
60
65
  type="primary"
@@ -62,25 +67,25 @@
62
67
  text
63
68
  @click="downHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
64
69
  @dblclick="bottomHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
65
- ></el-button>
66
- </el-tooltip>
70
+ ></TMagicButton>
71
+ </TMagicTooltip>
67
72
  </template>
68
- </el-table-column>
73
+ </TMagicTableColumn>
69
74
 
70
- <el-table-column
75
+ <TMagicTableColumn
71
76
  v-if="selection"
72
77
  align="center"
73
78
  header-align="center"
74
79
  type="selection"
75
80
  width="45"
76
- ></el-table-column>
81
+ ></TMagicTableColumn>
77
82
 
78
- <el-table-column width="60" label="序号" v-if="showIndex && config.showIndex">
83
+ <TMagicTableColumn width="60" label="序号" v-if="showIndex && config.showIndex">
79
84
  <template v-slot="scope">{{ scope.$index + 1 + pagecontext * pagesize }}</template>
80
- </el-table-column>
85
+ </TMagicTableColumn>
81
86
 
82
87
  <template v-for="(column, index) in config.items">
83
- <el-table-column
88
+ <TMagicTableColumn
84
89
  v-if="column.type !== 'hidden' && display(column.display)"
85
90
  :prop="column.name"
86
91
  :width="column.width"
@@ -91,7 +96,7 @@
91
96
  :class-name="config.dropSort === true ? 'el-table__column--dropable' : ''"
92
97
  >
93
98
  <template #default="scope">
94
- <m-form-container
99
+ <Container
95
100
  v-if="scope.$index > -1"
96
101
  labelWidth="0"
97
102
  :prop="getProp(scope.$index)"
@@ -100,18 +105,23 @@
100
105
  :model="scope.row"
101
106
  :size="size"
102
107
  @change="$emit('change', model[modelName])"
103
- ></m-form-container>
108
+ ></Container>
104
109
  </template>
105
- </el-table-column>
110
+ </TMagicTableColumn>
106
111
  </template>
107
- </el-table>
108
- </el-tooltip>
112
+ </TMagicTable>
113
+ </TMagicTooltip>
109
114
  <slot></slot>
110
- <el-button v-if="addable" size="small" type="primary" plain @click="newHandler()">添加</el-button> &nbsp;
111
- <el-button :icon="Grid" size="small" type="primary" @click="toggleMode" v-if="enableToggleMode && !isFullscreen"
112
- >展开配置</el-button
115
+ <TMagicButton v-if="addable" size="small" type="primary" plain @click="newHandler()">添加</TMagicButton> &nbsp;
116
+ <TMagicButton
117
+ :icon="Grid"
118
+ size="small"
119
+ type="primary"
120
+ @click="toggleMode"
121
+ v-if="enableToggleMode && !isFullscreen"
122
+ >展开配置</TMagicButton
113
123
  >
114
- <el-button
124
+ <TMagicButton
115
125
  :icon="FullScreen"
116
126
  size="small"
117
127
  type="primary"
@@ -119,8 +129,8 @@
119
129
  v-if="config.enableFullscreen !== false"
120
130
  >
121
131
  {{ isFullscreen ? '退出全屏' : '全屏编辑' }}
122
- </el-button>
123
- <el-upload
132
+ </TMagicButton>
133
+ <TMagicUpload
124
134
  v-if="importable"
125
135
  ref="excelBtn"
126
136
  action="/noop"
@@ -128,13 +138,13 @@
128
138
  :auto-upload="false"
129
139
  style="display: inline-block"
130
140
  >
131
- <el-button size="small" type="success" plain>导入EXCEL</el-button> </el-upload
141
+ <TMagicButton size="small" type="success" plain>导入EXCEL</TMagicButton> </TMagicUpload
132
142
  >&nbsp;
133
- <el-button v-if="importable" size="small" type="warning" plain @click="clearHandler()">清空</el-button>
143
+ <TMagicButton v-if="importable" size="small" type="warning" plain @click="clearHandler()">清空</TMagicButton>
134
144
  </div>
135
145
 
136
- <div class="bottom" style="text-align: right">
137
- <el-pagination
146
+ <div class="bottom" style="text-align: right" v-if="config.pagination">
147
+ <TMagicPagination
138
148
  layout="total, sizes, prev, pager, next, jumper"
139
149
  :hide-on-single-page="model[modelName].length < pagesize"
140
150
  :current-page="pagecontext + 1"
@@ -144,470 +154,430 @@
144
154
  @size-change="handleSizeChange"
145
155
  @current-change="handleCurrentChange"
146
156
  >
147
- </el-pagination>
157
+ </TMagicPagination>
148
158
  </div>
149
159
  </div>
150
160
  </template>
151
161
 
152
- <script lang="ts">
153
- /* eslint-disable no-param-reassign */
154
- import { computed, defineComponent, inject, onMounted, PropType, ref, toRefs } from 'vue';
162
+ <script setup lang="ts" name="MFormTable">
163
+ import { computed, inject, onMounted, ref, toRefs, watchEffect } from 'vue';
155
164
  import { ArrowDown, ArrowUp, Delete, FullScreen, Grid } from '@element-plus/icons-vue';
156
- import { ElMessage, UploadFile } from 'element-plus';
157
165
  import { cloneDeep } from 'lodash-es';
158
166
  import Sortable, { SortableEvent } from 'sortablejs';
159
167
 
168
+ import {
169
+ TMagicButton,
170
+ TMagicIcon,
171
+ tMagicMessage,
172
+ TMagicPagination,
173
+ TMagicTable,
174
+ TMagicTableColumn,
175
+ TMagicTooltip,
176
+ TMagicUpload,
177
+ } from '@tmagic/design';
160
178
  import { asyncLoadJs, sleep } from '@tmagic/utils';
161
179
 
162
180
  import { ColumnConfig, FormState, SortProp, TableConfig } from '../schema';
163
- import { display, initValue } from '../utils/form';
164
-
165
- export default defineComponent({
166
- props: {
167
- name: {
168
- type: String,
169
- required: true,
170
- },
171
-
172
- model: {
173
- type: Object,
174
- required: true,
175
- default: () => ({}),
176
- },
177
-
178
- config: {
179
- type: Object as PropType<TableConfig>,
180
- required: true,
181
- default: () => ({}),
182
- },
183
-
184
- prop: {
185
- type: String,
186
- },
187
-
188
- labelWidth: {
189
- type: String,
190
- },
191
-
192
- sort: {
193
- type: Boolean,
194
- default: false,
195
- },
196
-
197
- sortKey: {
198
- type: String,
199
- default: '',
200
- },
201
-
202
- text: {
203
- type: String,
204
- },
205
-
206
- size: String,
207
-
208
- enableToggleMode: {
209
- type: Boolean,
210
- default: true,
211
- },
212
-
213
- showIndex: {
214
- type: Boolean,
215
- default: true,
216
- },
181
+ import { display as displayFunc, initValue } from '../utils/form';
182
+
183
+ import Container from './Container.vue';
184
+
185
+ const props = withDefaults(
186
+ defineProps<{
187
+ model: any;
188
+ config: TableConfig;
189
+ name: string;
190
+ prop?: string;
191
+ labelWidth?: string;
192
+ sort?: boolean;
193
+ sortKey?: string;
194
+ text?: string;
195
+ size?: string;
196
+ enableToggleMode?: boolean;
197
+ showIndex?: boolean;
198
+ }>(),
199
+ {
200
+ prop: '',
201
+ sortKey: '',
202
+ enableToggleMode: true,
203
+ showIndex: true,
217
204
  },
218
-
219
- emits: ['change', 'select'],
220
-
221
- components: { Delete },
222
-
223
- setup(props, { emit }) {
224
- let timer: any | null = null;
225
- const mForm = inject<FormState | undefined>('mForm');
226
-
227
- const elTable = ref<any>();
228
- const excelBtn = ref<any>();
229
- const mTable = ref<HTMLDivElement>();
230
-
231
- const pagesize = ref(10);
232
- const pagecontext = ref(0);
233
- const updateKey = ref(1);
234
- const isFullscreen = ref(false);
235
-
236
- const modelName = computed(() => props.name || props.config.name || '');
237
-
238
- const sortChange = ({ prop, order }: SortProp) => {
239
- if (order === 'ascending') {
240
- props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => a[prop] - b[prop]);
241
- } else if (order === 'descending') {
242
- props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => b[prop] - a[prop]);
243
- }
244
- };
245
-
246
- const foreUpdate = () => {
247
- updateKey.value += 1;
248
- setTimeout(() => rowDrop());
249
- };
250
-
251
- const swapArray = (index1: number, index2: number) => {
252
- [props.model[modelName.value][index1]] = props.model[modelName.value].splice(
253
- index2,
254
- 1,
255
- props.model[modelName.value][index1],
256
- );
257
- if (props.sortKey) {
258
- for (let i = props.model[modelName.value].length - 1, v = 0; i >= 0; i--, v++) {
259
- props.model[modelName.value][v][props.sortKey] = i;
260
- }
261
- }
262
- mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
263
- };
264
-
265
- const rowDrop = () => {
266
- const tableEl = elTable.value?.$el;
267
- if (tableEl?.querySelectorAll('.el-table__body > tbody')) {
268
- // eslint-disable-next-line prefer-destructuring
269
- const el = tableEl.querySelectorAll('.el-table__body > tbody')[0];
270
- const sortable = Sortable.create(el, {
271
- onEnd: ({ newIndex, oldIndex }: SortableEvent) => {
272
- if (typeof newIndex === 'undefined') return;
273
- if (typeof oldIndex === 'undefined') return;
274
- swapArray(newIndex, oldIndex);
275
- emit('change', props.model[modelName.value]);
276
- foreUpdate();
277
- sortable.destroy();
278
- mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
205
+ );
206
+
207
+ const emit = defineEmits(['change', 'select']);
208
+
209
+ let timer: any | null = null;
210
+ const mForm = inject<FormState | undefined>('mForm');
211
+
212
+ const tMagicTable = ref<InstanceType<typeof TMagicTable>>();
213
+ const excelBtn = ref<InstanceType<typeof TMagicUpload>>();
214
+ const mTable = ref<HTMLDivElement>();
215
+
216
+ const pagesize = ref(10);
217
+ const pagecontext = ref(0);
218
+ const updateKey = ref(1);
219
+ const isFullscreen = ref(false);
220
+
221
+ const modelName = computed(() => props.name || props.config.name || '');
222
+
223
+ const data = computed(() =>
224
+ props.config.pagination
225
+ ? props.model[modelName.value].filter(
226
+ (item: any, index: number) =>
227
+ index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value,
228
+ )
229
+ : props.model[modelName.value],
230
+ );
231
+
232
+ const sortChange = ({ prop, order }: SortProp) => {
233
+ if (order === 'ascending') {
234
+ props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => a[prop] - b[prop]);
235
+ } else if (order === 'descending') {
236
+ props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => b[prop] - a[prop]);
237
+ }
238
+ };
239
+
240
+ const foreUpdate = () => {
241
+ updateKey.value += 1;
242
+ setTimeout(() => rowDrop());
243
+ };
244
+
245
+ const swapArray = (index1: number, index2: number) => {
246
+ [props.model[modelName.value][index1]] = props.model[modelName.value].splice(
247
+ index2,
248
+ 1,
249
+ props.model[modelName.value][index1],
250
+ );
251
+ if (props.sortKey) {
252
+ for (let i = props.model[modelName.value].length - 1, v = 0; i >= 0; i--, v++) {
253
+ props.model[modelName.value][v][props.sortKey] = i;
254
+ }
255
+ }
256
+ mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
257
+ };
258
+
259
+ const rowDrop = () => {
260
+ const tableEl = tMagicTable.value?.instance.$el;
261
+ const tBodyEl = tableEl?.querySelector('.el-table__body > tbody');
262
+ if (tBodyEl) {
263
+ // eslint-disable-next-line prefer-destructuring
264
+ const sortable = Sortable.create(tBodyEl, {
265
+ onEnd: ({ newIndex, oldIndex }: SortableEvent) => {
266
+ if (typeof newIndex === 'undefined') return;
267
+ if (typeof oldIndex === 'undefined') return;
268
+ swapArray(newIndex, oldIndex);
269
+ emit('change', props.model[modelName.value]);
270
+ foreUpdate();
271
+ sortable.destroy();
272
+ mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
273
+ sleep(1000).then(() => {
274
+ const elTrs = tableEl.querySelectorAll('.el-table__body > tbody > tr');
275
+ if (elTrs?.[newIndex]) {
276
+ elTrs[newIndex].style.backgroundColor = 'rgba(243, 89, 59, 0.2)';
279
277
  sleep(1000).then(() => {
280
- const eltrs = tableEl.querySelectorAll('.el-table__body > tbody > tr');
281
- if (eltrs?.[newIndex]) {
282
- eltrs[newIndex].style.backgroundColor = 'rgba(243, 89, 59, 0.2)';
283
- sleep(1000).then(() => {
284
- eltrs[newIndex].style.backgroundColor = '';
285
- });
286
- }
278
+ elTrs[newIndex].style.backgroundColor = '';
287
279
  });
288
- },
289
- });
290
- }
291
- };
292
-
293
- const newHandler = async (row?: any) => {
294
- if (props.config.max && props.model[modelName.value].length >= props.config.max) {
295
- ElMessage.error(`最多新增配置不能超过${props.config.max}条`);
296
- return;
297
- }
298
-
299
- const columns = props.config.items;
300
- const enumValues = props.config.enum || [];
301
- let enumV = [];
302
- const { length } = props.model[modelName.value];
303
- const key = props.config.key || 'id';
304
- let inputs: any = {};
305
-
306
- if (enumValues.length) {
307
- if (length >= enumValues.length) {
308
- return;
309
- }
310
- enumV = enumValues.filter((item) => {
311
- let i = 0;
312
- for (; i < length; i++) {
313
- if (item[key] === props.model[modelName.value][i][key]) {
314
- break;
315
- }
316
280
  }
317
- return i === length;
318
- });
319
-
320
- if (enumV.length > 0) {
321
- // eslint-disable-next-line prefer-destructuring
322
- inputs = enumV[0];
323
- }
324
- } else if (Array.isArray(row)) {
325
- columns.forEach((column, index) => {
326
- column.name && (inputs[column.name] = row[index]);
327
281
  });
328
- } else {
329
- if (typeof props.config.defaultAdd === 'function') {
330
- inputs = await props.config.defaultAdd(mForm, {
331
- model: props.model[modelName.value],
332
- formValue: mForm?.values,
333
- });
334
- } else if (props.config.defaultAdd) {
335
- inputs = props.config.defaultAdd;
282
+ },
283
+ });
284
+ }
285
+ };
286
+
287
+ const newHandler = async (row?: any) => {
288
+ if (props.config.max && props.model[modelName.value].length >= props.config.max) {
289
+ tMagicMessage.error(`最多新增配置不能超过${props.config.max}条`);
290
+ return;
291
+ }
292
+
293
+ const columns = props.config.items;
294
+ const enumValues = props.config.enum || [];
295
+ let enumV = [];
296
+ const { length } = props.model[modelName.value];
297
+ const key = props.config.key || 'id';
298
+ let inputs: any = {};
299
+
300
+ if (enumValues.length) {
301
+ if (length >= enumValues.length) {
302
+ return;
303
+ }
304
+ enumV = enumValues.filter((item) => {
305
+ let i = 0;
306
+ for (; i < length; i++) {
307
+ if (item[key] === props.model[modelName.value][i][key]) {
308
+ break;
336
309
  }
337
-
338
- inputs = await initValue(mForm, {
339
- config: columns,
340
- initValues: inputs,
341
- });
342
- }
343
-
344
- if (props.sortKey && length) {
345
- inputs[props.sortKey] = props.model[modelName.value][length - 1][props.sortKey] - 1;
346
310
  }
311
+ return i === length;
312
+ });
347
313
 
348
- props.model[modelName.value].push(inputs);
349
- emit('change', props.model[modelName.value]);
350
- };
351
-
352
- if (!(globalThis as any).XLSX) {
353
- asyncLoadJs('https://cdn.bootcdn.net/ajax/libs/xlsx/0.17.0/xlsx.full.min.js');
314
+ if (enumV.length > 0) {
315
+ // eslint-disable-next-line prefer-destructuring
316
+ inputs = enumV[0];
354
317
  }
355
-
356
- onMounted(() => {
357
- if (props.config.defautSort) {
358
- sortChange(props.config.defautSort);
359
- } else if (props.config.defaultSort) {
360
- sortChange(props.config.defaultSort);
361
- }
362
-
363
- if (props.sort && props.sortKey) {
364
- props.model[modelName.value].sort((a: any, b: any) => b[props.sortKey] - a[props.sortKey]);
365
- }
366
-
367
- if (props.config.dropSort) {
368
- rowDrop();
369
- }
318
+ } else if (Array.isArray(row)) {
319
+ columns.forEach((column, index) => {
320
+ column.name && (inputs[column.name] = row[index]);
370
321
  });
322
+ } else {
323
+ if (typeof props.config.defaultAdd === 'function') {
324
+ inputs = await props.config.defaultAdd(mForm, {
325
+ model: props.model[modelName.value],
326
+ formValue: mForm?.values,
327
+ });
328
+ } else if (props.config.defaultAdd) {
329
+ inputs = props.config.defaultAdd;
330
+ }
371
331
 
372
- return {
373
- mForm,
374
- pagesize,
375
- pagecontext,
376
- foreUpdate,
377
- isFullscreen,
378
- elTable,
379
- mTable,
380
- excelBtn,
381
- modelName,
382
- updateKey,
383
- ArrowDown,
384
- ArrowUp,
385
- Delete,
386
- FullScreen,
387
- Grid,
388
-
389
- data: computed(() =>
390
- props.model[modelName.value].filter(
391
- (item: any, index: number) =>
392
- index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value,
393
- ),
394
- ),
395
- addable: computed(() => {
396
- if (!props.model[modelName.value].length) {
397
- return true;
398
- }
399
- if (typeof props.config.addable === 'function') {
400
- return props.config.addable(mForm, {
401
- model: props.model[modelName.value],
402
- formValue: mForm?.values,
403
- prop: props.prop,
404
- });
405
- }
406
- return typeof props.config.addable === 'undefined' ? true : props.config.addable;
407
- }),
408
- selection: computed(() => {
409
- if (typeof props.config.selection === 'function') {
410
- return props.config.selection(mForm, { model: props.model[modelName.value] });
411
- }
412
- return props.config.selection;
413
- }),
414
- importable: computed(() => {
415
- if (typeof props.config.importable === 'function') {
416
- return props.config.importable(mForm, {
417
- formValue: mForm?.values,
418
- model: props.model[modelName.value],
419
- });
420
- }
421
- return typeof props.config.importable === 'undefined' ? false : props.config.importable;
422
- }),
423
-
424
- sortChange,
425
-
426
- display(fuc: any) {
427
- return display(mForm, fuc, props);
428
- },
429
-
430
- itemExtra(fuc: any, index: number) {
431
- if (typeof fuc === 'function') {
432
- return fuc(mForm, {
433
- values: mForm?.initValues,
434
- model: props.model,
435
- formValue: mForm ? mForm.values : props.model,
436
- prop: props.prop,
437
- index,
438
- });
439
- }
440
-
441
- return fuc;
442
- },
443
-
444
- newHandler,
445
-
446
- removeHandler(index: number) {
447
- props.model[modelName.value].splice(index, 1);
448
- emit('change', props.model[modelName.value]);
449
- },
450
-
451
- selectHandle(selection: any, row: any) {
452
- if (typeof props.config.selection === 'string' && props.config.selection === 'single') {
453
- elTable.value?.clearSelection();
454
- elTable.value?.toggleRowSelection(row, true);
455
- }
456
- emit('select', selection, row);
457
- if (typeof props.config.onSelect === 'function') {
458
- props.config.onSelect(mForm, { selection, row, config: props.config });
459
- }
460
- },
461
-
462
- toggleRowSelection(row: any, selected: boolean) {
463
- elTable.value?.toggleRowSelection.call(elTable.value, row, selected);
464
- },
465
-
466
- makeConfig(config: ColumnConfig) {
467
- const newConfig = cloneDeep(config);
468
- delete newConfig.display;
469
- return newConfig;
470
- },
471
-
472
- upHandler(index: number) {
473
- if (timer) {
474
- clearTimeout(timer);
475
- }
476
-
477
- timer = setTimeout(() => {
478
- swapArray(index, index - 1);
479
- }, 300);
480
- },
481
-
482
- topHandler(index: number) {
483
- if (timer) {
484
- clearTimeout(timer);
485
- }
486
-
487
- // 首先判断当前元素需要上移几个位置,置底移动到数组的第一位
488
- const moveNum = index;
489
-
490
- // 循环出需要一个一个上移的次数
491
- for (let i = 0; i < moveNum; i++) {
492
- swapArray(index, index - 1);
493
- index -= 1;
494
- }
495
- },
496
-
497
- downHandler(index: number) {
498
- if (timer) {
499
- clearTimeout(timer);
500
- }
501
-
502
- timer = setTimeout(() => {
503
- swapArray(index, index + 1);
504
- }, 300);
505
- },
506
-
507
- bottomHandler(index: number) {
508
- if (timer) {
509
- clearTimeout(timer);
510
- }
511
-
512
- // 首先判断当前元素需要上移几个位置,置底移动到数组的第一位
513
- const moveNum = props.model[modelName.value].length - 1 - index;
514
-
515
- // 循环出需要一个一个上移的次数
516
- for (let i = 0; i < moveNum; i++) {
517
- swapArray(index, index + 1);
518
- index += 1;
519
- }
520
- },
521
-
522
- // 希望支持单行可控制是否显示删除按钮,不会影响现有逻辑
523
- showDelete(index: number) {
524
- const deleteFunc = props.config.delete;
525
- if (deleteFunc && typeof deleteFunc === 'function') {
526
- return deleteFunc(props.model[modelName.value], index, mForm?.values);
527
- }
528
- return true;
529
- },
530
-
531
- clearHandler() {
532
- const len = props.model[modelName.value].length;
533
- props.model[modelName.value].splice(0, len);
534
- mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
535
- },
332
+ inputs = await initValue(mForm, {
333
+ config: columns,
334
+ initValues: inputs,
335
+ });
336
+ }
337
+
338
+ if (props.sortKey && length) {
339
+ inputs[props.sortKey] = props.model[modelName.value][length - 1][props.sortKey] - 1;
340
+ }
341
+
342
+ props.model[modelName.value].push(inputs);
343
+ emit('change', props.model[modelName.value]);
344
+ };
345
+
346
+ if (!(globalThis as any).XLSX) {
347
+ asyncLoadJs('https://cdn.bootcdn.net/ajax/libs/xlsx/0.17.0/xlsx.full.min.js');
348
+ }
349
+
350
+ onMounted(() => {
351
+ if (props.config.defautSort) {
352
+ sortChange(props.config.defautSort);
353
+ } else if (props.config.defaultSort) {
354
+ sortChange(props.config.defaultSort);
355
+ }
356
+
357
+ if (props.sort && props.sortKey) {
358
+ props.model[modelName.value].sort((a: any, b: any) => b[props.sortKey] - a[props.sortKey]);
359
+ }
360
+ });
536
361
 
537
- excelHandler(file: UploadFile) {
538
- if (!file || !file.raw) {
539
- return false;
540
- }
541
- const reader = new FileReader();
542
- reader.onload = () => {
543
- const data = reader.result;
544
- const pdata = (globalThis as any).XLSX.read(data, { type: 'array' });
545
- pdata.SheetNames.forEach((sheetName: string) => {
546
- const arr = (globalThis as any).XLSX.utils.sheet_to_json(pdata.Sheets[sheetName], { header: 1 });
547
- if (arr?.[0]) {
548
- arr.forEach((row: any) => {
549
- newHandler(row);
550
- });
551
- }
552
- setTimeout(() => {
553
- excelBtn.value?.clearFiles();
554
- }, 300);
555
- });
556
- };
557
- reader.readAsArrayBuffer(file.raw);
558
-
559
- return false;
560
- },
362
+ watchEffect(() => {
363
+ if (props.config.dropSort) {
364
+ rowDrop();
365
+ }
366
+ });
561
367
 
562
- handleSizeChange(val: number) {
563
- pagesize.value = val;
564
- },
368
+ const addable = computed(() => {
369
+ if (!props.model[modelName.value].length) {
370
+ return true;
371
+ }
372
+ if (typeof props.config.addable === 'function') {
373
+ return props.config.addable(mForm, {
374
+ model: props.model[modelName.value],
375
+ formValue: mForm?.values,
376
+ prop: props.prop,
377
+ });
378
+ }
379
+ return typeof props.config.addable === 'undefined' ? true : props.config.addable;
380
+ });
565
381
 
566
- handleCurrentChange(val: number) {
567
- pagecontext.value = val - 1;
568
- },
382
+ const selection = computed(() => {
383
+ if (typeof props.config.selection === 'function') {
384
+ return props.config.selection(mForm, { model: props.model[modelName.value] });
385
+ }
386
+ return props.config.selection;
387
+ });
569
388
 
570
- toggleMode() {
571
- const calcLabelWidth = (label: string) => {
572
- if (!label) return '0px';
573
- const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
574
- const chLength = label.length - zhLength;
575
- return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
576
- };
577
-
578
- // 切换为groupList的形式
579
- props.config.type = 'groupList';
580
- props.config.enableToggleMode = true;
581
- props.config.tableItems = props.config.items;
582
- props.config.items =
583
- props.config.groupItems ||
584
- props.config.items.map((item: any) => {
585
- const text = item.text || item.label;
586
- const labelWidth = calcLabelWidth(text);
587
- return {
588
- ...item,
589
- text,
590
- labelWidth,
591
- span: item.span || 12,
592
- };
593
- });
594
- },
389
+ const importable = computed(() => {
390
+ if (typeof props.config.importable === 'function') {
391
+ return props.config.importable(mForm, {
392
+ formValue: mForm?.values,
393
+ model: props.model[modelName.value],
394
+ });
395
+ }
396
+ return typeof props.config.importable === 'undefined' ? false : props.config.importable;
397
+ });
595
398
 
596
- toggleFullscreen() {
597
- if (isFullscreen.value) {
598
- mTable.value?.classList.remove('fixed');
599
- isFullscreen.value = false;
600
- } else {
601
- mTable.value?.classList.add('fixed');
602
- isFullscreen.value = true;
603
- }
604
- },
399
+ const display = (fuc: any) => displayFunc(mForm, fuc, props);
605
400
 
606
- getProp(index: number) {
607
- const { prop } = toRefs(props);
608
- return `${prop.value}${prop.value ? '.' : ''}${index + 1 + pagecontext.value * pagesize.value - 1}`;
609
- },
610
- };
611
- },
401
+ const itemExtra = (fuc: any, index: number) => {
402
+ if (typeof fuc === 'function') {
403
+ return fuc(mForm, {
404
+ values: mForm?.initValues,
405
+ model: props.model,
406
+ formValue: mForm ? mForm.values : props.model,
407
+ prop: props.prop,
408
+ index,
409
+ });
410
+ }
411
+
412
+ return fuc;
413
+ };
414
+
415
+ const removeHandler = (index: number) => {
416
+ props.model[modelName.value].splice(index, 1);
417
+ emit('change', props.model[modelName.value]);
418
+ };
419
+
420
+ const selectHandle = (selection: any, row: any) => {
421
+ if (typeof props.config.selection === 'string' && props.config.selection === 'single') {
422
+ tMagicTable.value?.clearSelection();
423
+ tMagicTable.value?.toggleRowSelection(row, true);
424
+ }
425
+ emit('select', selection, row);
426
+ if (typeof props.config.onSelect === 'function') {
427
+ props.config.onSelect(mForm, { selection, row, config: props.config });
428
+ }
429
+ };
430
+
431
+ const toggleRowSelection = (row: any, selected: boolean) => {
432
+ tMagicTable.value?.toggleRowSelection.call(tMagicTable.value, row, selected);
433
+ };
434
+
435
+ const makeConfig = (config: ColumnConfig) => {
436
+ const newConfig = cloneDeep(config);
437
+ delete newConfig.display;
438
+ return newConfig;
439
+ };
440
+
441
+ const upHandler = (index: number) => {
442
+ if (timer) {
443
+ clearTimeout(timer);
444
+ }
445
+
446
+ timer = setTimeout(() => {
447
+ swapArray(index, index - 1);
448
+ }, 300);
449
+ };
450
+
451
+ const topHandler = (index: number) => {
452
+ if (timer) {
453
+ clearTimeout(timer);
454
+ }
455
+
456
+ // 首先判断当前元素需要上移几个位置,置底移动到数组的第一位
457
+ const moveNum = index;
458
+
459
+ // 循环出需要一个一个上移的次数
460
+ for (let i = 0; i < moveNum; i++) {
461
+ swapArray(index, index - 1);
462
+ index -= 1;
463
+ }
464
+ };
465
+
466
+ const downHandler = (index: number) => {
467
+ if (timer) {
468
+ clearTimeout(timer);
469
+ }
470
+
471
+ timer = setTimeout(() => {
472
+ swapArray(index, index + 1);
473
+ }, 300);
474
+ };
475
+
476
+ const bottomHandler = (index: number) => {
477
+ if (timer) {
478
+ clearTimeout(timer);
479
+ }
480
+
481
+ // 首先判断当前元素需要上移几个位置,置底移动到数组的第一位
482
+ const moveNum = props.model[modelName.value].length - 1 - index;
483
+
484
+ // 循环出需要一个一个上移的次数
485
+ for (let i = 0; i < moveNum; i++) {
486
+ swapArray(index, index + 1);
487
+ index += 1;
488
+ }
489
+ };
490
+
491
+ // 希望支持单行可控制是否显示删除按钮,不会影响现有逻辑
492
+ const showDelete = (index: number) => {
493
+ const deleteFunc = props.config.delete;
494
+ if (deleteFunc && typeof deleteFunc === 'function') {
495
+ return deleteFunc(props.model[modelName.value], index, mForm?.values);
496
+ }
497
+ return true;
498
+ };
499
+
500
+ const clearHandler = () => {
501
+ const len = props.model[modelName.value].length;
502
+ props.model[modelName.value].splice(0, len);
503
+ mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
504
+ };
505
+
506
+ const excelHandler = (file: any) => {
507
+ if (!file || !file.raw) {
508
+ return false;
509
+ }
510
+ const reader = new FileReader();
511
+ reader.onload = () => {
512
+ const data = reader.result;
513
+ const pdata = (globalThis as any).XLSX.read(data, { type: 'array' });
514
+ pdata.SheetNames.forEach((sheetName: string) => {
515
+ const arr = (globalThis as any).XLSX.utils.sheet_to_json(pdata.Sheets[sheetName], { header: 1 });
516
+ if (arr?.[0]) {
517
+ arr.forEach((row: any) => {
518
+ newHandler(row);
519
+ });
520
+ }
521
+ setTimeout(() => {
522
+ excelBtn.value?.clearFiles();
523
+ }, 300);
524
+ });
525
+ };
526
+ reader.readAsArrayBuffer(file.raw);
527
+
528
+ return false;
529
+ };
530
+
531
+ const handleSizeChange = (val: number) => {
532
+ pagesize.value = val;
533
+ };
534
+
535
+ const handleCurrentChange = (val: number) => {
536
+ pagecontext.value = val - 1;
537
+ };
538
+
539
+ const toggleMode = () => {
540
+ const calcLabelWidth = (label: string) => {
541
+ if (!label) return '0px';
542
+ const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
543
+ const chLength = label.length - zhLength;
544
+ return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
545
+ };
546
+
547
+ // 切换为groupList的形式
548
+ props.config.type = 'groupList';
549
+ props.config.enableToggleMode = true;
550
+ props.config.tableItems = props.config.items;
551
+ props.config.items =
552
+ props.config.groupItems ||
553
+ props.config.items.map((item: any) => {
554
+ const text = item.text || item.label;
555
+ const labelWidth = calcLabelWidth(text);
556
+ return {
557
+ ...item,
558
+ text,
559
+ labelWidth,
560
+ span: item.span || 12,
561
+ };
562
+ });
563
+ };
564
+
565
+ const toggleFullscreen = () => {
566
+ if (isFullscreen.value) {
567
+ mTable.value?.classList.remove('fixed');
568
+ isFullscreen.value = false;
569
+ } else {
570
+ mTable.value?.classList.add('fixed');
571
+ isFullscreen.value = true;
572
+ }
573
+ };
574
+
575
+ const getProp = (index: number) => {
576
+ const { prop } = toRefs(props);
577
+ return `${prop.value}${prop.value ? '.' : ''}${index + 1 + pagecontext.value * pagesize.value - 1}`;
578
+ };
579
+
580
+ defineExpose({
581
+ toggleRowSelection,
612
582
  });
613
583
  </script>