Commit a984eac9658748134d56bb07b33958f1624dc7d4

Authored by xingyu
1 parent a74c6b08

feat: 完善xtable组件

yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue
@@ -12,6 +12,12 @@ import { useAppStore } from '@/store/modules/app' @@ -12,6 +12,12 @@ import { useAppStore } from '@/store/modules/app'
12 import { useDesign } from '@/hooks/web/useDesign' 12 import { useDesign } from '@/hooks/web/useDesign'
13 import { XTableProps } from './type' 13 import { XTableProps } from './type'
14 import { isBoolean, isFunction } from '@/utils/is' 14 import { isBoolean, isFunction } from '@/utils/is'
  15 +import { useMessage } from '@/hooks/web/useMessage'
  16 +import download from '@/utils/download'
  17 +import { useI18n } from '@/hooks/web/useI18n'
  18 +
  19 +const { t } = useI18n()
  20 +const message = useMessage() // 消息弹窗
15 21
16 const appStore = useAppStore() 22 const appStore = useAppStore()
17 23
@@ -21,30 +27,6 @@ const prefixCls = getPrefixCls('x-vxe-table') @@ -21,30 +27,6 @@ const prefixCls = getPrefixCls('x-vxe-table')
21 const attrs = useAttrs() 27 const attrs = useAttrs()
22 const emit = defineEmits(['register']) 28 const emit = defineEmits(['register'])
23 29
24 -const props = defineProps({  
25 - options: {  
26 - type: Object as PropType<XTableProps>,  
27 - default: () => {}  
28 - }  
29 -})  
30 -const innerProps = ref<Partial<XTableProps>>()  
31 -  
32 -const getProps = computed(() => {  
33 - const options = innerProps.value || props.options  
34 - options.size = currentSize as any  
35 - options.height = 700  
36 - getColumnsConfig(options)  
37 - getProxyConfig(options)  
38 - getPageConfig(options)  
39 - getToolBarConfig(options)  
40 - // console.log(options);  
41 - return {  
42 - ...options,  
43 - ...attrs  
44 - }  
45 -})  
46 -  
47 -const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref  
48 watch( 30 watch(
49 () => appStore.getIsDark, 31 () => appStore.getIsDark,
50 () => { 32 () => {
@@ -57,6 +39,7 @@ watch( @@ -57,6 +39,7 @@ watch(
57 }, 39 },
58 { immediate: true } 40 { immediate: true }
59 ) 41 )
  42 +
60 const currentSize = computed(() => { 43 const currentSize = computed(() => {
61 let resSize: SizeType = 'small' 44 let resSize: SizeType = 'small'
62 const appsize = appStore.getCurrentSize 45 const appsize = appStore.getCurrentSize
@@ -74,25 +57,42 @@ const currentSize = computed(() =&gt; { @@ -74,25 +57,42 @@ const currentSize = computed(() =&gt; {
74 return resSize 57 return resSize
75 }) 58 })
76 59
77 -const reload = () => {  
78 - const g = unref(xGrid)  
79 - if (!g) {  
80 - return 60 +const props = defineProps({
  61 + options: {
  62 + type: Object as PropType<XTableProps>,
  63 + default: () => {}
81 } 64 }
82 - g.commitProxy('query')  
83 -} 65 +})
  66 +const innerProps = ref<Partial<XTableProps>>()
84 67
85 -const getSearchData = () => {  
86 - const g = unref(xGrid)  
87 - if (!g) {  
88 - return 68 +const getProps = computed(() => {
  69 + const options = innerProps.value || props.options
  70 + options.size = currentSize as any
  71 + options.height = 700
  72 + getOptionInitConfig(options)
  73 + getColumnsConfig(options)
  74 + getProxyConfig(options)
  75 + getPageConfig(options)
  76 + getToolBarConfig(options)
  77 + // console.log(options);
  78 + return {
  79 + ...options,
  80 + ...attrs
89 } 81 }
90 - const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))  
91 - return queryParams  
92 -} 82 +})
  83 +
  84 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
93 85
94 let proxyForm = false 86 let proxyForm = false
95 87
  88 +const getOptionInitConfig = (options: XTableProps) => {
  89 + options.size = currentSize as any
  90 + options.rowConfig = {
  91 + isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
  92 + isHover: true // 当鼠标移到行时,是否要高亮当前行
  93 + }
  94 +}
  95 +
96 // columns 96 // columns
97 const getColumnsConfig = (options: XTableProps) => { 97 const getColumnsConfig = (options: XTableProps) => {
98 const { allSchemas } = options 98 const { allSchemas } = options
@@ -131,21 +131,55 @@ const getProxyConfig = (options: XTableProps) =&gt; { @@ -131,21 +131,55 @@ const getProxyConfig = (options: XTableProps) =&gt; {
131 if (options.params) { 131 if (options.params) {
132 queryParams = Object.assign(queryParams, options.params) 132 queryParams = Object.assign(queryParams, options.params)
133 } 133 }
134 - queryParams.pageSize = page.currentPage  
135 - queryParams.page = page.pageSize  
136 - 134 + if (!options?.treeConfig) {
  135 + queryParams.pageSize = page.pageSize
  136 + queryParams.pageNo = page.currentPage
  137 + }
137 return new Promise(async (resolve) => { 138 return new Promise(async (resolve) => {
138 resolve(await getListApi(queryParams)) 139 resolve(await getListApi(queryParams))
139 }) 140 })
  141 + },
  142 + delete: ({ body }) => {
  143 + return new Promise(async (resolve) => {
  144 + if (options.deleteApi) {
  145 + resolve(await options.deleteApi(JSON.stringify(body)))
  146 + } else {
  147 + Promise.reject('未设置deleteApi')
  148 + }
  149 + })
  150 + },
  151 + queryAll: ({ form }) => {
  152 + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
  153 + return new Promise(async (resolve) => {
  154 + if (options.getAllListApi) {
  155 + resolve(await options.getAllListApi(queryParams))
  156 + } else {
  157 + resolve(await getListApi(queryParams))
  158 + }
  159 + })
140 } 160 }
141 } 161 }
142 } 162 }
143 } 163 }
  164 + if (options.exportListApi) {
  165 + options.exportConfig = {
  166 + filename: options?.exportName,
  167 + // 默认选中类型
  168 + type: 'csv',
  169 + // 自定义数据量列表
  170 + modes: options?.getAllListApi ? ['current', 'all'] : ['current'],
  171 + columns: options?.allSchemas?.printSchema
  172 + }
  173 + }
