Kaynağa Gözat

feat: 接入vextable组件 (#2508)

lzdjack 2 yıl önce
ebeveyn
işleme
6753e24b3d
51 değiştirilmiş dosya ile 2676 ekleme ve 14 silme
  1. 2 1
      build/vite/plugin/styleImport.ts
  2. 5 0
      package.json
  3. 12 0
      src/components/VxeTable/index.ts
  4. 108 0
      src/components/VxeTable/src/VxeBasicTable.tsx
  5. 59 0
      src/components/VxeTable/src/componentMap.ts
  6. 22 0
      src/components/VxeTable/src/componentType.ts
  7. 20 0
      src/components/VxeTable/src/components/AApiSelect.tsx
  8. 16 0
      src/components/VxeTable/src/components/AAutoComplete.tsx
  9. 120 0
      src/components/VxeTable/src/components/AButton.tsx
  10. 59 0
      src/components/VxeTable/src/components/AButtonGroup.tsx
  11. 42 0
      src/components/VxeTable/src/components/ACascader.tsx
  12. 5 0
      src/components/VxeTable/src/components/ACheckboxGroup.tsx
  13. 33 0
      src/components/VxeTable/src/components/ADatePicker.tsx
  14. 27 0
      src/components/VxeTable/src/components/AEmpty.tsx
  15. 16 0
      src/components/VxeTable/src/components/AInput.tsx
  16. 16 0
      src/components/VxeTable/src/components/AInputNumber.tsx
  17. 17 0
      src/components/VxeTable/src/components/AInputSearch.tsx
  18. 18 0
      src/components/VxeTable/src/components/AMonthPicker.tsx
  19. 5 0
      src/components/VxeTable/src/components/ARadioGroup.tsx
  20. 30 0
      src/components/VxeTable/src/components/ARangePicker.tsx
  21. 15 0
      src/components/VxeTable/src/components/ARate.tsx
  22. 271 0
      src/components/VxeTable/src/components/ASelect.tsx
  23. 53 0
      src/components/VxeTable/src/components/ASwitch.tsx
  24. 18 0
      src/components/VxeTable/src/components/ATimePicker.tsx
  25. 35 0
      src/components/VxeTable/src/components/ATreeSelect.tsx
  26. 18 0
      src/components/VxeTable/src/components/AWeekPicker.tsx
  27. 18 0
      src/components/VxeTable/src/components/AYearPicker.tsx
  28. 427 0
      src/components/VxeTable/src/components/common.tsx
  29. 112 0
      src/components/VxeTable/src/components/index.tsx
  30. 4 0
      src/components/VxeTable/src/const.ts
  31. 8 0
      src/components/VxeTable/src/css/common.scss
  32. 105 0
      src/components/VxeTable/src/css/component.scss
  33. 6 0
      src/components/VxeTable/src/css/index.scss
  34. 24 0
      src/components/VxeTable/src/css/scrollbar.scss
  35. 30 0
      src/components/VxeTable/src/css/toolbar.scss
  36. 6 0
      src/components/VxeTable/src/css/variable.scss
  37. 17 0
      src/components/VxeTable/src/emits.ts
  38. 19 0
      src/components/VxeTable/src/helper.ts
  39. 131 0
      src/components/VxeTable/src/methods.ts
  40. 52 0
      src/components/VxeTable/src/props.ts
  41. 4 0
      src/components/VxeTable/src/setting.ts
  42. 7 0
      src/components/VxeTable/src/types.ts
  43. 2 1
      src/components/registerGlobComp.ts
  44. 1 0
      src/locales/lang/en/routes/demo.ts
  45. 1 0
      src/locales/lang/zh-CN/routes/demo.ts
  46. 1 0
      src/main.ts
  47. 8 0
      src/router/routes/modules/demo/comp.ts
  48. 46 0
      src/settings/componentSetting.ts
  49. 97 0
      src/views/demo/table/VxeTable.vue
  50. 110 0
      src/views/demo/table/tableData.tsx
  51. 398 12
      yarn.lock

+ 2 - 1
build/vite/plugin/styleImport.ts

@@ -2,7 +2,7 @@
  *  Introduces component library styles on demand.
  * https://github.com/anncwb/vite-plugin-style-import
  */
-import { createStyleImportPlugin } from 'vite-plugin-style-import';
+import { createStyleImportPlugin, VxeTableResolve } from 'vite-plugin-style-import';
 
 export function configStyleImportPlugin(_isBuild: boolean) {
   if (!_isBuild) {
@@ -77,6 +77,7 @@ export function configStyleImportPlugin(_isBuild: boolean) {
         },
       },
     ],
+    resolves: [VxeTableResolve()],
   });
   return styleImportPlugin;
 }

+ 5 - 0
package.json

@@ -50,6 +50,7 @@
     "crypto-js": "^4.1.1",
     "dayjs": "^1.11.1",
     "echarts": "^5.3.2",
+    "exceljs": "^4.3.0",
     "intro.js": "^5.1.0",
     "lodash-es": "^4.17.21",
     "mockjs": "^1.1.0",
@@ -69,6 +70,9 @@
     "vue-json-pretty": "^2.0.6",
     "vue-router": "^4.0.14",
     "vue-types": "^4.1.1",
+    "vxe-table": "^4.3.9",
+    "vxe-table-plugin-export-xlsx": "^3.0.4",
+    "xe-utils": "^3.5.7",
     "xlsx": "^0.18.5"
   },
   "devDependencies": {
@@ -121,6 +125,7 @@
     "rimraf": "^3.0.2",
     "rollup": "^2.70.2",
     "rollup-plugin-visualizer": "^5.6.0",
+    "sass": "^1.57.1",
     "stylelint": "^14.7.1",
     "stylelint-config-prettier": "^9.0.3",
     "stylelint-config-recommended": "^7.0.0",

+ 12 - 0
src/components/VxeTable/index.ts

@@ -0,0 +1,12 @@
+import { withInstall } from '/@/utils';
+import vxeBasicTable from './src/VxeBasicTable';
+import { VXETable } from 'vxe-table';
+import VXETablePluginAntd from './src/components';
+import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx';
+import './src/setting';
+
+export const VxeBasicTable = withInstall(vxeBasicTable);
+export * from 'vxe-table';
+export * from './src/types';
+
+VXETable.use(VXETablePluginAntd).use(VXETablePluginExportXLSX);

+ 108 - 0
src/components/VxeTable/src/VxeBasicTable.tsx

@@ -0,0 +1,108 @@
+import { defineComponent } from 'vue';
+import { computed, ref } from 'vue';
+import { BasicTableProps } from './types';
+import { omit } from 'lodash';
+import { basicProps } from './props';
+import { ignorePropKeys } from './const';
+import { basicEmits } from './emits';
+import XEUtils from 'xe-utils';
+import type { VxeGridInstance, VxeGridEventProps, GridMethods, TableMethods } from 'vxe-table';
+import { Grid as VxeGrid } from 'vxe-table';
+
+import { extendSlots } from '/@/utils/helper/tsxHelper';
+import { gridComponentMethodKeys } from './methods';
+
+export default defineComponent({
+  name: 'VxeBasicTable',
+  props: basicProps,
+  emits: basicEmits,
+  setup(props, { emit, attrs }) {
+    const tableElRef = ref<VxeGridInstance>();
+    const emitEvents: VxeGridEventProps = {};
+
+    const extendTableMethods = (methodKeys) => {
+      const funcs: any = {};
+      methodKeys.forEach((name) => {
+        funcs[name] = (...args: any[]) => {
+          const $vxegrid: any = tableElRef.value;
+          if ($vxegrid && $vxegrid[name]) {
+            return $vxegrid[name](...args);
+          }
+        };
+      });
+
+      return funcs;
+    };
+
+    const gridExtendTableMethods = extendTableMethods(gridComponentMethodKeys) as GridMethods &
+      TableMethods;
+
+    basicEmits.forEach((name) => {
+      const type = XEUtils.camelCase(`on-${name}`) as keyof VxeGridEventProps;
+
+      emitEvents[type] = (...args: any[]) => emit(name, ...args);
+    });
+
+    /**
+     * @description: 二次封装需要的所有属性
+     *  1.部分属性需要和全局属性进行合并
+     */
+    const getBindValues = computed<BasicTableProps>(() => {
+      const propsData: BasicTableProps = {
+        ...attrs,
+        ...props,
+      };
+
+      return propsData;
+    });
+
+    /**
+     * @description: Table 所有属性
+     */
+    const getBindGridValues = computed(() => {
+      const omitProps = omit(getBindValues.value, ignorePropKeys);
+
+      return {
+        ...omitProps,
+        ...getBindGridEvent,
+      };
+    });
+
+    /**
+     * @description: 组件外层class
+     */
+    const getWrapperClass = computed(() => {
+      return [attrs.class];
+    });
+
+    /**
+     * @description: 重写Vxe-table 方法
+     */
+    const getBindGridEvent: VxeGridEventProps = {
+      ...emitEvents,
+    };
+
+    return {
+      getWrapperClass,
+      getBindGridValues,
+      tableElRef,
+      ...gridExtendTableMethods,
+    };
+  },
+  render() {
+    const { tableClass, tableStyle } = this.$props;
+
+    return (
+      <div class={`h-full flex flex-col bg-white ${this.getWrapperClass}`}>
+        <VxeGrid
+          ref="tableElRef"
+          class={`vxe-grid_scrollbar px-6 py-4 ${tableClass}`}
+          style={tableStyle}
+          {...this.getBindGridValues}
+        >
+          {extendSlots(this.$slots)}
+        </VxeGrid>
+      </div>
+    );
+  },
+});

+ 59 - 0
src/components/VxeTable/src/componentMap.ts

@@ -0,0 +1,59 @@
+import type { Component } from 'vue';
+
+import type { ComponentType } from './componentType';
+import { ApiSelect, ApiTreeSelect } from '/@/components/Form';
+import {
+  Input,
+  Select,
+  Radio,
+  Checkbox,
+  AutoComplete,
+  Cascader,
+  DatePicker,
+  InputNumber,
+  Switch,
+  TimePicker,
+  TreeSelect,
+  Rate,
+  Button,
+  Empty,
+} from 'ant-design-vue';
+
+const componentMap = new Map<ComponentType, Component>();
+
+componentMap.set('AButton', Button);
+
+componentMap.set('AInput', Input);
+componentMap.set('AInputSearch', Input.Search);
+componentMap.set('AInputNumber', InputNumber);
+componentMap.set('AAutoComplete', AutoComplete);
+
+componentMap.set('ASelect', Select);
+componentMap.set('ATreeSelect', TreeSelect);
+componentMap.set('ASwitch', Switch);
+componentMap.set('ARadioGroup', Radio.Group);
+componentMap.set('ACheckboxGroup', Checkbox.Group);
+componentMap.set('ACascader', Cascader);
+componentMap.set('ARate', Rate);
+
+componentMap.set('ADatePicker', DatePicker);
+componentMap.set('AMonthPicker', DatePicker.MonthPicker);
+componentMap.set('ARangePicker', DatePicker.RangePicker);
+componentMap.set('AWeekPicker', DatePicker.WeekPicker);
+componentMap.set('AYearPicker', DatePicker.YearPicker);
+componentMap.set('ATimePicker', TimePicker);
+
+componentMap.set('AApiSelect', ApiSelect);
+componentMap.set('AApiTreeSelect', ApiTreeSelect);
+
+componentMap.set('AEmpty', Empty);
+
+export function add(compName: ComponentType, component: Component) {
+  componentMap.set(compName, component);
+}
+
+export function del(compName: ComponentType) {
+  componentMap.delete(compName);
+}
+
+export { componentMap };

+ 22 - 0
src/components/VxeTable/src/componentType.ts

@@ -0,0 +1,22 @@
+export type ComponentType =
+  | 'AInput'
+  | 'AInputNumber'
+  | 'ASelect'
+  | 'AApiSelect'
+  | 'ATreeSelect'
+  | 'AApiTreeSelect'
+  | 'ARadioGroup'
+  | 'ACheckboxGroup'
+  | 'AAutoComplete'
+  | 'ACascader'
+  | 'ADatePicker'
+  | 'AMonthPicker'
+  | 'ARangePicker'
+  | 'AWeekPicker'
+  | 'ATimePicker'
+  | 'AYearPicker'
+  | 'ASwitch'
+  | 'ARate'
+  | 'AInputSearch'
+  | 'AButton'
+  | 'AEmpty';

+ 20 - 0
src/components/VxeTable/src/components/AApiSelect.tsx

@@ -0,0 +1,20 @@
+import XEUtils from 'xe-utils';
+import { createDefaultRender, createEditRender, createFormItemRender } from './common';
+
+export default {
+  renderDefault: createDefaultRender({}, (_, params) => {
+    return {
+      params: XEUtils.get(params, 'row'),
+    };
+  }),
+  renderEdit: createEditRender({}, (_, params) => {
+    return {
+      params: XEUtils.get(params, 'row'),
+    };
+  }),
+  renderItemContent: createFormItemRender({}, (_, params) => {
+    return {
+      params: XEUtils.get(params, 'row'),
+    };
+  }),
+};

+ 16 - 0
src/components/VxeTable/src/components/AAutoComplete.tsx

@@ -0,0 +1,16 @@
+import {
+  createEditRender,
+  createDefaultRender,
+  createFilterRender,
+  createDefaultFilterRender,
+  createFormItemRender,
+} from './common';
+
+export default {
+  autofocus: 'input.ant-input',
+  renderDefault: createDefaultRender(),
+  renderEdit: createEditRender(),
+  renderFilter: createFilterRender(),
+  defaultFilterMethod: createDefaultFilterRender(),
+  renderItemContent: createFormItemRender(),
+};

+ 120 - 0
src/components/VxeTable/src/components/AButton.tsx

@@ -0,0 +1,120 @@
+import { h } from 'vue';
+import {
+  FormItemContentRenderParams,
+  FormItemRenderOptions,
+  VxeGlobalRendererHandles,
+} from 'vxe-table';
+import XEUtils from 'xe-utils';
+import { cellText, createEvents, createProps, getComponent } from './common';
+
+const COMPONENT_NAME = 'AButton';
+
+export function createEditRender() {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
+    params: VxeGlobalRendererHandles.RenderEditParams,
+  ) {
+    const { attrs } = renderOpts;
+    const Component = getComponent(COMPONENT_NAME);
+
+    return [
+      h(Component, {
+        ...attrs,
+        ...createProps(renderOpts, null),
+        ...createEvents(renderOpts, params),
+      }),
+    ];
+  };
+}
+
+export function createDefaultRender() {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
+    params: VxeGlobalRendererHandles.RenderEditParams,
+  ) {
+    const { attrs } = renderOpts;
+    const Component = getComponent(COMPONENT_NAME);
+
+    return [
+      h(
+        Component,
+        {
+          ...attrs,
+          ...createProps(renderOpts, null),
+          ...createEvents(renderOpts, params),
+        },
+        cellText(renderOpts.content),
+      ),
+    ];
+  };
+}
+
+export function createFormItemRender() {
+  return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+    const { attrs, content } = renderOpts;
+    const { property, $form, data } = params;
+    const props = createProps(renderOpts, null);
+    const Component = getComponent(COMPONENT_NAME);
+
+    return [
+      h(
+        Component,
+        {
+          ...attrs,
+          ...props,
+          ...createEvents(
+            renderOpts,
+            params,
+            (value: any) => {
+              // 处理 model 值双向绑定
+              XEUtils.set(data, property, value);
+            },
+            () => {
+              // 处理 change 事件相关逻辑
+              $form.updateStatus({
+                ...params,
+                field: property,
+              });
+            },
+          ),
+        },
+        {
+          default: () => cellText(content || props.content),
+        },
+      ),
+    ];
+  };
+}
+
+function createToolbarButtonRender() {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderToolOptions,
+    params: VxeGlobalRendererHandles.RenderButtonParams,
+  ) {
+    const { attrs } = renderOpts;
+    const { button } = params;
+    const props = createProps(renderOpts, null);
+    const Component = getComponent(COMPONENT_NAME);
+
+    return [
+      h(
+        Component,
+        {
+          ...attrs,
+          ...props,
+          ...createEvents(renderOpts, params),
+        },
+        {
+          default: () => cellText(button?.content || props.content),
+        },
+      ),
+    ];
+  };
+}
+
+export default {
+  renderEdit: createEditRender(),
+  renderDefault: createDefaultRender(),
+  renderItemContent: createFormItemRender(),
+  renderToolbarButton: createToolbarButtonRender(),
+};

