@@ -2,11 +2,13 @@ import type { Recordable } from '@vben/types';
2
2
3
3
import { h } from 'vue' ;
4
4
5
+ import { IconifyIcon } from '@vben/icons' ;
6
+ import { $te } from '@vben/locales' ;
5
7
import { setupVbenVxeTable , useVbenVxeGrid } from '@vben/plugins/vxe-table' ;
6
- import { get } from '@vben/utils' ;
8
+ import { get , isFunction , isString } from '@vben/utils' ;
7
9
8
10
import { objectOmit } from '@vueuse/core' ;
9
- import { Button , Image , Switch , Tag } from 'ant-design-vue' ;
11
+ import { Button , Image , Popconfirm , Switch , Tag } from 'ant-design-vue' ;
10
12
11
13
import { $t } from '#/locales' ;
12
14
@@ -31,7 +33,7 @@ setupVbenVxeTable({
31
33
response : {
32
34
result : 'items' ,
33
35
total : 'total' ,
34
- list : 'items ' ,
36
+ list : '' ,
35
37
} ,
36
38
showActiveMsg : true ,
37
39
showResponseMsg : false ,
@@ -119,6 +121,143 @@ setupVbenVxeTable({
119
121
} ,
120
122
} ) ;
121
123
124
+ /**
125
+ * 注册表格的操作按钮渲染器
126
+ */
127
+ vxeUI . renderer . add ( 'CellOperation' , {
128
+ renderTableDefault ( { attrs, options, props } , { column, row } ) {
129
+ const defaultProps = { size : 'small' , type : 'link' , ...props } ;
130
+ let align = 'end' ;
131
+ switch ( column . align ) {
132
+ case 'center' : {
133
+ align = 'center' ;
134
+ break ;
135
+ }
136
+ case 'left' : {
137
+ align = 'start' ;
138
+ break ;
139
+ }
140
+ default : {
141
+ align = 'end' ;
142
+ break ;
143
+ }
144
+ }
145
+ const presets : Recordable < Recordable < any > > = {
146
+ delete : {
147
+ danger : true ,
148
+ text : $t ( 'common.delete' ) ,
149
+ } ,
150
+ edit : {
151
+ text : $t ( 'common.edit' ) ,
152
+ } ,
153
+ } ;
154
+ const operations : Array < Recordable < any > > = (
155
+ options || [ 'edit' , 'delete' ]
156
+ )
157
+ . map ( ( opt ) => {
158
+ if ( isString ( opt ) ) {
159
+ return presets [ opt ]
160
+ ? { code : opt , ...presets [ opt ] , ...defaultProps }
161
+ : {
162
+ code : opt ,
163
+ text : $te ( `common.${ opt } ` ) ? $t ( `common.${ opt } ` ) : opt ,
164
+ ...defaultProps ,
165
+ } ;
166
+ } else {
167
+ return { ...defaultProps , ...presets [ opt . code ] , ...opt } ;
168
+ }
169
+ } )
170
+ . map ( ( opt ) => {
171
+ const optBtn : Recordable < any > = { } ;
172
+ Object . keys ( opt ) . forEach ( ( key ) => {
173
+ optBtn [ key ] = isFunction ( opt [ key ] ) ? opt [ key ] ( row ) : opt [ key ] ;
174
+ } ) ;
175
+ return optBtn ;
176
+ } )
177
+ . filter ( ( opt ) => opt . show !== false ) ;
178
+
179
+ function renderBtn ( opt : Recordable < any > , listen = true ) {
180
+ return h (
181
+ Button ,
182
+ {
183
+ ...props ,
184
+ ...opt ,
185
+ icon : undefined ,
186
+ onClick : listen
187
+ ? ( ) =>
188
+ attrs ?. onClick ?.( {
189
+ code : opt . code ,
190
+ row,
191
+ } )
192
+ : undefined ,
193
+ } ,
194
+ {
195
+ default : ( ) => {
196
+ const content = [ ] ;
197
+ if ( opt . icon ) {
198
+ content . push (
199
+ h ( IconifyIcon , { class : 'size-5' , icon : opt . icon } ) ,
200
+ ) ;
201
+ }
202
+ content . push ( opt . text ) ;
203
+ return content ;
204
+ } ,
205
+ } ,
206
+ ) ;
207
+ }
208
+
209
+ function renderConfirm ( opt : Recordable < any > ) {
210
+ return h (
211
+ Popconfirm ,
212
+ {
213
+ getPopupContainer ( el ) {
214
+ return (
215
+ el
216
+ . closest ( '.vxe-table--viewport-wrapper' )
217
+ ?. querySelector ( '.vxe-table--main-wrapper' )
218
+ ?. querySelector ( 'tbody' ) || document . body
219
+ ) ;
220
+ } ,
221
+ placement : 'topLeft' ,
222
+ title : $t ( 'ui.actionTitle.delete' , [ attrs ?. nameTitle || '' ] ) ,
223
+ ...props ,
224
+ ...opt ,
225
+ icon : undefined ,
226
+ onConfirm : ( ) => {
227
+ attrs ?. onClick ?.( {
228
+ code : opt . code ,
229
+ row,
230
+ } ) ;
231
+ } ,
232
+ } ,
233
+ {
234
+ default : ( ) => renderBtn ( { ...opt } , false ) ,
235
+ description : ( ) =>
236
+ h (
237
+ 'div' ,
238
+ { class : 'truncate' } ,
239
+ $t ( 'ui.actionMessage.deleteConfirm' , [
240
+ row [ attrs ?. nameField || 'name' ] ,
241
+ ] ) ,
242
+ ) ,
243
+ } ,
244
+ ) ;
245
+ }
246
+
247
+ const btns = operations . map ( ( opt ) =>
248
+ opt . code === 'delete' ? renderConfirm ( opt ) : renderBtn ( opt ) ,
249
+ ) ;
250
+ return h (
251
+ 'div' ,
252
+ {
253
+ class : 'flex table-operations' ,
254
+ style : { justifyContent : align } ,
255
+ } ,
256
+ btns ,
257
+ ) ;
258
+ } ,
259
+ } ) ;
260
+
122
261
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
123
262
// vxeUI.formats.add
124
263
} ,
0 commit comments