Kaynağa Gözat

!349 vue3 XTable 组件
Merge pull request !349 from xingyu/dev

芋道源码 2 yıl önce
ebeveyn
işleme
135ee3f39d
45 değiştirilmiş dosya ile 980 ekleme ve 509 silme
  1. 1 1
      README.md
  2. 7 9
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
  3. 11 11
      yudao-ui-admin-vue3/README.md
  4. 13 13
      yudao-ui-admin-vue3/package.json
  5. 239 180
      yudao-ui-admin-vue3/pnpm-lock.yaml
  6. 3 0
      yudao-ui-admin-vue3/src/components/XTable/index.ts
  7. 335 0
      yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue
  8. 81 0
      yudao-ui-admin-vue3/src/components/XTable/src/style/dark.scss
  9. 6 0
      yudao-ui-admin-vue3/src/components/XTable/src/style/index.scss
  10. 16 0
      yudao-ui-admin-vue3/src/components/XTable/src/style/light.scss
  11. 26 0
      yudao-ui-admin-vue3/src/components/XTable/src/type.ts
  12. 2 0
      yudao-ui-admin-vue3/src/components/index.ts
  13. 32 0
      yudao-ui-admin-vue3/src/hooks/web/useXTable.ts
  14. 1 18
      yudao-ui-admin-vue3/src/plugins/vxeTable/index.ts
  15. 5 6
      yudao-ui-admin-vue3/src/views/infra/apiAccessLog/index.vue
  16. 8 9
      yudao-ui-admin-vue3/src/views/infra/apiErrorLog/index.vue
  17. 6 8
      yudao-ui-admin-vue3/src/views/infra/codegen/index.vue
  18. 7 9
      yudao-ui-admin-vue3/src/views/infra/config/index.vue
  19. 6 8
      yudao-ui-admin-vue3/src/views/infra/dataSourceConfig/index.vue
  20. 7 9
      yudao-ui-admin-vue3/src/views/infra/fileConfig/index.vue
  21. 6 8
      yudao-ui-admin-vue3/src/views/infra/fileList/index.vue
  22. 5 7
      yudao-ui-admin-vue3/src/views/infra/job/JobLog.vue
  23. 9 11
      yudao-ui-admin-vue3/src/views/infra/job/index.vue
  24. 7 9
      yudao-ui-admin-vue3/src/views/pay/app/index.vue
  25. 7 9
      yudao-ui-admin-vue3/src/views/pay/merchant/index.vue
  26. 5 7
      yudao-ui-admin-vue3/src/views/pay/order/index.vue
  27. 5 7
      yudao-ui-admin-vue3/src/views/pay/refund/index.vue
  28. 6 6
      yudao-ui-admin-vue3/src/views/system/dept/index.vue
  29. 14 29
      yudao-ui-admin-vue3/src/views/system/dict/index.vue
  30. 6 8
      yudao-ui-admin-vue3/src/views/system/errorCode/index.vue
  31. 5 7
      yudao-ui-admin-vue3/src/views/system/loginlog/index.vue
  32. 6 6
      yudao-ui-admin-vue3/src/views/system/menu/index.vue
  33. 6 8
      yudao-ui-admin-vue3/src/views/system/notice/index.vue
  34. 6 8
      yudao-ui-admin-vue3/src/views/system/oauth2/client/index.vue
  35. 5 7
      yudao-ui-admin-vue3/src/views/system/oauth2/token/index.vue
  36. 5 7
      yudao-ui-admin-vue3/src/views/system/operatelog/index.vue
  37. 7 9
      yudao-ui-admin-vue3/src/views/system/post/index.vue
  38. 6 8
      yudao-ui-admin-vue3/src/views/system/role/index.vue
  39. 12 15
      yudao-ui-admin-vue3/src/views/system/sensitiveWord/index.vue
  40. 6 8
      yudao-ui-admin-vue3/src/views/system/sms/smsChannel/index.vue
  41. 5 7
      yudao-ui-admin-vue3/src/views/system/sms/smsLog/index.vue
  42. 6 8
      yudao-ui-admin-vue3/src/views/system/sms/smsTemplate/index.vue
  43. 7 9
      yudao-ui-admin-vue3/src/views/system/tenant/index.vue
  44. 6 8
      yudao-ui-admin-vue3/src/views/system/tenantPackage/index.vue
  45. 10 12
      yudao-ui-admin-vue3/src/views/system/user/index.vue

+ 1 - 1
README.md

