@tmagic/form 1.2.0-beta.2 → 1.2.0-beta.20

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