+ 59 - 0
src/components/VxeTable/src/components/AButtonGroup.tsx

@@ -0,0 +1,59 @@
+import {
+  FormItemContentRenderParams,
+  FormItemRenderOptions,
+  VxeGlobalRendererHandles,
+} from 'vxe-table';
+import { createDefaultRender, createEditRender, createFormItemRender } from './AButton';
+
+function createEditButtonRender() {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
+    params: VxeGlobalRendererHandles.RenderEditParams,
+  ) {
+    const buttonEditRender = createEditRender();
+    const { children } = renderOpts;
+    if (children) {
+      return children.map(
+        (childRenderOpts: VxeGlobalRendererHandles.RenderEditOptions) =>
+          buttonEditRender(childRenderOpts, params)[0],
+      );
+    }
+    return [];
+  };
+}
+
+function createDefaultButtonRender() {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
+    params: VxeGlobalRendererHandles.RenderDefaultParams,
+  ) {
+    const buttonDefaultRender = createDefaultRender();
+    const { children } = renderOpts;
+    if (children) {
+      return children.map(
+        (childRenderOpts: VxeGlobalRendererHandles.RenderDefaultOptions) =>
+          buttonDefaultRender(childRenderOpts, params)[0],
+      );
+    }
+    return [];
+  };
+}
+
+function createButtonItemRender() {
+  return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+    const buttonItemRender = createFormItemRender();
+    const { children } = renderOpts;
+    if (children) {
+      return children.map(
+        (childRenderOpts: FormItemRenderOptions) => buttonItemRender(childRenderOpts, params)[0],
+      );
+    }
+    return [];
+  };
+}
+
+export default {
+  renderEdit: createEditButtonRender(),
+  renderDefault: createDefaultButtonRender(),
+  renderItemContent: createButtonItemRender(),
+};

+ 42 - 0
src/components/VxeTable/src/components/ACascader.tsx

@@ -0,0 +1,42 @@
+import { VxeGlobalRendererHandles } from 'vxe-table';
+import XEUtils from 'xe-utils';
+import {
+  createEditRender,
+  createCellRender,
+  createFormItemRender,
+  createExportMethod,
+} from './common';
+
+function matchCascaderData(index: number, list: any[], values: any[], labels: any[]) {
+  const val = values[index];
+  if (list && values.length > index) {
+    XEUtils.each(list, (item) => {
+      if (item.value === val) {
+        labels.push(item.label);
+        matchCascaderData(++index, item.children, values, labels);
+      }
+    });
+  }
+}
+
+function getCascaderCellValue(
+  renderOpts: VxeGlobalRendererHandles.RenderOptions,
+  params: VxeGlobalRendererHandles.RenderCellParams,
+) {
+  const { props = {} } = renderOpts;
+  const { row, column } = params;
+  const cellValue = XEUtils.get(row, column.field as string);
+  const values = cellValue || [];
+  const labels: Array<any> = [];
+  matchCascaderData(0, props.options, values, labels);
+  return (
+    props.showAllLevels === false ? labels.slice(labels.length - 1, labels.length) : labels
+  ).join(` ${props.separator || '/'} `);
+}
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getCascaderCellValue),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getCascaderCellValue),
+};

+ 5 - 0
src/components/VxeTable/src/components/ACheckboxGroup.tsx

@@ -0,0 +1,5 @@
+import { createFormItemRender } from './common';
+
+export default {
+  renderItemContent: createFormItemRender(),
+};

+ 33 - 0
src/components/VxeTable/src/components/ADatePicker.tsx

@@ -0,0 +1,33 @@
+import { VxeGlobalRendererHandles } from 'vxe-table';
+import XEUtils from 'xe-utils';
+import {
+  createCellRender,
+  createEditRender,
+  createExportMethod,
+  createFormItemRender,
+} from './common';
+
+export function getDatePickerCellValue(
+  renderOpts: VxeGlobalRendererHandles.RenderOptions,
+  params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
+  defaultFormat: string,
+) {
+  const { props = {} } = renderOpts;
+  const { row, column } = params;
+  let cellValue = XEUtils.get(row, column.field as string);
+  if (cellValue) {
+    cellValue = cellValue.format(props.format || defaultFormat);
+  }
+  return cellValue;
+}
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getDatePickerCellValue, () => {
+    return ['YYYY-MM-DD'];
+  }),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getDatePickerCellValue, () => {
+    return ['YYYY-MM-DD'];
+  }),
+};

+ 27 - 0
src/components/VxeTable/src/components/AEmpty.tsx

@@ -0,0 +1,27 @@
+import { h } from 'vue';
+import { VxeGlobalRendererHandles } from 'vxe-table';
+import { getComponent } from './common';
+
+function createEmptyRender() {
+  return function (renderOpts: VxeGlobalRendererHandles.RenderEmptyOptions) {
+    const { name, attrs, props } = renderOpts;
+
+    const Component = getComponent(name);
+    return [
+      h(
+        'div',
+        {
+          class: 'flex items-center justify-center',
+        },
+        h(Component, {
+          ...attrs,
+          ...props,
+        }),
+      ),
+    ];
+  };
+}
+
+export default {
+  renderEmpty: createEmptyRender(),
+};

+ 16 - 0
src/components/VxeTable/src/components/AInput.tsx

@@ -0,0 +1,16 @@
+import {
+  createEditRender,
+  createDefaultRender,
+  createFilterRender,
+  createDefaultFilterRender,
+  createFormItemRender,
+} from './common';
+
+export default {
+  autofocus: 'input.ant-input',
+  renderDefault: createDefaultRender(),
+  renderEdit: createEditRender(),
+  renderFilter: createFilterRender(),
+  defaultFilterMethod: createDefaultFilterRender(),
+  renderItemContent: createFormItemRender(),
+};

+ 16 - 0
src/components/VxeTable/src/components/AInputNumber.tsx

@@ -0,0 +1,16 @@
+import {
+  createEditRender,
+  createFilterRender,
+  createFormItemRender,
+  createDefaultFilterRender,
+  createDefaultRender,
+} from './common';
+
+export default {
+  autofocus: 'input.ant-input-number-input',
+  renderDefault: createDefaultRender(),
+  renderEdit: createEditRender(),
+  renderFilter: createFilterRender(),
+  defaultFilterMethod: createDefaultFilterRender(),
+  renderItemContent: createFormItemRender(),
+};

+ 17 - 0
src/components/VxeTable/src/components/AInputSearch.tsx

@@ -0,0 +1,17 @@
+import {
+  createEditRender,
+  createDefaultRender,
+  createFilterRender,
+  createDefaultFilterRender,
+  createFormItemRender,
+  createToolbarToolRender,
+} from './common';
+
+export default {
+  renderDefault: createDefaultRender(),
+  renderEdit: createEditRender(),
+  renderFilter: createFilterRender(),
+  defaultFilterMethod: createDefaultFilterRender(),
+  renderItemContent: createFormItemRender(),
+  renderToolbarTool: createToolbarToolRender(),
+};

+ 18 - 0
src/components/VxeTable/src/components/AMonthPicker.tsx

@@ -0,0 +1,18 @@
+import { getDatePickerCellValue } from './ADatePicker';
+import {
+  createCellRender,
+  createEditRender,
+  createExportMethod,
+  createFormItemRender,
+} from './common';
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getDatePickerCellValue, () => {
+    return ['YYYY-MM'];
+  }),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getDatePickerCellValue, () => {
+    return ['YYYY-MM'];
+  }),
+};

+ 5 - 0
src/components/VxeTable/src/components/ARadioGroup.tsx

@@ -0,0 +1,5 @@
+import { createFormItemRender } from './common';
+
+export default {
+  renderItemContent: createFormItemRender(),
+};

