@tmagic/table 1.4.8 → 1.4.9
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/package.json +6 -8
- package/src/ActionsColumn.vue +123 -0
- package/src/ComponentColumn.vue +51 -0
- package/src/ExpandColumn.vue +47 -0
- package/src/PopoverColumn.vue +43 -0
- package/src/Table.vue +218 -0
- package/src/TextColumn.vue +80 -0
- package/src/index.ts +31 -0
- package/src/schema.ts +71 -0
- package/src/shims-vue.d.ts +6 -0
- package/src/utils.ts +39 -0
package/package.json
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.4.
|
|
2
|
+
"version": "1.4.9",
|
|
3
3
|
"name": "@tmagic/table",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"sideEffects": [
|
|
6
|
-
"dist/*"
|
|
7
|
-
],
|
|
8
5
|
"main": "dist/tmagic-table.umd.cjs",
|
|
9
6
|
"module": "dist/tmagic-table.js",
|
|
10
7
|
"types": "types/index.d.ts",
|
|
@@ -22,7 +19,8 @@
|
|
|
22
19
|
},
|
|
23
20
|
"files": [
|
|
24
21
|
"dist",
|
|
25
|
-
"types"
|
|
22
|
+
"types",
|
|
23
|
+
"src"
|
|
26
24
|
],
|
|
27
25
|
"license": "Apache-2.0",
|
|
28
26
|
"engines": {
|
|
@@ -49,9 +47,9 @@
|
|
|
49
47
|
"peerDependencies": {
|
|
50
48
|
"vue": "^3.4.27",
|
|
51
49
|
"typescript": "*",
|
|
52
|
-
"@tmagic/
|
|
53
|
-
"@tmagic/
|
|
54
|
-
"@tmagic/
|
|
50
|
+
"@tmagic/form": "1.4.9",
|
|
51
|
+
"@tmagic/utils": "1.4.9",
|
|
52
|
+
"@tmagic/design": "1.4.9"
|
|
55
53
|
},
|
|
56
54
|
"peerDependenciesMeta": {
|
|
57
55
|
"typescript": {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TMagicTableColumn :label="config.label" :width="config.width" :fixed="config.fixed">
|
|
3
|
+
<template v-slot="scope">
|
|
4
|
+
<TMagicTooltip
|
|
5
|
+
v-for="(action, actionIndex) in config.actions"
|
|
6
|
+
:placement="action.tooltipPlacement || 'top'"
|
|
7
|
+
:key="actionIndex"
|
|
8
|
+
:disabled="!Boolean(action.tooltip)"
|
|
9
|
+
:content="action.tooltip"
|
|
10
|
+
>
|
|
11
|
+
<TMagicButton
|
|
12
|
+
v-show="display(action.display, scope.row) && !editState[scope.$index]"
|
|
13
|
+
class="action-btn"
|
|
14
|
+
link
|
|
15
|
+
size="small"
|
|
16
|
+
:type="action.buttonType || 'primary'"
|
|
17
|
+
:icon="action.icon"
|
|
18
|
+
@click="actionHandler(action, scope.row, scope.$index)"
|
|
19
|
+
><span v-html="formatter(action.text, scope.row)"></span
|
|
20
|
+
></TMagicButton>
|
|
21
|
+
</TMagicTooltip>
|
|
22
|
+
<TMagicButton
|
|
23
|
+
class="action-btn"
|
|
24
|
+
v-show="editState[scope.$index]"
|
|
25
|
+
link
|
|
26
|
+
type="primary"
|
|
27
|
+
size="small"
|
|
28
|
+
@click="save(scope.$index, config)"
|
|
29
|
+
>保存</TMagicButton
|
|
30
|
+
>
|
|
31
|
+
<TMagicButton
|
|
32
|
+
class="action-btn"
|
|
33
|
+
v-show="editState[scope.$index]"
|
|
34
|
+
link
|
|
35
|
+
type="primary"
|
|
36
|
+
size="small"
|
|
37
|
+
@click="editState[scope.$index] = undefined"
|
|
38
|
+
>取消</TMagicButton
|
|
39
|
+
>
|
|
40
|
+
</template>
|
|
41
|
+
</TMagicTableColumn>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script lang="ts" setup>
|
|
45
|
+
import { TMagicButton, tMagicMessage, TMagicTableColumn, TMagicTooltip } from '@tmagic/design';
|
|
46
|
+
|
|
47
|
+
import { ColumnActionConfig, ColumnConfig } from './schema';
|
|
48
|
+
|
|
49
|
+
defineOptions({
|
|
50
|
+
name: 'MTableActionsColumn',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const props = withDefaults(
|
|
54
|
+
defineProps<{
|
|
55
|
+
columns: any[];
|
|
56
|
+
config: ColumnConfig;
|
|
57
|
+
rowkeyName?: string;
|
|
58
|
+
editState?: any;
|
|
59
|
+
}>(),
|
|
60
|
+
{
|
|
61
|
+
columns: () => [],
|
|
62
|
+
config: () => ({}),
|
|
63
|
+
rowkeyName: 'c_id',
|
|
64
|
+
editState: () => [],
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const emit = defineEmits(['after-action']);
|
|
69
|
+
|
|
70
|
+
const display = (fuc: boolean | Function | undefined, row: any) => {
|
|
71
|
+
if (typeof fuc === 'function') {
|
|
72
|
+
return fuc(row);
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const formatter = (fuc: string | Function | undefined, row: any) => {
|
|
78
|
+
if (typeof fuc === 'function') {
|
|
79
|
+
return fuc(row);
|
|
80
|
+
}
|
|
81
|
+
return fuc;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const actionHandler = async (action: ColumnActionConfig, row: any, index: number) => {
|
|
85
|
+
await action.before?.(row, index);
|
|
86
|
+
if (action.type === 'edit') {
|
|
87
|
+
props.editState[index] = row;
|
|
88
|
+
} else {
|
|
89
|
+
await action.handler?.(row, index);
|
|
90
|
+
}
|
|
91
|
+
action.after?.(row, index);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const save = async (index: number, config: ColumnConfig) => {
|
|
95
|
+
const action = config.actions?.find((item) => item.type === 'edit')?.action;
|
|
96
|
+
if (!action) return;
|
|
97
|
+
|
|
98
|
+
const data: any = {};
|
|
99
|
+
const row = props.editState[index];
|
|
100
|
+
props.columns
|
|
101
|
+
.filter((item) => item.type)
|
|
102
|
+
.forEach((column) => {
|
|
103
|
+
data[column.prop] = row[column.prop];
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const res: any = await action({
|
|
107
|
+
data,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (res) {
|
|
111
|
+
if (res.ret === 0) {
|
|
112
|
+
tMagicMessage.success('保存成功');
|
|
113
|
+
props.editState[index] = undefined;
|
|
114
|
+
emit('after-action');
|
|
115
|
+
} else {
|
|
116
|
+
tMagicMessage.error(res.msg || '保存失败');
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
props.editState[index] = undefined;
|
|
120
|
+
emit('after-action');
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
</script>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TMagicTableColumn
|
|
3
|
+
show-overflow-tooltip
|
|
4
|
+
:label="config.label"
|
|
5
|
+
:width="config.width"
|
|
6
|
+
:fixed="config.fixed"
|
|
7
|
+
:sortable="config.sortable"
|
|
8
|
+
:prop="config.prop"
|
|
9
|
+
>
|
|
10
|
+
<template v-slot="scope">
|
|
11
|
+
<component
|
|
12
|
+
:is="config.component"
|
|
13
|
+
v-bind="componentProps(scope.row, scope.$index)"
|
|
14
|
+
v-on="componentListeners(scope.row, scope.$index)"
|
|
15
|
+
></component>
|
|
16
|
+
</template>
|
|
17
|
+
</TMagicTableColumn>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script lang="ts" setup>
|
|
21
|
+
import { TMagicTableColumn } from '@tmagic/design';
|
|
22
|
+
|
|
23
|
+
import { ColumnConfig } from './schema';
|
|
24
|
+
|
|
25
|
+
defineOptions({
|
|
26
|
+
name: 'MTableColumn',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(
|
|
30
|
+
defineProps<{
|
|
31
|
+
config: ColumnConfig;
|
|
32
|
+
}>(),
|
|
33
|
+
{
|
|
34
|
+
config: () => ({}),
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const componentProps = (row: any, index: number) => {
|
|
39
|
+
if (typeof props.config.props === 'function') {
|
|
40
|
+
return props.config.props(row, index) || {};
|
|
41
|
+
}
|
|
42
|
+
return props.config.props || {};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const componentListeners = (row: any, index: number) => {
|
|
46
|
+
if (typeof props.config.listeners === 'function') {
|
|
47
|
+
return props.config.listeners(row, index) || {};
|
|
48
|
+
}
|
|
49
|
+
return props.config.listeners || {};
|
|
50
|
+
};
|
|
51
|
+
</script>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TMagicTableColumn type="expand">
|
|
3
|
+
<template #default="scope">
|
|
4
|
+
<MTable
|
|
5
|
+
v-if="config.table"
|
|
6
|
+
:show-header="false"
|
|
7
|
+
:columns="config.table"
|
|
8
|
+
:data="(config.prop && scope.row[config.prop]) || []"
|
|
9
|
+
></MTable>
|
|
10
|
+
<MForm
|
|
11
|
+
v-if="config.form"
|
|
12
|
+
:config="config.form"
|
|
13
|
+
:init-values="config.values || (config.prop && scope.row[config.prop]) || {}"
|
|
14
|
+
></MForm>
|
|
15
|
+
<div v-if="config.expandContent" v-html="config.expandContent(scope.row, config.prop)"></div>
|
|
16
|
+
<component v-if="config.component" :is="config.component" v-bind="componentProps(scope.row)"></component>
|
|
17
|
+
</template>
|
|
18
|
+
</TMagicTableColumn>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script lang="ts" setup>
|
|
22
|
+
import { TMagicTableColumn } from '@tmagic/design';
|
|
23
|
+
import { MForm } from '@tmagic/form';
|
|
24
|
+
|
|
25
|
+
import { ColumnConfig } from './schema';
|
|
26
|
+
import MTable from './Table.vue';
|
|
27
|
+
|
|
28
|
+
defineOptions({
|
|
29
|
+
name: 'MTableExpandColumn',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const props = withDefaults(
|
|
33
|
+
defineProps<{
|
|
34
|
+
config: ColumnConfig;
|
|
35
|
+
}>(),
|
|
36
|
+
{
|
|
37
|
+
config: () => ({}),
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const componentProps = (row: any) => {
|
|
42
|
+
if (typeof props.config.props === 'function') {
|
|
43
|
+
return props.config.props(row) || {};
|
|
44
|
+
}
|
|
45
|
+
return props.config.props || {};
|
|
46
|
+
};
|
|
47
|
+
</script>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TMagicTableColumn :label="config.label" :width="config.width" :fixed="config.fixed">
|
|
3
|
+
<template v-slot="scope">
|
|
4
|
+
<TMagicPopover
|
|
5
|
+
v-if="config.popover"
|
|
6
|
+
:placement="config.popover.placement"
|
|
7
|
+
:width="config.popover.width"
|
|
8
|
+
:trigger="config.popover.trigger"
|
|
9
|
+
>
|
|
10
|
+
<MTable
|
|
11
|
+
v-if="config.popover.tableEmbed"
|
|
12
|
+
:show-header="config.showHeader"
|
|
13
|
+
:columns="config.table"
|
|
14
|
+
:data="(config.prop && scope.row[config.prop]) || []"
|
|
15
|
+
></MTable>
|
|
16
|
+
<template #reference>
|
|
17
|
+
<TMagicButton link type="primary"> {{ config.text || formatter(config, scope.row) }}</TMagicButton>
|
|
18
|
+
</template>
|
|
19
|
+
</TMagicPopover>
|
|
20
|
+
</template>
|
|
21
|
+
</TMagicTableColumn>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script lang="ts" setup>
|
|
25
|
+
import { TMagicButton, TMagicPopover, TMagicTableColumn } from '@tmagic/design';
|
|
26
|
+
|
|
27
|
+
import { ColumnConfig } from './schema';
|
|
28
|
+
import MTable from './Table.vue';
|
|
29
|
+
import { formatter } from './utils';
|
|
30
|
+
|
|
31
|
+
defineOptions({
|
|
32
|
+
name: 'MTablePopoverColumn',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
withDefaults(
|
|
36
|
+
defineProps<{
|
|
37
|
+
config: ColumnConfig;
|
|
38
|
+
}>(),
|
|
39
|
+
{
|
|
40
|
+
config: () => ({}),
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
</script>
|
package/src/Table.vue
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TMagicTable
|
|
3
|
+
tooltip-effect="dark"
|
|
4
|
+
:tooltip-options="{ popperOptions: { strategy: 'absolute' } }"
|
|
5
|
+
class="m-table"
|
|
6
|
+
ref="tMagicTable"
|
|
7
|
+
v-loading="loading"
|
|
8
|
+
:data="tableData"
|
|
9
|
+
:show-header="showHeader"
|
|
10
|
+
:max-height="bodyHeight"
|
|
11
|
+
:default-expand-all="defaultExpandAll"
|
|
12
|
+
:border="hasBorder"
|
|
13
|
+
:row-key="rowkeyName || 'id'"
|
|
14
|
+
:tree-props="{ children: 'children' }"
|
|
15
|
+
:empty-text="emptyText || '暂无数据'"
|
|
16
|
+
:span-method="objectSpanMethod"
|
|
17
|
+
@sort-change="sortChange"
|
|
18
|
+
@select="selectHandler"
|
|
19
|
+
@select-all="selectAllHandler"
|
|
20
|
+
@selection-change="selectionChangeHandler"
|
|
21
|
+
@cell-click="cellClickHandler"
|
|
22
|
+
@expand-change="expandChange"
|
|
23
|
+
>
|
|
24
|
+
<template v-for="(item, columnIndex) in columns">
|
|
25
|
+
<template v-if="item.type === 'expand'">
|
|
26
|
+
<ExpandColumn :config="item" :key="columnIndex"></ExpandColumn>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<template v-else-if="item.type === 'component'">
|
|
30
|
+
<ComponentColumn :config="item" :key="columnIndex"></ComponentColumn>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<template v-else-if="item.selection">
|
|
34
|
+
<component
|
|
35
|
+
width="40"
|
|
36
|
+
type="selection"
|
|
37
|
+
:is="tableColumnComponent?.component || 'el-table-column'"
|
|
38
|
+
:key="columnIndex"
|
|
39
|
+
:selectable="item.selectable"
|
|
40
|
+
></component>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<template v-else-if="item.actions">
|
|
44
|
+
<ActionsColumn
|
|
45
|
+
:columns="columns"
|
|
46
|
+
:config="item"
|
|
47
|
+
:rowkey-name="rowkeyName"
|
|
48
|
+
:edit-state="editState"
|
|
49
|
+
:key="columnIndex"
|
|
50
|
+
@after-action="$emit('after-action')"
|
|
51
|
+
></ActionsColumn>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<template v-else-if="item.type === 'popover'">
|
|
55
|
+
<PopoverColumn :key="columnIndex" :config="item"></PopoverColumn>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<template v-else>
|
|
59
|
+
<TextColumn :key="columnIndex" :config="item" :edit-state="editState"></TextColumn>
|
|
60
|
+
</template>
|
|
61
|
+
</template>
|
|
62
|
+
</TMagicTable>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script lang="ts" setup>
|
|
66
|
+
import { computed, ref } from 'vue';
|
|
67
|
+
import { cloneDeep } from 'lodash-es';
|
|
68
|
+
|
|
69
|
+
import { getConfig, TMagicTable } from '@tmagic/design';
|
|
70
|
+
|
|
71
|
+
import ActionsColumn from './ActionsColumn.vue';
|
|
72
|
+
import ComponentColumn from './ComponentColumn.vue';
|
|
73
|
+
import ExpandColumn from './ExpandColumn.vue';
|
|
74
|
+
import PopoverColumn from './PopoverColumn.vue';
|
|
75
|
+
import type { ColumnConfig } from './schema';
|
|
76
|
+
import TextColumn from './TextColumn.vue';
|
|
77
|
+
|
|
78
|
+
defineOptions({
|
|
79
|
+
name: 'MTable',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const props = withDefaults(
|
|
83
|
+
defineProps<{
|
|
84
|
+
data: any[];
|
|
85
|
+
columns?: ColumnConfig[];
|
|
86
|
+
/** 合并行或列的计算方法 */
|
|
87
|
+
spanMethod?: (data: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number];
|
|
88
|
+
loading?: boolean;
|
|
89
|
+
/** Table 的最大高度。合法的值为数字或者单位为 px 的高度 */
|
|
90
|
+
bodyHeight?: string | number;
|
|
91
|
+
/** 是否显示表头 */
|
|
92
|
+
showHeader?: boolean;
|
|
93
|
+
/** 空数据时显示的文本内容 */
|
|
94
|
+
emptyText?: string;
|
|
95
|
+
/** 是否默认展开所有行,当 Table 包含展开行存在或者为树形表格时有效 */
|
|
96
|
+
defaultExpandAll?: boolean;
|
|
97
|
+
rowkeyName?: string;
|
|
98
|
+
/** 是否带有纵向边框 */
|
|
99
|
+
border?: boolean;
|
|
100
|
+
}>(),
|
|
101
|
+
{
|
|
102
|
+
columns: () => [],
|
|
103
|
+
loading: false,
|
|
104
|
+
showHeader: true,
|
|
105
|
+
defaultExpandAll: false,
|
|
106
|
+
border: false,
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const emit = defineEmits([
|
|
111
|
+
'sort-change',
|
|
112
|
+
'after-action',
|
|
113
|
+
'select',
|
|
114
|
+
'select-all',
|
|
115
|
+
'selection-change',
|
|
116
|
+
'expand-change',
|
|
117
|
+
'cell-click',
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
const tMagicTable = ref<InstanceType<typeof TMagicTable>>();
|
|
121
|
+
|
|
122
|
+
const editState = ref([]);
|
|
123
|
+
|
|
124
|
+
const tableColumnComponent = getConfig('components')?.tableColumn;
|
|
125
|
+
const selectionColumn = computed(() => {
|
|
126
|
+
const column = props.columns.filter((item) => item.selection);
|
|
127
|
+
return column.length ? column[0] : null;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const tableData = computed(() => {
|
|
131
|
+
if (selectionColumn.value) {
|
|
132
|
+
return props.data || [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return cloneDeep(props.data) || [];
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const hasBorder = computed(() => (typeof props.border !== 'undefined' ? props.border : true));
|
|
139
|
+
|
|
140
|
+
const sortChange = (data: any) => {
|
|
141
|
+
emit('sort-change', data);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const selectHandler = (selection: any, row: any) => {
|
|
145
|
+
const column = selectionColumn.value;
|
|
146
|
+
if (!column) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (column.selection === 'single') {
|
|
151
|
+
// this.clearSelection()
|
|
152
|
+
// this.toggleRowSelection(row, true)
|
|
153
|
+
}
|
|
154
|
+
emit('select', selection, row);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const selectAllHandler = (selection: any) => {
|
|
158
|
+
emit('select-all', selection);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const selectionChangeHandler = (selection: any) => {
|
|
162
|
+
emit('selection-change', selection);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const cellClickHandler = (...args: any[]) => {
|
|
166
|
+
emit('cell-click', ...args);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const expandChange = (...args: any[]) => {
|
|
170
|
+
emit('expand-change', ...args);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const toggleRowSelection = (row: any, selected: boolean) => {
|
|
174
|
+
tMagicTable.value?.toggleRowSelection(row, selected);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const toggleRowExpansion = (row: any, expanded: boolean) => {
|
|
178
|
+
tMagicTable.value?.toggleRowExpansion(row, expanded);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const clearSelection = () => {
|
|
182
|
+
tMagicTable.value?.clearSelection();
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const objectSpanMethod = (data: any) => {
|
|
186
|
+
if (typeof props.spanMethod === 'function') {
|
|
187
|
+
return props.spanMethod(data);
|
|
188
|
+
}
|
|
189
|
+
return () => ({
|
|
190
|
+
rowspan: 0,
|
|
191
|
+
colspan: 0,
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
defineExpose({
|
|
196
|
+
toggleRowSelection,
|
|
197
|
+
toggleRowExpansion,
|
|
198
|
+
clearSelection,
|
|
199
|
+
});
|
|
200
|
+
</script>
|
|
201
|
+
|
|
202
|
+
<style lang="scss">
|
|
203
|
+
.m-table {
|
|
204
|
+
.el-button.action-btn + .el-button.action-btn {
|
|
205
|
+
margin-left: 0;
|
|
206
|
+
}
|
|
207
|
+
.keep-all {
|
|
208
|
+
word-break: keep-all;
|
|
209
|
+
}
|
|
210
|
+
.el-table .cell > div {
|
|
211
|
+
display: inline-block;
|
|
212
|
+
vertical-align: middle;
|
|
213
|
+
}
|
|
214
|
+
.el-table__row.el-table__row--level-1 {
|
|
215
|
+
color: #999;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
</style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TMagicTableColumn
|
|
3
|
+
show-overflow-tooltip
|
|
4
|
+
:label="config.label"
|
|
5
|
+
:width="config.width"
|
|
6
|
+
:fixed="config.fixed"
|
|
7
|
+
:sortable="config.sortable"
|
|
8
|
+
:prop="config.prop"
|
|
9
|
+
>
|
|
10
|
+
<template v-slot="scope">
|
|
11
|
+
<TMagicForm v-if="config.type && editState[scope.$index]" label-width="0" :model="editState[scope.$index]">
|
|
12
|
+
<m-form-container
|
|
13
|
+
:prop="config.prop"
|
|
14
|
+
:rules="config.rules"
|
|
15
|
+
:config="config"
|
|
16
|
+
:name="config.prop"
|
|
17
|
+
:model="editState[scope.$index]"
|
|
18
|
+
></m-form-container>
|
|
19
|
+
</TMagicForm>
|
|
20
|
+
|
|
21
|
+
<TMagicButton
|
|
22
|
+
v-else-if="config.action === 'actionLink' && config.prop"
|
|
23
|
+
link
|
|
24
|
+
type="primary"
|
|
25
|
+
@click="config.handler?.(scope.row)"
|
|
26
|
+
>
|
|
27
|
+
<span v-html="formatter(config, scope.row)"></span>
|
|
28
|
+
</TMagicButton>
|
|
29
|
+
|
|
30
|
+
<a v-else-if="config.action === 'img' && config.prop" target="_blank" :href="scope.row[config.prop]"
|
|
31
|
+
><img :src="scope.row[config.prop]" height="50"
|
|
32
|
+
/></a>
|
|
33
|
+
|
|
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
|
+
>
|
|
41
|
+
|
|
42
|
+
<el-tooltip v-else-if="config.action === 'tip'" placement="left">
|
|
43
|
+
<template #content>
|
|
44
|
+
<div>{{ formatter(config, scope.row) }}</div>
|
|
45
|
+
</template>
|
|
46
|
+
<TMagicButton link type="primary">{{ config.buttonText || '扩展配置' }}</TMagicButton>
|
|
47
|
+
</el-tooltip>
|
|
48
|
+
|
|
49
|
+
<TMagicTag
|
|
50
|
+
v-else-if="config.action === 'tag' && config.prop"
|
|
51
|
+
:type="typeof config.type === 'function' ? config.type(scope.row[config.prop], scope.row) : config.type"
|
|
52
|
+
close-transition
|
|
53
|
+
>{{ formatter(config, scope.row) }}</TMagicTag
|
|
54
|
+
>
|
|
55
|
+
<div v-else v-html="formatter(config, scope.row)"></div>
|
|
56
|
+
</template>
|
|
57
|
+
</TMagicTableColumn>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<script lang="ts" setup>
|
|
61
|
+
import { TMagicButton, TMagicForm, TMagicTableColumn, TMagicTag } from '@tmagic/design';
|
|
62
|
+
|
|
63
|
+
import { ColumnConfig } from './schema';
|
|
64
|
+
import { formatter } from './utils';
|
|
65
|
+
|
|
66
|
+
defineOptions({
|
|
67
|
+
name: 'MTableColumn',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
withDefaults(
|
|
71
|
+
defineProps<{
|
|
72
|
+
config: ColumnConfig;
|
|
73
|
+
editState?: any;
|
|
74
|
+
}>(),
|
|
75
|
+
{
|
|
76
|
+
config: () => ({}),
|
|
77
|
+
editState: () => ({}),
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
</script>
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { App } from 'vue';
|
|
20
|
+
|
|
21
|
+
import Table from './Table.vue';
|
|
22
|
+
|
|
23
|
+
export { default as MagicTable } from './Table.vue';
|
|
24
|
+
export * from './schema';
|
|
25
|
+
export * from './utils';
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
install(app: App) {
|
|
29
|
+
app.component('m-table', Table);
|
|
30
|
+
},
|
|
31
|
+
};
|
package/src/schema.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { FormConfig, FormValue } from '@tmagic/form';
|
|
20
|
+
|
|
21
|
+
export interface ColumnActionConfig {
|
|
22
|
+
type?: 'delete' | 'copy' | 'edit';
|
|
23
|
+
buttonType?: string;
|
|
24
|
+
display?: (row: any) => boolean;
|
|
25
|
+
text?: string | ((row: any) => string);
|
|
26
|
+
name?: string;
|
|
27
|
+
tooltip?: string;
|
|
28
|
+
tooltipPlacement?: string;
|
|
29
|
+
icon?: any;
|
|
30
|
+
handler?: (row: any, index: number) => Promise<any> | any;
|
|
31
|
+
before?: (row: any, index: number) => Promise<void> | void;
|
|
32
|
+
after?: (row: any, index: number) => Promise<void> | void;
|
|
33
|
+
action?: (data: { data: any }) => Promise<void> | void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ColumnConfig<T = any> {
|
|
37
|
+
form?: FormConfig;
|
|
38
|
+
rules?: any;
|
|
39
|
+
values?: FormValue;
|
|
40
|
+
selection?: boolean | 'single';
|
|
41
|
+
selectable?: (row: any, index: number) => boolean;
|
|
42
|
+
label?: string;
|
|
43
|
+
fixed?: 'left' | 'right' | boolean;
|
|
44
|
+
width?: number | string;
|
|
45
|
+
actions?: ColumnActionConfig[];
|
|
46
|
+
type?: 'popover' | 'expand' | 'component' | string | ((value: any, row: T) => string);
|
|
47
|
+
text?: string;
|
|
48
|
+
prop?: string;
|
|
49
|
+
showHeader?: boolean;
|
|
50
|
+
table?: ColumnConfig[];
|
|
51
|
+
formatter?: 'datetime' | ((item: any, row: T) => any);
|
|
52
|
+
popover?: {
|
|
53
|
+
placement: string;
|
|
54
|
+
width: string;
|
|
55
|
+
trigger: string;
|
|
56
|
+
tableEmbed: boolean;
|
|
57
|
+
};
|
|
58
|
+
sortable?: boolean | 'custom';
|
|
59
|
+
action?: 'tip' | 'actionLink' | 'img' | 'link' | 'tag';
|
|
60
|
+
handler?: (row: T) => void;
|
|
61
|
+
/** 当type为expand时有效,展开为html */
|
|
62
|
+
expandContent?: (row: T, prop?: string) => string;
|
|
63
|
+
/** 当type为expand时,展开为vue组件;当type为component时显示的组件 */
|
|
64
|
+
component?: any;
|
|
65
|
+
/** 当type为expand时,展开的vue组件props;当type为component时显示的组件的props */
|
|
66
|
+
props?: any;
|
|
67
|
+
/** 当type为component时显示的组件的事件监听 */
|
|
68
|
+
listeners?: any;
|
|
69
|
+
/** 当type为tip时有效,显示文案 */
|
|
70
|
+
buttonText?: string;
|
|
71
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { datetimeFormatter } from '@tmagic/utils';
|
|
20
|
+
|
|
21
|
+
import { ColumnConfig } from './schema';
|
|
22
|
+
|
|
23
|
+
export const formatter = (item: ColumnConfig, row: any) => {
|
|
24
|
+
if (!item.prop) return '';
|
|
25
|
+
|
|
26
|
+
if (item.formatter) {
|
|
27
|
+
if (item.formatter === 'datetime') {
|
|
28
|
+
// eslint-disable-next-line no-param-reassign
|
|
29
|
+
item.formatter = (value: string) => datetimeFormatter(value);
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return item.formatter(row[item.prop], row);
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return row[item.prop];
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
return row[item.prop];
|
|
38
|
+
}
|
|
39
|
+
};
|