Commit f831b43dec4d9413f5f0d6e43e51e6ee3b5ebd6b

Authored by xingyu
1 parent 6f8384af

feat: 封装xTable 组件

yudao-ui-admin-vue3/src/components/XTable/index.ts 0 → 100644
  1 +import XTable from './src/XTable.vue'
  2 +
  3 +export { XTable }
yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue 0 → 100644
  1 +<template>
  2 + <VxeGrid v-bind="getProps" ref="xGrid" :class="`${prefixCls}`" class="xtable-scrollbar">
  3 + <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
  4 + <slot :name="item" v-bind="data || {}"></slot>
  5 + </template>
  6 + </VxeGrid>
  7 +</template>
  8 +<script lang="ts" setup name="XTable">
  9 +import { computed, PropType, ref, unref, useAttrs, watch } from 'vue'
  10 +import { SizeType, VxeGridInstance } from 'vxe-table'
  11 +import { useAppStore } from '@/store/modules/app'
  12 +import { useDesign } from '@/hooks/web/useDesign'
  13 +import { XTableProps } from './type'
  14 +import { isBoolean, isFunction } from '@/utils/is'
  15 +
  16 +const appStore = useAppStore()
  17 +
  18 +const { getPrefixCls } = useDesign()
  19 +const prefixCls = getPrefixCls('x-vxe-table')
  20 +
  21 +const attrs = useAttrs()
  22 +const emit = defineEmits(['register'])
  23 +
  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(
  49 + () => appStore.getIsDark,
  50 + () => {
  51 + if (appStore.getIsDark == true) {
  52 + import('./style/dark.scss')
  53 + }
  54 + if (appStore.getIsDark == false) {
  55 + import('./style/light.scss')
  56 + }
  57 + },
  58 + { immediate: true }
  59 +)
  60 +const currentSize = computed(() => {
  61 + let resSize: SizeType = 'small'
  62 + const appsize = appStore.getCurrentSize
  63 + switch (appsize) {
  64 + case 'large':
  65 + resSize = 'medium'
  66 + break
  67 + case 'default':
  68 + resSize = 'small'
  69 + break
  70 + case 'small':
  71 + resSize = 'mini'
  72 + break
  73 + }
  74 + return resSize
  75 +})
  76 +
  77 +const reload = () => {
  78 + const g = unref(xGrid)
  79 + if (!g) {
  80 + return
  81 + }
  82 + g.commitProxy('query')
  83 +}
  84 +
  85 +const getSearchData = () => {
  86 + const g = unref(xGrid)
  87 + if (!g) {
  88 + return
  89 + }
  90 + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
  91 + return queryParams
  92 +}
  93 +
  94 +let proxyForm = false
  95 +
  96 +// columns
  97 +const getColumnsConfig = (options: XTableProps) => {
  98 + const { allSchemas } = options
  99 + if (!allSchemas) return
  100 + if (allSchemas.printSchema) {
  101 + options.printConfig = {
  102 + columns: allSchemas.printSchema
  103 + }
  104 + }
  105 + if (allSchemas.formSchema) {
  106 + proxyForm = true
  107 + options.formConfig = {
  108 + enabled: true,
  109 + titleWidth: 100,
  110 + titleAlign: 'right',
  111 + items: allSchemas.searchSchema
  112 + }
  113 + }
  114 + if (allSchemas.tableSchema) {
  115 + options.columns = allSchemas.tableSchema
  116 + }
  117 +}
  118 +
  119 +// 动态请求
  120 +const getProxyConfig = (options: XTableProps) => {
  121 + const { getListApi, proxyConfig, data } = options
  122 + if (proxyConfig || data) return
  123 + if (getListApi && isFunction(getListApi)) {
  124 + options.proxyConfig = {
  125 + seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
  126 + form: proxyForm, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
  127 + props: { result: 'list', total: 'total' },
  128 + ajax: {
  129 + query: async ({ page, form }) => {
  130 + let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
  131 + if (options.params) {
  132 + queryParams = Object.assign(queryParams, options.params)
  133 + }
  134 + queryParams.pageSize = page.currentPage
  135 + queryParams.page = page.pageSize
  136 +
  137 + return new Promise(async (resolve) => {
  138 + resolve(await getListApi(queryParams))
  139 + })
  140 + }
  141 + }
  142 + }
  143 + }
  144 +}
  145 +
  146 +// 分页
  147 +const getPageConfig = (options: XTableProps) => {
  148 + const { pagination, pagerConfig } = options
  149 + if (pagerConfig) return
  150 + if (pagination) {
  151 + if (isBoolean(pagination)) {
  152 + options.pagerConfig = {
  153 + border: false, // 带边框
  154 + background: true, // 带背景颜色
  155 + perfect: false, // 配套的样式
  156 + pageSize: 10, // 每页大小
  157 + pagerCount: 7, // 显示页码按钮的数量
  158 + autoHidden: false, // 当只有一页时自动隐藏
  159 + pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
  160 + layouts: [
  161 + 'PrevJump',
  162 + 'PrevPage',
  163 + 'JumpNumber',
  164 + 'NextPage',
  165 + 'NextJump',
  166 + 'Sizes',
  167 + 'FullJump',
  168 + 'Total'
  169 + ]
  170 + }
  171 + return
  172 + }
  173 + options.pagerConfig = pagination
  174 + }
  175 +}
  176 +
  177 +// tool bar
  178 +const getToolBarConfig = (options: XTableProps) => {
  179 + const { toolBar, toolbarConfig } = options
  180 + if (toolbarConfig) return
  181 + if (toolBar) {
  182 + if (!isBoolean(toolBar)) {
  183 + options.toolbarConfig = toolBar
  184 + return
  185 + }
  186 + } else {
  187 + options.toolbarConfig = {
  188 + slots: { buttons: 'toolbar_buttons' }
  189 + }
  190 + }
  191 +}
  192 +
  193 +const setProps = (prop: Partial<XTableProps>) => {
  194 + innerProps.value = { ...unref(innerProps), ...prop }
  195 +}
  196 +
  197 +defineExpose({ reload, Ref: xGrid, getSearchData })
  198 +emit('register', { reload, getSearchData, setProps })
  199 +</script>
  200 +<style lang="scss">
  201 +@import './style/index.scss';
  202 +</style>