+ 30 - 0
src/components/VxeTable/src/components/ARangePicker.tsx

@@ -0,0 +1,30 @@
+import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
+import XEUtils from 'xe-utils';
+import {
+  createCellRender,
+  createEditRender,
+  createExportMethod,
+  createFormItemRender,
+} from './common';
+
+function getRangePickerCellValue(
+  renderOpts: VxeColumnPropTypes.EditRender,
+  params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
+) {
+  const { props = {} } = renderOpts;
+  const { row, column } = params;
+  let cellValue = XEUtils.get(row, column.field as string);
+  if (cellValue) {
+    cellValue = XEUtils.map(cellValue, (date: any) =>
+      date.format(props.format || 'YYYY-MM-DD'),
+    ).join(' ~ ');
+  }
+  return cellValue;
+}
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getRangePickerCellValue),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getRangePickerCellValue),
+};

+ 15 - 0
src/components/VxeTable/src/components/ARate.tsx

@@ -0,0 +1,15 @@
+import {
+  createEditRender,
+  createDefaultRender,
+  createFilterRender,
+  createDefaultFilterRender,
+  createFormItemRender,
+} from './common';
+
+export default {
+  renderDefault: createDefaultRender(),
+  renderEdit: createEditRender(),
+  renderFilter: createFilterRender(),
+  defaultFilterMethod: createDefaultFilterRender(),
+  renderItemContent: createFormItemRender(),
+};

+ 271 - 0
src/components/VxeTable/src/components/ASelect.tsx

@@ -0,0 +1,271 @@
+import { ComponentOptions, h, resolveComponent } from 'vue';
+import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
+import XEUtils from 'xe-utils';
+import {
+  cellText,
+  createCellRender,
+  createEvents,
+  createProps,
+  isEmptyValue,
+  createExportMethod,
+  createFormItemRender,
+} from './common';
+
+function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) {
+  const labelProp = optionProps.label || 'label';
+  const valueProp = optionProps.value || 'value';
+  return XEUtils.map(options, (item, oIndex) => {
+    return h(
+      resolveComponent('a-select-option') as ComponentOptions,
+      {
+        key: oIndex,
+        value: item[valueProp],
+        disabled: item.disabled,
+      },
+      {
+        default: () => cellText(item[labelProp]),
+      },
+    );
+  });
+}
+
+function createEditRender() {
+  return function (
+    renderOpts: VxeColumnPropTypes.EditRender,
+    params: VxeGlobalRendererHandles.RenderEditParams,
+  ) {
+    const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
+    const { row, column, $table } = params;
+    const { attrs } = renderOpts;
+    const cellValue = XEUtils.get(row, column.field as string);
+    const props = createProps(renderOpts, cellValue);
+    const ons = createEvents(
+      renderOpts,
+      params,
+      (value: any) => {
+        // 处理 model 值双向绑定
+        XEUtils.set(row, column.field as string, value);
+      },
+      () => {
+        // 处理 change 事件相关逻辑
+        $table.updateStatus(params);
+      },
+    );
+    if (optionGroups) {
+      const groupOptions = optionGroupProps.options || 'options';
+      const groupLabel = optionGroupProps.label || 'label';
+      return [
+        h(
+          resolveComponent('a-select') as ComponentOptions,
+          {
+            ...attrs,
+            ...props,
+            ...ons,
+          },
+          {
+            default: () => {
+              return XEUtils.map(optionGroups, (group, gIndex) => {
+                return h(
+                  resolveComponent('a-select-opt-group') as ComponentOptions,
+                  {
+                    key: gIndex,
+                  },
+                  {
+                    label: () => {
+                      return h('span', {}, group[groupLabel]);
+                    },
+                    default: () => renderOptions(group[groupOptions], optionProps),
+                  },
+                );
+              });
+            },
+          },
+        ),
+      ];
+    }
+    return [
+      h(
+        resolveComponent('a-select') as ComponentOptions,
+        {
+          ...props,
+          ...attrs,
+          ...ons,
+        },
+        {
+          default: () => renderOptions(options, optionProps),
+        },
+      ),
+    ];
+  };
+}
+
+function getSelectCellValue(
+  renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
+  params: VxeGlobalRendererHandles.RenderCellParams,
+) {
+  const {
+    options = [],
+    optionGroups,
+    props = {},
+    optionProps = {},
+    optionGroupProps = {},
+  } = renderOpts;
+  const { row, column } = params;
+  const labelProp = optionProps.label || 'label';
+  const valueProp = optionProps.value || 'value';
+  const groupOptions = optionGroupProps.options || 'options';
+  const cellValue = XEUtils.get(row, column.field as string);
+  if (!isEmptyValue(cellValue)) {
+    return XEUtils.map(
+      props.mode === 'multiple' ? cellValue : [cellValue],
+      optionGroups
+        ? (value) => {
+            let selectItem;
+            for (let index = 0; index < optionGroups.length; index++) {
+              selectItem = XEUtils.find(
+                optionGroups[index][groupOptions],
+                (item) => item[valueProp] === value,
+              );
+              if (selectItem) {
+                break;
+              }
+            }
+            return selectItem ? selectItem[labelProp] : value;
+          }
+        : (value) => {
+            const selectItem = XEUtils.find(options, (item) => item[valueProp] === value);
+            return selectItem ? selectItem[labelProp] : value;
+          },
+    ).join(', ');
+  }
+  return '';
+}
+
+function createFilterRender() {
+  return function (
+    renderOpts: VxeColumnPropTypes.FilterRender,
+    params: VxeGlobalRendererHandles.RenderFilterParams,
+  ) {
+    const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
+    const groupOptions = optionGroupProps.options || 'options';
+    const groupLabel = optionGroupProps.label || 'label';
+    const { column } = params;
+    const { attrs } = renderOpts;
+
+    return [
+      h(
+        'div',
+        {
+          class: 'vxe-table--filter-antd-wrapper',
+        },
+        optionGroups
+          ? column.filters.map((option, oIndex) => {
+              const optionValue = option.data;
+              const props = createProps(renderOpts, optionValue);
+
+              return h(
+                resolveComponent('a-select') as ComponentOptions,
+                {
+                  key: oIndex,
+                  ...attrs,
+                  ...props,
+                  ...createEvents(
+                    renderOpts,
+                    params,
+                    (value: any) => {
+                      // 处理 model 值双向绑定
+                      option.data = value;
+                    },
+                    () => {
+                      // 处理 change 事件相关逻辑
+                      const { $panel } = params;
+                      $panel.changeOption(
+                        null,
+                        props.mode === 'multiple'
+                          ? option.data && option.data.length > 0
+                          : !XEUtils.eqNull(option.data),
+                        option,
+                      );
+                    },
+                  ),
+                },
+                {
+                  default: () => {
+                    return XEUtils.map(optionGroups, (group, gIndex) => {
+                      return h(
+                        resolveComponent('a-select-opt-group') as ComponentOptions,
+                        {
+                          key: gIndex,
+                        },
+                        {
+                          label: () => {
+                            return h('span', {}, group[groupLabel]);
+                          },
+                          default: () => renderOptions(group[groupOptions], optionProps),
+                        },
+                      );
+                    });
+                  },
+                },
+              );
+            })
+          : column.filters.map((option, oIndex) => {
+              const optionValue = option.data;
+              const props = createProps(renderOpts, optionValue);
+              return h(
+                resolveComponent('a-select') as ComponentOptions,
+                {
+                  key: oIndex,
+                  ...attrs,
+                  ...props,
+                  ...createEvents(
+                    renderOpts,
+                    params,
+                    (value: any) => {
+                      // 处理 model 值双向绑定
+                      option.data = value;
+                    },
+                    () => {
+                      // 处理 change 事件相关逻辑
+                      const { $panel } = params;
+                      $panel.changeOption(
+                        null,
+                        props.mode === 'multiple'
+                          ? option.data && option.data.length > 0
+                          : !XEUtils.eqNull(option.data),
+                        option,
+                      );
+                    },
+                  ),
+                },
+                {
+                  default: () => renderOptions(options, optionProps),
+                },
+              );
+            }),
+      ),
+    ];
+  };
+}
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getSelectCellValue),
+  renderFilter: createFilterRender(),
+  defaultFilterMethod(params) {
+    const { option, row, column } = params;
+    const { data } = option;
+    const { field, filterRender: renderOpts } = column;
+    const { props = {} } = renderOpts;
+    const cellValue = XEUtils.get(row, field);
+    if (props.mode === 'multiple') {
+      if (XEUtils.isArray(cellValue)) {
+        return XEUtils.includeArrays(cellValue, data);
+      }
+      return data.indexOf(cellValue) > -1;
+    }
+    return cellValue == data;
+  },
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getSelectCellValue),
+};

+ 53 - 0
src/components/VxeTable/src/components/ASwitch.tsx

@@ -0,0 +1,53 @@
+import { h } from 'vue';
+import XEUtils from 'xe-utils';
+import {
+  createEditRender,
+  createDefaultRender,
+  createProps,
+  createEvents,
+  createDefaultFilterRender,
+  createFormItemRender,
+  getComponent,
+} from './common';
+
+export default {
+  renderDefault: createDefaultRender(),
+  renderEdit: createEditRender(),
+  renderFilter(renderOpts, params) {
+    const { column } = params;
+    const { name, attrs } = renderOpts;
+    const Component = getComponent(name);
+
+    return [
+      h(
+        'div',
+        {
+          class: 'vxe-table--filter-antd-wrapper',
+        },
+        column.filters.map((option, oIndex) => {
+          const optionValue = option.data;
+          return h(Component, {
+            key: oIndex,
+            ...attrs,
+            ...createProps(renderOpts, optionValue),
+            ...createEvents(
+              renderOpts,
+              params,
+              (value: any) => {
+                // 处理 model 值双向绑定
+                option.data = value;
+              },
+              () => {
+                // 处理 change 事件相关逻辑
+                const { $panel } = params;
+                $panel.changeOption(null, XEUtils.isBoolean(option.data), option);
+              },
+            ),
+          });
+        }),
+      ),
+    ];
+  },
+  defaultFilterMethod: createDefaultFilterRender(),
+  renderItemContent: createFormItemRender(),
+};

+ 18 - 0
src/components/VxeTable/src/components/ATimePicker.tsx

@@ -0,0 +1,18 @@
+import { getDatePickerCellValue } from './ADatePicker';
+import {
+  createEditRender,
+  createCellRender,
+  createFormItemRender,
+  createExportMethod,
+} from './common';
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getDatePickerCellValue, () => {
+    return ['HH:mm:ss'];
+  }),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getDatePickerCellValue, () => {
+    return ['HH:mm:ss'];
+  }),
+};

+ 35 - 0
src/components/VxeTable/src/components/ATreeSelect.tsx

@@ -0,0 +1,35 @@
+import { VxeGlobalRendererHandles } from 'vxe-table';
+import XEUtils from 'xe-utils';
+import {
+  createEditRender,
+  createCellRender,
+  isEmptyValue,
+  createFormItemRender,
+  createExportMethod,
+} from './common';
+
+function getTreeSelectCellValue(
+  renderOpts: VxeGlobalRendererHandles.RenderOptions,
+  params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
+) {
+  const { props = {} } = renderOpts;
+  const { treeData, treeCheckable } = props;
+  const { row, column } = params;
+  const cellValue = XEUtils.get(row, column.field as string);
+  if (!isEmptyValue(cellValue)) {
+    return XEUtils.map(treeCheckable ? cellValue : [cellValue], (value) => {
+      const matchObj = XEUtils.findTree(treeData, (item: any) => item.value === value, {
+        children: 'children',
+      });
+      return matchObj ? matchObj.item.title : value;
+    }).join(', ');
+  }
+  return cellValue;
+}
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getTreeSelectCellValue),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getTreeSelectCellValue),
+};

+ 18 - 0
src/components/VxeTable/src/components/AWeekPicker.tsx

@@ -0,0 +1,18 @@
+import { getDatePickerCellValue } from './ADatePicker';
+import {
+  createEditRender,
+  createCellRender,
+  createFormItemRender,
+  createExportMethod,
+} from './common';
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getDatePickerCellValue, () => {
+    return ['YYYY-WW周'];
+  }),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getDatePickerCellValue, () => {
+    return ['YYYY-WW周'];
+  }),
+};

