@tmagic/form 1.6.0 → 1.7.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/style.css +29 -3
- package/dist/tmagic-form.js +1788 -1581
- package/dist/tmagic-form.umd.cjs +1830 -1619
- package/package.json +6 -6
- package/src/Form.vue +18 -5
- package/src/containers/Container.vue +109 -134
- package/src/containers/Fieldset.vue +31 -7
- package/src/containers/FlexLayout.vue +59 -0
- package/src/containers/Tabs.vue +11 -1
- package/src/fields/Cascader.vue +25 -16
- package/src/fields/Checkbox.vue +3 -3
- package/src/fields/CheckboxGroup.vue +1 -1
- package/src/fields/ColorPicker.vue +2 -2
- package/src/fields/Date.vue +2 -2
- package/src/fields/DateTime.vue +2 -2
- package/src/fields/Daterange.vue +2 -2
- package/src/fields/Number.vue +2 -2
- package/src/fields/NumberRange.vue +6 -6
- package/src/fields/RadioGroup.vue +18 -16
- package/src/fields/Select.vue +2 -2
- package/src/fields/Switch.vue +2 -2
- package/src/fields/Text.vue +21 -9
- package/src/fields/Textarea.vue +2 -2
- package/src/fields/Time.vue +2 -2
- package/src/fields/Timerange.vue +2 -2
- package/src/index.ts +5 -2
- package/src/table/ActionsColumn.vue +97 -0
- package/src/table/SortColumn.vue +101 -0
- package/src/table/Table.vue +170 -0
- package/src/table/type.ts +18 -0
- package/src/table/useAdd.ts +111 -0
- package/src/table/useFullscreen.ts +28 -0
- package/src/table/useImport.ts +68 -0
- package/src/table/usePagination.ts +30 -0
- package/src/table/useSelection.ts +34 -0
- package/src/table/useSortable.ts +48 -0
- package/src/table/useTableColumns.ts +194 -0
- package/src/theme/container.scss +17 -0
- package/src/theme/form.scss +15 -3
- package/src/theme/text.scss +6 -0
- package/src/utils/form.ts +56 -2
- package/types/index.d.ts +103 -56
- package/src/containers/Table.vue +0 -681
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { computed, h, inject, type Ref } from 'vue';
|
|
2
|
+
import { cloneDeep } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
import type { TableColumnOptions } from '@tmagic/design';
|
|
5
|
+
import type { FormState, TableColumnConfig } from '@tmagic/form-schema';
|
|
6
|
+
|
|
7
|
+
import Container from '../containers/Container.vue';
|
|
8
|
+
import type { ContainerChangeEventData } from '../schema';
|
|
9
|
+
import { display as displayFunc, getDataByPage, sortArray } from '../utils/form';
|
|
10
|
+
|
|
11
|
+
import ActionsColumn from './ActionsColumn.vue';
|
|
12
|
+
import SortColumn from './SortColumn.vue';
|
|
13
|
+
import type { TableProps } from './type';
|
|
14
|
+
|
|
15
|
+
export const useTableColumns = (
|
|
16
|
+
props: TableProps,
|
|
17
|
+
emit: (event: 'select' | 'change' | 'addDiffCount', ...args: any[]) => void,
|
|
18
|
+
currentPage: Ref<number>,
|
|
19
|
+
pageSize: Ref<number>,
|
|
20
|
+
modelName: Ref<string | number>,
|
|
21
|
+
) => {
|
|
22
|
+
const mForm = inject<FormState | undefined>('mForm');
|
|
23
|
+
|
|
24
|
+
const display = (fuc: any) => displayFunc(mForm, fuc, props);
|
|
25
|
+
|
|
26
|
+
const lastData = computed(() =>
|
|
27
|
+
props.config.pagination
|
|
28
|
+
? getDataByPage(props.lastValues[modelName.value], currentPage.value, pageSize.value)
|
|
29
|
+
: props.lastValues[modelName.value] || [],
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const itemExtra = (fuc: any, index: number) => {
|
|
33
|
+
if (typeof fuc === 'function') {
|
|
34
|
+
return fuc(mForm, {
|
|
35
|
+
values: mForm?.initValues,
|
|
36
|
+
model: props.model,
|
|
37
|
+
formValue: mForm ? mForm.values : props.model,
|
|
38
|
+
prop: props.prop,
|
|
39
|
+
index,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return fuc;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const selection = computed(() => {
|
|
47
|
+
if (typeof props.config.selection === 'function') {
|
|
48
|
+
return props.config.selection(mForm, { model: props.model[modelName.value] });
|
|
49
|
+
}
|
|
50
|
+
return props.config.selection;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const getProp = (index: number) => {
|
|
54
|
+
return `${props.prop}${props.prop ? '.' : ''}${index + 1 + currentPage.value * pageSize.value - 1}`;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const makeConfig = (config: TableColumnConfig, row: any) => {
|
|
58
|
+
const newConfig = cloneDeep(config);
|
|
59
|
+
if (typeof config.itemsFunction === 'function') {
|
|
60
|
+
newConfig.items = config.itemsFunction(row);
|
|
61
|
+
}
|
|
62
|
+
delete newConfig.display;
|
|
63
|
+
return newConfig;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
|
67
|
+
emit('change', props.model, eventData);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const onAddDiffCount = () => emit('addDiffCount');
|
|
71
|
+
|
|
72
|
+
const columns = computed<TableColumnOptions[]>(() => {
|
|
73
|
+
const columns: TableColumnOptions[] = [];
|
|
74
|
+
|
|
75
|
+
if (props.config.itemExtra && !props.config.dropSort) {
|
|
76
|
+
columns.push({
|
|
77
|
+
props: {
|
|
78
|
+
fixed: 'left',
|
|
79
|
+
width: 30,
|
|
80
|
+
type: 'expand',
|
|
81
|
+
},
|
|
82
|
+
cell: ({ $index }: any) =>
|
|
83
|
+
h('span', {
|
|
84
|
+
innerHTML: itemExtra(props.config.itemExtra, $index),
|
|
85
|
+
class: 'm-form-tip',
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
columns.push({
|
|
91
|
+
props: {
|
|
92
|
+
label: '操作',
|
|
93
|
+
fixed: props.config.fixed === false ? undefined : 'left',
|
|
94
|
+
width: props.config.operateColWidth || 112,
|
|
95
|
+
align: 'center',
|
|
96
|
+
},
|
|
97
|
+
cell: ({ row, $index }: any) =>
|
|
98
|
+
h(ActionsColumn, {
|
|
99
|
+
row,
|
|
100
|
+
index: $index,
|
|
101
|
+
model: props.model,
|
|
102
|
+
config: props.config,
|
|
103
|
+
prop: props.prop,
|
|
104
|
+
disabled: props.disabled,
|
|
105
|
+
sortKey: props.sortKey,
|
|
106
|
+
name: modelName.value,
|
|
107
|
+
currentPage: currentPage.value,
|
|
108
|
+
pageSize: pageSize.value,
|
|
109
|
+
onChange: (v: any) => {
|
|
110
|
+
emit('change', v);
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (props.sort && props.model[modelName.value] && props.model[modelName.value].length > 1) {
|
|
116
|
+
columns.push({
|
|
117
|
+
props: {
|
|
118
|
+
label: '排序',
|
|
119
|
+
width: 80,
|
|
120
|
+
},
|
|
121
|
+
cell: ({ $index }: any) =>
|
|
122
|
+
h(SortColumn, {
|
|
123
|
+
index: $index,
|
|
124
|
+
model: props.model,
|
|
125
|
+
disabled: props.disabled,
|
|
126
|
+
name: modelName.value,
|
|
127
|
+
currentPage: currentPage.value,
|
|
128
|
+
pageSize: pageSize.value,
|
|
129
|
+
onSwap: (index1: number, index2: number) => {
|
|
130
|
+
const newData = sortArray(props.model[modelName.value], index1, index2, props.sortKey);
|
|
131
|
+
emit('change', newData);
|
|
132
|
+
mForm?.$emit('field-change', newData);
|
|
133
|
+
},
|
|
134
|
+
}),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (selection.value) {
|
|
139
|
+
columns.push({
|
|
140
|
+
props: {
|
|
141
|
+
align: 'center',
|
|
142
|
+
headerAlign: 'center',
|
|
143
|
+
type: 'selection',
|
|
144
|
+
width: 45,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (props.showIndex && props.config.showIndex) {
|
|
150
|
+
columns.push({
|
|
151
|
+
props: {
|
|
152
|
+
label: '序号',
|
|
153
|
+
width: 60,
|
|
154
|
+
},
|
|
155
|
+
cell: ({ $index }: any) => h('span', $index + 1 + currentPage.value * pageSize.value),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const column of props.config.items) {
|
|
160
|
+
if (column.type !== 'hidden' && display(column.display)) {
|
|
161
|
+
columns.push({
|
|
162
|
+
props: {
|
|
163
|
+
prop: column.name,
|
|
164
|
+
label: column.label,
|
|
165
|
+
width: column.width,
|
|
166
|
+
sortable: column.sortable,
|
|
167
|
+
sortOrders: ['ascending', 'descending'],
|
|
168
|
+
class: props.config.dropSort === true ? 'el-table__column--dropable' : '',
|
|
169
|
+
},
|
|
170
|
+
cell: ({ row, $index }: any) =>
|
|
171
|
+
h(Container, {
|
|
172
|
+
labelWidth: '0',
|
|
173
|
+
disabled: props.disabled,
|
|
174
|
+
prop: getProp($index),
|
|
175
|
+
rules: column.rules,
|
|
176
|
+
config: makeConfig(column, row),
|
|
177
|
+
model: row,
|
|
178
|
+
lastValues: lastData.value[$index],
|
|
179
|
+
isCompare: props.isCompare,
|
|
180
|
+
size: props.size,
|
|
181
|
+
onChange: changeHandler,
|
|
182
|
+
onAddDiffCount,
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return columns;
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
columns,
|
|
193
|
+
};
|
|
194
|
+
};
|
package/src/theme/container.scss
CHANGED
|
@@ -3,3 +3,20 @@
|
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
}
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
.m-form-container {
|
|
8
|
+
&.has-tip {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: baseline;
|
|
11
|
+
|
|
12
|
+
.tmagic-design-form-item {
|
|
13
|
+
flex: 1;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.tmagic-design-form-item {
|
|
18
|
+
&.show-diff {
|
|
19
|
+
background: #f7dadd;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/theme/form.scss
CHANGED
|
@@ -19,17 +19,21 @@
|
|
|
19
19
|
height: 100%;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
.
|
|
22
|
+
.tmagic-design-table {
|
|
23
23
|
.cell > div.m-form-container {
|
|
24
24
|
display: block;
|
|
25
|
+
|
|
26
|
+
&.has-tip {
|
|
27
|
+
display: flex;
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
.
|
|
32
|
+
.tmagic-design-tabs {
|
|
29
33
|
margin-bottom: 10px;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
.
|
|
36
|
+
.tmagic-design-form-item.tmagic-form-hidden {
|
|
33
37
|
> .el-form-item__label {
|
|
34
38
|
display: none;
|
|
35
39
|
}
|
|
@@ -39,5 +43,13 @@
|
|
|
39
43
|
> .t-form__label {
|
|
40
44
|
display: none;
|
|
41
45
|
}
|
|
46
|
+
|
|
47
|
+
> .t-form__controls {
|
|
48
|
+
margin-left: 0 !important;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&.t-form:not(.t-form-inline) .t-form__item:last-of-type {
|
|
53
|
+
margin-bottom: var(--td-comp-margin-xxl);
|
|
42
54
|
}
|
|
43
55
|
}
|
package/src/theme/text.scss
CHANGED
package/src/utils/form.ts
CHANGED
|
@@ -21,6 +21,8 @@ import dayjs from 'dayjs';
|
|
|
21
21
|
import utc from 'dayjs/plugin/utc';
|
|
22
22
|
import { cloneDeep } from 'lodash-es';
|
|
23
23
|
|
|
24
|
+
import { getValueByKeyPath } from '@tmagic/utils';
|
|
25
|
+
|
|
24
26
|
import {
|
|
25
27
|
ChildConfig,
|
|
26
28
|
ContainerCommonConfig,
|
|
@@ -31,6 +33,7 @@ import {
|
|
|
31
33
|
FormValue,
|
|
32
34
|
HtmlField,
|
|
33
35
|
Rule,
|
|
36
|
+
SortProp,
|
|
34
37
|
TabPaneConfig,
|
|
35
38
|
TypeFunction,
|
|
36
39
|
} from '../schema';
|
|
@@ -89,8 +92,13 @@ const setValue = (mForm: FormState | undefined, value: FormValue, initValue: For
|
|
|
89
92
|
|
|
90
93
|
// 如果fieldset配置checkbox,checkbox的值保存在value中
|
|
91
94
|
if (type === 'fieldset' && checkbox) {
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
const checkboxName = typeof checkbox === 'object' && typeof checkbox.name === 'string' ? checkbox.name : 'value';
|
|
96
|
+
const checkboxFalseValue =
|
|
97
|
+
typeof checkbox === 'object' && typeof checkbox.falseValue !== 'undefined' ? checkbox.falseValue : 0;
|
|
98
|
+
|
|
99
|
+
if (name && typeof value[name] === 'object') {
|
|
100
|
+
value[name][checkboxName] =
|
|
101
|
+
typeof initValue[name] === 'object' ? initValue[name][checkboxName] || checkboxFalseValue : checkboxFalseValue;
|
|
94
102
|
}
|
|
95
103
|
}
|
|
96
104
|
};
|
|
@@ -136,6 +144,18 @@ const initValueItem = function (
|
|
|
136
144
|
|
|
137
145
|
setValue(mForm, value, initValue, item);
|
|
138
146
|
|
|
147
|
+
if (type === 'table') {
|
|
148
|
+
if (item.defautSort) {
|
|
149
|
+
sortChange(value[name], item.defautSort);
|
|
150
|
+
} else if (item.defaultSort) {
|
|
151
|
+
sortChange(value[name], item.defaultSort);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (item.sort && item.sortKey) {
|
|
155
|
+
value[name].sort((a: any, b: any) => b[item.sortKey] - a[item.sortKey]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
139
159
|
return value;
|
|
140
160
|
};
|
|
141
161
|
|
|
@@ -197,6 +217,7 @@ export const filterFunction = <T = any>(
|
|
|
197
217
|
prop: props.prop,
|
|
198
218
|
config: props.config,
|
|
199
219
|
index: props.index,
|
|
220
|
+
getFormValue: (prop: string) => getValueByKeyPath(prop, mForm?.values || props.model),
|
|
200
221
|
});
|
|
201
222
|
}
|
|
202
223
|
|
|
@@ -297,3 +318,36 @@ export const datetimeFormatter = (
|
|
|
297
318
|
}
|
|
298
319
|
return defaultValue;
|
|
299
320
|
};
|
|
321
|
+
|
|
322
|
+
export const getDataByPage = (data: any[] = [], pagecontext: number, pagesize: number) =>
|
|
323
|
+
data.filter(
|
|
324
|
+
(item: any, index: number) => index >= pagecontext * pagesize && index + 1 <= (pagecontext + 1) * pagesize,
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
export const sortArray = (data: any[], newIndex: number, oldIndex: number, sortKey?: string) => {
|
|
328
|
+
if (newIndex === oldIndex) {
|
|
329
|
+
return data;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (newIndex < 0 || newIndex >= data.length || oldIndex < 0 || oldIndex >= data.length) {
|
|
333
|
+
return data;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const newData = data.toSpliced(newIndex, 0, ...data.splice(oldIndex, 1));
|
|
337
|
+
|
|
338
|
+
if (sortKey) {
|
|
339
|
+
for (let i = newData.length - 1, v = 0; i >= 0; i--, v++) {
|
|
340
|
+
newData[v][sortKey] = i;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return newData;
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
export const sortChange = (data: any[], { prop, order }: SortProp) => {
|
|
348
|
+
if (order === 'ascending') {
|
|
349
|
+
data = data.sort((a: any, b: any) => a[prop] - b[prop]);
|
|
350
|
+
} else if (order === 'descending') {
|
|
351
|
+
data = data.sort((a: any, b: any) => b[prop] - a[prop]);
|
|
352
|
+
}
|
|
353
|
+
};
|