vue3-smart-table 1.0.3 → 1.0.5
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/README.md +4 -1
- package/dist/vue3-smart-table.cjs.js +1 -1
- package/dist/vue3-smart-table.cjs.js.map +1 -1
- package/dist/vue3-smart-table.es.js +419 -403
- package/dist/vue3-smart-table.es.js.map +1 -1
- package/dist/vue3-smart-table.umd.js +2 -2
- package/dist/vue3-smart-table.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/SmartTable/hooks/useOperationColumn.ts +5 -1
- package/src/components/SmartTable/index.vue +218 -21
- package/src/components/SmartTable/renderers/index.ts +14 -2
- package/src/components/SmartTable/types.ts +3 -0
- package/src/components/SmartTable/column/index.vue +0 -170
|
@@ -74,14 +74,23 @@ const copy = createFunctionalRenderer((props) => {
|
|
|
74
74
|
'color': rp.iconColor || '#409EFF',
|
|
75
75
|
'user-select': 'none'
|
|
76
76
|
}
|
|
77
|
+
const testStyle = {
|
|
78
|
+
'padding-right': '10px',
|
|
79
|
+
'display': '-webkit-box',
|
|
80
|
+
'-webkit-box-orient': 'vertical',
|
|
81
|
+
'-webkit-line-clamp': rp.lineClamp ?? 2,
|
|
82
|
+
'overflow': 'hidden',
|
|
83
|
+
...rp.textStyles
|
|
84
|
+
}
|
|
77
85
|
return h('div', {
|
|
78
86
|
class: 'st_copy_wrapper',
|
|
79
87
|
style: 'width: 100%; position: relative; display: inline-block;'
|
|
80
88
|
},
|
|
81
89
|
[
|
|
82
90
|
h('span', {
|
|
83
|
-
class:
|
|
84
|
-
style:
|
|
91
|
+
class: `st_copy_text ${rp.textClass ?? ''}`,
|
|
92
|
+
style: testStyle,
|
|
93
|
+
title: val
|
|
85
94
|
}, val),
|
|
86
95
|
val && h('span', {
|
|
87
96
|
class: 'st_copy_btn',
|
|
@@ -155,6 +164,7 @@ const img = createFunctionalRenderer((props) => {
|
|
|
155
164
|
return h(ElImage, {
|
|
156
165
|
src: imageList[0],
|
|
157
166
|
previewSrcList: rp.previewSrcList || imageList,
|
|
167
|
+
previewTeleported: true,
|
|
158
168
|
fit: rp.fit || 'contain',
|
|
159
169
|
style: defaultStyle,
|
|
160
170
|
...rp
|
|
@@ -170,6 +180,7 @@ const img = createFunctionalRenderer((props) => {
|
|
|
170
180
|
h(ElImage, {
|
|
171
181
|
src: imageList[0],
|
|
172
182
|
previewSrcList: rp.previewSrcList || imageList,
|
|
183
|
+
previewTeleported: true,
|
|
173
184
|
fit: rp.fit || 'contain',
|
|
174
185
|
style: defaultStyle,
|
|
175
186
|
...rp
|
|
@@ -252,6 +263,7 @@ const icon = createFunctionalRenderer((props) => {
|
|
|
252
263
|
return h(ElImage, {
|
|
253
264
|
src: val,
|
|
254
265
|
previewSrcList: [val],
|
|
266
|
+
previewTeleported: true,
|
|
255
267
|
fit: 'contain',
|
|
256
268
|
style: 'width:40px;height:40px',
|
|
257
269
|
...rp
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<!-- ========== selection 列 ========== -->
|
|
3
|
-
<el-table-column
|
|
4
|
-
v-if="col.type === 'selection'"
|
|
5
|
-
type="selection"
|
|
6
|
-
v-bind="col.columnProps"
|
|
7
|
-
/>
|
|
8
|
-
|
|
9
|
-
<!-- ========== index 列 ========== -->
|
|
10
|
-
<el-table-column
|
|
11
|
-
v-else-if="col.type === 'index'"
|
|
12
|
-
type="index"
|
|
13
|
-
:label="col.label || '#'"
|
|
14
|
-
align="center"
|
|
15
|
-
v-bind="col.columnProps"
|
|
16
|
-
>
|
|
17
|
-
<template #default="{ $index }">
|
|
18
|
-
{{ computeIndex($index) }}
|
|
19
|
-
</template>
|
|
20
|
-
</el-table-column>
|
|
21
|
-
|
|
22
|
-
<!-- ========== operation 列 ========== -->
|
|
23
|
-
<el-table-column
|
|
24
|
-
v-else-if="col.type === 'operation' && showOperationColumn"
|
|
25
|
-
:label="col.label || '操作'"
|
|
26
|
-
align="center"
|
|
27
|
-
v-bind="{
|
|
28
|
-
...col.columnProps,
|
|
29
|
-
width: operationWidth
|
|
30
|
-
}"
|
|
31
|
-
>
|
|
32
|
-
<template #default="{ row }">
|
|
33
|
-
<el-button
|
|
34
|
-
v-for="btn in getVisibleButtons(row)"
|
|
35
|
-
:key="btn.label"
|
|
36
|
-
:type="btn.type || 'primary'"
|
|
37
|
-
link
|
|
38
|
-
@click="btn.action(row)"
|
|
39
|
-
>
|
|
40
|
-
{{ btn.label }}
|
|
41
|
-
</el-button>
|
|
42
|
-
</template>
|
|
43
|
-
</el-table-column>
|
|
44
|
-
|
|
45
|
-
<!-- ========== 普通列 / renderer / editable ========== -->
|
|
46
|
-
<el-table-column
|
|
47
|
-
v-else-if="isDataOrOperationColumn(col)"
|
|
48
|
-
:label="col.label"
|
|
49
|
-
align="center"
|
|
50
|
-
v-bind="col.columnProps || {}"
|
|
51
|
-
>
|
|
52
|
-
|
|
53
|
-
<template #default="scope">
|
|
54
|
-
<!-- 父组件插槽优先 -->
|
|
55
|
-
<template v-if="col.render === 'slot' && $slots[col?.slot || col.key]">
|
|
56
|
-
<slot :name="col?.slot || col.key" v-bind="scope" />
|
|
57
|
-
</template>
|
|
58
|
-
|
|
59
|
-
<!-- renderer -->
|
|
60
|
-
<component
|
|
61
|
-
v-else-if="col.render && renderer[col.render]"
|
|
62
|
-
:is="renderer[col.render]"
|
|
63
|
-
:row="scope.row"
|
|
64
|
-
:col="col"
|
|
65
|
-
:onCellChange="handleCellChange"
|
|
66
|
-
:onCellBlur="handleCellBlur"
|
|
67
|
-
:onCellEnter="handleCellEnter"
|
|
68
|
-
:onClick="handleCellClick"
|
|
69
|
-
/>
|
|
70
|
-
<!-- 默认文本 -->
|
|
71
|
-
<span v-else
|
|
72
|
-
:style="col.renderProps?.style || ''"
|
|
73
|
-
:class="col.renderProps?.class || ''"
|
|
74
|
-
:title="getValueByPath(scope.row, col.key)">
|
|
75
|
-
{{ getValueByPath(scope.row, col.key) }}
|
|
76
|
-
</span>
|
|
77
|
-
</template>
|
|
78
|
-
</el-table-column>
|
|
79
|
-
|
|
80
|
-
</template>
|
|
81
|
-
|
|
82
|
-
<script setup lang="ts">
|
|
83
|
-
import { computed, toRefs } from 'vue'
|
|
84
|
-
import type { PropType } from 'vue'
|
|
85
|
-
import type { ColumnConfig } from '../types'
|
|
86
|
-
import { getRendererManager } from '../renderer'
|
|
87
|
-
import { registerBuiltInRenderers } from '../renderers'
|
|
88
|
-
import { useOperationColumn } from '../hooks/useOperationColumn'
|
|
89
|
-
import { getValueByPath } from '../utils/path'
|
|
90
|
-
|
|
91
|
-
const props = defineProps({
|
|
92
|
-
col: { type: Object as PropType<ColumnConfig>, required: true },
|
|
93
|
-
permissions: { type: Array as PropType<string[]>, default: () => [] },
|
|
94
|
-
pagination: { type: Object, default: () => ({}) },
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
const emit = defineEmits(['cellBlur', 'cellEnter', 'cellChange', 'cellClick'])
|
|
98
|
-
|
|
99
|
-
const computeIndex = (index: number) => {
|
|
100
|
-
const page = props.pagination?.page
|
|
101
|
-
const size = props.pagination?.size
|
|
102
|
-
return page && size ? (page - 1) * size + index + 1 : index + 1
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** 解构 col 响应式引用 */
|
|
106
|
-
const { col } = toRefs(props)
|
|
107
|
-
|
|
108
|
-
/** ========== 事件统一上抛 ========== */
|
|
109
|
-
const handleCellChange = (row: any, key: string) => emit('cellChange', row, key)
|
|
110
|
-
const handleCellBlur = (row: any, key: string) => emit('cellBlur', row, key)
|
|
111
|
-
const handleCellEnter = (row: any, key: string) => emit('cellEnter', row, key)
|
|
112
|
-
const handleCellClick = (row: any, col: any) => emit('cellClick', row, col)
|
|
113
|
-
|
|
114
|
-
/** ========== renderer 注册 ========== */
|
|
115
|
-
// 注册内置渲染器(重复调用会自动跳过已存在的)
|
|
116
|
-
registerBuiltInRenderers(getRendererManager())
|
|
117
|
-
|
|
118
|
-
// 获取所有渲染器(内置 + 自定义)
|
|
119
|
-
const renderer = computed(() => {
|
|
120
|
-
const manager = getRendererManager()
|
|
121
|
-
const allRenderers: Record<string, any> = {}
|
|
122
|
-
|
|
123
|
-
// 合并内置渲染器和自定义渲染器
|
|
124
|
-
manager.names().forEach((name: string) => {
|
|
125
|
-
const r = manager.get(name)
|
|
126
|
-
if (r) allRenderers[name] = r
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
return allRenderers
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
/** ========== operation 列逻辑 ========== */
|
|
133
|
-
const {
|
|
134
|
-
hasAnyButton,
|
|
135
|
-
hasAnyVisibleButton,
|
|
136
|
-
optWidth,
|
|
137
|
-
getMaxOptWidth,
|
|
138
|
-
getVisibleButtons
|
|
139
|
-
} = useOperationColumn(
|
|
140
|
-
col.value.buttons || [],
|
|
141
|
-
col.value.maxbtn ?? 10,
|
|
142
|
-
props.permissions || []
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
/** 是否显示操作列 */
|
|
146
|
-
const showOperationColumn = computed(() => {
|
|
147
|
-
const buttons = col.value.buttons || []
|
|
148
|
-
if (!buttons.length) return false // 没有配置按钮直接隐藏
|
|
149
|
-
const rows = col.value.__rows || []
|
|
150
|
-
// 无行数据时,至少有一个按钮有权限就显示
|
|
151
|
-
if (!rows.length) return hasAnyButton.value
|
|
152
|
-
// 有行数据时,至少一行有可见按钮才显示
|
|
153
|
-
return hasAnyVisibleButton(col.value.__rows || [])
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
/** 操作列宽度 */
|
|
157
|
-
const operationWidth = computed(() => {
|
|
158
|
-
// 无行数据,用静态宽度
|
|
159
|
-
if (!col.value.__rows) return optWidth.value
|
|
160
|
-
// 有行数据,取最大宽度
|
|
161
|
-
return getMaxOptWidth(col.value.__rows)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
function isDataOrOperationColumn(c: ColumnConfig) {
|
|
165
|
-
if (c.type === 'selection' || c.type === 'index') return false
|
|
166
|
-
if (c.type === 'operation' && !showOperationColumn.value) return false
|
|
167
|
-
if (c.visible === false) return false
|
|
168
|
-
return true
|
|
169
|
-
}
|
|
170
|
-
</script>
|