+ 18 - 0
src/components/VxeTable/src/components/AYearPicker.tsx

@@ -0,0 +1,18 @@
+import { getDatePickerCellValue } from './ADatePicker';
+import {
+  createEditRender,
+  createCellRender,
+  createFormItemRender,
+  createExportMethod,
+} from './common';
+
+export default {
+  renderEdit: createEditRender(),
+  renderCell: createCellRender(getDatePickerCellValue, () => {
+    return ['YYYY'];
+  }),
+  renderItemContent: createFormItemRender(),
+  exportMethod: createExportMethod(getDatePickerCellValue, () => {
+    return ['YYYY'];
+  }),
+};

+ 427 - 0
src/components/VxeTable/src/components/common.tsx

@@ -0,0 +1,427 @@
+import { ComponentOptions, h } from 'vue';
+import {
+  FormItemContentRenderParams,
+  FormItemRenderOptions,
+  VxeGlobalRendererHandles,
+} from 'vxe-table';
+import XEUtils from 'xe-utils';
+import { componentMap } from '../componentMap';
+import { ComponentType } from '../componentType';
+import { createPlaceholderMessage } from '../helper';
+
+/**
+ * @description: 获取组件
+ */
+export function getComponent(componentName) {
+  const Component = componentMap.get(componentName as ComponentType);
+  if (!Component) throw `您还没注册此组件 ${componentName}`;
+  return Component as ComponentOptions;
+}
+
+export function isEmptyValue(cellValue: any) {
+  return cellValue === null || cellValue === undefined || cellValue === '';
+}
+
+export function formatText(cellValue: any) {
+  return '' + (isEmptyValue(cellValue) ? '' : cellValue);
+}
+
+export function cellText(cellValue: any): string[] {
+  return [formatText(cellValue)];
+}
+
+/**
+ * @description: 方法名转换
+ */
+export function getOnName(type: string) {
+  return 'on' + type.substring(0, 1).toLocaleUpperCase() + type.substring(1);
+}
+
+/**
+ * @description: 获取组件传值所接受的属性
+ */
+function getModelKey(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
+  let prop = 'value';
+  switch (renderOpts.name) {
+    case 'ASwitch':
+      prop = 'checked';
+      break;
+  }
+  return prop;
+}
+
+/**
+ * @description: 回去双向更新的方法
+ */
+function getModelEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
+  let type = 'update:value';
+  switch (renderOpts.name) {
+    case 'ASwitch':
+      type = 'update:checked';
+      break;
+  }
+  return type;
+}
+
+/**
+ * @description: chang值改变方法
+ * @param {}
+ * @return {*}
+ * @author: *
+ */
+function getChangeEvent() {
+  return 'change';
+}
+
+function getClickEvent() {
+  return 'click';
+}
+/**
+ * @description: 获取方法
+ * @param {}
+ * @return {*}
+ * @author: *
+ */
+export function createEvents(
+  renderOpts: VxeGlobalRendererHandles.RenderOptions,
+  params: VxeGlobalRendererHandles.RenderParams,
+  inputFunc?: Function,
+  changeFunc?: Function,
+  clickFunc?: Function,
+) {
+  const { events } = renderOpts;
+  const modelEvent = getModelEvent(renderOpts);
+  const changeEvent = getChangeEvent();
+  const clickEvent = getClickEvent();
+  const isSameEvent = changeEvent === modelEvent;
+  const ons: { [type: string]: Function } = {};
+
+  XEUtils.objectEach(events, (func: Function, key: string) => {
+    ons[getOnName(key)] = function (...args: any[]) {
+      func(params, ...args);
+    };
+  });
+  if (inputFunc) {
+    ons[getOnName(modelEvent)] = function (targetEvnt: any) {
+      inputFunc(targetEvnt);
+      if (events && events[modelEvent]) {
+        events[modelEvent](params, targetEvnt);
+      }
+      if (isSameEvent && changeFunc) {
+        changeFunc(targetEvnt);
+      }
+    };
+  }
+  if (!isSameEvent && changeFunc) {
+    ons[getOnName(changeEvent)] = function (...args: any[]) {
+      changeFunc(...args);
+      if (events && events[changeEvent]) {
+        events[changeEvent](params, ...args);
+      }
+    };
+  }
+  if (clickFunc) {
+    ons[getOnName(clickEvent)] = function (...args: any[]) {
+      clickFunc(...args);
+      if (events && events[clickEvent]) {
+        events[clickEvent](params, ...args);
+      }
+    };
+  }
+  return ons;
+}
+
+/**
+ * @description: 获取属性
+ */
+export function createProps(
+  renderOpts: VxeGlobalRendererHandles.RenderOptions,
+  value: any,
+  defaultProps?: { [prop: string]: any },
+) {
+  const name = renderOpts.name as ComponentType;
+  return XEUtils.assign(
+    {
+      placeholder: createPlaceholderMessage(name),
+      allowClear: true,
+    },
+    defaultProps,
+    renderOpts.props,
+    {
+      [getModelKey(renderOpts)]: value,
+    },
+  );
+}
+
+/**
+ * @description: 创建单元格默认显示内容
+ */
+export function createDefaultRender(
+  defaultProps?: { [key: string]: any },
+  callBack?: (
+    renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
+    params: VxeGlobalRendererHandles.RenderDefaultParams,
+  ) => Record<string, any>,
+) {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
+    params: VxeGlobalRendererHandles.RenderDefaultParams,
+  ) {
+    const { row, column, $table } = params;
+    const { name, attrs } = renderOpts;
+    const cellValue = XEUtils.get(row, column.field as string);
+    const args = (callBack && callBack(renderOpts, params)) ?? {};
+
+    const Component = getComponent(name);
+    return [
+      h(Component, {
+        ...attrs,
+        ...createProps(renderOpts, cellValue, defaultProps),
+        ...args,
+        ...createEvents(
+          renderOpts,
+          params,
+          (value: any) => XEUtils.set(row, column.field as string, value),
+          () => $table.updateStatus(params),
+        ),
+      }),
+    ];
+  };
+}
+
+/**
+ * @description: 创建编辑单元格
+ */
+export function createEditRender(
+  defaultProps?: { [key: string]: any },
+  callBack?: (
+    renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
+    params: VxeGlobalRendererHandles.RenderEditParams,
+  ) => Record<string, any>,
+) {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
+    params: VxeGlobalRendererHandles.RenderEditParams,
+  ) {
+    const { row, column, $table } = params;
+    const { name, attrs } = renderOpts;
+    const cellValue = XEUtils.get(row, column.field as string);
+    const args = (callBack && callBack(renderOpts, params)) ?? {};
+
+    const Component = getComponent(name);
+    return [
+      h(Component, {
+        ...attrs,
+        ...createProps(renderOpts, cellValue, defaultProps),
+        ...args,
+        ...createEvents(
+          renderOpts,
+          params,
+          (value: any) => XEUtils.set(row, column.field as string, value),
+          () => $table.updateStatus(params),
+        ),
+      }),
+    ];
+  };
+}
+
+/**
+ * @description: 创建筛选渲染内容
+ */
+export function createFilterRender(
+  defaultProps?: { [key: string]: any },
+  callBack?: (
+    renderOpts: VxeGlobalRendererHandles.RenderFilterOptions,
+    params: VxeGlobalRendererHandles.RenderFilterParams,
+  ) => Record<string, any>,
+) {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderFilterOptions,
+    params: VxeGlobalRendererHandles.RenderFilterParams,
+  ) {
+    const { column } = params;
+    const { name, attrs } = renderOpts;
+    const args = (callBack && callBack(renderOpts, params)) ?? {};
+
+    const Component = getComponent(name);
+    return [
+      h(
+        'div',
+        {
+          class: 'vxe-table--filter-antd-wrapper',
+        },
+        column.filters.map((option, oIndex) => {
+          const optionValue = option.data;
+          const checked = !!option.data;
+
+          return h(Component, {
+            key: oIndex,
+            ...attrs,
+            ...createProps(renderOpts, optionValue, defaultProps),
+            ...args,
+            ...createEvents(
+              renderOpts,
+              params,
+              (value: any) => {
+                // 处理 model 值双向绑定
+                option.data = value;
+              },
+              () => {
+                // 处理 change 事件相关逻辑
+                const { $panel } = params;
+                $panel.changeOption(null, checked, option);
+              },
+            ),
+          });
+        }),
+      ),
+    ];
+  };
+}
+
+/**
+ * @description: 默认过滤
+ * @param {}
+ * @return {*}
+ * @author: *
+ */
+
+export function createDefaultFilterRender() {
+  return function (params: VxeGlobalRendererHandles.FilterMethodParams) {
+    const { option, row, column } = params;
+    const { data } = option;
+    const cellValue = XEUtils.get(row, column.field as string);
+    return cellValue === data;
+  };
+}
+
+/**
+ * @description: 创建 form表单渲染
+ */
+export function createFormItemRender(
+  defaultProps?: { [key: string]: any },
+  callBack?: (
+    renderOpts: FormItemRenderOptions,
+    params: FormItemContentRenderParams,
+  ) => Record<string, any>,
+) {
+  return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+    const args = (callBack && callBack(renderOpts, params)) ?? {};
+    const { data, property, $form } = params;
+    const { name } = renderOpts;
+    const { attrs } = renderOpts;
+    const itemValue = XEUtils.get(data, property);
+
+    const Component = getComponent(name);
+    return [
+      h(Component, {
+        ...attrs,
+        ...createProps(renderOpts, itemValue, defaultProps),
+        ...args,
+        ...createEvents(
+          renderOpts,
+          params,
+          (value: any) => {
+            // 处理 model 值双向绑定
+            XEUtils.set(data, property, value);
+          },
+          () => {
+            // 处理 change 事件相关逻辑
+            $form.updateStatus({
+              ...params,
+              field: property,
+            });
+          },
+        ),
+      }),
+    ];
+  };
+}
+
+/**
+ * @description: cell渲染
+ */
+export function createCellRender(
+  getSelectCellValue: Function,
+  callBack?: (
+    renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
+    params: VxeGlobalRendererHandles.RenderCellParams,
+  ) => Array<any>,
+) {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
+    params: VxeGlobalRendererHandles.RenderCellParams,
+  ) {
+    const args = (callBack && callBack(renderOpts, params)) ?? [];
+    const cellLabel = getSelectCellValue && getSelectCellValue(renderOpts, params, ...args);
+    const { placeholder } = renderOpts;
+
+    return [
+      h(
+        'span',
+        {
+          class: 'vxe-cell--label',
+        },
+        placeholder && isEmptyValue(cellLabel)
+          ? [
+              h(
+                'span',
+                {
+                  class: 'vxe-cell--placeholder',
+                },
+                formatText(placeholder),
+              ),
+            ]
+          : formatText(cellLabel),
+      ),
+    ];
+  };
+}
+
+/**
+ * @description: 创建 导出渲染
+ * @param {}
+ * @return {*}
+ * @author: *
+ */
+export function createExportMethod(
+  getExportCellValue: Function,
+  callBack?: (params: VxeGlobalRendererHandles.ExportMethodParams) => Array<any>,
+) {
+  return function (params: VxeGlobalRendererHandles.ExportMethodParams) {
+    const { row, column, options } = params;
+    const args = (callBack && callBack(params)) ?? [];
+    return options && options.original
+      ? XEUtils.get(row, column.field as string)
+      : getExportCellValue(column.editRender || column.cellRender, params, ...args);
+  };
+}
+
+/**
+ * @description: 创建单元格默认显示内容
+ */
+export function createToolbarToolRender(
+  defaultProps?: { [key: string]: any },
+  callBack?: (
+    renderOpts: VxeGlobalRendererHandles.RenderToolOptions,
+    params: VxeGlobalRendererHandles.RenderToolParams,
+  ) => Record<string, any>,
+) {
+  return function (
+    renderOpts: VxeGlobalRendererHandles.RenderToolOptions,
+    params: VxeGlobalRendererHandles.RenderToolParams,
+  ) {
+    const { name, attrs } = renderOpts;
+    const args = (callBack && callBack(renderOpts, params)) ?? {};
+
+    const Component = getComponent(name);
+    return [
+      h(Component, {
+        ...attrs,
+        ...createProps(renderOpts, null, defaultProps),
+        ...args,
+        ...createEvents(renderOpts, params),
+      }),
+    ];
+  };
+}