yudao-ui-admin-vue3/src/components/XTable/src/style/dark.scss 0 → 100644
  1 +// 修改样式变量
  2 +//@import 'vxe-table/styles/variable.scss';
  3 +
  4 +/*font*/
  5 +$vxe-font-color: #e5e7eb;
  6 +// $vxe-font-size: 14px !default;
  7 +// $vxe-font-size-medium: 16px !default;
  8 +// $vxe-font-size-small: 14px !default;
  9 +// $vxe-font-size-mini: 12px !default;
  10 +
  11 +/*color*/
  12 +$vxe-primary-color: #409eff !default;
  13 +$vxe-success-color: #67c23a !default;
  14 +$vxe-info-color: #909399 !default;
  15 +$vxe-warning-color: #e6a23c !default;
  16 +$vxe-danger-color: #f56c6c !default;
  17 +$vxe-disabled-color: #bfbfbf !default;
  18 +$vxe-primary-disabled-color: #c0c4cc !default;
  19 +
  20 +/*loading*/
  21 +$vxe-loading-color: $vxe-primary-color !default;
  22 +$vxe-loading-background-color: #1d1e1f !default;
  23 +$vxe-loading-z-index: 999 !default;
  24 +
  25 +/*icon*/
  26 +$vxe-icon-font-family: Verdana, Arial, Tahoma !default;
  27 +$vxe-icon-background-color: #e5e7eb !default;
  28 +
  29 +/*toolbar*/
  30 +$vxe-toolbar-background-color: #1d1e1f !default;
  31 +$vxe-toolbar-button-border: #dcdfe6 !default;
  32 +$vxe-toolbar-custom-active-background-color: #d9dadb !default;
  33 +$vxe-toolbar-panel-background-color: #e5e7eb !default;
  34 +
  35 +$vxe-table-font-color: #e5e7eb;
  36 +$vxe-table-header-background-color: #1d1e1f;
  37 +$vxe-table-body-background-color: #141414;
  38 +$vxe-table-row-striped-background-color: #1d1d1d;
  39 +$vxe-table-row-hover-background-color: #1d1e1f;
  40 +$vxe-table-row-hover-striped-background-color: #1e1e1e;
  41 +$vxe-table-footer-background-color: #1d1e1f;
  42 +$vxe-table-row-current-background-color: #302d2d;
  43 +$vxe-table-column-current-background-color: #302d2d;
  44 +$vxe-table-column-hover-background-color: #302d2d;
  45 +$vxe-table-row-hover-current-background-color: #302d2d;
  46 +$vxe-table-row-checkbox-checked-background-color: #3e3c37 !default;
  47 +$vxe-table-row-hover-checkbox-checked-background-color: #615a4a !default;
  48 +$vxe-table-menu-background-color: #1d1e1f;
  49 +$vxe-table-border-width: 1px !default;
  50 +$vxe-table-border-color: #4c4d4f !default;
  51 +$vxe-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default;
  52 +$vxe-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default;
  53 +
  54 +$vxe-form-background-color: #141414;
  55 +
  56 +/*pager*/
  57 +$vxe-pager-background-color: #1d1e1f !default;
  58 +$vxe-pager-perfect-background-color: #262727 !default;
  59 +$vxe-pager-perfect-button-background-color: #a7a3a3 !default;
  60 +
  61 +$vxe-input-background-color: #141414;
  62 +$vxe-input-border-color: #4c4d4f !default;
  63 +
  64 +$vxe-select-option-hover-background-color: #262626 !default;
  65 +$vxe-select-panel-background-color: #141414 !default;
  66 +$vxe-select-empty-color: #262626 !default;
  67 +$vxe-optgroup-title-color: #909399 !default;
  68 +
  69 +/*button*/
  70 +$vxe-button-default-background-color: #262626;
  71 +$vxe-button-dropdown-panel-background-color: #141414;
  72 +
  73 +/*modal*/
  74 +$vxe-modal-header-background-color: #141414;
  75 +$vxe-modal-body-background-color: #141414;
  76 +$vxe-modal-border-color: #3b3b3b;
  77 +
  78 +/*pulldown*/
  79 +$vxe-pulldown-panel-background-color: #262626 !default;
  80 +
  81 +@import 'vxe-table/styles/index';
