vue3-smart-table 1.0.4 → 1.0.6

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.
@@ -164,6 +164,7 @@ const img = createFunctionalRenderer((props) => {
164
164
  return h(ElImage, {
165
165
  src: imageList[0],
166
166
  previewSrcList: rp.previewSrcList || imageList,
167
+ previewTeleported: true,
167
168
  fit: rp.fit || 'contain',
168
169
  style: defaultStyle,
169
170
  ...rp
@@ -179,6 +180,7 @@ const img = createFunctionalRenderer((props) => {
179
180
  h(ElImage, {
180
181
  src: imageList[0],
181
182
  previewSrcList: rp.previewSrcList || imageList,
183
+ previewTeleported: true,
182
184
  fit: rp.fit || 'contain',
183
185
  style: defaultStyle,
184
186
  ...rp
@@ -241,10 +243,11 @@ export function isDataColumn(
241
243
  }
242
244
 
243
245
  const formatter = createFunctionalRenderer((props) => {
244
- const { col, row } = props
246
+ const { col, row, index } = props
245
247
  const val = getValueByPath(props.row, props.col.key) ?? ''
246
248
  if (isDataColumn(col)) {
247
- return col.formatter?.(val, row)
249
+ // formatter 函数签名: (value, row, index) => string
250
+ return col.formatter?.(val, row, index)
248
251
  }
249
252
  return val ?? ''
250
253
  })
@@ -261,6 +264,7 @@ const icon = createFunctionalRenderer((props) => {
261
264
  return h(ElImage, {
262
265
  src: val,
263
266
  previewSrcList: [val],
267
+ previewTeleported: true,
264
268
  fit: 'contain',
265
269
  style: 'width:40px;height:40px',
266
270
  ...rp
@@ -15,6 +15,7 @@ import { getValueByPath, setValueByPath } from '../utils/path'
15
15
  interface Props {
16
16
  readonly row: any
17
17
  readonly col: ColumnConfig
18
+ readonly index: number
18
19
  onCellBlur?: (row: any, col: ColumnConfig) => void
19
20
  onCellEnter?: (row: any, col: ColumnConfig) => void
20
21
  }
@@ -15,6 +15,7 @@ import { getValueByPath, setValueByPath } from '../utils/path'
15
15
  interface Props {
16
16
  readonly row: any
17
17
  readonly col: ColumnConfig
18
+ readonly index: number
18
19
  onCellChange?: (row: any, col: ColumnConfig) => void
19
20
  onCellBlur?: (row: any, col: ColumnConfig) => void
20
21
  onCellEnter?: (row: any, col: ColumnConfig) => void
@@ -23,6 +23,7 @@ import { getValueByPath, setValueByPath } from '../utils/path'
23
23
  interface Props {
24
24
  readonly row: any
25
25
  readonly col: ColumnConfig
26
+ readonly index: number
26
27
  onCellChange?: (row: any, col: ColumnConfig) => void
27
28
  onCellBlur?: (row: any, col: ColumnConfig) => void
28
29
  onCellEnter?: (row: any, col: ColumnConfig) => void
@@ -223,7 +223,17 @@ export interface BaseColumn<R extends DefaultRow> {
223
223
  export interface SelectionColumn<R extends DefaultRow> extends BaseColumn<R> { type: 'selection' }
224
224
  export interface IndexColumn<R extends DefaultRow> extends BaseColumn<R> { type: 'index' }
225
225
  export interface OperationColumn<R extends DefaultRow> extends BaseColumn<R> { type: 'operation'; buttons: ButtonConfig<R>[] }
226
- export interface DataColumn<R extends DefaultRow> extends BaseColumn<R> { type?: 'default'; formatter?: (value: any, row: R) => any }
226
+ export interface DataColumn<R extends DefaultRow> extends BaseColumn<R> {
227
+ type?: 'default'
228
+ /**
229
+ * 格式化函数
230
+ * @param value 单元格值
231
+ * @param row 当前行数据
232
+ * @param index 当前行索引(从0开始)
233
+ * @returns 格式化后的显示内容
234
+ */
235
+ formatter?: (value: any, row: R, index: number) => any
236
+ }
227
237
 
228
238
  export type ColumnConfig<R extends DefaultRow = any> =
229
239
  | SelectionColumn<R>
@@ -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>