+ 112 - 0
src/components/VxeTable/src/components/index.tsx

@@ -0,0 +1,112 @@
+import { VXETableCore, VxeGlobalInterceptorHandles } from 'vxe-table';
+import AAutoComplete from './AAutoComplete';
+import AInput from './AInput';
+import AInputNumber from './AInputNumber';
+import ASelect from './ASelect';
+import ACascader from './ACascader';
+import ADatePicker from './ADatePicker';
+import AMonthPicker from './AMonthPicker';
+import ARangePicker from './ARangePicker';
+import AWeekPicker from './AWeekPicker';
+import ATreeSelect from './ATreeSelect';
+import ATimePicker from './ATimePicker';
+import ARate from './ARate';
+import ASwitch from './ASwitch';
+import ARadioGroup from './ARadioGroup';
+import ACheckboxGroup from './ACheckboxGroup';
+import AButton from './AButton';
+import AButtonGroup from './AButtonGroup';
+import AApiSelect from './AApiSelect';
+import AEmpty from './AEmpty';
+import AInputSearch from './AInputSearch';
+import AYearPicker from './AYearPicker';
+
+/**
+ * 检查触发源是否属于目标节点
+ */
+function getEventTargetNode(evnt: any, container: HTMLElement, className: string) {
+  let targetElem;
+  let target = evnt.target;
+  while (target && target.nodeType && target !== document) {
+    if (
+      className &&
+      target.className &&
+      target.className.split &&
+      target.className.split(' ').indexOf(className) > -1
+    ) {
+      targetElem = target;
+    } else if (target === container) {
+      return { flag: className ? !!targetElem : true, container, targetElem: targetElem };
+    }
+    target = target.parentNode;
+  }
+  return { flag: false };
+}
+
+/**
+ * 事件兼容性处理
+ */
+function handleClearEvent(
+  params:
+    | VxeGlobalInterceptorHandles.InterceptorClearFilterParams
+    | VxeGlobalInterceptorHandles.InterceptorClearActivedParams
+    | VxeGlobalInterceptorHandles.InterceptorClearAreasParams,
+) {
+  const { $event } = params;
+  const bodyElem = document.body;
+  if (
+    // 下拉框
+    getEventTargetNode($event, bodyElem, 'ant-select-dropdown').flag ||
+    // 级联
+    getEventTargetNode($event, bodyElem, 'ant-cascader-menus').flag ||
+    // 日期
+    getEventTargetNode($event, bodyElem, 'ant-calendar-picker-container').flag ||
+    // 时间选择
+    getEventTargetNode($event, bodyElem, 'ant-time-picker-panel').flag
+  ) {
+    return false;
+  }
+}
+
+/**
+ * 基于 vxe-table 表格的适配插件,用于兼容 ant-design-vue 组件库
+ */
+export const VXETablePluginAntd = {
+  install(vxetablecore: VXETableCore) {
+    const { interceptor, renderer } = vxetablecore;
+
+    renderer.mixin({
+      AAutoComplete,
+      AInput,
+      AInputNumber,
+      ASelect,
+      ACascader,
+      ADatePicker,
+      AMonthPicker,
+      ARangePicker,
+      AWeekPicker,
+      ATimePicker,
+      ATreeSelect,
+      ARate,
+      ASwitch,
+      ARadioGroup,
+      ACheckboxGroup,
+      AButton,
+      AButtonGroup,
+      AApiSelect,
+      AEmpty,
+      AInputSearch,
+      AYearPicker,
+    });
+
+    interceptor.add('event.clearFilter', handleClearEvent);
+    interceptor.add('event.clearActived', handleClearEvent);
+    interceptor.add('event.clearAreas', handleClearEvent);
+  },
+};
+
+if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) {
+  window.VXETable.use(VXETablePluginAntd);
+}
+
+export default VXETablePluginAntd;

+ 4 - 0
src/components/VxeTable/src/const.ts

@@ -0,0 +1,4 @@
+/**
+ * @description: 传给vxe-table 时需要忽略的prop
+ */
+export const ignorePropKeys = ['tableClass', 'tableStyle'];

+ 8 - 0
src/components/VxeTable/src/css/common.scss

@@ -0,0 +1,8 @@
+*,
+::before,
+::after {
+  box-sizing: border-box;
+  border-width: 0;
+  border-style: solid;
+  border-color: initial;
+}

+ 105 - 0
src/components/VxeTable/src/css/component.scss

@@ -0,0 +1,105 @@
+%ResetBorder {
+  border: 0;
+  box-shadow: none;
+}
+
+%CompWidth {
+  & > .ant-input,
+  & > .ant-input-number,
+  & > .ant-select,
+  & > .ant-cascader-picker,
+  & > .ant-calendar-picker,
+  & > .ant-time-picker {
+    width: 100%;
+  }
+}
+.vxe-form {
+  .vxe-form--item-content {
+    @extend %CompWidth;
+  }
+}
+.vxe-table--filter-antd-wrapper {
+  & > .ant-input,
+  & > .ant-input-number,
+  & > .ant-select,
+  & > .ant-rate {
+    width: 180px;
+  }
+}
+.vxe-cell,
+.vxe-tree-cell {
+  @extend %CompWidth;
+  & > .ant-rate {
+    vertical-align: bottom;
+    .anticon-star {
+      display: block;
+    }
+  }
+}
+.col--valid-error {
+  & > .vxe-cell,
+  & > .vxe-tree-cell {
+    & > .ant-input,
+    & > .ant-select .ant-input,
+    & > .ant-select .ant-select-selection,
+    & > .ant-input-number,
+    & > .ant-cascader-picker .ant-cascader-input,
+    & > .ant-calendar-picker .ant-calendar-picker-input {
+      // border-color: $vxe-table-validate-error-color;
+      box-shadow: none;
+    }
+  }
+}
+.vxe-table.cell--highlight {
+  .vxe-cell,
+  .vxe-tree-cell {
+    & > .ant-input,
+    & > .ant-input-number {
+      padding: 0;
+      @extend %ResetBorder;
+    }
+    & > .ant-select {
+      .ant-input {
+        padding: 0;
+        @extend %ResetBorder;
+      }
+    }
+    & > .ant-input-number {
+      .ant-input-number-input {
+        padding: 0;
+      }
+      .ant-input-number-handler-wrap,
+      .ant-input-number-handler-down {
+        @extend %ResetBorder;
+      }
+    }
+    & > .ant-select {
+      .ant-select-selection {
+        @extend %ResetBorder;
+        .ant-select-selection__rendered {
+          margin: 0;
+        }
+      }
+    }
+    & > .ant-cascader-picker {
+      .ant-input {
+        @extend %ResetBorder;
+      }
+      .ant-cascader-picker-label {
+        padding: 0;
+      }
+    }
+    & > .ant-calendar-picker {
+      .ant-calendar-picker-input {
+        padding: 0;
+        @extend %ResetBorder;
+      }
+    }
+    & > .ant-time-picker {
+      .ant-time-picker-input {
+        padding: 0;
+        @extend %ResetBorder;
+      }
+    }
+  }
+}

+ 6 - 0
src/components/VxeTable/src/css/index.scss

@@ -0,0 +1,6 @@
+@import './common.scss';
+@import './variable.scss';
+@import './scrollbar.scss';
+@import './toolbar.scss';
+@import './component.scss';
+@import 'vxe-table/styles/index.scss';

+ 24 - 0
src/components/VxeTable/src/css/scrollbar.scss

@@ -0,0 +1,24 @@
+.vxe-grid_scrollbar {
+  ::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+  }
+  ::-webkit-scrollbar-track {
+    background-color: #ffffff;
+  }
+  ::-webkit-scrollbar-thumb {
+    background-color: rgba(0, 0, 0, 0.1);
+    border-radius: 5px;
+    border: 1px solid #f1f1f1;
+    box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
+  }
+  ::-webkit-scrollbar-thumb:hover {
+    background-color: #a8a8a8;
+  }
+  ::-webkit-scrollbar-thumb:active {
+    background-color: #a8a8a8;
+  }
+  ::-webkit-scrollbar-corner {
+    background-color: #ffffff;
+  }
+}

+ 30 - 0
src/components/VxeTable/src/css/toolbar.scss

@@ -0,0 +1,30 @@
+.vxe-toolbar .vxe-custom--option-wrapper .vxe-custom--footer {
+  display: flex;
+}
+
+.vxe-toolbar .vxe-tools--wrapper,
+.vxe-toolbar .vxe-tools--operate button:first-child {
+  margin: 0;
+}
+
+.vxe-toolbar .vxe-tools--wrapper,
+.vxe-toolbar .vxe-tools--operate .vxe-button {
+  margin-left: 1px;
+  border-radius: 0 !important;
+}
+
+.vxe-toolbar .vxe-tools--wrapper,
+.vxe-toolbar .vxe-tools--operate button:first-child {
+  margin-left: 10px;
+}
+
+.vxe-toolbar .vxe-tools--wrapper,
+.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper {
+  margin-left: 1px;
+  border-radius: 0 !important;
+}
+
+.vxe-toolbar .vxe-tools--wrapper,
+.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper .vxe-button {
+  margin-left: 1px;
+}

+ 6 - 0
src/components/VxeTable/src/css/variable.scss

@@ -0,0 +1,6 @@
+$vxe-primary-color: rgb(9, 96, 189) !default;
+$vxe-table-row-current-background-color: rgba(9, 96, 189, 0.3);
+$vxe-table-row-hover-current-background-color: rgba(9, 96, 189, 0.2);
+$vxe-table-column-hover-background-color: rgba(9, 96, 189, 0.3);
+$vxe-table-column-current-background-color: rgba(9, 96, 189, 0.2);
+$vxe-table-validate-error-color: #f56c6c;

+ 17 - 0
src/components/VxeTable/src/emits.ts

@@ -0,0 +1,17 @@
+import tableEmits from 'vxe-table/es/table/src/emits';
+
+export const basicEmits = [
+  ...tableEmits,
+  'page-change',
+  'form-submit',
+  'form-submit-invalid',
+  'form-reset',
+  'form-collapse',
+  'form-toggle-collapse',
+  'toolbar-button-click',
+  'toolbar-tool-click',
+  'zoom',
+
+  //... 如有缺少在此处追加
+  // xxx
+];

+ 19 - 0
src/components/VxeTable/src/helper.ts

@@ -0,0 +1,19 @@
+import { ComponentType } from './componentType';
+import { useI18n } from '/@/hooks/web/useI18n';
+
+const { t } = useI18n();
+
+/**
+ * @description: 生成placeholder
+ */
+export function createPlaceholderMessage(component: ComponentType) {
+  if (!component) return;
+  if (component.includes('RangePicker')) {
+    return [t('common.chooseText'), t('common.chooseText')];
+  }
+  if (component.includes('Input') || component.includes('Complete') || component.includes('Rate')) {
+    return t('common.inputText');
+  } else {
+    return t('common.chooseText');
+  }
+}

+ 131 - 0
src/components/VxeTable/src/methods.ts

