@tmagic/form 1.7.10 → 1.7.12
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/es/containers/GroupList.vue_vue_type_script_setup_true_lang.js +5 -69
- package/dist/es/{table → containers/table}/ActionsColumn.js +1 -1
- package/dist/es/{table → containers/table}/ActionsColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/{table → containers/table}/SortColumn.js +1 -1
- package/dist/es/{table → containers/table}/SortColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/{table → containers/table}/Table.js +1 -1
- package/dist/es/{table → containers/table}/Table.vue_vue_type_script_setup_true_lang.js +13 -60
- package/dist/es/containers/table/useFullscreen.js +22 -0
- package/dist/es/{table → containers/table}/useImport.js +3 -5
- package/dist/es/{table → containers/table}/usePagination.js +2 -2
- package/dist/es/{table → containers/table}/useSelection.js +1 -1
- package/dist/es/{table → containers/table}/useSortable.js +2 -2
- package/dist/es/{table → containers/table}/useTableColumns.js +5 -5
- package/dist/es/containers/table-group-list/TableGroupList.js +5 -0
- package/dist/es/containers/table-group-list/TableGroupList.vue_vue_type_script_setup_true_lang.js +161 -0
- package/dist/es/{table → containers/table-group-list}/useAdd.js +6 -4
- package/dist/es/index.js +2 -3
- package/dist/es/plugin.js +3 -4
- package/dist/tmagic-form.umd.cjs +732 -677
- package/package.json +6 -6
- package/src/containers/GroupList.vue +5 -80
- package/src/{table → containers/table}/ActionsColumn.vue +1 -1
- package/src/{table → containers/table}/Table.vue +11 -56
- package/src/{table → containers/table}/type.ts +0 -1
- package/src/containers/table/useFullscreen.ts +31 -0
- package/src/{table → containers/table}/useImport.ts +2 -5
- package/src/{table → containers/table}/usePagination.ts +1 -1
- package/src/{table → containers/table}/useSortable.ts +1 -1
- package/src/{table → containers/table}/useTableColumns.ts +8 -5
- package/src/containers/table-group-list/TableGroupList.vue +173 -0
- package/src/{table → containers/table-group-list}/useAdd.ts +17 -7
- package/src/index.ts +3 -2
- package/src/plugin.ts +3 -4
- package/types/index.d.ts +245 -286
- package/dist/es/table/useFullscreen.js +0 -15
- package/src/table/useFullscreen.ts +0 -18
- /package/src/{table → containers/table}/SortColumn.vue +0 -0
- /package/src/{table → containers/table}/useSelection.ts +0 -0
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.7.
|
|
2
|
+
"version": "1.7.12",
|
|
3
3
|
"name": "@tmagic/form",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"@vue/test-utils": "^2.4.6"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"vue": "^3.5.
|
|
54
|
-
"typescript": "^6.0.
|
|
55
|
-
"@tmagic/design": "1.7.
|
|
56
|
-
"@tmagic/form-schema": "1.7.
|
|
57
|
-
"@tmagic/utils": "1.7.
|
|
53
|
+
"vue": "^3.5.33",
|
|
54
|
+
"typescript": "^6.0.3",
|
|
55
|
+
"@tmagic/design": "1.7.12",
|
|
56
|
+
"@tmagic/form-schema": "1.7.12",
|
|
57
|
+
"@tmagic/utils": "1.7.12"
|
|
58
58
|
},
|
|
59
59
|
"peerDependenciesMeta": {
|
|
60
60
|
"typescript": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
v-for="(item, index) in model[name]"
|
|
11
11
|
:key="index"
|
|
12
12
|
:model="item"
|
|
13
|
-
:lastValues="getLastValues(lastValues[name], Number(index))"
|
|
13
|
+
:lastValues="getLastValues(lastValues?.[name], Number(index))"
|
|
14
14
|
:is-compare="isCompare"
|
|
15
15
|
:config="config"
|
|
16
16
|
:prop="prop"
|
|
@@ -27,33 +27,18 @@
|
|
|
27
27
|
></MFieldsGroupListItem>
|
|
28
28
|
|
|
29
29
|
<div class="m-fields-group-list-footer">
|
|
30
|
-
<
|
|
31
|
-
>切换为表格</TMagicButton
|
|
32
|
-
>
|
|
30
|
+
<slot name="toggle-button"></slot>
|
|
33
31
|
<div style="display: flex; justify-content: flex-end; flex: 1">
|
|
34
|
-
<
|
|
35
|
-
v-if="addable"
|
|
36
|
-
:size="config.enableToggleMode ? 'small' : 'default'"
|
|
37
|
-
:icon="Plus"
|
|
38
|
-
v-bind="config.addButtonConfig?.props || { type: 'primary' }"
|
|
39
|
-
:disabled="disabled"
|
|
40
|
-
@click="addHandler"
|
|
41
|
-
>{{ config.addButtonConfig?.text || '新增' }}</TMagicButton
|
|
42
|
-
>
|
|
32
|
+
<slot name="add-button"></slot>
|
|
43
33
|
</div>
|
|
44
34
|
</div>
|
|
45
35
|
</div>
|
|
46
36
|
</template>
|
|
47
37
|
|
|
48
38
|
<script setup lang="ts">
|
|
49
|
-
import { computed, inject } from 'vue';
|
|
50
|
-
import { Grid, Plus } from '@element-plus/icons-vue';
|
|
51
39
|
import { cloneDeep } from 'lodash-es';
|
|
52
40
|
|
|
53
|
-
import {
|
|
54
|
-
|
|
55
|
-
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
|
56
|
-
import { initValue } from '../utils/form';
|
|
41
|
+
import type { ContainerChangeEventData, GroupListConfig } from '../schema';
|
|
57
42
|
|
|
58
43
|
import MFieldsGroupListItem from './GroupListItem.vue';
|
|
59
44
|
|
|
@@ -71,6 +56,7 @@ const props = defineProps<{
|
|
|
71
56
|
prop?: string;
|
|
72
57
|
size?: string;
|
|
73
58
|
disabled?: boolean;
|
|
59
|
+
showIndex?: boolean;
|
|
74
60
|
}>();
|
|
75
61
|
|
|
76
62
|
const emit = defineEmits<{
|
|
@@ -78,60 +64,10 @@ const emit = defineEmits<{
|
|
|
78
64
|
addDiffCount: [];
|
|
79
65
|
}>();
|
|
80
66
|
|
|
81
|
-
const mForm = inject<FormState | undefined>('mForm');
|
|
82
|
-
|
|
83
|
-
const addable = computed(() => {
|
|
84
|
-
if (!props.name) return false;
|
|
85
|
-
|
|
86
|
-
if (typeof props.config.addable === 'function') {
|
|
87
|
-
return props.config.addable(mForm, {
|
|
88
|
-
model: props.model[props.name],
|
|
89
|
-
formValue: mForm?.values,
|
|
90
|
-
prop: props.prop,
|
|
91
|
-
config: props.config,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
96
|
-
});
|
|
97
|
-
|
|
98
67
|
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
|
99
68
|
emit('change', props.model, eventData);
|
|
100
69
|
};
|
|
101
70
|
|
|
102
|
-
const addHandler = async () => {
|
|
103
|
-
if (!props.name) return false;
|
|
104
|
-
|
|
105
|
-
let initValues = {};
|
|
106
|
-
|
|
107
|
-
if (typeof props.config.defaultAdd === 'function') {
|
|
108
|
-
initValues = await props.config.defaultAdd(mForm, {
|
|
109
|
-
model: props.model[props.name],
|
|
110
|
-
formValue: mForm?.values,
|
|
111
|
-
prop: props.prop,
|
|
112
|
-
config: props.config,
|
|
113
|
-
});
|
|
114
|
-
} else if (props.config.defaultAdd) {
|
|
115
|
-
initValues = props.config.defaultAdd;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const groupValue = await initValue(mForm, {
|
|
119
|
-
config: props.config.items,
|
|
120
|
-
initValues,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
props.model[props.name].push(groupValue);
|
|
124
|
-
|
|
125
|
-
emit('change', props.model[props.name], {
|
|
126
|
-
changeRecords: [
|
|
127
|
-
{
|
|
128
|
-
propPath: `${props.prop}.${props.model[props.name].length - 1}`,
|
|
129
|
-
value: groupValue,
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
|
|
135
71
|
const removeHandler = (index: number) => {
|
|
136
72
|
if (!props.name) return false;
|
|
137
73
|
|
|
@@ -153,17 +89,6 @@ const swapHandler = (idx1: number, idx2: number) => {
|
|
|
153
89
|
emit('change', props.model[props.name]);
|
|
154
90
|
};
|
|
155
91
|
|
|
156
|
-
const toggleMode = () => {
|
|
157
|
-
props.config.type = 'table';
|
|
158
|
-
props.config.groupItems = props.config.items;
|
|
159
|
-
props.config.items = (props.config.tableItems ||
|
|
160
|
-
props.config.items.map((item: any) => ({
|
|
161
|
-
...item,
|
|
162
|
-
label: item.label || item.text,
|
|
163
|
-
text: null,
|
|
164
|
-
}))) as any;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
92
|
const onAddDiffCount = () => emit('addDiffCount');
|
|
168
93
|
|
|
169
94
|
const getLastValues = (item: any, index: number) => item?.[index] || {};
|
|
@@ -38,7 +38,7 @@ import { cloneDeep } from 'lodash-es';
|
|
|
38
38
|
|
|
39
39
|
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
|
40
40
|
|
|
41
|
-
import type { FormState, TableConfig } from '
|
|
41
|
+
import type { FormState, TableConfig } from '../../schema';
|
|
42
42
|
|
|
43
43
|
const emit = defineEmits(['change']);
|
|
44
44
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
v-bind="$attrs"
|
|
5
5
|
class="m-fields-table-wrap"
|
|
6
6
|
:class="{ fixed: isFullscreen }"
|
|
7
|
-
:style="isFullscreen ? `z-index: ${
|
|
7
|
+
:style="isFullscreen ? `z-index: ${fullscreenZIndex}` : ''"
|
|
8
8
|
>
|
|
9
9
|
<div class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
|
|
10
10
|
<span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
|
|
@@ -34,13 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
<div style="display: flex; justify-content: space-between; margin: 10px 0">
|
|
36
36
|
<div style="display: flex">
|
|
37
|
-
<
|
|
38
|
-
:icon="Grid"
|
|
39
|
-
size="small"
|
|
40
|
-
@click="toggleMode"
|
|
41
|
-
v-if="enableToggleMode && config.enableToggleMode !== false && !isFullscreen"
|
|
42
|
-
>展开配置</TMagicButton
|
|
43
|
-
>
|
|
37
|
+
<slot name="toggle-button" v-if="!isFullscreen"></slot>
|
|
44
38
|
<TMagicButton
|
|
45
39
|
:icon="FullScreen"
|
|
46
40
|
size="small"
|
|
@@ -64,17 +58,7 @@
|
|
|
64
58
|
>清空</TMagicButton
|
|
65
59
|
>
|
|
66
60
|
</div>
|
|
67
|
-
<
|
|
68
|
-
v-if="addable"
|
|
69
|
-
class="m-form-table-add-button"
|
|
70
|
-
size="small"
|
|
71
|
-
plain
|
|
72
|
-
:icon="Plus"
|
|
73
|
-
v-bind="config.addButtonConfig?.props || { type: 'primary' }"
|
|
74
|
-
:disabled="disabled"
|
|
75
|
-
@click="newHandler()"
|
|
76
|
-
>{{ config.addButtonConfig?.text || '新增一行' }}</TMagicButton
|
|
77
|
-
>
|
|
61
|
+
<slot name="add-button"></slot>
|
|
78
62
|
</div>
|
|
79
63
|
|
|
80
64
|
<div class="bottom" style="text-align: right" v-if="config.pagination">
|
|
@@ -97,15 +81,14 @@
|
|
|
97
81
|
|
|
98
82
|
<script setup lang="ts">
|
|
99
83
|
import { computed, ref, useTemplateRef } from 'vue';
|
|
100
|
-
import { FullScreen
|
|
84
|
+
import { FullScreen } from '@element-plus/icons-vue';
|
|
101
85
|
|
|
102
|
-
import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload
|
|
86
|
+
import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload } from '@tmagic/design';
|
|
103
87
|
|
|
104
|
-
import type { SortProp } from '
|
|
105
|
-
import { sortChange } from '
|
|
88
|
+
import type { SortProp } from '../../schema';
|
|
89
|
+
import { sortChange } from '../../utils/form';
|
|
106
90
|
|
|
107
91
|
import type { TableProps } from './type';
|
|
108
|
-
import { useAdd } from './useAdd';
|
|
109
92
|
import { useFullscreen } from './useFullscreen';
|
|
110
93
|
import { useImport } from './useImport';
|
|
111
94
|
import { usePagination } from './usePagination';
|
|
@@ -120,13 +103,12 @@ defineOptions({
|
|
|
120
103
|
const props = withDefaults(defineProps<TableProps>(), {
|
|
121
104
|
prop: '',
|
|
122
105
|
sortKey: '',
|
|
123
|
-
enableToggleMode: true,
|
|
124
106
|
showIndex: true,
|
|
125
107
|
lastValues: () => ({}),
|
|
126
108
|
isCompare: false,
|
|
127
109
|
});
|
|
128
110
|
|
|
129
|
-
const emit = defineEmits(['change', 'select', 'addDiffCount']);
|
|
111
|
+
const emit = defineEmits(['change', 'select', 'addDiffCount', 'add']);
|
|
130
112
|
|
|
131
113
|
const modelName = computed(() => props.name || props.config.name || '');
|
|
132
114
|
const tMagicTableRef = useTemplateRef<InstanceType<typeof TMagicTable>>('tMagicTable');
|
|
@@ -136,44 +118,17 @@ const { pageSize, currentPage, paginationData, handleSizeChange, handleCurrentCh
|
|
|
136
118
|
modelName,
|
|
137
119
|
);
|
|
138
120
|
|
|
139
|
-
const { nextZIndex } = useZIndex();
|
|
140
121
|
const updateKey = ref(1);
|
|
141
122
|
|
|
142
|
-
const { addable, newHandler } = useAdd(props, emit);
|
|
143
123
|
const { columns } = useTableColumns(props, emit, currentPage, pageSize, modelName);
|
|
144
124
|
useSortable(props, emit, tMagicTableRef, modelName, updateKey);
|
|
145
|
-
const { isFullscreen, toggleFullscreen } = useFullscreen();
|
|
146
|
-
|
|
125
|
+
const { isFullscreen, fullscreenZIndex, toggleFullscreen } = useFullscreen();
|
|
126
|
+
|
|
127
|
+
const { importable, excelHandler, clearHandler } = useImport(props, emit);
|
|
147
128
|
const { selectHandle, toggleRowSelection } = useSelection(props, emit, tMagicTableRef);
|
|
148
129
|
|
|
149
130
|
const data = computed(() => (props.config.pagination ? paginationData.value : props.model[modelName.value]));
|
|
150
131
|
|
|
151
|
-
const toggleMode = () => {
|
|
152
|
-
const calcLabelWidth = (label: string) => {
|
|
153
|
-
if (!label) return '0px';
|
|
154
|
-
const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
|
|
155
|
-
const chLength = label.length - zhLength;
|
|
156
|
-
return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// 切换为groupList的形式
|
|
160
|
-
props.config.type = 'groupList';
|
|
161
|
-
props.config.enableToggleMode = true;
|
|
162
|
-
props.config.tableItems = props.config.items;
|
|
163
|
-
props.config.items =
|
|
164
|
-
props.config.groupItems ||
|
|
165
|
-
props.config.items.map((item: any) => {
|
|
166
|
-
const text = item.text || item.label;
|
|
167
|
-
const labelWidth = calcLabelWidth(text);
|
|
168
|
-
return {
|
|
169
|
-
...item,
|
|
170
|
-
text,
|
|
171
|
-
labelWidth,
|
|
172
|
-
span: item.span || 12,
|
|
173
|
-
};
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
|
-
|
|
177
132
|
const sortChangeHandler = (sortOptions: SortProp) => {
|
|
178
133
|
const modelName = props.name || props.config.name || '';
|
|
179
134
|
sortChange(props.model[modelName], sortOptions);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ref, watch } from 'vue';
|
|
2
|
+
|
|
3
|
+
import { useZIndex } from '@tmagic/design';
|
|
4
|
+
|
|
5
|
+
export const useFullscreen = () => {
|
|
6
|
+
const { nextZIndex } = useZIndex();
|
|
7
|
+
|
|
8
|
+
const fullscreenZIndex = ref(nextZIndex());
|
|
9
|
+
|
|
10
|
+
const isFullscreen = ref(false);
|
|
11
|
+
|
|
12
|
+
const toggleFullscreen = () => {
|
|
13
|
+
if (isFullscreen.value) {
|
|
14
|
+
isFullscreen.value = false;
|
|
15
|
+
} else {
|
|
16
|
+
isFullscreen.value = true;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
watch(isFullscreen, (value) => {
|
|
21
|
+
if (value) {
|
|
22
|
+
fullscreenZIndex.value = nextZIndex();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
isFullscreen,
|
|
28
|
+
fullscreenZIndex,
|
|
29
|
+
toggleFullscreen,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -8,8 +8,7 @@ import type { TableProps } from './type';
|
|
|
8
8
|
|
|
9
9
|
export const useImport = (
|
|
10
10
|
props: TableProps,
|
|
11
|
-
emit: (event: 'select' | 'change' | 'addDiffCount', ...args: any[]) => void,
|
|
12
|
-
newHandler: (row: any) => void,
|
|
11
|
+
emit: (event: 'select' | 'change' | 'addDiffCount' | 'add', ...args: any[]) => void,
|
|
13
12
|
) => {
|
|
14
13
|
const mForm = inject<FormState | undefined>('mForm');
|
|
15
14
|
const modelName = computed(() => props.name || props.config.name || '');
|
|
@@ -41,9 +40,7 @@ export const useImport = (
|
|
|
41
40
|
pdata.SheetNames.forEach((sheetName: string) => {
|
|
42
41
|
const arr = (globalThis as any).XLSX.utils.sheet_to_json(pdata.Sheets[sheetName], { header: 1 });
|
|
43
42
|
if (arr?.[0]) {
|
|
44
|
-
|
|
45
|
-
newHandler(row);
|
|
46
|
-
});
|
|
43
|
+
emit('add', arr);
|
|
47
44
|
}
|
|
48
45
|
setTimeout(() => {
|
|
49
46
|
excelBtn.value?.clearFiles();
|
|
@@ -4,7 +4,7 @@ import type { default as SortableType, SortableEvent } from 'sortablejs';
|
|
|
4
4
|
import { type TMagicTable } from '@tmagic/design';
|
|
5
5
|
import type { FormState } from '@tmagic/form-schema';
|
|
6
6
|
|
|
7
|
-
import { sortArray } from '
|
|
7
|
+
import { sortArray } from '../../utils/form';
|
|
8
8
|
|
|
9
9
|
import type { TableProps } from './type';
|
|
10
10
|
|
|
@@ -5,9 +5,9 @@ import { cloneDeep } from 'lodash-es';
|
|
|
5
5
|
import { type TableColumnOptions, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
|
6
6
|
import type { FormItemConfig, FormState, TableColumnConfig } from '@tmagic/form-schema';
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
8
|
+
import type { ContainerChangeEventData } from '../../schema';
|
|
9
|
+
import { display as displayFunc, getDataByPage, sortArray } from '../../utils/form';
|
|
10
|
+
import Container from '../Container.vue';
|
|
11
11
|
|
|
12
12
|
import ActionsColumn from './ActionsColumn.vue';
|
|
13
13
|
import SortColumn from './SortColumn.vue';
|
|
@@ -187,7 +187,7 @@ export const useTableColumns = (
|
|
|
187
187
|
columns.push({
|
|
188
188
|
props: {
|
|
189
189
|
prop: column.name,
|
|
190
|
-
label: column.label,
|
|
190
|
+
label: column.label || column.text,
|
|
191
191
|
width: column.width,
|
|
192
192
|
sortable: column.sortable,
|
|
193
193
|
sortOrders: ['ascending', 'descending'],
|
|
@@ -223,7 +223,10 @@ export const useTableColumns = (
|
|
|
223
223
|
gap: '5px',
|
|
224
224
|
},
|
|
225
225
|
},
|
|
226
|
-
[
|
|
226
|
+
[
|
|
227
|
+
h('span', column.label || column.text),
|
|
228
|
+
h(TMagicIcon, {}, { default: () => h(WarningFilled) }),
|
|
229
|
+
],
|
|
227
230
|
),
|
|
228
231
|
content: () =>
|
|
229
232
|
h('div', {
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="displayMode === 'table' ? MFormTable : MFormGroupList"
|
|
4
|
+
ref="tableGroupList"
|
|
5
|
+
v-bind="$attrs"
|
|
6
|
+
:model="model"
|
|
7
|
+
:name="`${name}`"
|
|
8
|
+
:config="currentConfig"
|
|
9
|
+
:disabled="disabled"
|
|
10
|
+
:size="size"
|
|
11
|
+
:is-compare="isCompare"
|
|
12
|
+
:last-values="lastValues"
|
|
13
|
+
:prop="prop"
|
|
14
|
+
:label-width="labelWidth"
|
|
15
|
+
:show-index="showIndex"
|
|
16
|
+
:sort-key="sortKey"
|
|
17
|
+
:sort="sort"
|
|
18
|
+
@change="onChange"
|
|
19
|
+
@select="onSelect"
|
|
20
|
+
@addDiffCount="onAddDiffCount"
|
|
21
|
+
@add="onAdd"
|
|
22
|
+
>
|
|
23
|
+
<template #toggle-button>
|
|
24
|
+
<TMagicButton
|
|
25
|
+
v-if="config.enableToggleMode || enableToggleMode"
|
|
26
|
+
:icon="Grid"
|
|
27
|
+
size="small"
|
|
28
|
+
@click="toggleDisplayMode"
|
|
29
|
+
>
|
|
30
|
+
{{ displayMode === 'table' ? '展开配置' : '切换为表格' }}
|
|
31
|
+
</TMagicButton>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<template #add-button v-if="addable">
|
|
35
|
+
<TMagicButton
|
|
36
|
+
:class="displayMode === 'table' ? 'm-form-table-add-button' : ''"
|
|
37
|
+
:size="addButtonSize"
|
|
38
|
+
:plain="displayMode === 'table'"
|
|
39
|
+
:icon="Plus"
|
|
40
|
+
:disabled="disabled"
|
|
41
|
+
v-bind="currentConfig.addButtonConfig?.props || { type: 'primary' }"
|
|
42
|
+
@click="newHandler"
|
|
43
|
+
>
|
|
44
|
+
{{ currentConfig.addButtonConfig?.text || (displayMode === 'table' ? '新增一行' : '新增') }}
|
|
45
|
+
</TMagicButton>
|
|
46
|
+
</template>
|
|
47
|
+
</component>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script setup lang="ts">
|
|
51
|
+
import { computed, ref, useTemplateRef } from 'vue';
|
|
52
|
+
import { Grid, Plus } from '@element-plus/icons-vue';
|
|
53
|
+
|
|
54
|
+
import { TMagicButton } from '@tmagic/design';
|
|
55
|
+
import type { GroupListConfig, TableConfig } from '@tmagic/form-schema';
|
|
56
|
+
|
|
57
|
+
import type { ContainerChangeEventData } from '../../schema';
|
|
58
|
+
import MFormGroupList from '../GroupList.vue';
|
|
59
|
+
import MFormTable from '../table/Table.vue';
|
|
60
|
+
|
|
61
|
+
import { useAdd } from './useAdd';
|
|
62
|
+
|
|
63
|
+
defineOptions({
|
|
64
|
+
name: 'MFormTableGroupList',
|
|
65
|
+
inheritAttrs: false,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const props = defineProps<{
|
|
69
|
+
model: any;
|
|
70
|
+
lastValues?: any;
|
|
71
|
+
isCompare?: boolean;
|
|
72
|
+
config: TableConfig | GroupListConfig;
|
|
73
|
+
name: string;
|
|
74
|
+
prop?: string;
|
|
75
|
+
labelWidth?: string;
|
|
76
|
+
disabled?: boolean;
|
|
77
|
+
size?: string;
|
|
78
|
+
enableToggleMode?: true;
|
|
79
|
+
showIndex?: boolean;
|
|
80
|
+
sortKey?: string;
|
|
81
|
+
sort?: boolean;
|
|
82
|
+
}>();
|
|
83
|
+
|
|
84
|
+
const emit = defineEmits(['change', 'select', 'addDiffCount']);
|
|
85
|
+
|
|
86
|
+
const { addable, newHandler } = useAdd(props, emit);
|
|
87
|
+
|
|
88
|
+
const isGroupListType = (type: string | undefined) => type === 'groupList' || type === 'group-list';
|
|
89
|
+
|
|
90
|
+
const displayMode = ref<'table' | 'groupList'>(isGroupListType(props.config.type) ? 'groupList' : 'table');
|
|
91
|
+
|
|
92
|
+
const calcLabelWidth = (label: string) => {
|
|
93
|
+
if (!label) return '0px';
|
|
94
|
+
const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
|
|
95
|
+
const chLength = label.length - zhLength;
|
|
96
|
+
return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// 当原始 config 是 table 形态时,table 模式直接透传;
|
|
100
|
+
// 若原始是 groupList,则基于它派生出 table 所需的 config
|
|
101
|
+
const tableConfig = computed<TableConfig>(() => {
|
|
102
|
+
if (!isGroupListType(props.config.type)) {
|
|
103
|
+
return props.config as TableConfig;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const source = props.config as GroupListConfig;
|
|
107
|
+
return {
|
|
108
|
+
...props.config,
|
|
109
|
+
type: 'table',
|
|
110
|
+
groupItems: source.items,
|
|
111
|
+
items:
|
|
112
|
+
source.tableItems ||
|
|
113
|
+
(source.items as any[]).map((item: any) => ({
|
|
114
|
+
...item,
|
|
115
|
+
label: item.label || item.text,
|
|
116
|
+
text: null,
|
|
117
|
+
})),
|
|
118
|
+
} as any as TableConfig;
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// 反向派生 groupList 所需的 config
|
|
122
|
+
const groupListConfig = computed<GroupListConfig>(() => {
|
|
123
|
+
if (isGroupListType(props.config.type)) {
|
|
124
|
+
return props.config as GroupListConfig;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const source = props.config as TableConfig;
|
|
128
|
+
return {
|
|
129
|
+
...props.config,
|
|
130
|
+
type: 'groupList',
|
|
131
|
+
tableItems: source.items,
|
|
132
|
+
items:
|
|
133
|
+
source.groupItems ||
|
|
134
|
+
(source.items as any[]).map((item: any) => {
|
|
135
|
+
const text = item.text || item.label;
|
|
136
|
+
return {
|
|
137
|
+
...item,
|
|
138
|
+
text,
|
|
139
|
+
labelWidth: calcLabelWidth(text),
|
|
140
|
+
span: item.span || 12,
|
|
141
|
+
};
|
|
142
|
+
}),
|
|
143
|
+
} as any as GroupListConfig;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// 运行时类型由 displayMode 决定,`<component :is>` 无法做联合类型收窄,统一转 any 交给子组件处理
|
|
147
|
+
const currentConfig = computed<any>(() => (displayMode.value === 'table' ? tableConfig.value : groupListConfig.value));
|
|
148
|
+
|
|
149
|
+
// 保持原 Table/GroupList 模式下新增按钮的不同尺寸策略
|
|
150
|
+
const addButtonSize = computed(() => {
|
|
151
|
+
if (displayMode.value === 'table') return 'small';
|
|
152
|
+
return props.config.enableToggleMode !== false ? 'small' : 'default';
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const toggleDisplayMode = () => {
|
|
156
|
+
displayMode.value = displayMode.value === 'table' ? 'groupList' : 'table';
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const onChange = (v: any, eventData?: ContainerChangeEventData) => emit('change', v, eventData);
|
|
160
|
+
const onSelect = (...args: any[]) => emit('select', ...args);
|
|
161
|
+
const onAddDiffCount = () => emit('addDiffCount');
|
|
162
|
+
const onAdd = (rows: any[]) => {
|
|
163
|
+
rows.forEach((row: any) => {
|
|
164
|
+
newHandler(row);
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const tableGroupListRef = useTemplateRef<InstanceType<typeof MFormTable>>('tableGroupList');
|
|
169
|
+
|
|
170
|
+
defineExpose({
|
|
171
|
+
toggleRowSelection: (row: any, selected: boolean) => tableGroupListRef.value?.toggleRowSelection?.(row, selected),
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
@@ -1,30 +1,40 @@
|
|
|
1
1
|
import { computed, inject } from 'vue';
|
|
2
2
|
|
|
3
3
|
import { tMagicMessage } from '@tmagic/design';
|
|
4
|
-
import type { FormConfig, FormState } from '@tmagic/form-schema';
|
|
4
|
+
import type { FormConfig, FormState, TableConfig, TableGroupListCommonConfig } from '@tmagic/form-schema';
|
|
5
5
|
|
|
6
|
-
import { initValue } from '
|
|
7
|
-
|
|
8
|
-
import type { TableProps } from './type';
|
|
6
|
+
import { initValue } from '../../utils/form';
|
|
7
|
+
import type { TableProps } from '../table/type';
|
|
9
8
|
|
|
10
9
|
export const useAdd = (
|
|
11
|
-
props: TableProps,
|
|
12
|
-
|
|
10
|
+
props: Pick<TableProps, 'name' | 'model' | 'prop' | 'sortKey'> & {
|
|
11
|
+
config: Pick<TableGroupListCommonConfig, 'addable' | 'max' | 'beforeAddRow' | 'defaultAdd' | 'enum'> &
|
|
12
|
+
Pick<TableConfig, 'key' | 'name'> & {
|
|
13
|
+
items: { name?: string | number }[];
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
emit: (event: 'change', ...args: any[]) => void,
|
|
13
17
|
) => {
|
|
14
18
|
const mForm = inject<FormState | undefined>('mForm');
|
|
15
19
|
|
|
16
20
|
const addable = computed(() => {
|
|
17
21
|
const modelName = props.name || props.config.name || '';
|
|
22
|
+
|
|
23
|
+
if (!modelName) return false;
|
|
24
|
+
|
|
18
25
|
if (!props.model[modelName].length) {
|
|
19
26
|
return true;
|
|
20
27
|
}
|
|
28
|
+
|
|
21
29
|
if (typeof props.config.addable === 'function') {
|
|
22
30
|
return props.config.addable(mForm, {
|
|
23
31
|
model: props.model[modelName],
|
|
24
32
|
formValue: mForm?.values,
|
|
25
33
|
prop: props.prop,
|
|
34
|
+
config: props.config,
|
|
26
35
|
});
|
|
27
36
|
}
|
|
37
|
+
|
|
28
38
|
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
29
39
|
});
|
|
30
40
|
|
|
@@ -37,7 +47,7 @@ export const useAdd = (
|
|
|
37
47
|
}
|
|
38
48
|
|
|
39
49
|
if (typeof props.config.beforeAddRow === 'function') {
|
|
40
|
-
const beforeCheckRes = props.config.beforeAddRow(mForm, {
|
|
50
|
+
const beforeCheckRes = await props.config.beforeAddRow(mForm, {
|
|
41
51
|
model: props.model[modelName],
|
|
42
52
|
formValue: mForm?.values,
|
|
43
53
|
prop: props.prop,
|
package/src/index.ts
CHANGED
|
@@ -32,8 +32,9 @@ export { default as MFlexLayout } from './containers/FlexLayout.vue';
|
|
|
32
32
|
export { default as MPanel } from './containers/Panel.vue';
|
|
33
33
|
export { default as MRow } from './containers/Row.vue';
|
|
34
34
|
export { default as MTabs } from './containers/Tabs.vue';
|
|
35
|
-
export { default as MTable } from './table/
|
|
36
|
-
export { default as MGroupList } from './containers/
|
|
35
|
+
export { default as MTable } from './containers/table-group-list/TableGroupList.vue';
|
|
36
|
+
export { default as MGroupList } from './containers/table-group-list/TableGroupList.vue';
|
|
37
|
+
export { default as MTableGroupList } from './containers/table-group-list/TableGroupList.vue';
|
|
37
38
|
export { default as MText } from './fields/Text.vue';
|
|
38
39
|
export { default as MNumber } from './fields/Number.vue';
|
|
39
40
|
export { default as MNumberRange } from './fields/NumberRange.vue';
|