144 } 174 }
145 175
146 // 分页 176 // 分页
147 const getPageConfig = (options: XTableProps) => { 177 const getPageConfig = (options: XTableProps) => {
148 - const { pagination, pagerConfig } = options 178 + const { pagination, pagerConfig, treeConfig } = options
  179 + if (treeConfig) {
  180 + options.treeConfig = options.treeConfig
  181 + return
  182 + }
149 if (pagerConfig) return 183 if (pagerConfig) return
150 if (pagination) { 184 if (pagination) {
151 if (isBoolean(pagination)) { 185 if (isBoolean(pagination)) {
@@ -171,6 +205,28 @@ const getPageConfig = (options: XTableProps) =&gt; { @@ -171,6 +205,28 @@ const getPageConfig = (options: XTableProps) =&gt; {
171 return 205 return
172 } 206 }
173 options.pagerConfig = pagination 207 options.pagerConfig = pagination
  208 + } else {
  209 + if (pagination != false) {
  210 + options.pagerConfig = {
  211 + border: false, // 带边框
  212 + background: true, // 带背景颜色
  213 + perfect: false, // 配套的样式
  214 + pageSize: 10, // 每页大小
  215 + pagerCount: 7, // 显示页码按钮的数量
  216 + autoHidden: false, // 当只有一页时自动隐藏
  217 + pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
  218 + layouts: [
  219 + 'PrevJump',
  220 + 'PrevPage',
  221 + 'JumpNumber',
  222 + 'NextPage',
  223 + 'NextJump',
  224 + 'Sizes',
  225 + 'FullJump',
  226 + 'Total'
  227 + ]
  228 + }
  229 + }
174 } 230 }
175 } 231 }
176 232
@@ -190,12 +246,70 @@ const getToolBarConfig = (options: XTableProps) =&gt; { @@ -190,12 +246,70 @@ const getToolBarConfig = (options: XTableProps) =&gt; {
190 } 246 }
191 } 247 }
192 248
  249 +// 刷新列表
  250 +const reload = () => {
  251 + const g = unref(xGrid)
  252 + if (!g) {
  253 + return
  254 + }
  255 + g.commitProxy('query')
  256 +}
  257 +
  258 +// 删除
  259 +const deleteData = async (ids: string | number) => {
  260 + const g = unref(xGrid)
  261 + if (!g) {
  262 + return
  263 + }
  264 + const options = innerProps.value || props.options
  265 + if (!options.deleteApi) {
  266 + console.error('未传入delListApi')
  267 + return
  268 + }
  269 + return new Promise(async () => {
  270 + message.delConfirm().then(async () => {
  271 + await (options?.deleteApi && options?.deleteApi(ids))
  272 + message.success(t('common.delSuccess'))
  273 + // 刷新列表
  274 + reload()
  275 + })
  276 + })
  277 +}
  278 +
  279 +// 导出
  280 +const exportList = async (fileName?: string) => {
  281 + const g = unref(xGrid)
  282 + if (!g) {
  283 + return
  284 + }
  285 + const options = innerProps.value || props.options
  286 + if (!options?.exportListApi) {
  287 + console.error('未传入exportListApi')
  288 + return
  289 + }
  290 + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
  291 + message.exportConfirm().then(async () => {
  292 + const res = await (options?.exportListApi && options?.exportListApi(queryParams))
  293 + download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
  294 + })
  295 +}
  296 +
  297 +// 获取查询参数
  298 +const getSearchData = () => {
  299 + const g = unref(xGrid)
  300 + if (!g) {
  301 + return
  302 + }
  303 + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
  304 + return queryParams
  305 +}
  306 +