@@ -0,0 +1,131 @@
+import { GridMethods, TableMethods } from 'vxe-table';
+
+export const gridComponentMethodKeys: (keyof GridMethods | keyof TableMethods)[] = [
+  // vxe-grid 部分
+  'dispatchEvent',
+  'commitProxy',
+  'getFormItems',
+  'getPendingRecords',
+  'zoom',
+  'isMaximized',
+  'maximize',
+  'revert',
+  'getProxyInfo',
+
+  // vxe-table和vxe-grid公共部分
+  'clearAll',
+  'syncData',
+  'updateData',
+  'loadData',
+  'reloadData',
+  'reloadRow',
+  'loadColumn',
+  'reloadColumn',
+  'getRowNode',
+  'getColumnNode',
+  'getRowIndex',
+  'getVTRowIndex',
+  'getVMRowIndex',
+  'getColumnIndex',
+  'getVTColumnIndex',
+  'getVMColumnIndex',
+  'createData',
+  'createRow',
+  'revertData',
+  'clearData',
+  'isInsertByRow',
+  'isUpdateByRow',
+  'getColumns',
+  'getColumnById',
+  'getColumnByField',
+  'getTableColumn',
+  'getData',
+  'getCheckboxRecords',
+  'getParentRow',
+  'getRowSeq',
+  'getRowById',
+  'getRowid',
+  'getTableData',
+  'hideColumn',
+  'showColumn',
+  'resetColumn',
+  'refreshColumn',
+  'refreshScroll',
+  'recalculate',
+  'closeTooltip',
+  'isAllCheckboxChecked',
+  'isAllCheckboxIndeterminate',
+  'getCheckboxIndeterminateRecords',
+  'setCheckboxRow',
+  'isCheckedByCheckboxRow',
+  'isIndeterminateByCheckboxRow',
+  'toggleCheckboxRow',
+  'setAllCheckboxRow',
+  'getRadioReserveRecord',
+  'clearRadioReserve',
+  'getCheckboxReserveRecords',
+  'clearCheckboxReserve',
+  'toggleAllCheckboxRow',
+  'clearCheckboxRow',
+  'setCurrentRow',
+  'isCheckedByRadioRow',
+  'setRadioRow',
+  'clearCurrentRow',
+  'clearRadioRow',
+  'getCurrentRecord',
+  'getRadioRecord',
+  'getCurrentColumn',
+  'setCurrentColumn',
+  'clearCurrentColumn',
+  'sort',
+  'clearSort',
+  'isSort',
+  'getSortColumns',
+  'closeFilter',
+  'isFilter',
+  'isRowExpandLoaded',
+  'clearRowExpandLoaded',
+  'reloadRowExpand',
+  'reloadRowExpand',
+  'toggleRowExpand',
+  'setAllRowExpand',
+  'setRowExpand',
+  'isExpandByRow',
+  'clearRowExpand',
+  'clearRowExpandReserve',
+  'getRowExpandRecords',
+  'getTreeExpandRecords',
+  'isTreeExpandLoaded',
+  'clearTreeExpandLoaded',
+  'reloadTreeExpand',
+  'reloadTreeChilds',
+  'toggleTreeExpand',
+  'setAllTreeExpand',
+  'setTreeExpand',
+  'isTreeExpandByRow',
+  'clearTreeExpand',
+  'clearTreeExpandReserve',
+  'getScroll',
+  'scrollTo',
+  'scrollToRow',
+  'scrollToColumn',
+  'clearScroll',
+  'updateFooter',
+  'updateStatus',
+  'setMergeCells',
+  'removeInsertRow',
+  'removeMergeCells',
+  'getMergeCells',
+  'clearMergeCells',
+  'setMergeFooterItems',
+  'removeMergeFooterItems',
+  'getMergeFooterItems',
+  'clearMergeFooterItems',
+  'openTooltip',
+  'focus',
+  'blur',
+  'connect',
+
+  //... 如有缺少在此处追加
+  // xxx
+];

+ 52 - 0
src/components/VxeTable/src/props.ts

@@ -0,0 +1,52 @@
+import { VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table';
+import tableProps from 'vxe-table/es/table/src/props';
+import { CSSProperties } from 'vue';
+
+/**
+ * @description: table二次开发需要后,需要接受的所有prop属性
+ */
+export const basicProps = {
+  ...tableProps,
+  columns: Array as PropType<VxeGridPropTypes.Columns>,
+  pagerConfig: {
+    type: Object as PropType<VxeGridPropTypes.PagerConfig>,
+    default: () => ({}),
+  },
+  proxyConfig: {
+    type: Object as PropType<VxeGridPropTypes.ProxyConfig>,
+    default: () => ({}),
+  },
+  toolbarConfig: {
+    type: Object as PropType<VxeGridPropTypes.ToolbarConfig>,
+    default: () => ({}),
+  },
+  formConfig: {
+    type: Object as PropType<VxeGridPropTypes.FormConfig>,
+    default: () => ({}),
+  },
+  zoomConfig: {
+    type: Object as PropType<VxeGridPropTypes.ZoomConfig>,
+    default: () => ({}),
+  },
+  printConfig: {
+    type: Object as PropType<VxeTablePropTypes.PrintConfig>,
+    default: () => ({}),
+  },
+  exportConfig: {
+    type: Object as PropType<VxeTablePropTypes.ExportConfig>,
+    default: () => ({}),
+  },
+  importConfig: {
+    type: Object as PropType<VxeTablePropTypes.ImportConfig>,
+    default: () => ({}),
+  },
+  size: String as PropType<VxeGridPropTypes.Size>,
+  tableClass: {
+    type: String,
+    default: '',
+  },
+  tableStyle: {
+    type: Object as PropType<CSSProperties>,
+    default: () => ({}),
+  },
+};

+ 4 - 0
src/components/VxeTable/src/setting.ts

@@ -0,0 +1,4 @@
+import { VXETable } from '..';
+import componentSetting from '/@/settings/componentSetting';
+
+VXETable.setup(componentSetting.vxeTable);

+ 7 - 0
src/components/VxeTable/src/types.ts

@@ -0,0 +1,7 @@
+import { CSSProperties } from 'vue';
+import { VxeGridProps } from 'vxe-table';
+
+export type BasicTableProps = VxeGridProps & {
+  tableClass?: string;
+  tableStyle?: CSSProperties;
+};

+ 2 - 1
src/components/registerGlobComp.ts

@@ -1,7 +1,8 @@
 import type { App } from 'vue';
 import { Button } from './Button';
 import { Input, Layout } from 'ant-design-vue';
+import VXETable from 'vxe-table';
 
 export function registerGlobComp(app: App) {
-  app.use(Input).use(Button).use(Layout);
+  app.use(Input).use(Button).use(Layout).use(VXETable);
 }

+ 1 - 0
src/locales/lang/en/routes/demo.ts

@@ -198,5 +198,6 @@ export default {
     editRowTable: 'Editable row',
     authColumn: 'Auth column',
     resizeParentHeightTable: 'resizeParentHeightTable',
+    vxeTable: 'VxeTable',
   },
 };

+ 1 - 0
src/locales/lang/zh-CN/routes/demo.ts

@@ -189,5 +189,6 @@ export default {
     editRowTable: '可编辑行',
     authColumn: '权限列',
     resizeParentHeightTable: '继承父元素高度',
+    vxeTable: 'VxeTable',
   },
 };

+ 1 - 0
src/main.ts

@@ -1,6 +1,7 @@
 import 'virtual:windi-base.css';
 import 'virtual:windi-components.css';
 import '/@/design/index.less';
+import '/@/components/VxeTable/src/css/index.scss';
 import 'virtual:windi-utilities.css';
 // Register icon sprite
 import 'virtual:svg-icons-register';

+ 8 - 0
src/router/routes/modules/demo/comp.ts

@@ -255,6 +255,14 @@ const comp: AppRouteModule = {
             title: t('routes.demo.table.resizeParentHeightTable'),
           },
         },
+        {
+          path: 'vxeTable',
+          name: 'VxeTableDemo',
+          component: () => import('/@/views/demo/table/VxeTable.vue'),
+          meta: {
+            title: t('routes.demo.table.vxeTable'),
+          },
+        },
       ],
     },
     {

+ 46 - 0
src/settings/componentSetting.ts

@@ -42,6 +42,52 @@ export default {
       return data;
     },
   },
