@tmagic/table 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.
- package/dist/tmagic-table.mjs +353 -435
- package/dist/tmagic-table.mjs.map +1 -1
- package/dist/tmagic-table.umd.js +355 -437
- package/dist/tmagic-table.umd.js.map +1 -1
- package/package.json +7 -7
- package/src/ActionsColumn.vue +35 -91
- package/src/ExpandColumn.vue +27 -21
- package/src/PopoverColumn.vue +23 -24
- package/src/Table.vue +125 -141
- package/src/TextColumn.vue +35 -36
- package/src/index.ts +1 -5
- package/src/schema.ts +20 -13
- package/src/utils.ts +2 -0
- package/types/ActionsColumn.vue.d.ts +69 -94
- package/types/ExpandColumn.vue.d.ts +78 -15
- package/types/PopoverColumn.vue.d.ts +78 -17
- package/types/Table.vue.d.ts +212 -111
- package/types/TextColumn.vue.d.ts +89 -26
- package/types/schema.d.ts +20 -13
package/src/Table.vue
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<TMagicTable
|
|
3
3
|
tooltip-effect="dark"
|
|
4
4
|
class="m-table"
|
|
5
|
-
ref="
|
|
5
|
+
ref="tMagicTable"
|
|
6
6
|
v-loading="loading"
|
|
7
7
|
:data="tableData"
|
|
8
8
|
:show-header="showHeader"
|
|
9
9
|
:max-height="bodyHeight"
|
|
10
10
|
:default-expand-all="defaultExpandAll"
|
|
11
11
|
:border="hasBorder"
|
|
12
|
-
:row-key="rowkeyName || '
|
|
12
|
+
:row-key="rowkeyName || 'id'"
|
|
13
13
|
:tree-props="{ children: 'children' }"
|
|
14
14
|
:empty-text="emptyText || '暂无数据'"
|
|
15
15
|
:span-method="objectSpanMethod"
|
|
@@ -17,190 +17,174 @@
|
|
|
17
17
|
@select="selectHandler"
|
|
18
18
|
@select-all="selectAllHandler"
|
|
19
19
|
@selection-change="selectionChangeHandler"
|
|
20
|
+
@cell-click="cellClickHandler"
|
|
21
|
+
@expand-change="expandChange"
|
|
20
22
|
>
|
|
21
23
|
<template v-for="(item, columnIndex) in columns">
|
|
22
24
|
<template v-if="item.type === 'expand'">
|
|
23
|
-
<
|
|
25
|
+
<ExpandColumn :config="item" :key="columnIndex"></ExpandColumn>
|
|
24
26
|
</template>
|
|
25
27
|
|
|
26
28
|
<template v-else-if="item.selection">
|
|
27
|
-
<
|
|
29
|
+
<component
|
|
30
|
+
width="40"
|
|
31
|
+
type="selection"
|
|
32
|
+
:is="tableColumnComponent.component"
|
|
33
|
+
:key="columnIndex"
|
|
34
|
+
:selectable="item.selectable"
|
|
35
|
+
></component>
|
|
28
36
|
</template>
|
|
29
37
|
|
|
30
38
|
<template v-else-if="item.actions">
|
|
31
|
-
<
|
|
39
|
+
<ActionsColumn
|
|
32
40
|
:columns="columns"
|
|
33
41
|
:config="item"
|
|
34
42
|
:rowkey-name="rowkeyName"
|
|
35
43
|
:edit-state="editState"
|
|
36
44
|
:key="columnIndex"
|
|
37
|
-
@
|
|
38
|
-
></
|
|
45
|
+
@after-action="$emit('after-action')"
|
|
46
|
+
></ActionsColumn>
|
|
39
47
|
</template>
|
|
40
48
|
|
|
41
49
|
<template v-else-if="item.type === 'popover'">
|
|
42
|
-
<
|
|
50
|
+
<PopoverColumn :key="columnIndex" :config="item"></PopoverColumn>
|
|
43
51
|
</template>
|
|
44
52
|
|
|
45
53
|
<template v-else>
|
|
46
|
-
<
|
|
54
|
+
<TextColumn :key="columnIndex" :config="item" :edit-state="editState"></TextColumn>
|
|
47
55
|
</template>
|
|
48
56
|
</template>
|
|
49
|
-
</
|
|
57
|
+
</TMagicTable>
|
|
50
58
|
</template>
|
|
51
59
|
|
|
52
|
-
<script lang="ts">
|
|
53
|
-
import {
|
|
54
|
-
import { ElTable } from 'element-plus';
|
|
60
|
+
<script lang="ts" setup name="MTable">
|
|
61
|
+
import { computed, ref } from 'vue';
|
|
55
62
|
import { cloneDeep } from 'lodash-es';
|
|
56
63
|
|
|
64
|
+
import { getConfig, TMagicTable } from '@tmagic/design';
|
|
65
|
+
|
|
57
66
|
import ActionsColumn from './ActionsColumn.vue';
|
|
58
67
|
import ExpandColumn from './ExpandColumn.vue';
|
|
59
68
|
import PopoverColumn from './PopoverColumn.vue';
|
|
60
69
|
import TextColumn from './TextColumn.vue';
|
|
61
70
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
props: {
|
|
68
|
-
data: {
|
|
69
|
-
type: Array,
|
|
70
|
-
require: true,
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
columns: {
|
|
74
|
-
type: Array as PropType<any[]>,
|
|
75
|
-
require: true,
|
|
76
|
-
default: () => [],
|
|
77
|
-
},
|
|
78
|
-
|
|
71
|
+
const props = withDefaults(
|
|
72
|
+
defineProps<{
|
|
73
|
+
data: any[];
|
|
74
|
+
columns?: any[];
|
|
79
75
|
/** 合并行或列的计算方法 */
|
|
80
|
-
spanMethod: {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
spanMethod?: (data: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number];
|
|
77
|
+
loading?: boolean;
|
|
78
|
+
/** Table 的最大高度。合法的值为数字或者单位为 px 的高度 */
|
|
79
|
+
bodyHeight?: string | number;
|
|
80
|
+
/** 是否显示表头 */
|
|
81
|
+
showHeader?: boolean;
|
|
82
|
+
/** 空数据时显示的文本内容 */
|
|
83
|
+
emptyText?: string;
|
|
84
|
+
/** 是否默认展开所有行,当 Table 包含展开行存在或者为树形表格时有效 */
|
|
85
|
+
defaultExpandAll?: boolean;
|
|
86
|
+
rowkeyName?: string;
|
|
87
|
+
/** 是否带有纵向边框 */
|
|
88
|
+
border?: boolean;
|
|
89
|
+
}>(),
|
|
90
|
+
{
|
|
91
|
+
columns: () => [],
|
|
92
|
+
loading: false,
|
|
93
|
+
showHeader: true,
|
|
94
|
+
defaultExpandAll: false,
|
|
95
|
+
border: false,
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const emit = defineEmits([
|
|
100
|
+
'sort-change',
|
|
101
|
+
'after-action',
|
|
102
|
+
'select',
|
|
103
|
+
'select-all',
|
|
104
|
+
'selection-change',
|
|
105
|
+
'expand-change',
|
|
106
|
+
'cell-click',
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
const tMagicTable = ref<InstanceType<typeof TMagicTable>>();
|
|
110
|
+
|
|
111
|
+
const editState = ref([]);
|
|
112
|
+
|
|
113
|
+
const tableColumnComponent = getConfig('components').tableColumn;
|
|
114
|
+
const selectionColumn = computed(() => {
|
|
115
|
+
const column = props.columns.filter((item) => item.selection);
|
|
116
|
+
return column.length ? column[0] : null;
|
|
117
|
+
});
|
|
85
118
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
119
|
+
const tableData = computed(() => {
|
|
120
|
+
if (selectionColumn.value) {
|
|
121
|
+
return props.data || [];
|
|
122
|
+
}
|
|
90
123
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
type: [String, Number],
|
|
94
|
-
},
|
|
124
|
+
return cloneDeep(props.data) || [];
|
|
125
|
+
});
|
|
95
126
|
|
|
96
|
-
|
|
97
|
-
showHeader: {
|
|
98
|
-
type: Boolean,
|
|
99
|
-
default: true,
|
|
100
|
-
},
|
|
127
|
+
const hasBorder = computed(() => (typeof props.border !== 'undefined' ? props.border : true));
|
|
101
128
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
},
|
|
129
|
+
const sortChange = (data: any) => {
|
|
130
|
+
emit('sort-change', data);
|
|
131
|
+
};
|
|
106
132
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
133
|
+
const selectHandler = (selection: any, row: any) => {
|
|
134
|
+
const column = selectionColumn.value;
|
|
135
|
+
if (!column) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
112
138
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
139
|
+
if (column.selection === 'single') {
|
|
140
|
+
// this.clearSelection()
|
|
141
|
+
// this.toggleRowSelection(row, true)
|
|
142
|
+
}
|
|
143
|
+
emit('select', selection, row);
|
|
144
|
+
};
|
|
116
145
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
default: false,
|
|
121
|
-
},
|
|
122
|
-
},
|
|
146
|
+
const selectAllHandler = (selection: any) => {
|
|
147
|
+
emit('select-all', selection);
|
|
148
|
+
};
|
|
123
149
|
|
|
124
|
-
|
|
150
|
+
const selectionChangeHandler = (selection: any) => {
|
|
151
|
+
emit('selection-change', selection);
|
|
152
|
+
};
|
|
125
153
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
editState: [],
|
|
131
|
-
};
|
|
132
|
-
},
|
|
154
|
+
const cellClickHandler = (...args: any[]) => {
|
|
155
|
+
emit('cell-click', ...args);
|
|
156
|
+
};
|
|
133
157
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return this.data || [];
|
|
138
|
-
}
|
|
158
|
+
const expandChange = (...args: any[]) => {
|
|
159
|
+
emit('expand-change', ...args);
|
|
160
|
+
};
|
|
139
161
|
|
|
140
|
-
|
|
141
|
-
|
|
162
|
+
const toggleRowSelection = (row: any, selected: boolean) => {
|
|
163
|
+
tMagicTable.value?.toggleRowSelection(row, selected);
|
|
164
|
+
};
|
|
142
165
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
},
|
|
166
|
+
const toggleRowExpansion = (row: any, expanded: boolean) => {
|
|
167
|
+
tMagicTable.value?.toggleRowExpansion(row, expanded);
|
|
168
|
+
};
|
|
147
169
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
},
|
|
170
|
+
const clearSelection = () => {
|
|
171
|
+
tMagicTable.value?.clearSelection();
|
|
172
|
+
};
|
|
152
173
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
this.$emit('select', selection, row);
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
selectAllHandler(selection: any) {
|
|
172
|
-
this.$emit('select-all', selection);
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
selectionChangeHandler(selection: any) {
|
|
176
|
-
this.$emit('selection-change', selection);
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
toggleRowSelection(row: any, selected: boolean) {
|
|
180
|
-
const table = this.$refs.table as InstanceType<typeof ElTable>;
|
|
181
|
-
table.toggleRowSelection.bind(table)(row, selected);
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
toggleRowExpansion(row: any, expanded: boolean) {
|
|
185
|
-
const table = this.$refs.table as InstanceType<typeof ElTable>;
|
|
186
|
-
table.toggleRowExpansion.bind(table)(row, expanded);
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
clearSelection() {
|
|
190
|
-
const table = this.$refs.table as InstanceType<typeof ElTable>;
|
|
191
|
-
table.clearSelection.bind(table)();
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
objectSpanMethod(data: any) {
|
|
195
|
-
if (typeof this.spanMethod === 'function') {
|
|
196
|
-
return this.spanMethod(data);
|
|
197
|
-
}
|
|
198
|
-
return () => ({
|
|
199
|
-
rowspan: 0,
|
|
200
|
-
colspan: 0,
|
|
201
|
-
});
|
|
202
|
-
},
|
|
203
|
-
},
|
|
174
|
+
const objectSpanMethod = (data: any) => {
|
|
175
|
+
if (typeof props.spanMethod === 'function') {
|
|
176
|
+
return props.spanMethod(data);
|
|
177
|
+
}
|
|
178
|
+
return () => ({
|
|
179
|
+
rowspan: 0,
|
|
180
|
+
colspan: 0,
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
defineExpose({
|
|
185
|
+
toggleRowSelection,
|
|
186
|
+
toggleRowExpansion,
|
|
187
|
+
clearSelection,
|
|
204
188
|
});
|
|
205
189
|
</script>
|
|
206
190
|
|
package/src/TextColumn.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<TMagicTableColumn
|
|
3
3
|
show-overflow-tooltip
|
|
4
4
|
:label="config.label"
|
|
5
5
|
:width="config.width"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
:prop="config.prop"
|
|
9
9
|
>
|
|
10
10
|
<template v-slot="scope">
|
|
11
|
-
<
|
|
11
|
+
<TMagicForm v-if="config.type && editState[scope.$index]" label-width="0" :model="editState[scope.$index]">
|
|
12
12
|
<m-form-container
|
|
13
13
|
:prop="config.prop"
|
|
14
14
|
:rules="config.rules"
|
|
@@ -16,62 +16,61 @@
|
|
|
16
16
|
:name="config.prop"
|
|
17
17
|
:model="editState[scope.$index]"
|
|
18
18
|
></m-form-container>
|
|
19
|
-
</
|
|
19
|
+
</TMagicForm>
|
|
20
20
|
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
<TMagicButton
|
|
22
|
+
v-else-if="config.action === 'actionLink' && config.prop"
|
|
23
|
+
text
|
|
24
|
+
type="primary"
|
|
25
|
+
@click="config.handler?.(scope.row)"
|
|
26
|
+
>
|
|
27
|
+
<span v-html="formatter(config, scope.row)"></span>
|
|
28
|
+
</TMagicButton>
|
|
24
29
|
|
|
25
|
-
<a v-else-if="config.action === 'img'" target="_blank" :href="scope.row[config.prop]"
|
|
30
|
+
<a v-else-if="config.action === 'img' && config.prop" target="_blank" :href="scope.row[config.prop]"
|
|
26
31
|
><img :src="scope.row[config.prop]" height="50"
|
|
27
32
|
/></a>
|
|
28
33
|
|
|
29
|
-
<a
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
<a
|
|
35
|
+
v-else-if="config.action === 'link' && config.prop"
|
|
36
|
+
target="_blank"
|
|
37
|
+
:href="scope.row[config.prop]"
|
|
38
|
+
class="keep-all"
|
|
39
|
+
>{{ scope.row[config.prop] }}</a
|
|
40
|
+
>
|
|
32
41
|
|
|
33
42
|
<el-tooltip v-else-if="config.action === 'tip'" placement="left">
|
|
34
43
|
<template #content>
|
|
35
44
|
<div>{{ formatter(config, scope.row) }}</div>
|
|
36
45
|
</template>
|
|
37
|
-
<
|
|
46
|
+
<TMagicButton text type="primary">扩展配置</TMagicButton>
|
|
38
47
|
</el-tooltip>
|
|
39
48
|
|
|
40
|
-
<
|
|
41
|
-
v-else-if="config.action === 'tag'"
|
|
49
|
+
<TMagicTag
|
|
50
|
+
v-else-if="config.action === 'tag' && config.prop"
|
|
42
51
|
:type="typeof config.type === 'function' ? config.type(scope.row[config.prop], scope.row) : config.type"
|
|
43
52
|
close-transition
|
|
44
|
-
>{{ formatter(config, scope.row) }}</
|
|
53
|
+
>{{ formatter(config, scope.row) }}</TMagicTag
|
|
45
54
|
>
|
|
46
55
|
<div v-else v-html="formatter(config, scope.row)"></div>
|
|
47
56
|
</template>
|
|
48
|
-
</
|
|
57
|
+
</TMagicTableColumn>
|
|
49
58
|
</template>
|
|
50
59
|
|
|
51
|
-
<script lang="ts">
|
|
52
|
-
import {
|
|
60
|
+
<script lang="ts" setup name="MTableColumn">
|
|
61
|
+
import { TMagicButton, TMagicForm, TMagicTableColumn, TMagicTag } from '@tmagic/design';
|
|
53
62
|
|
|
54
63
|
import { ColumnConfig } from './schema';
|
|
55
64
|
import { formatter } from './utils';
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
config:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
editState: {
|
|
66
|
-
type: Object,
|
|
67
|
-
default: () => {},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
setup() {
|
|
72
|
-
return {
|
|
73
|
-
formatter,
|
|
74
|
-
};
|
|
66
|
+
withDefaults(
|
|
67
|
+
defineProps<{
|
|
68
|
+
config: ColumnConfig;
|
|
69
|
+
editState?: any;
|
|
70
|
+
}>(),
|
|
71
|
+
{
|
|
72
|
+
config: () => ({}),
|
|
73
|
+
editState: () => ({}),
|
|
75
74
|
},
|
|
76
|
-
|
|
75
|
+
);
|
|
77
76
|
</script>
|
package/src/index.ts
CHANGED
|
@@ -22,12 +22,8 @@ import Table from './Table.vue';
|
|
|
22
22
|
|
|
23
23
|
export { default as MagicTable } from './Table.vue';
|
|
24
24
|
|
|
25
|
-
const components = [Table];
|
|
26
|
-
|
|
27
25
|
export default {
|
|
28
26
|
install(app: App) {
|
|
29
|
-
|
|
30
|
-
app.component(component.name, component);
|
|
31
|
-
});
|
|
27
|
+
app.component('m-table', Table);
|
|
32
28
|
},
|
|
33
29
|
};
|
package/src/schema.ts
CHANGED
|
@@ -20,9 +20,10 @@ import { FormConfig, FormValue } from '@tmagic/form';
|
|
|
20
20
|
|
|
21
21
|
export interface ColumnActionConfig {
|
|
22
22
|
type?: 'delete' | 'copy' | 'edit';
|
|
23
|
-
display?: (
|
|
24
|
-
text: string;
|
|
23
|
+
display?: (row: any) => boolean;
|
|
24
|
+
text: string | ((row: any) => string);
|
|
25
25
|
name: string;
|
|
26
|
+
icon?: any;
|
|
26
27
|
handler?: (row: any) => Promise<any> | any;
|
|
27
28
|
before?: (row: any) => void;
|
|
28
29
|
after?: (row: any) => void;
|
|
@@ -35,23 +36,29 @@ export type ColumnConfig = {
|
|
|
35
36
|
values?: FormValue;
|
|
36
37
|
selection?: boolean | 'single';
|
|
37
38
|
selectable?: (row: any, index: number) => boolean;
|
|
38
|
-
label
|
|
39
|
+
label?: string;
|
|
39
40
|
fixed?: 'left' | 'right' | boolean;
|
|
40
41
|
width?: number | string;
|
|
41
42
|
actions?: ColumnActionConfig[];
|
|
42
|
-
type
|
|
43
|
-
text
|
|
44
|
-
prop
|
|
45
|
-
showHeader
|
|
43
|
+
type?: 'popover' | 'expand' | string | ((value: any, row: any) => string);
|
|
44
|
+
text?: string;
|
|
45
|
+
prop?: string;
|
|
46
|
+
showHeader?: boolean;
|
|
46
47
|
table?: ColumnConfig[];
|
|
47
48
|
formatter?: 'datetime' | ((item: any, row: Record<string, any>) => any);
|
|
48
|
-
popover
|
|
49
|
-
placement:
|
|
50
|
-
width:
|
|
51
|
-
trigger:
|
|
52
|
-
tableEmbed:
|
|
49
|
+
popover?: {
|
|
50
|
+
placement: string;
|
|
51
|
+
width: string;
|
|
52
|
+
trigger: string;
|
|
53
|
+
tableEmbed: string;
|
|
53
54
|
};
|
|
54
55
|
sortable?: boolean | 'custom';
|
|
55
56
|
action?: 'tip' | 'actionLink' | 'img' | 'link' | 'tag';
|
|
56
|
-
handler
|
|
57
|
+
handler?: (row: any) => void;
|
|
58
|
+
/** 当type为expand时有效,展开为html */
|
|
59
|
+
expandContent?: (row: any, prop?: string) => string;
|
|
60
|
+
/** 当type为expand时有效,展开为vue组件 */
|
|
61
|
+
component?: any;
|
|
62
|
+
/** 当type为expand时有效,展开的vue组件props */
|
|
63
|
+
props?: any;
|
|
57
64
|
};
|
package/src/utils.ts
CHANGED
|
@@ -21,6 +21,8 @@ import { datetimeFormatter } from '@tmagic/utils';
|
|
|
21
21
|
import { ColumnConfig } from './schema';
|
|
22
22
|
|
|
23
23
|
export const formatter = (item: ColumnConfig, row: any) => {
|
|
24
|
+
if (!item.prop) return '';
|
|
25
|
+
|
|
24
26
|
if (item.formatter) {
|
|
25
27
|
if (item.formatter === 'datetime') {
|
|
26
28
|
// eslint-disable-next-line no-param-reassign
|