193 const setProps = (prop: Partial<XTableProps>) => { 307 const setProps = (prop: Partial<XTableProps>) => {
194 innerProps.value = { ...unref(innerProps), ...prop } 308 innerProps.value = { ...unref(innerProps), ...prop }
195 } 309 }
196 310
197 -defineExpose({ reload, Ref: xGrid, getSearchData })  
198 -emit('register', { reload, getSearchData, setProps }) 311 +defineExpose({ reload, Ref: xGrid, getSearchData, deleteData, exportList })
  312 +emit('register', { reload, getSearchData, setProps, deleteData, exportList })
199 </script> 313 </script>
200 <style lang="scss"> 314 <style lang="scss">
201 @import './style/index.scss'; 315 @import './style/index.scss';
yudao-ui-admin-vue3/src/components/XTable/src/type.ts
1 import { CrudSchema } from '@/hooks/web/useCrudSchemas' 1 import { CrudSchema } from '@/hooks/web/useCrudSchemas'
2 -import type { VxeGridProps, VxeGridPropTypes } from 'vxe-table' 2 +import type { VxeGridProps, VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table'
3 3
4 export type XTableProps<D = any> = VxeGridProps<D> & { 4 export type XTableProps<D = any> = VxeGridProps<D> & {
5 allSchemas?: CrudSchema 5 allSchemas?: CrudSchema
  6 + height?: number // 高度 默认730
  7 + topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
  8 + treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
6 getListApi?: Function 9 getListApi?: Function
  10 + getAllListApi?: Function
7 deleteApi?: Function 11 deleteApi?: Function
8 exportListApi?: Function 12 exportListApi?: Function
  13 + exportName?: string // 导出文件夹名称
9 params?: any 14 params?: any
10 pagination?: boolean | VxeGridPropTypes.PagerConfig 15 pagination?: boolean | VxeGridPropTypes.PagerConfig
11 toolBar?: boolean | VxeGridPropTypes.ToolbarConfig 16 toolBar?: boolean | VxeGridPropTypes.ToolbarConfig
yudao-ui-admin-vue3/src/hooks/web/useXTable.ts
@@ -4,6 +4,8 @@ import { XTableProps } from &#39;@/components/XTable/src/type&#39; @@ -4,6 +4,8 @@ import { XTableProps } from &#39;@/components/XTable/src/type&#39;
4 export interface tableMethod { 4 export interface tableMethod {
5 reload: () => void 5 reload: () => void
6 setProps: (props: XTableProps) => void 6 setProps: (props: XTableProps) => void
  7 + deleteData: (ids: string | number) => void
  8 + exportList: (fileName?: string) => void
7 } 9 }
8 10
9 export function useXTable(props: XTableProps): [Function, tableMethod] { 11 export function useXTable(props: XTableProps): [Function, tableMethod] {
@@ -22,7 +24,9 @@ export function useXTable(props: XTableProps): [Function, tableMethod] { @@ -22,7 +24,9 @@ export function useXTable(props: XTableProps): [Function, tableMethod] {
22 } 24 }
23 const methods: tableMethod = { 25 const methods: tableMethod = {
24 reload: () => getInstance().reload(), 26 reload: () => getInstance().reload(),
25 - setProps: (props) => getInstance().setProps(props) 27 + setProps: (props) => getInstance().setProps(props),
  28 + deleteData: (ids: string | number) => getInstance().deleteData(ids),
  29 + exportList: (fileName?: string) => getInstance().exportList(fileName)
26 } 30 }
27 return [register, methods] 31 return [register, methods]
28 } 32 }
yudao-ui-admin-vue3/src/plugins/vxeTable/index.ts
1 -import { App, unref, watch } from 'vue' 1 +import { App, unref } from 'vue'
2 import XEUtils from 'xe-utils' 2 import XEUtils from 'xe-utils'
3 -import './index.scss'  
4 import './renderer' 3 import './renderer'
5 import { i18n } from '@/plugins/vueI18n' 4 import { i18n } from '@/plugins/vueI18n'
6 -import { useAppStore } from '@/store/modules/app'  
7 import zhCN from 'vxe-table/lib/locale/lang/zh-CN' 5 import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
8 import enUS from 'vxe-table/lib/locale/lang/en-US' 6 import enUS from 'vxe-table/lib/locale/lang/en-US'
9 import { 7 import {
@@ -46,21 +44,6 @@ import { @@ -46,21 +44,6 @@ import {
46 Table 44 Table
47 } from 'vxe-table' 45 } from 'vxe-table'
48 46
49 -const appStore = useAppStore()  
50 -watch(  
51 - () => appStore.getIsDark,  
52 - () => {  
53 - if (appStore.getIsDark) {  
54 - import('./theme/dark.scss')  
55 - } else {  
56 - import('./theme/light.scss')  
57 - }  
58 - },  
59 - {  
60 - deep: true,  
61 - immediate: true  
62 - }  
63 -)  
64 // 全局默认参数 47 // 全局默认参数
65 VXETable.setup({ 48 VXETable.setup({
66 size: 'medium', // 全局尺寸 49 size: 'medium', // 全局尺寸