+  vxeTable: {
+    table: {
+      border: true,
+      stripe: true,
+      columnConfig: {
+        resizable: true,
+        isCurrent: true,
+        isHover: true,
+      },
+      rowConfig: {
+        isCurrent: true,
+        isHover: true,
+      },
+      emptyRender: {
+        name: 'AEmpty',
+      },
+      printConfig: {},
+      exportConfig: {},
+      customConfig: {
+        storage: true,
+      },
+    },
+    grid: {
+      toolbarConfig: {
+        enabled: true,
+        export: true,
+        zoom: true,
+        print: true,
+        refresh: true,
+        custom: true,
+      },
+      pagerConfig: {
+        pageSizes: [20, 50, 100, 500],
+        pageSize: 20,
+        autoHidden: true,
+      },
+      proxyConfig: {
+        form: true,
+        props: {
+          result: 'items',
+          total: 'total',
+        },
+      },
+      zoomConfig: {},
+    },
+  },
   // scrollbar setting
   scrollbar: {
     // Whether to use native scroll bar

+ 97 - 0
src/views/demo/table/VxeTable.vue

@@ -0,0 +1,97 @@
+<template>
+  <PageWrapper
+    title="VxeTable表格"
+    content="只展示部分操作,详细功能请查看VxeTable官网事例"
+    contentFullHeight
+    fixedHeight
+  >
+    <VxeBasicTable ref="tableRef" v-bind="gridOptions">
+      <template #action="{ row }">
+        <TableAction :actions="createActions(row)" />
+      </template>
+    </VxeBasicTable>
+  </PageWrapper>
+</template>
+<script lang="ts" setup>
+  import { reactive, ref } from 'vue';
+  import { TableAction, ActionItem } from '/@/components/Table';
+  import { PageWrapper } from '/@/components/Page';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { vxeTableColumns, vxeTableFormSchema } from './tableData';
+  import { VxeBasicTable, BasicTableProps, VxeGridInstance } from '/@/components/VxeTable';
+  import { demoListApi } from '/@/api/demo/table';
+
+  const { createMessage } = useMessage();
+
+  const tableRef = ref<VxeGridInstance>();
+
+  const gridOptions = reactive<BasicTableProps>({
+    id: 'VxeTable',
+    editConfig: { trigger: 'click', mode: 'cell', showStatus: true },
+    columns: vxeTableColumns,
+    toolbarConfig: {
+      buttons: [
+        {
+          content: '自定义按钮',
+          buttonRender: {
+            name: 'AButton',
+            props: {
+              type: 'primary',
+            },
+            events: {
+              click: () => {
+                createMessage.success('点击了自定义按钮');
+              },
+            },
+          },
+        },
+      ],
+    },
+    formConfig: {
+      enabled: true,
+      items: vxeTableFormSchema,
+    },
+    height: 'auto',
+    proxyConfig: {
+      ajax: {
+        query: async ({ page, form }) => {
+          return demoListApi({
+            pageNum: page.currentPage,
+            pageSize: page.pageSize,
+            ...form,
+          });
+        },
+        queryAll: async ({ form }) => {
+          const data = await demoListApi(form);
+          return data;
+        },
+      },
+    },
+  });
+
+  // 操作按钮(权限控制)
+  const createActions = (record) => {
+    const actions: ActionItem[] = [
+      {
+        label: '详情',
+        onClick: () => {
+          console.log(record);
+        },
+      },
+      {
+        label: '编辑',
+        onClick: () => {},
+      },
+      {
+        label: '删除',
+        color: 'error',
+        popConfirm: {
+          title: '是否确认删除',
+          confirm: () => {},
+        },
+      },
+    ];
+
+    return actions;
+  };
+</script>

+ 110 - 0
src/views/demo/table/tableData.tsx

@@ -1,5 +1,7 @@
+import { optionsListApi } from '/@/api/demo/select';
 import { FormProps, FormSchema } from '/@/components/Table';
 import { BasicColumn } from '/@/components/Table/src/types/table';
+import { VxeFormItemProps, VxeGridPropTypes } from '/@/components/VxeTable';
 
 export function getBasicColumns(): BasicColumn[] {
   return [
@@ -302,3 +304,111 @@ export function getTreeTableData() {
     return arr;
   })();
 }
+
+export const vxeTableColumns: VxeGridPropTypes.Columns = [
+  {
+    title: '序号',
+    type: 'seq',
+    fixed: 'left',
+    width: '50',
+    align: 'center',
+  },
+  {
+    title: '固定列',
+    field: 'name',
+    width: 150,
+    showOverflow: 'tooltip',
+    fixed: 'left',
+  },
+  {
+    title: '自适应列',
+    field: 'address',
+  },
+  {
+    title: '自定义列(自定义导出)',
+    field: 'no',
+    width: 200,
+    showOverflow: 'tooltip',
+    align: 'center',
+    slots: {
+      default: ({ row }) => {
+        const text = `自定义${row.no}`;
+        return [<div class="text-red-500">{text}</div>];
+      },
+    },
+    exportMethod: ({ row }) => {
+      return `自定义${row.no}导出`;
+    },
+  },
+  {
+    title: '自定义编辑',
+    width: 150,
+    field: 'name1',
+    align: 'center',
+    editRender: {
+      name: 'AInput',
+      placeholder: '请点击输入',
+    },
+  },
+  {
+    title: '开始时间',
+    width: 150,
+    field: 'beginTime',
+    showOverflow: 'tooltip',
+    align: 'center',
+  },
+  {
+    title: '结束时间',
+    width: 150,
+    field: 'endTime',
+    showOverflow: 'tooltip',
+    align: 'center',
+  },
+  {
+    width: 160,
+    title: '操作',
+    align: 'center',
+    slots: { default: 'action' },
+    fixed: 'right',
+  },
+];
+
+export const vxeTableFormSchema: VxeFormItemProps[] = [
+  {
+    field: 'field0',
+    title: 'field0',
+    itemRender: {
+      name: 'AInput',
+    },
+    span: 6,
+  },
+  {
+    field: 'field1',
+    title: 'field1',
+    itemRender: {
+      name: 'AApiSelect',
+      props: {
+        api: optionsListApi,
+        resultField: 'list',
+        labelField: 'name',
+        valueField: 'id',
+      },
+    },
+    span: 6,
+  },
+  {
+    span: 12,
+    align: 'right',
+    className: '!pr-0',
+    itemRender: {
+      name: 'AButtonGroup',
+      children: [
+        {
+          props: { type: 'primary', content: '查询', htmlType: 'submit' },
+          attrs: { class: 'mr-2' },
+        },
+        { props: { type: 'default', htmlType: 'reset', content: '重置' } },
+      ],
+    },
+  },
+];

+ 398 - 12
yarn.lock

@@ -1151,6 +1151,31 @@
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
+"@fast-csv/format@4.3.5":
+  version "4.3.5"
+  resolved "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz#90d83d1b47b6aaf67be70d6118f84f3e12ee1ff3"
+  integrity sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==
+  dependencies:
+    "@types/node" "^14.0.1"
+    lodash.escaperegexp "^4.1.2"
+    lodash.isboolean "^3.0.3"
+    lodash.isequal "^4.5.0"
+    lodash.isfunction "^3.0.9"
+    lodash.isnil "^4.0.0"
+
+"@fast-csv/parse@4.3.6":
+  version "4.3.6"
+  resolved "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz#ee47d0640ca0291034c7aa94039a744cfb019264"
+  integrity sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==
+  dependencies:
+    "@types/node" "^14.0.1"
+    lodash.escaperegexp "^4.1.2"
+    lodash.groupby "^4.6.0"
+    lodash.isfunction "^3.0.9"
+    lodash.isnil "^4.0.0"
+    lodash.isundefined "^3.0.1"
+    lodash.uniq "^4.5.0"
+
 "@humanwhocodes/config-array@^0.9.2":
   version "0.9.5"
   resolved "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7"
@@ -1719,6 +1744,11 @@
   resolved "https://registry.npmmirror.com/@types/node/-/node-18.0.3.tgz#463fc47f13ec0688a33aec75d078a0541a447199"
   integrity sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==
 
+"@types/node@^14.0.1":
+  version "14.18.36"
+  resolved "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz#c414052cb9d43fab67d679d5f3c641be911f5835"
+  integrity sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==
+
 "@types/node@^14.17.1":
   version "14.18.21"
   resolved "https://registry.npmmirror.com/@types/node/-/node-14.18.21.tgz#0155ee46f6be28b2ff0342ca1a9b9fd4468bef41"
@@ -2355,6 +2385,35 @@ archive-type@^4.0.0:
   dependencies:
     file-type "^4.2.0"
 
+archiver-utils@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
+  integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
+  dependencies:
+    glob "^7.1.4"
+    graceful-fs "^4.2.0"
+    lazystream "^1.0.0"
+    lodash.defaults "^4.2.0"
+    lodash.difference "^4.5.0"
+    lodash.flatten "^4.4.0"
+    lodash.isplainobject "^4.0.6"
+    lodash.union "^4.6.0"
+    normalize-path "^3.0.0"
+    readable-stream "^2.0.0"
+
+archiver@^5.0.0:
+  version "5.3.1"
+  resolved "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6"
+  integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==
+  dependencies:
+    archiver-utils "^2.1.0"
+    async "^3.2.3"
+    buffer-crc32 "^0.2.1"
+    readable-stream "^3.6.0"
+    readdir-glob "^1.0.0"
+    tar-stream "^2.2.0"
+    zip-stream "^4.1.0"
+
 arg@^4.1.0:
   version "4.1.3"
   resolved "https://registry.npmmirror.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
@@ -2530,6 +2589,11 @@ before-after-hook@^2.2.0:
   resolved "https://registry.npmmirror.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e"
   integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==
 
+big-integer@^1.6.17:
+  version "1.6.51"
+  resolved "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
+  integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
+
 big.js@^5.2.2:
   version "5.2.2"
   resolved "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -2594,6 +2658,14 @@ binary-mirror-config@^1:
   resolved "https://registry.npmmirror.com/binary-mirror-config/-/binary-mirror-config-1.41.0.tgz#b68032588392bee9262971f977922d075513964b"
   integrity sha512-ZiIhR1s6Sv1Fv6qCQqfPjx0Cj86BgFlhqNxZgHkQOWcxJcMbO3mj1iqsuVjowYqJqeZL8e52+IEv7IRnSX6T6w==
 
+binary@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
+  integrity sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==
+  dependencies:
+    buffers "~0.1.1"
+    chainsaw "~0.1.0"
+
 bl@^1.0.0:
   version "1.2.3"
   resolved "https://registry.npmmirror.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7"
@@ -2602,7 +2674,7 @@ bl@^1.0.0:
     readable-stream "^2.3.5"
     safe-buffer "^5.1.1"
 
-bl@^4.1.0:
+bl@^4.0.3, bl@^4.1.0:
   version "4.1.0"
   resolved "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
   integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
@@ -2616,6 +2688,11 @@ bluebird@^3.5.0:
   resolved "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
   integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
 
+bluebird@~3.4.1:
+  version "3.4.7"
+  resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
+  integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==
+
 boolbase@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
@@ -2682,7 +2759,7 @@ buffer-alloc@^1.2.0:
     buffer-alloc-unsafe "^1.1.0"
     buffer-fill "^1.0.0"
 
-buffer-crc32@~0.2.3:
+buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
   version "0.2.13"
   resolved "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
   integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
@@ -2697,6 +2774,11 @@ buffer-from@^1.0.0:
   resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
   integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
 
+buffer-indexof-polyfill@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
+  integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
+
 buffer@^5.2.1, buffer@^5.5.0:
   version "5.7.1"
   resolved "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
@@ -2705,6 +2787,11 @@ buffer@^5.2.1, buffer@^5.5.0:
     base64-js "^1.3.1"
     ieee754 "^1.1.13"
 
+buffers@~0.1.1:
+  version "0.1.1"
+  resolved "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
+  integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==
+
 builtin-modules@^3.0.0, builtin-modules@^3.1.0:
   version "3.3.0"
   resolved "https://registry.npmmirror.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
@@ -2830,6 +2917,13 @@ cfb@~1.2.1:
     adler-32 "~1.3.0"
     crc-32 "~1.2.0"
 
+chainsaw@~0.1.0:
+  version "0.1.0"
+  resolved "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
+  integrity sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==
+  dependencies:
+    traverse ">=0.3.0 <0.4"
+
 chalk@^1.0.0, chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.npmmirror.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -2881,7 +2975,7 @@ chardet@^0.7.0:
   resolved "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-chokidar@^3.5.2:
+"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.2:
   version "3.5.3"
   resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
   integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
@@ -3083,6 +3177,16 @@ component-emitter@^1.2.1:
   resolved "https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
   integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
 
+compress-commons@^4.1.0:
+  version "4.1.1"
+  resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d"
+  integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==
+  dependencies:
+    buffer-crc32 "^0.2.13"
+    crc32-stream "^4.0.2"
+    normalize-path "^3.0.0"
+    readable-stream "^3.6.0"
+
 compute-scroll-into-view@^1.0.17:
   version "1.0.17"
   resolved "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab"
@@ -3366,11 +3470,19 @@ cosmiconfig@^7, cosmiconfig@^7.0.0, cosmiconfig@^7.0.1:
     path-type "^4.0.0"
     yaml "^1.10.0"
 
-crc-32@~1.2.0, crc-32@~1.2.1:
+crc-32@^1.2.0, crc-32@~1.2.0, crc-32@~1.2.1:
   version "1.2.2"
   resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"
   integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
 
+crc32-stream@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007"
+  integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==
+  dependencies:
+    crc-32 "^1.2.0"
+    readable-stream "^3.4.0"
+
 create-require@^1.1.0:
   version "1.1.1"
   resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
@@ -3521,6 +3633,11 @@ dayjs@^1.10.5, dayjs@^1.11.1:
   resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258"
   integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==
 
+dayjs@^1.8.34:
+  version "1.11.7"
+  resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2"
+  integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==
+
 de-indent@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
@@ -3839,6 +3956,13 @@ download@^7.1.0:
     p-event "^2.1.0"
     pify "^3.0.0"
 
+duplexer2@~0.1.4:
+  version "0.1.4"
+  resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
+  integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==
+  dependencies:
+    readable-stream "^2.0.2"
+
 duplexer3@^0.1.4:
   version "0.1.4"
   resolved "https://registry.npmmirror.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@@ -3899,7 +4023,7 @@ encodeurl@~1.0.2:
   resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
   integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
 
-end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
   version "1.4.4"
   resolved "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
   integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@@ -4313,6 +4437,21 @@ etag@^1.8.1:
   resolved "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
   integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
 
+exceljs@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.npmjs.org/exceljs/-/exceljs-4.3.0.tgz#939bc0d4c59c200acadb7051be34d25c109853c4"
+  integrity sha512-hTAeo5b5TPvf8Z02I2sKIT4kSfCnOO2bCxYX8ABqODCdAjppI3gI9VYiGCQQYVcBaBSKlFDMKlAQRqC+kV9O8w==
+  dependencies:
+    archiver "^5.0.0"
+    dayjs "^1.8.34"
+    fast-csv "^4.3.1"
+    jszip "^3.5.0"
+    readable-stream "^3.6.0"
+    saxes "^5.0.1"
+    tmp "^0.2.0"
+    unzipper "^0.10.11"
+    uuid "^8.3.0"
+
 exec-buffer@^3.0.0:
   version "3.2.0"
   resolved "https://registry.npmmirror.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b"
@@ -4460,6 +4599,14 @@ extglob@^2.0.2:
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
+fast-csv@^4.3.1:
+  version "4.3.6"
+  resolved "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz#70349bdd8fe4d66b1130d8c91820b64a21bc4a63"
+  integrity sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==
+  dependencies:
+    "@fast-csv/format" "4.3.5"
+    "@fast-csv/parse" "4.3.6"
+
 fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
   version "3.1.3"
   resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
@@ -4745,6 +4892,16 @@ fsevents@~2.3.2:
   resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
   integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
 
+fstream@^1.0.12:
+  version "1.0.12"
+  resolved "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+  integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
+  dependencies:
+    graceful-fs "^4.1.2"
+    inherits "~2.0.0"
+    mkdirp ">=0.5 0"
+    rimraf "2"
+
 function-bind@^1.1.1:
   version "1.1.1"
   resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -4924,7 +5081,7 @@ glob-parent@^6.0.1:
   dependencies:
     is-glob "^4.0.3"
 
-glob@^7.1.3, glob@^7.1.6:
+glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
   version "7.2.3"
   resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
   integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
@@ -5369,6 +5526,16 @@ imagemin@^7.0.1:
     p-pipe "^3.0.0"
     replace-ext "^1.0.0"
 
+immediate@~3.0.5:
+  version "3.0.6"
+  resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
+  integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
+
+immutable@^4.0.0:
+  version "4.2.2"
+  resolved "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz#2da9ff4384a4330c36d4d1bc88e90f9e0b0ccd16"
+  integrity sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==
+
 import-fresh@^3.0.0, import-fresh@^3.2.1:
   version "3.3.0"
   resolved "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@@ -5414,7 +5581,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3:
   version "2.0.4"
   resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -5986,6 +6153,16 @@ jsonpointer@^5.0.0:
   resolved "https://registry.npmmirror.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072"
   integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==
 
+jszip@^3.5.0:
+  version "3.10.1"
+  resolved "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
+  integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
+  dependencies:
+    lie "~3.3.0"
+    pako "~1.0.2"
+    readable-stream "~2.3.6"
+    setimmediate "^1.0.5"
+
 junk@^3.1.0:
   version "3.1.0"
   resolved "https://registry.npmmirror.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
@@ -6032,6 +6209,13 @@ kolorist@^1.5.1:
   resolved "https://registry.npmmirror.com/kolorist/-/kolorist-1.5.1.tgz#c3d66dc4fabde4f6b7faa6efda84c00491f9e52b"
   integrity sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==
 
+lazystream@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638"
+  integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==
+  dependencies:
+    readable-stream "^2.0.5"
+
 less@^4.1.2:
   version "4.1.3"
   resolved "https://registry.npmmirror.com/less/-/less-4.1.3.tgz#175be9ddcbf9b250173e0a00b4d6920a5b770246"
@@ -6062,6 +6246,13 @@ levn@^0.4.1:
     prelude-ls "^1.2.1"
     type-check "~0.4.0"
 
+lie@~3.3.0:
+  version "3.3.0"
+  resolved "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
+  integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
+  dependencies:
+    immediate "~3.0.5"
+
 lilconfig@2.0.4:
   version "2.0.4"
   resolved "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082"
@@ -6092,6 +6283,11 @@ lint-staged@12.3.7:
     supports-color "^9.2.1"
     yaml "^1.10.2"
 
+listenercount@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
+  integrity sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==
+
 listr2@^4.0.1:
   version "4.0.5"
   resolved "https://registry.npmmirror.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5"
@@ -6168,11 +6364,66 @@ lodash.debounce@^4.0.8:
   resolved "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
   integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
 
+lodash.defaults@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+  integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
+
+lodash.difference@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
+  integrity sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==
+
+lodash.escaperegexp@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
+  integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==
+
+lodash.flatten@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+  integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==
+
+lodash.groupby@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz#0b08a1dcf68397c397855c3239783832df7403d1"
+  integrity sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==
+
+lodash.isboolean@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+  integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
+
+lodash.isequal@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
+  integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
+
+lodash.isfunction@^3.0.9:
+  version "3.0.9"
+  resolved "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051"
+  integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==
+
 lodash.ismatch@^4.4.0:
   version "4.4.0"
   resolved "https://registry.npmmirror.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
   integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==
 
+lodash.isnil@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz#49e28cd559013458c814c5479d3c663a21bfaa6c"
+  integrity sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==
+
+lodash.isplainobject@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+  integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
+lodash.isundefined@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48"
+  integrity sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==
+
 lodash.merge@^4.6.2:
   version "4.6.2"
   resolved "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -6188,6 +6439,16 @@ lodash.truncate@^4.4.2:
   resolved "https://registry.npmmirror.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
   integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
 
+lodash.union@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
+  integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==
+
+lodash.uniq@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+  integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
+
 lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
   version "4.17.21"
   resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
@@ -6493,6 +6754,13 @@ minimatch@^5.0.1:
   dependencies:
     brace-expansion "^2.0.1"
 
+minimatch@^5.1.0:
+  version "5.1.6"
+  resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
+  integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
+  dependencies:
+    brace-expansion "^2.0.1"
+
 minimatch@^5.1.1:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.2.tgz#0939d7d6f0898acbd1508abe534d1929368a8fff"
@@ -6514,6 +6782,11 @@ minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
   resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
   integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
 
+minimist@^1.2.6:
+  version "1.2.7"
+  resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
+  integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
+
 mixin-deep@^1.2.0:
   version "1.3.2"
   resolved "https://registry.npmmirror.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -6522,6 +6795,13 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
+"mkdirp@>=0.5 0":
+  version "0.5.6"
+  resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+  integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+  dependencies:
+    minimist "^1.2.6"
+
 mockjs@^1.1.0:
   version "1.1.0"
   resolved "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz#e6a0c378e91906dbaff20911cc0273b3c7d75b06"
@@ -6995,6 +7275,11 @@ p-try@^2.0.0:
   resolved "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
+pako@~1.0.2:
+  version "1.0.11"
+  resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+  integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
 param-case@^3.0.4:
   version "3.0.4"
   resolved "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
@@ -7511,7 +7796,7 @@ read-pkg@^5.2.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0:
+readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
   integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -7520,7 +7805,7 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stre
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
-readable-stream@^2.0.0, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6:
+readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6:
   version "2.3.7"
   resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
   integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -7533,6 +7818,13 @@ readable-stream@^2.0.0, readable-stream@^2.3.0, readable-stream@^2.3.5, readable
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readdir-glob@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz#b185789b8e6a43491635b6953295c5c5e3fd224c"
+  integrity sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==
+  dependencies:
+    minimatch "^5.1.0"
+
 readdirp@~3.6.0:
   version "3.6.0"
   resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@@ -7734,14 +8026,14 @@ rfdc@^1.3.0:
   resolved "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
   integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
 
-rimraf@^2.5.4:
+rimraf@2, rimraf@^2.5.4:
   version "2.7.1"
   resolved "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
   integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
   dependencies:
     glob "^7.1.3"
 
-rimraf@^3.0.2:
+rimraf@^3.0.0, rimraf@^3.0.2:
   version "3.0.2"
   resolved "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
   integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
@@ -7824,11 +8116,27 @@ safe-regex@^1.1.0:
   resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
+sass@^1.57.1:
+  version "1.57.1"
+  resolved "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz#dfafd46eb3ab94817145e8825208ecf7281119b5"
+  integrity sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==
+  dependencies:
+    chokidar ">=3.0.0 <4.0.0"
+    immutable "^4.0.0"
+    source-map-js ">=0.6.2 <2.0.0"
+
 sax@^1.2.4:
   version "1.2.4"
   resolved "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
 
+saxes@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
+  integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
+  dependencies:
+    xmlchars "^2.2.0"
+
 scroll-into-view-if-needed@^2.2.25:
   version "2.2.29"
   resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885"
@@ -7908,6 +8216,11 @@ set-value@^2.0.0, set-value@^2.0.1:
     is-plain-object "^2.0.3"
     split-string "^3.0.1"
 
+setimmediate@^1.0.5, setimmediate@~1.0.4:
+  version "1.0.5"
+  resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+  integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
+
 shallow-equal@^1.0.0:
   version "1.2.1"
   resolved "https://registry.npmmirror.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
@@ -8058,7 +8371,7 @@ sortablejs@^1.15.0:
   resolved "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a"
   integrity sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==
 
-source-map-js@^1.0.2:
+"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
   integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
@@ -8578,6 +8891,17 @@ tar-stream@^1.5.2:
     to-buffer "^1.1.1"
     xtend "^4.0.0"
 
+tar-stream@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
+  integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
+  dependencies:
+    bl "^4.0.3"
+    end-of-stream "^1.4.1"
+    fs-constants "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^3.1.1"
+
 temp-dir@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
@@ -8676,6 +9000,13 @@ tmp@^0.0.33:
   dependencies:
     os-tmpdir "~1.0.2"
 
+tmp@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
+  integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
+  dependencies:
+    rimraf "^3.0.0"
+
 to-buffer@^1.1.1:
   version "1.1.1"
   resolved "https://registry.npmmirror.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
@@ -8730,6 +9061,11 @@ tr46@~0.0.3:
   resolved "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
   integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
 
+"traverse@>=0.3.0 <0.4":
+  version "0.3.9"
+  resolved "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
+  integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==
+
 traverse@^0.6.6:
   version "0.6.6"
   resolved "https://registry.npmmirror.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
@@ -8933,6 +9269,22 @@ unset-value@^1.0.0:
     has-value "^0.3.1"
     isobject "^3.0.0"
 
+unzipper@^0.10.11:
+  version "0.10.11"
+  resolved "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz#0b4991446472cbdb92ee7403909f26c2419c782e"
+  integrity sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==
+  dependencies:
+    big-integer "^1.6.17"
+    binary "~0.3.0"
+    bluebird "~3.4.1"
+    buffer-indexof-polyfill "~1.0.0"
+    duplexer2 "~0.1.4"
+    fstream "^1.0.12"
+    graceful-fs "^4.2.2"
+    listenercount "~1.0.1"
+    readable-stream "~2.3.6"
+    setimmediate "~1.0.4"
+
 upath@^1.2.0:
   version "1.2.0"
   resolved "https://registry.npmmirror.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
@@ -9011,6 +9363,11 @@ uuid@^3.0.1, uuid@^3.3.2:
   resolved "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
   integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
 
+uuid@^8.3.0:
+  version "8.3.2"
+  resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+  integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
 v8-compile-cache-lib@^3.0.1:
   version "3.0.1"
   resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
@@ -9296,6 +9653,16 @@ vue@^3.2.45:
     "@vue/server-renderer" "3.2.45"
     "@vue/shared" "3.2.45"
 
+vxe-table-plugin-export-xlsx@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.npmjs.org/vxe-table-plugin-export-xlsx/-/vxe-table-plugin-export-xlsx-3.0.4.tgz#35faabc0791b4e9aa516b78ea3fd45e67314afe4"
+  integrity sha512-Og/NbXRIb+BS6sJ48oDNVrZnlkcpaCd/zS8JBAZjHLgioWr1Xoob6FEpaeXBebGPPgTumZNUrrBO57JhhYAerA==
+
+vxe-table@^4.3.9:
+  version "4.3.9"
+  resolved "https://registry.npmjs.org/vxe-table/-/vxe-table-4.3.9.tgz#4b288e5e666eb4fb47e9732d51d967e2aa69b61f"
+  integrity sha512-Ns7Ooa7lOHBpks90i0k0BMNyxfMpUo39ryxTgKE41X3xVnI9tGQs2U6+klfDlsuqYfmG3ibyzHN3OCrWbbKo4Q==
+
 warning@^4.0.0:
   version "4.0.3"
   resolved "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
@@ -9581,6 +9948,11 @@ write-file-atomic@^4.0.1:
     imurmurhash "^0.1.4"
     signal-exit "^3.0.7"
 
+xe-utils@^3.5.7:
+  version "3.5.7"
+  resolved "https://registry.npmjs.org/xe-utils/-/xe-utils-3.5.7.tgz#2c885852dfadd5c8beeffdc1f884f8ceb962c669"
+  integrity sha512-3H+fDBKBR2wLJgyA7k9C/w1Xljx6Maml5ukV0WDY06HjYyGs2FEz6XhcwRCLIDXX4pBP3Gu0nX9DbCeuuRA2Ew==
+
 xlsx@^0.18.5:
   version "0.18.5"
   resolved "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0"
@@ -9594,6 +9966,11 @@ xlsx@^0.18.5:
     wmf "~1.0.1"
     word "~0.3.0"
 
+xmlchars@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
+  integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+
 xtend@^4.0.0, xtend@~4.0.1:
   version "4.0.2"
   resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -9703,6 +10080,15 @@ yocto-queue@^0.1.0:
   resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
   integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
 
+zip-stream@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79"
+  integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==
+  dependencies:
+    archiver-utils "^2.1.0"
+    compress-commons "^4.1.0"
+    readable-stream "^3.6.0"
+
 zrender@5.3.2:
   version "5.3.2"
   resolved "https://registry.npmmirror.com/zrender/-/zrender-5.3.2.tgz#f67b11d36d3d020d62411d3bb123eb1c93cccd69"