mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	feat: 封装xTable 组件
This commit is contained in:
		
							
								
								
									
										3
									
								
								yudao-ui-admin-vue3/src/components/XTable/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								yudao-ui-admin-vue3/src/components/XTable/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| import XTable from './src/XTable.vue' | ||||
|  | ||||
| export { XTable } | ||||
							
								
								
									
										202
									
								
								yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| <template> | ||||
|   <VxeGrid v-bind="getProps" ref="xGrid" :class="`${prefixCls}`" class="xtable-scrollbar"> | ||||
|     <template #[item]="data" v-for="item in Object.keys($slots)" :key="item"> | ||||
|       <slot :name="item" v-bind="data || {}"></slot> | ||||
|     </template> | ||||
|   </VxeGrid> | ||||
| </template> | ||||
| <script lang="ts" setup name="XTable"> | ||||
| import { computed, PropType, ref, unref, useAttrs, watch } from 'vue' | ||||
| import { SizeType, VxeGridInstance } from 'vxe-table' | ||||
| import { useAppStore } from '@/store/modules/app' | ||||
| import { useDesign } from '@/hooks/web/useDesign' | ||||
| import { XTableProps } from './type' | ||||
| import { isBoolean, isFunction } from '@/utils/is' | ||||
|  | ||||
| const appStore = useAppStore() | ||||
|  | ||||
| const { getPrefixCls } = useDesign() | ||||
| const prefixCls = getPrefixCls('x-vxe-table') | ||||
|  | ||||
| const attrs = useAttrs() | ||||
| const emit = defineEmits(['register']) | ||||
|  | ||||
| const props = defineProps({ | ||||
|   options: { | ||||
|     type: Object as PropType<XTableProps>, | ||||
|     default: () => {} | ||||
|   } | ||||
| }) | ||||
| const innerProps = ref<Partial<XTableProps>>() | ||||
|  | ||||
| const getProps = computed(() => { | ||||
|   const options = innerProps.value || props.options | ||||
|   options.size = currentSize as any | ||||
|   options.height = 700 | ||||
|   getColumnsConfig(options) | ||||
|   getProxyConfig(options) | ||||
|   getPageConfig(options) | ||||
|   getToolBarConfig(options) | ||||
|   // console.log(options); | ||||
|   return { | ||||
|     ...options, | ||||
|     ...attrs | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref | ||||
| watch( | ||||
|   () => appStore.getIsDark, | ||||
|   () => { | ||||
|     if (appStore.getIsDark == true) { | ||||
|       import('./style/dark.scss') | ||||
|     } | ||||
|     if (appStore.getIsDark == false) { | ||||
|       import('./style/light.scss') | ||||
|     } | ||||
|   }, | ||||
|   { immediate: true } | ||||
| ) | ||||
| const currentSize = computed(() => { | ||||
|   let resSize: SizeType = 'small' | ||||
|   const appsize = appStore.getCurrentSize | ||||
|   switch (appsize) { | ||||
|     case 'large': | ||||
|       resSize = 'medium' | ||||
|       break | ||||
|     case 'default': | ||||
|       resSize = 'small' | ||||
|       break | ||||
|     case 'small': | ||||
|       resSize = 'mini' | ||||
|       break | ||||
|   } | ||||
|   return resSize | ||||
| }) | ||||
|  | ||||
| const reload = () => { | ||||
|   const g = unref(xGrid) | ||||
|   if (!g) { | ||||
|     return | ||||
|   } | ||||
|   g.commitProxy('query') | ||||
| } | ||||
|  | ||||
| const getSearchData = () => { | ||||
|   const g = unref(xGrid) | ||||
|   if (!g) { | ||||
|     return | ||||
|   } | ||||
|   const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form))) | ||||
|   return queryParams | ||||
| } | ||||
|  | ||||
| let proxyForm = false | ||||
|  | ||||
| // columns | ||||
| const getColumnsConfig = (options: XTableProps) => { | ||||
|   const { allSchemas } = options | ||||
|   if (!allSchemas) return | ||||
|   if (allSchemas.printSchema) { | ||||
|     options.printConfig = { | ||||
|       columns: allSchemas.printSchema | ||||
|     } | ||||
|   } | ||||
|   if (allSchemas.formSchema) { | ||||
|     proxyForm = true | ||||
|     options.formConfig = { | ||||
|       enabled: true, | ||||
|       titleWidth: 100, | ||||
|       titleAlign: 'right', | ||||
|       items: allSchemas.searchSchema | ||||
|     } | ||||
|   } | ||||
|   if (allSchemas.tableSchema) { | ||||
|     options.columns = allSchemas.tableSchema | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 动态请求 | ||||
| const getProxyConfig = (options: XTableProps) => { | ||||
|   const { getListApi, proxyConfig, data } = options | ||||
|   if (proxyConfig || data) return | ||||
|   if (getListApi && isFunction(getListApi)) { | ||||
|     options.proxyConfig = { | ||||
|       seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号) | ||||
|       form: proxyForm, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为 | ||||
|       props: { result: 'list', total: 'total' }, | ||||
|       ajax: { | ||||
|         query: async ({ page, form }) => { | ||||
|           let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form))) | ||||
|           if (options.params) { | ||||
|             queryParams = Object.assign(queryParams, options.params) | ||||
|           } | ||||
|           queryParams.pageSize = page.currentPage | ||||
|           queryParams.page = page.pageSize | ||||
|  | ||||
|           return new Promise(async (resolve) => { | ||||
|             resolve(await getListApi(queryParams)) | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 分页 | ||||
| const getPageConfig = (options: XTableProps) => { | ||||
|   const { pagination, pagerConfig } = options | ||||
|   if (pagerConfig) return | ||||
|   if (pagination) { | ||||
|     if (isBoolean(pagination)) { | ||||
|       options.pagerConfig = { | ||||
|         border: false, // 带边框 | ||||
|         background: true, // 带背景颜色 | ||||
|         perfect: false, // 配套的样式 | ||||
|         pageSize: 10, // 每页大小 | ||||
|         pagerCount: 7, // 显示页码按钮的数量 | ||||
|         autoHidden: false, // 当只有一页时自动隐藏 | ||||
|         pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表 | ||||
|         layouts: [ | ||||
|           'PrevJump', | ||||
|           'PrevPage', | ||||
|           'JumpNumber', | ||||
|           'NextPage', | ||||
|           'NextJump', | ||||
|           'Sizes', | ||||
|           'FullJump', | ||||
|           'Total' | ||||
|         ] | ||||
|       } | ||||
|       return | ||||
|     } | ||||
|     options.pagerConfig = pagination | ||||
|   } | ||||
| } | ||||
|  | ||||
| // tool bar | ||||
| const getToolBarConfig = (options: XTableProps) => { | ||||
|   const { toolBar, toolbarConfig } = options | ||||
|   if (toolbarConfig) return | ||||
|   if (toolBar) { | ||||
|     if (!isBoolean(toolBar)) { | ||||
|       options.toolbarConfig = toolBar | ||||
|       return | ||||
|     } | ||||
|   } else { | ||||
|     options.toolbarConfig = { | ||||
|       slots: { buttons: 'toolbar_buttons' } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| const setProps = (prop: Partial<XTableProps>) => { | ||||
|   innerProps.value = { ...unref(innerProps), ...prop } | ||||
| } | ||||
|  | ||||
| defineExpose({ reload, Ref: xGrid, getSearchData }) | ||||
| emit('register', { reload, getSearchData, setProps }) | ||||
| </script> | ||||
| <style lang="scss"> | ||||
| @import './style/index.scss'; | ||||
| </style> | ||||
| @@ -0,0 +1,81 @@ | ||||
| // 修改样式变量 | ||||
| //@import 'vxe-table/styles/variable.scss'; | ||||
|  | ||||
| /*font*/ | ||||
| $vxe-font-color: #e5e7eb; | ||||
| // $vxe-font-size: 14px !default; | ||||
| // $vxe-font-size-medium: 16px !default; | ||||
| // $vxe-font-size-small: 14px !default; | ||||
| // $vxe-font-size-mini: 12px !default; | ||||
|  | ||||
| /*color*/ | ||||
| $vxe-primary-color: #409eff !default; | ||||
| $vxe-success-color: #67c23a !default; | ||||
| $vxe-info-color: #909399 !default; | ||||
| $vxe-warning-color: #e6a23c !default; | ||||
| $vxe-danger-color: #f56c6c !default; | ||||
| $vxe-disabled-color: #bfbfbf !default; | ||||
| $vxe-primary-disabled-color: #c0c4cc !default; | ||||
|  | ||||
| /*loading*/ | ||||
| $vxe-loading-color: $vxe-primary-color !default; | ||||
| $vxe-loading-background-color: #1d1e1f !default; | ||||
| $vxe-loading-z-index: 999 !default; | ||||
|  | ||||
| /*icon*/ | ||||
| $vxe-icon-font-family: Verdana, Arial, Tahoma !default; | ||||
| $vxe-icon-background-color: #e5e7eb !default; | ||||
|  | ||||
| /*toolbar*/ | ||||
| $vxe-toolbar-background-color: #1d1e1f !default; | ||||
| $vxe-toolbar-button-border: #dcdfe6 !default; | ||||
| $vxe-toolbar-custom-active-background-color: #d9dadb !default; | ||||
| $vxe-toolbar-panel-background-color: #e5e7eb !default; | ||||
|  | ||||
| $vxe-table-font-color: #e5e7eb; | ||||
| $vxe-table-header-background-color: #1d1e1f; | ||||
| $vxe-table-body-background-color: #141414; | ||||
| $vxe-table-row-striped-background-color: #1d1d1d; | ||||
| $vxe-table-row-hover-background-color: #1d1e1f; | ||||
| $vxe-table-row-hover-striped-background-color: #1e1e1e; | ||||
| $vxe-table-footer-background-color: #1d1e1f; | ||||
| $vxe-table-row-current-background-color: #302d2d; | ||||
| $vxe-table-column-current-background-color: #302d2d; | ||||
| $vxe-table-column-hover-background-color: #302d2d; | ||||
| $vxe-table-row-hover-current-background-color: #302d2d; | ||||
| $vxe-table-row-checkbox-checked-background-color: #3e3c37 !default; | ||||
| $vxe-table-row-hover-checkbox-checked-background-color: #615a4a !default; | ||||
| $vxe-table-menu-background-color: #1d1e1f; | ||||
| $vxe-table-border-width: 1px !default; | ||||
| $vxe-table-border-color: #4c4d4f !default; | ||||
| $vxe-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default; | ||||
| $vxe-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default; | ||||
|  | ||||
| $vxe-form-background-color: #141414; | ||||
|  | ||||
| /*pager*/ | ||||
| $vxe-pager-background-color: #1d1e1f !default; | ||||
| $vxe-pager-perfect-background-color: #262727 !default; | ||||
| $vxe-pager-perfect-button-background-color: #a7a3a3 !default; | ||||
|  | ||||
| $vxe-input-background-color: #141414; | ||||
| $vxe-input-border-color: #4c4d4f !default; | ||||
|  | ||||
| $vxe-select-option-hover-background-color: #262626 !default; | ||||
| $vxe-select-panel-background-color: #141414 !default; | ||||
| $vxe-select-empty-color: #262626 !default; | ||||
| $vxe-optgroup-title-color: #909399 !default; | ||||
|  | ||||
| /*button*/ | ||||
| $vxe-button-default-background-color: #262626; | ||||
| $vxe-button-dropdown-panel-background-color: #141414; | ||||
|  | ||||
| /*modal*/ | ||||
| $vxe-modal-header-background-color: #141414; | ||||
| $vxe-modal-body-background-color: #141414; | ||||
| $vxe-modal-border-color: #3b3b3b; | ||||
|  | ||||
| /*pulldown*/ | ||||
| $vxe-pulldown-panel-background-color: #262626 !default; | ||||
|  | ||||
| @import 'vxe-table/styles/index'; | ||||
| @@ -0,0 +1,6 @@ | ||||
| @import 'vxe-table/styles/variable.scss'; | ||||
| @import 'vxe-table/styles/modules.scss'; | ||||
| // @import './theme/light.scss'; | ||||
| i { | ||||
|   border-color: initial; | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| // 修改样式变量 | ||||
| // /*font*/ | ||||
| // $vxe-font-size: 12px !default; | ||||
| // $vxe-font-size-medium: 16px !default; | ||||
| // $vxe-font-size-small: 14px !default; | ||||
| // $vxe-font-size-mini: 12px !default; | ||||
| /*color*/ | ||||
| $vxe-primary-color: #409eff !default; | ||||
| $vxe-success-color: #67c23a !default; | ||||
| $vxe-info-color: #909399 !default; | ||||
| $vxe-warning-color: #e6a23c !default; | ||||
| $vxe-danger-color: #f56c6c !default; | ||||
| $vxe-disabled-color: #bfbfbf !default; | ||||
| $vxe-primary-disabled-color: #c0c4cc !default; | ||||
|  | ||||
| @import 'vxe-table/styles/index.scss'; | ||||
							
								
								
									
										20
									
								
								yudao-ui-admin-vue3/src/components/XTable/src/type.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								yudao-ui-admin-vue3/src/components/XTable/src/type.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| import { CrudSchema } from '@/hooks/web/useCrudSchemas' | ||||
| import type { VxeGridProps, VxeGridPropTypes } from 'vxe-table' | ||||
|  | ||||
| export type XTableProps<D = any> = VxeGridProps<D> & { | ||||
|   allSchemas?: CrudSchema | ||||
|   getListApi?: Function | ||||
|   deleteApi?: Function | ||||
|   exportListApi?: Function | ||||
|   params?: any | ||||
|   pagination?: boolean | VxeGridPropTypes.PagerConfig | ||||
|   toolBar?: boolean | VxeGridPropTypes.ToolbarConfig | ||||
|   afterFetch?: Function | ||||
| } | ||||
| export type XColumns = VxeGridPropTypes.Columns | ||||
|  | ||||
| export type VxeTableColumn = { | ||||
|   field: string | ||||
|   title?: string | ||||
|   children?: VxeTableColumn[] | ||||
| } & Recordable | ||||
| @@ -4,6 +4,7 @@ import { Form } from '@/components/Form' | ||||
| import { Table } from '@/components/Table' | ||||
| import { Search } from '@/components/Search' | ||||
| import { XModal } from '@/components/XModal' | ||||
| import { XTable } from '@/components/XTable' | ||||
| import { XButton, XTextButton } from '@/components/XButton' | ||||
| import { DictTag } from '@/components/DictTag' | ||||
| import { ContentWrap } from '@/components/ContentWrap' | ||||
| @@ -15,6 +16,7 @@ export const setupGlobCom = (app: App<Element>): void => { | ||||
|   app.component('Table', Table) | ||||
|   app.component('Search', Search) | ||||
|   app.component('XModal', XModal) | ||||
|   app.component('XTable', XTable) | ||||
|   app.component('XButton', XButton) | ||||
|   app.component('XTextButton', XTextButton) | ||||
|   app.component('DictTag', DictTag) | ||||
|   | ||||
							
								
								
									
										28
									
								
								yudao-ui-admin-vue3/src/hooks/web/useXTable.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								yudao-ui-admin-vue3/src/hooks/web/useXTable.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| import { ref, unref } from 'vue' | ||||
| import { XTableProps } from '@/components/XTable/src/type' | ||||
|  | ||||
| export interface tableMethod { | ||||
|   reload: () => void | ||||
|   setProps: (props: XTableProps) => void | ||||
| } | ||||
|  | ||||
| export function useXTable(props: XTableProps): [Function, tableMethod] { | ||||
|   const tableRef = ref<Nullable<tableMethod>>(null) | ||||
|  | ||||
|   function register(instance) { | ||||
|     tableRef.value = instance | ||||
|     props && instance.setProps(props) | ||||
|   } | ||||
|   function getInstance(): tableMethod { | ||||
|     const table = unref(tableRef) | ||||
|     if (!table) { | ||||
|       console.error('表格实例不存在') | ||||
|     } | ||||
|     return table as tableMethod | ||||
|   } | ||||
|   const methods: tableMethod = { | ||||
|     reload: () => getInstance().reload(), | ||||
|     setProps: (props) => getInstance().setProps(props) | ||||
|   } | ||||
|   return [register, methods] | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 xingyu
					xingyu