@@ -223,7 +223,7 @@ ps:核心功能已经实现,正在对接微信小程序中...
 |----------------------------------------------------------------------|:------------:|:------:|
 | [Vue](https://staging-cn.vuejs.org/)                                 |    Vue 框架    | 3.2.45 |
 | [Vite](https://cn.vitejs.dev//)                                      |   开发与构建工具    | 4.0.3  |
-| [Element Plus](https://element-plus.org/zh-CN/)                      | Element Plus | 2.2.27 |
+| [Element Plus](https://element-plus.org/zh-CN/)                      | Element Plus | 2.2.28 |
 | [TypeScript](https://www.typescriptlang.org/docs/)                   |  TypeScript  | 4.9.4  |
 | [pinia](https://pinia.vuejs.org/)                                    |    vuex5     | 2.0.28 |
 | [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) |     国际化      | 9.2.2  |

+ 7 - 9
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -43,7 +43,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="${classNameVar}Model" :loading="modelLoading" v-model="modelVisible" :title="modelTitle">
@@ -79,8 +79,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import { rules, allSchemas } from './${classNameVar}.data'
@@ -90,8 +89,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<${simpleClassName}Api.${simpleClassName}VO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: ${simpleClassName}Api.get${simpleClassName}PageApi,
   deleteApi: ${simpleClassName}Api.delete${simpleClassName}Api,
@@ -123,7 +121,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '${table.classComment}.xls')
+  await exportList('${table.classComment}.xls')
 }
 
 // 修改操作
@@ -145,7 +143,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -169,7 +167,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 11 - 11
yudao-ui-admin-vue3/README.md

@@ -26,19 +26,19 @@
 
 ### 前端依赖
 
-| 框架 | 说明 | 版本 |
-| --- | --- | --- |
+| 框架 | 说明 | 版本     |
+| --- | --- |--------|
 | [Vue](https://staging-cn.vuejs.org/) | vue 框架 | 3.2.45 |
-| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.3 |
-| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.27 |
-| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.9.4 |
+| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.3  |
+| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.28 |
+| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.9.4  |
 | [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.28 |
-| [vueuse](https://vueuse.org/) | 常用工具集 | 9.8.2 |
-| [vxe-table](https://vxetable.cn/) | vue 最强表单 | 4.3.7 |
-| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
-| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.6 |
-| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 |
-| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.0.0 |
+| [vueuse](https://vueuse.org/) | 常用工具集 | 9.8.2  |
+| [vxe-table](https://vxetable.cn/) | vue 最强表单 | 4.3.7  |
+| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2  |
+| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.6  |
+| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6  |
+| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.0.1  |
 | [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.23 |
 
 ### 推荐 VScode 开发,插件如下

+ 13 - 13
yudao-ui-admin-vue3/package.json

@@ -1,6 +1,6 @@
 {
   "name": "yudao-ui-admin-vue3",
-  "version": "1.6.5.1879",
+  "version": "1.6.5.1901",
   "description": "基于vue3、vite4、element-plus、typesScript",
   "author": "xingyu",
   "private": false,
@@ -30,13 +30,13 @@
     "@wangeditor/editor-for-vue": "^5.1.10",
     "@zxcvbn-ts/core": "^2.1.0",
     "animate.css": "^4.1.1",
-    "axios": "^1.2.1",
+    "axios": "^1.2.2",
     "cropperjs": "^1.5.13",
     "crypto-js": "^4.1.1",
     "dayjs": "^1.11.7",
     "echarts": "^5.4.1",
     "echarts-wordcloud": "^2.1.0",
-    "element-plus": "2.2.27",
+    "element-plus": "2.2.28",
     "intro.js": "^6.0.0",
     "jsencrypt": "^3.3.1",
     "lodash-es": "^4.17.21",
@@ -57,25 +57,25 @@
   "devDependencies": {
     "@commitlint/cli": "^17.3.0",
     "@commitlint/config-conventional": "^17.3.0",
-    "@iconify/json": "^2.1.157",
+    "@iconify/json": "^2.2.1",
     "@intlify/unplugin-vue-i18n": "^0.8.1",
     "@purge-icons/generated": "^0.9.0",
     "@types/intro.js": "^5.1.0",
     "@types/lodash-es": "^4.17.6",
-    "@types/node": "^18.11.17",
+    "@types/node": "^18.11.18",
     "@types/nprogress": "^0.2.0",
     "@types/qrcode": "^1.5.0",
     "@types/qs": "^6.9.7",
-    "@typescript-eslint/eslint-plugin": "^5.47.0",
-    "@typescript-eslint/parser": "^5.47.0",
+    "@typescript-eslint/eslint-plugin": "^5.48.0",
+    "@typescript-eslint/parser": "^5.48.0",
     "@vitejs/plugin-legacy": "^3.0.1",
     "@vitejs/plugin-vue": "^4.0.0",
     "@vitejs/plugin-vue-jsx": "^3.0.0",
     "autoprefixer": "^10.4.13",
     "consola": "^2.15.3",
-    "eslint": "^8.30.0",
-    "eslint-config-prettier": "^8.5.0",
-    "eslint-define-config": "^1.12.0",
+    "eslint": "^8.31.0",
+    "eslint-config-prettier": "^8.6.0",
+    "eslint-define-config": "^1.13.0",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-vue": "^9.8.0",
     "lint-staged": "^13.1.0",
@@ -84,9 +84,9 @@
     "postcss-scss": "^4.0.6",
     "prettier": "^2.8.1",
     "rimraf": "^3.0.2",
-    "rollup": "^3.8.1",
+    "rollup": "^3.9.1",
     "sass": "^1.57.1",
-    "stylelint": "^14.16.0",
+    "stylelint": "^14.16.1",
     "stylelint-config-html": "^1.1.0",
     "stylelint-config-prettier": "^9.0.4",
     "stylelint-config-recommended": "^9.0.0",
@@ -104,7 +104,7 @@
     "vite-plugin-svg-icons": "^2.0.1",
     "vite-plugin-vue-setup-extend": "^0.4.0",
     "vite-plugin-windicss": "^1.8.10",
-    "vue-tsc": "^1.0.17",
+    "vue-tsc": "^1.0.19",
     "windicss": "^3.5.6"
   },
   "engines": {

Dosya farkı çok büyük olduğundan ihmal edildi
+ 239 - 180
yudao-ui-admin-vue3/pnpm-lock.yaml


+ 3 - 0
yudao-ui-admin-vue3/src/components/XTable/index.ts

@@ -0,0 +1,3 @@
+import XTable from './src/XTable.vue'
+
+export { XTable }

+ 335 - 0
yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue

@@ -0,0 +1,335 @@
+<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'
+import { useMessage } from '@/hooks/web/useMessage'
+import download from '@/utils/download'
+import { useI18n } from '@/hooks/web/useI18n'
+
+const { t } = useI18n()
+const message = useMessage() // 消息弹窗
+
+const appStore = useAppStore()
+
+const { getPrefixCls } = useDesign()
+const prefixCls = getPrefixCls('x-vxe-table')
+
+const attrs = useAttrs()
+const emit = defineEmits(['register'])
+
+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 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
+  getOptionInitConfig(options)
+  getColumnsConfig(options)
+  getProxyConfig(options)
+  getPageConfig(options)
+  getToolBarConfig(options)
+  // console.log(options);
+  return {
+    ...options,
+    ...attrs
+  }
+})
+
+const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
+
+let proxyForm = false
+
+const getOptionInitConfig = (options: XTableProps) => {
+  options.size = currentSize as any
+  options.rowConfig = {
+    isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
+    isHover: true // 当鼠标移到行时,是否要高亮当前行
+  }
+}
+
+// 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, isList } = options
+  if (proxyConfig || data) return
+  if (getListApi && isFunction(getListApi) && !isList) {
+    if (!isList) {
+      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)
+            }
+            if (!options?.treeConfig) {
+              queryParams.pageSize = page.pageSize
+              queryParams.pageNo = page.currentPage
+            }
+            return new Promise(async (resolve) => {
+              resolve(await getListApi(queryParams))
+            })
+          },
+          delete: ({ body }) => {
+            return new Promise(async (resolve) => {
+              if (options.deleteApi) {
+                resolve(await options.deleteApi(JSON.stringify(body)))
+              } else {
+                Promise.reject('未设置deleteApi')
+              }
+            })
+          },
+          queryAll: ({ form }) => {
+            const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
+            return new Promise(async (resolve) => {
+              if (options.getAllListApi) {
+                resolve(await options.getAllListApi(queryParams))
+              } else {
+                resolve(await getListApi(queryParams))
+              }
+            })
+          }
+        }
+      }
+    } else {
+      options.proxyConfig = {
+        seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
+        form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
+        props: { result: 'data' },
+        ajax: {
+          query: ({ form }) => {
+            let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
+            if (options?.params) {
+              queryParams = Object.assign(queryParams, options.params)
+            }
+            return new Promise(async (resolve) => {
+              resolve(await getListApi(queryParams))
+            })
+          }
+        }
+      }
+    }
+  }
+  if (options.exportListApi) {
+    options.exportConfig = {
+      filename: options?.exportName,
+      // 默认选中类型
+      type: 'csv',
+      // 自定义数据量列表
+      modes: options?.getAllListApi ? ['current', 'all'] : ['current'],
+      columns: options?.allSchemas?.printSchema
+    }
+  }
+}
+
+// 分页
+const getPageConfig = (options: XTableProps) => {
+  const { pagination, pagerConfig, treeConfig } = options
+  if (treeConfig) {
+    options.treeConfig = options.treeConfig
+    return
+  }
+  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
+  } else {
+    if (pagination != false) {
+      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'
+        ]
+      }
+    }
+  }
+}
+
+// tool bar
+const getToolBarConfig = (options: XTableProps) => {
+  const { toolBar, toolbarConfig, topActionSlots } = options
+  if (toolbarConfig) return
+  if (toolBar) {
+    if (!isBoolean(toolBar)) {
+      options.toolbarConfig = toolBar
+      return
+    }
+  } else if (!topActionSlots) {
+    options.toolbarConfig = {
+      slots: { buttons: 'toolbar_buttons' }
+    }
+  }
+}
+
+// 刷新列表
+const reload = () => {
+  const g = unref(xGrid)
+  if (!g) {
+    return
+  }
+  g.commitProxy('query')
+}
+
+// 删除
+const deleteData = async (ids: string | number) => {
+  const g = unref(xGrid)
+  if (!g) {
+    return
+  }
+  const options = innerProps.value || props.options
+  if (!options.deleteApi) {
+    console.error('未传入delListApi')
+    return
+  }
+  return new Promise(async () => {
+    message.delConfirm().then(async () => {
+      await (options?.deleteApi && options?.deleteApi(ids))
+      message.success(t('common.delSuccess'))
+      // 刷新列表
+      reload()
+    })
+  })
+}
+
+// 导出
+const exportList = async (fileName?: string) => {
+  const g = unref(xGrid)
+  if (!g) {
+    return
+  }
+  const options = innerProps.value || props.options
+  if (!options?.exportListApi) {
+    console.error('未传入exportListApi')
+    return
+  }
+  const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
+  message.exportConfirm().then(async () => {
+    const res = await (options?.exportListApi && options?.exportListApi(queryParams))
+    download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
+  })
+}
+
+// 获取查询参数
+const getSearchData = () => {
+  const g = unref(xGrid)
+  if (!g) {
+    return
+  }
+  const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
+  return queryParams
+}
+
+const setProps = (prop: Partial<XTableProps>) => {
+  innerProps.value = { ...unref(innerProps), ...prop }
+}
+
+defineExpose({ reload, Ref: xGrid, getSearchData, deleteData, exportList })
+emit('register', { reload, getSearchData, setProps, deleteData, exportList })
+</script>
+<style lang="scss">
+@import './style/index.scss';
+</style>

+ 81 - 0
yudao-ui-admin-vue3/src/components/XTable/src/style/dark.scss

@@ -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';

+ 6 - 0
yudao-ui-admin-vue3/src/components/XTable/src/style/index.scss

@@ -0,0 +1,6 @@
+@import 'vxe-table/styles/variable.scss';
+@import 'vxe-table/styles/modules.scss';
+// @import './theme/light.scss';
+i {
+  border-color: initial;
+}

+ 16 - 0
yudao-ui-admin-vue3/src/components/XTable/src/style/light.scss

@@ -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';

+ 26 - 0
yudao-ui-admin-vue3/src/components/XTable/src/type.ts

@@ -0,0 +1,26 @@
+import { CrudSchema } from '@/hooks/web/useCrudSchemas'
+import type { VxeGridProps, VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table'
+
+export type XTableProps<D = any> = VxeGridProps<D> & {
+  allSchemas?: CrudSchema
+  height?: number // 高度 默认730
+  topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
+  treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
+  isList?: boolean // 是否不带分页的list
+  getListApi?: Function
+  getAllListApi?: Function
+  deleteApi?: Function
+  exportListApi?: Function
+  exportName?: string // 导出文件夹名称
+  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

+ 2 - 0
yudao-ui-admin-vue3/src/components/index.ts

@@ -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)

+ 32 - 0
yudao-ui-admin-vue3/src/hooks/web/useXTable.ts

@@ -0,0 +1,32 @@
+import { ref, unref } from 'vue'
+import { XTableProps } from '@/components/XTable/src/type'
+
+export interface tableMethod {
+  reload: () => void
+  setProps: (props: XTableProps) => void
+  deleteData: (ids: string | number) => void
+  exportList: (fileName?: string) => void
+}
+
+export const useXTable = (props: XTableProps): [Function, tableMethod] => {
+  const tableRef = ref<Nullable<tableMethod>>(null)
+
+  const register = (instance) => {
+    tableRef.value = instance
+    props && instance.setProps(props)
+  }
+  const 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),
+    deleteData: (ids: string | number) => getInstance().deleteData(ids),
+    exportList: (fileName?: string) => getInstance().exportList(fileName)
+  }
+  return [register, methods]
+}

+ 1 - 18
yudao-ui-admin-vue3/src/plugins/vxeTable/index.ts

@@ -1,9 +1,7 @@
-import { App, unref, watch } from 'vue'
+import { App, unref } from 'vue'
 import XEUtils from 'xe-utils'
-import './index.scss'
 import './renderer'
 import { i18n } from '@/plugins/vueI18n'
-import { useAppStore } from '@/store/modules/app'
 import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
 import enUS from 'vxe-table/lib/locale/lang/en-US'
 import {
@@ -46,21 +44,6 @@ import {
   Table
 } from 'vxe-table'
 
-const appStore = useAppStore()
-watch(
-  () => appStore.getIsDark,
-  () => {
-    if (appStore.getIsDark) {
-      import('./theme/dark.scss')
-    } else {
-      import('./theme/light.scss')
-    }
-  },
-  {
-    deep: true,
-    immediate: true
-  }
-)
 // 全局默认参数
 VXETable.setup({
   size: 'medium', // 全局尺寸

+ 5 - 6
yudao-ui-admin-vue3/src/views/infra/apiAccessLog/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #duration_default="{ row }">
         <span>{{ row.duration + 'ms' }}</span>
       </template>
@@ -17,7 +17,7 @@
           @click="handleDetail(row)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(详情) -->
@@ -38,15 +38,14 @@
 <script setup lang="ts" name="ApiAccessLog">
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { allSchemas } from './apiAccessLog.data'
 import * as ApiAccessLogApi from '@/api/infra/apiAccessLog'
+
 const { t } = useI18n() // 国际化
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions } = useVxeGrid<ApiAccessLogApi.ApiAccessLogVO>({
+const [registerTable] = useXTable({
   allSchemas: allSchemas,
   topActionSlots: false,
   getListApi: ApiAccessLogApi.getApiAccessLogPageApi

+ 8 - 9
yudao-ui-admin-vue3/src/views/infra/apiErrorLog/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:导出 -->
       <template #toolbar_buttons>
         <XButton
@@ -40,7 +40,7 @@
           @click="handleProcessClick(row, InfraApiErrorLogProcessStatusEnum.IGNORE, '已忽略')"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(详情) -->
@@ -54,18 +54,17 @@
 <script setup lang="ts" name="ApiErrorLog">
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { allSchemas } from './apiErrorLog.data'
 import * as ApiErrorLogApi from '@/api/infra/apiErrorLog'
 import { InfraApiErrorLogProcessStatusEnum } from '@/utils/constants'
 import { useMessage } from '@/hooks/web/useMessage'
-const message = useMessage()
+
 const { t } = useI18n() // 国际化
+const message = useMessage()
 
 // ========== 列表相关 ==========
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, exportList } = useVxeGrid<ApiErrorLogApi.ApiErrorLogVO>({
+const [registerTable, { reload, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: ApiErrorLogApi.getApiErrorLogPageApi,
   exportListApi: ApiErrorLogApi.exportApiErrorLogApi
@@ -84,7 +83,7 @@ const handleDetail = (row: ApiErrorLogApi.ApiErrorLogVO) => {
 }
 // 导出
 const handleExport = async () => {
-  await exportList(xGrid, '错误数据.xls')
+  await exportList('错误数据.xls')
 }
 // 异常处理操作
 const handleProcessClick = (
@@ -100,7 +99,7 @@ const handleProcessClick = (
     })
     .finally(async () => {
       // 刷新列表
-      await getList(xGrid)
+      await reload()
     })
     .catch(() => {})
 }

+ 6 - 8
yudao-ui-admin-vue3/src/views/infra/codegen/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:导入 -->
         <XButton
@@ -49,7 +49,7 @@
           @click="handleGenTable(row)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗:导入表 -->
   <ImportTable ref="importRef" @ok="handleQuery()" />
@@ -59,10 +59,9 @@
 <script setup lang="ts" name="Codegen">
 import { ref } from 'vue'
 import { useRouter } from 'vue-router'
-import { VxeGridInstance } from 'vxe-table'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
+import { useXTable } from '@/hooks/web/useXTable'
 import download from '@/utils/download'
 import * as CodegenApi from '@/api/infra/codegen'
 import { CodegenTableVO } from '@/api/infra/codegen/types'
@@ -73,8 +72,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 const { push } = useRouter() // 路由跳转
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<CodegenTableVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: CodegenApi.getCodegenTablePageApi,
   deleteApi: CodegenApi.deleteCodegenTableApi
@@ -112,10 +110,10 @@ const handleGenTable = async (row: CodegenTableVO) => {
 }
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 // 查询操作
 const handleQuery = async () => {
-  await getList(xGrid)
+  await reload()
 }
 </script>

+ 7 - 9
yudao-ui-admin-vue3/src/views/infra/config/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -46,7 +46,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal v-model="dialogVisible" :title="dialogTitle">
@@ -87,8 +87,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import * as ConfigApi from '@/api/infra/config'
@@ -97,8 +96,7 @@ import { rules, allSchemas } from './config.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<ConfigApi.ConfigVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: ConfigApi.getConfigPageApi,
   deleteApi: ConfigApi.deleteConfigApi,
@@ -127,7 +125,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '配置.xls')
+  await exportList('配置.xls')
 }
 
 // 修改操作
@@ -147,7 +145,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -171,7 +169,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/infra/dataSourceConfig/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <XButton
           type="primary"
@@ -34,7 +34,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -69,9 +69,8 @@
 // 全局相关的 import
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
+import { useXTable } from '@/hooks/web/useXTable'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import * as DataSourceConfiggApi from '@/api/infra/dataSourceConfig'
@@ -80,8 +79,7 @@ import { rules, allSchemas } from './dataSourceConfig.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<DataSourceConfiggApi.DataSourceConfigVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   isList: true,
   getListApi: DataSourceConfiggApi.getDataSourceConfigListApi,
@@ -125,7 +123,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -149,7 +147,7 @@ const submitForm = async () => {
       } finally {
         loading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 7 - 9
yudao-ui-admin-vue3/src/views/infra/fileConfig/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -44,7 +44,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -173,8 +173,7 @@ import {
 } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 // 业务相关的 import
 import * as FileConfigApi from '@/api/infra/fileConfig'
 import { rules, allSchemas } from './fileConfig.data'
@@ -183,8 +182,7 @@ import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<FileConfigApi.FileConfigVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: FileConfigApi.getFileConfigPageApi,
   deleteApi: FileConfigApi.deleteFileConfigApi
@@ -276,7 +274,7 @@ const handleMaster = (row: FileConfigApi.FileConfigVO) => {
     .confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder'))
     .then(async () => {
       await FileConfigApi.updateFileConfigMasterApi(row.id)
-      await getList(xGrid)
+      await reload()
     })
 }
 
@@ -287,7 +285,7 @@ const handleTest = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -308,7 +306,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
         dialogVisible.value = false
       } finally {
         actionLoading.value = false
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/infra/fileList/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <XButton
           type="primary"
@@ -24,7 +24,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(详情) -->
@@ -85,8 +85,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { ElUpload, ElImage, UploadInstance, UploadRawFile } from 'element-plus'
 // 业务相关的 import
 import { allSchemas } from './fileList.data'
@@ -98,8 +97,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<FileApi.FileVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: FileApi.getFilePageApi,
   deleteApi: FileApi.deleteFileApi
@@ -145,7 +143,7 @@ const handleFileSuccess = async (response: any): Promise<void> => {
   message.success('上传成功')
   uploadDialogVisible.value = false
   uploadDisabled.value = false
-  await getList(xGrid)
+  await reload()
 }
 // 文件数超出提示
 const handleExceed = (): void => {
@@ -166,7 +164,7 @@ const handleDetail = (row: FileApi.FileVO) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // ========== 复制相关 ==========

+ 5 - 7
yudao-ui-admin-vue3/src/views/infra/job/JobLog.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <XButton
           type="warning"
@@ -29,7 +29,7 @@
           @click="handleDetail(row)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(详情) -->
@@ -51,15 +51,13 @@
 import { ref } from 'vue'
 import dayjs from 'dayjs'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import * as JobLogApi from '@/api/infra/jobLog'
 import { allSchemas } from './jobLog.data'
 
 const { t } = useI18n() // 国际化
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, exportList } = useVxeGrid<JobLogApi.JobLogVO>({
+const [registerTable, { exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: JobLogApi.getJobLogPageApi,
   exportListApi: JobLogApi.exportJobLogApi
@@ -81,6 +79,6 @@ const handleDetail = async (row: JobLogApi.JobLogVO) => {
 }
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '定时任务详情.xls')
+  await exportList('定时任务详情.xls')
 }
 </script>

+ 9 - 11
yudao-ui-admin-vue3/src/views/infra/job/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -83,7 +83,7 @@
           </template>
         </el-dropdown>
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -134,8 +134,7 @@ import { useRouter } from 'vue-router'
 import { ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { Crontab } from '@/components/Crontab'
 import * as JobApi from '@/api/infra/job'
@@ -147,8 +146,7 @@ const message = useMessage() // 消息弹窗
 const { push } = useRouter()
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<JobApi.JobVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: JobApi.getJobPageApi,
   deleteApi: JobApi.deleteJobApi,
@@ -183,7 +181,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '定时任务.xls')
+  await exportList('定时任务.xls')
 }
 
 // 修改操作
@@ -252,7 +250,7 @@ const parseTime = (time) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 const handleChangeStatus = async (row: JobApi.JobVO) => {
   const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭'
@@ -267,7 +265,7 @@ const handleChangeStatus = async (row: JobApi.JobVO) => {
           : InfraJobStatusEnum.STOP
       await JobApi.updateJobStatusApi(row.id, status)
       message.success(text + '成功')
-      await getList(xGrid)
+      await reload()
     })
     .catch(() => {
       row.status =
@@ -289,7 +287,7 @@ const handleRun = (row: JobApi.JobVO) => {
   message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')).then(async () => {
     await JobApi.runJobApi(row.id)
     message.success('执行成功')
-    await getList(xGrid)
+    await reload()
   })
 }
 // 提交按钮
@@ -312,7 +310,7 @@ const submitForm = async () => {
         dialogVisible.value = false
       } finally {
         actionLoading.value = false
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 7 - 9
yudao-ui-admin-vue3/src/views/pay/app/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -43,7 +43,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal v-model="dialogVisible" :title="dialogTitle">
@@ -79,8 +79,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { rules, allSchemas } from './app.data'
 import * as AppApi from '@/api/pay/app'
@@ -89,8 +88,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<AppApi.AppVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: AppApi.getAppPageApi,
   deleteApi: AppApi.deleteAppApi,
@@ -119,7 +117,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '应用信息.xls')
+  await exportList('应用信息.xls')
 }
 
 // 修改操作
@@ -139,7 +137,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -163,7 +161,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 7 - 9
yudao-ui-admin-vue3/src/views/pay/merchant/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -43,7 +43,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -78,8 +78,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { rules, allSchemas } from './merchant.data'
 import * as MerchantApi from '@/api/pay/merchant'
@@ -87,8 +86,7 @@ import * as MerchantApi from '@/api/pay/merchant'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<MerchantApi.MerchantVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: MerchantApi.getMerchantPageApi,
   deleteApi: MerchantApi.deleteMerchantApi,
@@ -117,7 +115,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '商户列表.xls')
+  await exportList('商户列表.xls')
 }
 
 // 修改操作
@@ -137,7 +135,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -161,7 +159,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 5 - 7
yudao-ui-admin-vue3/src/views/pay/order/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -29,7 +29,7 @@
           @click="handleDetail(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(详情) -->
@@ -44,15 +44,13 @@
 <script setup lang="ts" name="Order">
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { allSchemas } from './order.data'
 import * as OrderApi from '@/api/pay/order'
 
 const { t } = useI18n() // 国际化
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, exportList } = useVxeGrid<OrderApi.OrderVO>({
+const [registerTable, { exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: OrderApi.getOrderPageApi,
   exportListApi: OrderApi.exportOrderApi
@@ -76,7 +74,7 @@ const handleCreate = () => {
 }
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '订单数据.xls')
+  await exportList('订单数据.xls')
 }
 
 // 详情操作

+ 5 - 7
yudao-ui-admin-vue3/src/views/pay/refund/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:导出 -->
         <XButton
@@ -21,7 +21,7 @@
           @click="handleDetail(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal v-model="dialogVisible" :title="t('action.detail')">
@@ -36,16 +36,14 @@
 <script setup lang="ts" name="Refund">
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { allSchemas } from './refund.data'
 import * as RefundApi from '@/api/pay/refund'
 
 const { t } = useI18n() // 国际化
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, exportList } = useVxeGrid<RefundApi.RefundVO>({
+const [registerTable, { exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: RefundApi.getRefundPageApi,
   exportListApi: RefundApi.exportRefundApi
@@ -53,7 +51,7 @@ const { gridOptions, exportList } = useVxeGrid<RefundApi.RefundVO>({
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '退款订单.xls')
+  await exportList('退款订单.xls')
 }
 
 // ========== CRUD 相关 ==========

+ 6 - 6
yudao-ui-admin-vue3/src/views/system/dept/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" show-overflow class="xtable-scrollbar">
+    <XTable @register="registerTable" show-overflow>
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -33,7 +33,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 添加或修改菜单对话框 -->
   <XModal id="deptModel" v-model="dialogVisible" :title="dialogTitle">
@@ -81,7 +81,7 @@ import { VxeGridInstance } from 'vxe-table'
 import { handleTree, defaultProps } from '@/utils/tree'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { allSchemas, rules } from './dept.data'
 import * as DeptApi from '@/api/system/dept'
@@ -119,7 +119,7 @@ const getTree = async () => {
   dept.children = handleTree(res)
   deptOptions.value.push(dept)
 }
-const { gridOptions, getList, deleteData } = useVxeGrid<DeptApi.DeptVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   treeConfig: treeConfig,
   getListApi: DeptApi.getDeptPageApi,
@@ -168,7 +168,7 @@ const submitForm = async () => {
         dialogVisible.value = false
       } finally {
         actionLoading.value = false
-        await getList(xGrid)
+        await reload()
       }
     }
   })
@@ -176,7 +176,7 @@ const submitForm = async () => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 const userNicknameFormat = (row) => {

+ 14 - 29
yudao-ui-admin-vue3/src/views/system/dict/index.vue

@@ -7,12 +7,7 @@
           <span>字典分类</span>
         </div>
       </template>
-      <vxe-grid
-        ref="xTypeGrid"
-        v-bind="typeGridOptions"
-        @cell-click="cellClickEvent"
-        class="xtable-scrollbar"
-      >
+      <XTable @register="registerType" @cell-click="cellClickEvent">
         <!-- 操作:新增类型 -->
         <template #toolbar_buttons>
           <XButton
@@ -39,7 +34,7 @@
             @click="handleTypeDelete(row.id)"
           />
         </template>
-      </vxe-grid>
+      </XTable>
       <!-- @星语:分页和列表重叠在一起了 -->
     </el-card>
     <!-- ====== 字典数据 ====== -->
@@ -55,7 +50,7 @@
       </div>
       <div v-if="tableTypeSelect">
         <!-- 列表 -->
-        <vxe-grid ref="xDataGrid" v-bind="dataGridOptions" class="xtable-scrollbar">
+        <XTable @register="registerData">
           <!-- 操作:新增数据 -->
           <template #toolbar_buttons>
             <XButton
@@ -82,7 +77,7 @@
               @click="handleDataDelete(row.id)"
             />
           </template>
-        </vxe-grid>
+        </XTable>
       </div>
     </el-card>
     <XModal id="dictModel" v-model="dialogVisible" :title="dialogTitle">
@@ -130,8 +125,8 @@
 import { ref, unref, reactive } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance, VxeTableEvents } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
+import { VxeTableEvents } from 'vxe-table'
 import { FormExpose } from '@/components/Form'
 import { ElInput, ElTag, ElCard } from 'element-plus'
 import * as DictTypeSchemas from './dict.type'
@@ -143,28 +138,18 @@ import { DictDataVO, DictTypeVO } from '@/api/system/dict/types'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const xTypeGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const {
-  gridOptions: typeGridOptions,
-  getList: typeGetList,
-  deleteData: typeDeleteData
-} = useVxeGrid<DictTypeVO>({
+const [registerType, { reload: typeGetList, deleteData: typeDeleteData }] = useXTable({
   allSchemas: DictTypeSchemas.allSchemas,
   getListApi: DictTypeApi.getDictTypePageApi,
   deleteApi: DictTypeApi.deleteDictTypeApi
 })
 
-const xDataGrid = ref<VxeGridInstance>() // 列表 Grid Ref
 const queryParams = reactive({
   dictType: null
 })
-const {
-  gridOptions: dataGridOptions,
-  getList: dataGetList,
-  deleteData: dataDeleteData
-} = useVxeGrid<DictDataVO>({
+const [registerData, { reload: dataGetList, deleteData: dataDeleteData }] = useXTable({
   allSchemas: DictDataSchemas.allSchemas,
-  queryParams: queryParams,
+  params: queryParams,
   getListApi: DictDataApi.getDictDataPageApi,
   deleteApi: DictDataApi.deleteDictDataApi
 })
@@ -199,7 +184,7 @@ const tableTypeSelect = ref(false)
 const cellClickEvent: VxeTableEvents.CellClick = async ({ row }) => {
   tableTypeSelect.value = true
   queryParams.dictType = row['type']
-  await dataGetList(xDataGrid)
+  await dataGetList()
   parentType.value = row['type']
 }
 // 弹出框
@@ -219,11 +204,11 @@ const setDialogTile = (type: string) => {
 
 // 删除操作
 const handleTypeDelete = async (rowId: number) => {
-  await typeDeleteData(xTypeGrid, rowId)
+  await typeDeleteData(rowId)
 }
 
 const handleDataDelete = async (rowId: number) => {
-  await dataDeleteData(xDataGrid, rowId)
+  await dataDeleteData(rowId)
 }
 
 // 提交按钮
@@ -247,7 +232,7 @@ const submitTypeForm = async () => {
         dialogVisible.value = false
       } finally {
         actionLoading.value = false
-        typeGetList(xTypeGrid)
+        typeGetList()
       }
     }
   })
@@ -272,7 +257,7 @@ const submitDataForm = async () => {
         dialogVisible.value = false
       } finally {
         actionLoading.value = false
-        dataGetList(xDataGrid)
+        dataGetList()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/errorCode/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:新增 -->
       <template #toolbar_buttons>
         <XButton
@@ -35,7 +35,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="errorCodeModel" v-model="dialogVisible" :title="dialogTitle">
@@ -71,8 +71,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import { rules, allSchemas } from './errorCode.data'
@@ -81,8 +80,7 @@ import * as ErrorCodeApi from '@/api/system/errorCode'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<ErrorCodeApi.ErrorCodeVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: ErrorCodeApi.getErrorCodePageApi,
   deleteApi: ErrorCodeApi.deleteErrorCodeApi
@@ -125,7 +123,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交新增/修改的表单
@@ -149,7 +147,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 5 - 7
yudao-ui-admin-vue3/src/views/system/loginlog/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:导出 -->
       <template #toolbar_buttons>
         <XButton
@@ -15,7 +15,7 @@
         <!-- 操作:详情 -->
         <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="postModel" v-model="dialogVisible" :title="dialogTitle">
@@ -31,16 +31,14 @@
 // 全局相关的 import
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 // 业务相关的 import
 import { allSchemas } from './loginLog.data'
 import { getLoginLogPageApi, exportLoginLogApi, LoginLogVO } from '@/api/system/loginLog'
 
 const { t } = useI18n() // 国际化
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, exportList } = useVxeGrid<LoginLogVO>({
+const [registerTable, { exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: getLoginLogPageApi,
   exportListApi: exportLoginLogApi
@@ -59,6 +57,6 @@ const handleDetail = async (row: LoginLogVO) => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '登录列表.xls')
+  await exportList('登录列表.xls')
 }
 </script>

+ 6 - 6
yudao-ui-admin-vue3/src/views/system/menu/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" show-overflow class="xtable-scrollbar">
+    <XTable @register="registerTable" show-overflow>
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -34,7 +34,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 添加或修改菜单对话框 -->
   <XModal id="menuModel" v-model="dialogVisible" :title="dialogTitle">
@@ -201,7 +201,7 @@ import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants'
 import { handleTree, defaultProps } from '@/utils/tree'
 import * as MenuApi from '@/api/system/menu'
 import { allSchemas, rules } from './menu.data'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
+import { useXTable } from '@/hooks/web/useXTable'
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
@@ -215,7 +215,7 @@ const treeConfig = {
   parentField: 'parentId',
   expandAll: false
 }
-const { gridOptions, getList, deleteData } = useVxeGrid<MenuApi.MenuVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   treeConfig: treeConfig,
   getListApi: MenuApi.getMenuListApi,
@@ -326,7 +326,7 @@ const submitForm = async () => {
     actionLoading.value = false
     wsCache.delete(CACHE_KEY.ROLE_ROUTERS)
     // 操作成功,重新加载列表
-    await getList(xGrid)
+    await reload()
   }
 }
 
@@ -338,6 +338,6 @@ const isExternal = (path: string) => {
 // ========== 删除 ==========
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 </script>

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/notice/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:新增 -->
       <template #toolbar_buttons>
         <XButton
@@ -35,7 +35,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="noticeModel" v-model="dialogVisible" :title="dialogTitle">
@@ -75,8 +75,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import * as NoticeApi from '@/api/system/notice'
@@ -86,8 +85,7 @@ import { Editor } from '@/components/Editor'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<NoticeApi.NoticeVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: NoticeApi.getNoticePageApi,
   deleteApi: NoticeApi.deleteNoticeApi
@@ -130,7 +128,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交新增/修改的表单
@@ -153,7 +151,7 @@ const submitForm = async () => {
         dialogVisible.value = false
       } finally {
         actionLoading.value = false
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/oauth2/client/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -51,7 +51,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="postModel" v-model="dialogVisible" :title="dialogTitle">
@@ -135,8 +135,7 @@ import { ref, unref } from 'vue'
 import { ElTag } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import * as ClientApi from '@/api/system/oauth2/client'
@@ -146,8 +145,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<ClientApi.OAuth2ClientVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: ClientApi.getOAuth2ClientPageApi,
   deleteApi: ClientApi.deleteOAuth2ClientApi
@@ -188,7 +186,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交新增/修改的表单
@@ -212,7 +210,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 5 - 7
yudao-ui-admin-vue3/src/views/system/oauth2/token/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #actionbtns_default="{ row }">
         <!-- 操作:详情 -->
         <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
@@ -13,7 +13,7 @@
           @click="handleForceLogout(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(详情) -->
@@ -28,8 +28,7 @@
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 
 import { allSchemas } from './token.data'
 import * as TokenApi from '@/api/system/oauth2/token'
@@ -37,8 +36,7 @@ import * as TokenApi from '@/api/system/oauth2/token'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList } = useVxeGrid<TokenApi.OAuth2TokenVO>({
+const [registerTable, { reload }] = useXTable({
   allSchemas: allSchemas,
   topActionSlots: false,
   getListApi: TokenApi.getAccessTokenPageApi
@@ -65,7 +63,7 @@ const handleForceLogout = (rowId: number) => {
     })
     .finally(async () => {
       // 刷新列表
-      await getList(xGrid)
+      await reload()
     })
 }
 </script>

+ 5 - 7
yudao-ui-admin-vue3/src/views/system/operatelog/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -22,7 +22,7 @@
         <!-- 操作:详情 -->
         <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="postModel" v-model="dialogVisible" :title="t('action.detail')">
@@ -45,16 +45,14 @@
 // 全局相关的 import
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 // 业务相关的 import
 import * as OperateLogApi from '@/api/system/operatelog'
 import { allSchemas } from './operatelog.data'
 
 const { t } = useI18n() // 国际化
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, exportList } = useVxeGrid<OperateLogApi.OperateLogVO>({
+const [registerTable, { exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: OperateLogApi.getOperateLogPageApi,
   exportListApi: OperateLogApi.exportOperateLogApi
@@ -73,6 +71,6 @@ const handleDetail = (row: OperateLogApi.OperateLogVO) => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '操作日志.xls')
+  await exportList('操作日志.xls')
 }
 </script>

+ 7 - 9
yudao-ui-admin-vue3/src/views/system/post/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -43,7 +43,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <!-- 弹窗 -->
   <XModal id="postModel" :loading="modelLoading" v-model="modelVisible" :title="modelTitle">
@@ -79,8 +79,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import * as PostApi from '@/api/system/post'
@@ -89,8 +88,7 @@ import { rules, allSchemas } from './post.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<PostApi.PostVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: PostApi.getPostPageApi,
   deleteApi: PostApi.deletePostApi,
@@ -121,7 +119,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '岗位列表.xls')
+  await exportList('岗位列表.xls')
 }
 
 // 修改操作
@@ -143,7 +141,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交新增/修改的表单
@@ -167,7 +165,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/role/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:新增 -->
       <template #toolbar_buttons>
         <XButton
@@ -49,7 +49,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal v-model="dialogVisible" :title="dialogTitle">
@@ -159,11 +159,10 @@ import {
   ElSwitch,
   ElTag
 } from 'element-plus'
-import { VxeGridInstance } from 'vxe-table'
 import { FormExpose } from '@/components/Form'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
+import { useXTable } from '@/hooks/web/useXTable'
 import { handleTree, defaultProps } from '@/utils/tree'
 import { SystemDataScopeEnum } from '@/utils/constants'
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
@@ -176,8 +175,7 @@ import * as PermissionApi from '@/api/system/permission'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<RoleApi.RoleVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: RoleApi.getRolePageApi,
   deleteApi: RoleApi.deleteRoleApi
@@ -221,7 +219,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -245,7 +243,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 12 - 15
yudao-ui-admin-vue3/src/views/system/sensitiveWord/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -53,7 +53,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal v-model="dialogVisible" :title="dialogTitle">
@@ -106,8 +106,7 @@
 import { onMounted, ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { ElTag, ElSelect, ElOption } from 'element-plus'
 import * as SensitiveWordApi from '@/api/system/sensitiveWord'
@@ -116,14 +115,12 @@ import { rules, allSchemas } from './sensitiveWord.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } =
-  useVxeGrid<SensitiveWordApi.SensitiveWordVO>({
-    allSchemas: allSchemas,
-    getListApi: SensitiveWordApi.getSensitiveWordPageApi,
-    deleteApi: SensitiveWordApi.deleteSensitiveWordApi,
-    exportListApi: SensitiveWordApi.exportSensitiveWordApi
-  })
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
+  allSchemas: allSchemas,
+  getListApi: SensitiveWordApi.getSensitiveWordPageApi,
+  deleteApi: SensitiveWordApi.deleteSensitiveWordApi,
+  exportListApi: SensitiveWordApi.exportSensitiveWordApi
+})
 const actionLoading = ref(false) // 遮罩层
 const actionType = ref('') // 操作按钮的类型
 const dialogVisible = ref(false) // 是否显示弹出层
@@ -152,7 +149,7 @@ const handleCreate = () => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '敏感词数据.xls')
+  await exportList('敏感词数据.xls')
 }
 
 // 修改操作
@@ -172,7 +169,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -196,7 +193,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/sms/smsChannel/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:新增 -->
       <template #toolbar_buttons>
         <XButton
@@ -35,7 +35,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal id="smsChannel" v-model="dialogVisible" :title="dialogTitle">
@@ -72,8 +72,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import * as SmsChannelApi from '@/api/system/sms/smsChannel'
@@ -83,8 +82,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<SmsChannelApi.SmsChannelVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: SmsChannelApi.getSmsChannelPageApi,
   deleteApi: SmsChannelApi.deleteSmsChannelApi
@@ -127,7 +125,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -151,7 +149,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 5 - 7
yudao-ui-admin-vue3/src/views/system/sms/smsLog/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:导出 -->
       <template #toolbar_buttons>
         <XButton
@@ -14,7 +14,7 @@
       <template #actionbtns_default="{ row }">
         <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
 
   <XModal id="smsLog" v-model="dialogVisible" :title="dialogTitle">
@@ -34,15 +34,13 @@
 // 全局相关的 import
 import { ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { allSchemas } from './sms.log.data'
 import * as SmsLoglApi from '@/api/system/sms/smsLog'
 const { t } = useI18n() // 国际化
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, exportList } = useVxeGrid<SmsLoglApi.SmsLogVO>({
+const [registerTable, { exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: SmsLoglApi.getSmsLogPageApi,
   exportListApi: SmsLoglApi.exportSmsLogApi
@@ -62,6 +60,6 @@ const handleDetail = (row: SmsLoglApi.SmsLogVO) => {
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '短信日志.xls')
+  await exportList('短信日志.xls')
 }
 </script>

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/sms/smsTemplate/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <!-- 操作:新增 -->
       <template #toolbar_buttons>
         <XButton
@@ -41,7 +41,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal id="smsTemplate" v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -113,8 +113,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { ElForm, ElFormItem, ElInput } from 'element-plus'
 // 业务相关的 import
@@ -125,8 +124,7 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData } = useVxeGrid<SmsTemplateApi.SmsTemplateVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: SmsTemplateApi.getSmsTemplatePageApi,
   deleteApi: SmsTemplateApi.deleteSmsTemplateApi
@@ -170,7 +168,7 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -194,7 +192,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 7 - 9
yudao-ui-admin-vue3/src/views/system/tenant/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <!-- 操作:新增 -->
         <XButton
@@ -49,7 +49,7 @@
           @click="handleDelete(row.id)"
         />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -89,8 +89,7 @@
 import { ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { ElTag } from 'element-plus'
 import { FormExpose } from '@/components/Form'
 import * as TenantApi from '@/api/system/tenant'
@@ -99,8 +98,7 @@ import { rules, allSchemas, tenantPackageOption } from './tenant.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<TenantApi.TenantVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
   getListApi: TenantApi.getTenantPageApi,
   deleteApi: TenantApi.deleteTenantApi,
@@ -153,12 +151,12 @@ const handleDetail = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 导出操作
 const handleExport = async () => {
-  await exportList(xGrid, '租户列表.xls')
+  await exportList('租户列表.xls')
 }
 
 // 提交按钮
@@ -183,7 +181,7 @@ const submitForm = async () => {
       } finally {
         actionLoading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 6 - 8
yudao-ui-admin-vue3/src/views/system/tenantPackage/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+    <XTable @register="registerTable">
       <template #toolbar_buttons>
         <XButton
           type="primary"
@@ -14,7 +14,7 @@
         <XTextButton preIcon="ep:edit" :title="t('action.edit')" @click="handleUpdate(row.id)" />
         <XTextButton preIcon="ep:delete" :title="t('action.del')" @click="handleDelete(row.id)" />
       </template>
-    </vxe-grid>
+    </XTable>
   </ContentWrap>
   <XModal v-model="dialogVisible" :title="dialogTitle">
     <!-- 对话框(添加 / 修改) -->
@@ -69,8 +69,7 @@ import { onMounted, ref, unref } from 'vue'
 import { handleTree, defaultProps } from '@/utils/tree'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
-import { VxeGridInstance } from 'vxe-table'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { ElCard, ElSwitch, ElTree } from 'element-plus'
 // 业务相关的 import
@@ -86,7 +85,6 @@ const menuExpand = ref(false)
 const menuNodeAll = ref(false)
 const treeRef = ref<InstanceType<typeof ElTree>>()
 const treeNodeAll = ref(false)
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
 const formRef = ref<FormExpose>() // 表单 Ref
 const loading = ref(false) // 遮罩层
 const actionType = ref('') // 操作按钮的类型
@@ -102,7 +100,7 @@ const getTree = async () => {
   menuOptions.value = handleTree(res)
 }
 
-const { gridOptions, getList, deleteData } = useVxeGrid<TenantPackageApi.TenantPackageVO>({
+const [registerTable, { reload, deleteData }] = useXTable({
   allSchemas: allSchemas,
   getListApi: TenantPackageApi.getTenantPackageTypePageApi,
   deleteApi: TenantPackageApi.deleteTenantPackageTypeApi
@@ -136,7 +134,7 @@ const handleUpdate = async (rowId: number) => {
 
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 
 // 提交按钮
@@ -162,7 +160,7 @@ const submitForm = async () => {
       } finally {
         loading.value = false
         // 刷新列表
-        await getList(xGrid)
+        await reload()
       }
     }
   })

+ 10 - 12
yudao-ui-admin-vue3/src/views/system/user/index.vue

@@ -27,7 +27,7 @@
         </div>
       </template>
       <!-- 列表 -->
-      <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
+      <XTable @register="registerTable">
         <template #toolbar_buttons>
           <!-- 操作:新增 -->
           <XButton
@@ -119,7 +119,7 @@
             </template>
           </el-dropdown>
         </template>
-      </vxe-grid>
+      </XTable>
     </el-card>
   </div>
   <XModal v-model="dialogVisible" :title="dialogTitle">
@@ -283,14 +283,13 @@ import {
   UploadRawFile
 } from 'element-plus'
 import { useRouter } from 'vue-router'
-import { VxeGridInstance } from 'vxe-table'
 import { handleTree, defaultProps } from '@/utils/tree'
 import download from '@/utils/download'
 import { CommonStatusEnum } from '@/utils/constants'
 import { getAccessToken, getTenantId } from '@/utils/auth'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useMessage } from '@/hooks/web/useMessage'
-import { useVxeGrid } from '@/hooks/web/useVxeGrid'
+import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 import { rules, allSchemas } from './user.data'
 import * as UserApi from '@/api/system/user'
@@ -312,10 +311,9 @@ const queryParams = reactive({
 // ========== 列表相关 ==========
 const tableTitle = ref('用户列表')
 // 列表相关的变量
-const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
-const { gridOptions, getList, deleteData, exportList } = useVxeGrid<UserApi.UserVO>({
+const [registerTable, { reload, deleteData, exportList }] = useXTable({
   allSchemas: allSchemas,
-  queryParams: queryParams,
+  params: queryParams,
   getListApi: UserApi.getUserPageApi,
   deleteApi: UserApi.deleteUserApi,
   exportListApi: UserApi.exportUserApi
@@ -334,7 +332,7 @@ const filterNode = (value: string, data: Tree) => {
 }
 const handleDeptNodeClick = async (row: { [key: string]: any }) => {
   queryParams.deptId = row.id
-  await getList(xGrid)
+  await reload()
 }
 const { push } = useRouter()
 const handleDeptEdit = () => {
@@ -409,7 +407,7 @@ const handleDetail = async (rowId: number) => {
 }
 // 删除操作
 const handleDelete = async (rowId: number) => {
-  await deleteData(xGrid, rowId)
+  await deleteData(rowId)
 }
 // 提交按钮
 const submitForm = async () => {
@@ -428,7 +426,7 @@ const submitForm = async () => {
   } finally {
     // unref(formRef)?.setSchema(allSchemas.formSchema)
     // 刷新列表
-    await getList(xGrid)
+    await reload()
     loading.value = false
   }
 }
@@ -443,7 +441,7 @@ const handleStatusChange = async (row: UserApi.UserVO) => {
       await UserApi.updateUserStatusApi(row.id, row.status)
       message.success(text + '成功')
       // 刷新列表
-      await getList(xGrid)
+      await reload()
     })
     .catch(() => {
       row.status =
@@ -544,7 +542,7 @@ const handleFileSuccess = async (response: any): Promise<void> => {
     text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
   }
   message.alert(text)
-  await getList(xGrid)
+  await reload()
 }
 // 文件数超出提示
 const handleExceed = (): void => {

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor