@@ -2,11 +2,13 @@ import type { Recordable } from '@vben/types';
22
33import { h } from 'vue' ;
44
5+ import { IconifyIcon } from '@vben/icons' ;
6+ import { $te } from '@vben/locales' ;
57import { setupVbenVxeTable , useVbenVxeGrid } from '@vben/plugins/vxe-table' ;
6- import { get } from '@vben/utils' ;
8+ import { get , isFunction , isString } from '@vben/utils' ;
79
810import { 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' ;
1012
1113import { $t } from '#/locales' ;
1214
@@ -31,7 +33,7 @@ setupVbenVxeTable({
3133 response : {
3234 result : 'items' ,
3335 total : 'total' ,
34- list : 'items ' ,
36+ list : '' ,
3537 } ,
3638 showActiveMsg : true ,
3739 showResponseMsg : false ,
@@ -119,6 +121,143 @@ setupVbenVxeTable({
119121 } ,
120122 } ) ;
121123
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+
122261 // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
123262 // vxeUI.formats.add
124263 } ,
0 commit comments