yudao-ui-admin-vue3/src/components/XTable/src/style/index.scss 0 → 100644
  1 +@import 'vxe-table/styles/variable.scss';
  2 +@import 'vxe-table/styles/modules.scss';
  3 +// @import './theme/light.scss';
  4 +i {
  5 + border-color: initial;
  6 +}
yudao-ui-admin-vue3/src/components/XTable/src/style/light.scss 0 → 100644
  1 +// 修改样式变量
  2 +// /*font*/
  3 +// $vxe-font-size: 12px !default;
  4 +// $vxe-font-size-medium: 16px !default;
  5 +// $vxe-font-size-small: 14px !default;
  6 +// $vxe-font-size-mini: 12px !default;
  7 +/*color*/
  8 +$vxe-primary-color: #409eff !default;
  9 +$vxe-success-color: #67c23a !default;
  10 +$vxe-info-color: #909399 !default;
  11 +$vxe-warning-color: #e6a23c !default;
  12 +$vxe-danger-color: #f56c6c !default;
  13 +$vxe-disabled-color: #bfbfbf !default;
  14 +$vxe-primary-disabled-color: #c0c4cc !default;
  15 +
  16 +@import 'vxe-table/styles/index.scss';
yudao-ui-admin-vue3/src/components/XTable/src/type.ts 0 → 100644
  1 +import { CrudSchema } from '@/hooks/web/useCrudSchemas'
  2 +import type { VxeGridProps, VxeGridPropTypes } from 'vxe-table'
  3 +
  4 +export type XTableProps<D = any> = VxeGridProps<D> & {
  5 + allSchemas?: CrudSchema
  6 + getListApi?: Function
  7 + deleteApi?: Function
  8 + exportListApi?: Function
  9 + params?: any
  10 + pagination?: boolean | VxeGridPropTypes.PagerConfig
  11 + toolBar?: boolean | VxeGridPropTypes.ToolbarConfig
  12 + afterFetch?: Function
  13 +}
  14 +export type XColumns = VxeGridPropTypes.Columns
  15 +
  16 +export type VxeTableColumn = {
  17 + field: string
  18 + title?: string
  19 + children?: VxeTableColumn[]
  20 +} & Recordable
yudao-ui-admin-vue3/src/components/index.ts
@@ -4,6 +4,7 @@ import { Form } from &#39;@/components/Form&#39; @@ -4,6 +4,7 @@ import { Form } from &#39;@/components/Form&#39;
4 import { Table } from '@/components/Table' 4 import { Table } from '@/components/Table'
5 import { Search } from '@/components/Search' 5 import { Search } from '@/components/Search'
6 import { XModal } from '@/components/XModal' 6 import { XModal } from '@/components/XModal'
  7 +import { XTable } from '@/components/XTable'
7 import { XButton, XTextButton } from '@/components/XButton' 8 import { XButton, XTextButton } from '@/components/XButton'
8 import { DictTag } from '@/components/DictTag' 9 import { DictTag } from '@/components/DictTag'
9 import { ContentWrap } from '@/components/ContentWrap' 10 import { ContentWrap } from '@/components/ContentWrap'
@@ -15,6 +16,7 @@ export const setupGlobCom = (app: App&lt;Element&gt;): void =&gt; { @@ -15,6 +16,7 @@ export const setupGlobCom = (app: App&lt;Element&gt;): void =&gt; {
15 app.component('Table', Table) 16 app.component('Table', Table)
16 app.component('Search', Search) 17 app.component('Search', Search)
17 app.component('XModal', XModal) 18 app.component('XModal', XModal)
  19 + app.component('XTable', XTable)
18 app.component('XButton', XButton) 20 app.component('XButton', XButton)
19 app.component('XTextButton', XTextButton) 21 app.component('XTextButton', XTextButton)
20 app.component('DictTag', DictTag) 22 app.component('DictTag', DictTag)
yudao-ui-admin-vue3/src/hooks/web/useXTable.ts 0 → 100644
  1 +import { ref, unref } from 'vue'
  2 +import { XTableProps } from '@/components/XTable/src/type'
  3 +
  4 +export interface tableMethod {
  5 + reload: () => void
  6 + setProps: (props: XTableProps) => void
  7 +}
  8 +
  9 +export function useXTable(props: XTableProps): [Function, tableMethod] {
  10 + const tableRef = ref<Nullable<tableMethod>>(null)
  11 +
  12 + function register(instance) {
  13 + tableRef.value = instance
  14 + props && instance.setProps(props)
  15 + }
  16 + function getInstance(): tableMethod {
  17 + const table = unref(tableRef)
  18 + if (!table) {
  19 + console.error('表格实例不存在')
  20 + }
  21 + return table as tableMethod
  22 + }
  23 + const methods: tableMethod = {
  24 + reload: () => getInstance().reload(),
  25 + setProps: (props) => getInstance().setProps(props)
  26 + }
  27 + return [register, methods]
  28 +}