Browse Source

feat: table search form visible control (#5121)

* feat: table search form visible control

* chore: fix docs and demo

* chore: type error fixed
Netfan 3 months ago
parent
commit
ed465d2b5b

+ 12 - 8
docs/src/components/common-ui/vben-vxe-table.md

@@ -165,6 +165,8 @@ vxeUI.renderer.add('CellLink', {
 
 **表单搜索** 部分采用了`Vben Form 表单`,参考 [Vben Form 表单文档](/components/common-ui/vben-form)。
 
+当启用了表单搜索时,可以在toolbarConfig中配置`search`为`true`来让表格在工具栏区域显示一个搜索表单控制按钮。
+
 <DemoPreview dir="demos/vben-vxe-table/form" />
 
 ## 单元格编辑
@@ -215,14 +217,15 @@ const [Grid, gridApi] = useVbenVxeGrid({
 
 useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表单的方法。
 
-| 方法名 | 描述 | 类型 |
-| --- | --- | --- |
-| setLoading | 设置loading状态 | `(loading)=>void` |
-| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partial<VxeGridProps['gridOptions'])=>void` |
-| reload | 重载表格,会进行初始化 | `(params:any)=>void` |
-| query | 重载表格,会保留当前分页 | `(params:any)=>void` |
-| grid | vxe-table grid实例 | `VxeGridInstance` |
-| formApi | vbenForm api实例 | `FormApi` |
+| 方法名 | 描述 | 类型 | 说明 |
+| --- | --- | --- | --- |
+| setLoading | 设置loading状态 | `(loading)=>void` | - |
+| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partial<VxeGridProps['gridOptions'])=>void` | - |
+| reload | 重载表格,会进行初始化 | `(params:any)=>void` | - |
+| query | 重载表格,会保留当前分页 | `(params:any)=>void` | - |
+| grid | vxe-table grid实例 | `VxeGridInstance` | - |
+| formApi | vbenForm api实例 | `FormApi` | - |
+| toggleSearchForm | 设置搜索表单显示状态 | `(show?: boolean)=>boolean` | 当省略参数时,则将表单在显示和隐藏两种状态之间切换 |
 
 ## Props
 
@@ -236,3 +239,4 @@ useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表
 | gridOptions    | grid组件的参数     | `VxeTableGridProps` |
 | gridEvents     | grid组件的触发的⌚️ | `VxeGridListeners`  |
 | formOptions    | 表单参数           | `VbenFormProps`     |
+| showSearchForm | 是否显示搜索表单   | `boolean`           |

+ 5 - 0
docs/src/demos/vben-vxe-table/form/index.vue

@@ -110,6 +110,11 @@ const gridOptions: VxeGridProps<RowType> = {
       },
     },
   },
+  toolbarConfig: {
+    // 是否显示搜索表单控制按钮
+    // @ts-ignore 正式环境时有完整的类型声明
+    search: true,
+  },
 };
 
 const [Grid] = useVbenVxeGrid({ formOptions, gridOptions });

+ 12 - 0
packages/effects/plugins/src/vxe-table/api.ts

@@ -8,6 +8,7 @@ import { toRaw } from 'vue';
 import { Store } from '@vben-core/shared/store';
 import {
   bindMethods,
+  isBoolean,
   isFunction,
   mergeWithArrayOverride,
   StateHandler,
@@ -20,6 +21,7 @@ function getDefaultState(): VxeGridProps {
     gridOptions: {},
     gridEvents: {},
     formOptions: undefined,
+    showSearchForm: true,
   };
 }
 
@@ -108,6 +110,16 @@ export class VxeGridApi {
     }
   }
 
+  toggleSearchForm(show?: boolean) {
+    this.setState({
+      showSearchForm: isBoolean(show) ? show : !this.state?.showSearchForm,
+    });
+    // nextTick(() => {
+    //   this.grid.recalculate();
+    // });
+    return this.state?.showSearchForm;
+  }
+
   unmount() {
     this.isMounted = false;
     this.stateHandler.reset();

+ 2 - 1
packages/effects/plugins/src/vxe-table/index.ts

@@ -1,5 +1,6 @@
 export { setupVbenVxeTable } from './init';
+export type { VxeTableGridOptions } from './types';
 export * from './use-vxe-grid';
-export { default as VbenVxeGrid } from './use-vxe-grid.vue';
 
+export { default as VbenVxeGrid } from './use-vxe-grid.vue';
 export type { VxeGridListeners, VxeGridProps } from 'vxe-table';

+ 16 - 1
packages/effects/plugins/src/vxe-table/types.ts

@@ -2,6 +2,7 @@ import type { ClassType, DeepPartial } from '@vben/types';
 import type { VbenFormProps } from '@vben-core/form-ui';
 import type {
   VxeGridListeners,
+  VxeGridPropTypes,
   VxeGridProps as VxeTableGridProps,
   VxeUIExport,
 } from 'vxe-table';
@@ -18,6 +19,16 @@ export interface VxePaginationInfo {
   total: number;
 }
 
+interface ToolbarConfigOptions extends VxeGridPropTypes.ToolbarConfig {
+  /** 是否显示切换搜索表单的按钮 */
+  search?: boolean;
+}
+
+export interface VxeTableGridOptions<T = any> extends VxeTableGridProps<T> {
+  /** 工具栏配置 */
+  toolbarConfig?: ToolbarConfigOptions;
+}
+
 export interface VxeGridProps {
   /**
    * 标题
@@ -38,7 +49,7 @@ export interface VxeGridProps {
   /**
    * vxe-grid 配置
    */
-  gridOptions?: DeepPartial<VxeTableGridProps>;
+  gridOptions?: DeepPartial<VxeTableGridOptions>;
   /**
    * vxe-grid 事件
    */
@@ -47,6 +58,10 @@ export interface VxeGridProps {
    * 表单配置
    */
   formOptions?: VbenFormProps;
+  /**
+   * 显示搜索表单
+   */
+  showSearchForm?: boolean;
 }
 
 export type ExtendedVxeGridApi = {

+ 45 - 11
packages/effects/plugins/src/vxe-table/use-vxe-grid.vue

@@ -1,7 +1,10 @@
 <script lang="ts" setup>
 import type { VbenFormProps } from '@vben-core/form-ui';
 import type {
+  VxeGridDefines,
   VxeGridInstance,
+  VxeGridListeners,
+  VxeGridPropTypes,
   VxeGridProps as VxeTableGridProps,
 } from 'vxe-table';
 
@@ -57,6 +60,7 @@ const {
   formOptions,
   tableTitle,
   tableTitleHelp,
+  showSearchForm,
 } = usePriorityValues(props, state);
 
 const { isMobile } = usePreferences();
@@ -103,21 +107,37 @@ const toolbarOptions = computed(() => {
   const slotActions = slots[TOOLBAR_ACTIONS]?.();
   const slotTools = slots[TOOLBAR_TOOLS]?.();
 
+  const toolbarConfig: VxeGridPropTypes.ToolbarConfig = {
+    tools:
+      gridOptions.value?.toolbarConfig?.search && !!formOptions.value
+        ? [
+            {
+              code: 'search',
+              icon: 'vxe-icon--search',
+              circle: true,
+              status: showSearchForm.value ? 'primary' : undefined,
+              title: $t('common.search'),
+            },
+          ]
+        : [],
+  };
+
   if (!showToolbar.value) {
-    return {};
+    return { toolbarConfig };
   }
+
+  // if (gridOptions.value?.toolbarConfig?.search) {
+  // }
   // 强制使用固定的toolbar配置,不允许用户自定义
   // 减少配置的复杂度,以及后续维护的成本
-  return {
-    toolbarConfig: {
-      slots: {
-        ...(slotActions || showTableTitle.value
-          ? { buttons: TOOLBAR_ACTIONS }
-          : {}),
-        ...(slotTools ? { tools: TOOLBAR_TOOLS } : {}),
-      },
-    },
+  toolbarConfig.slots = {
+    ...(slotActions || showTableTitle.value
+      ? { buttons: TOOLBAR_ACTIONS }
+      : {}),
+    ...(slotTools ? { tools: TOOLBAR_TOOLS } : {}),
   };
+
+  return { toolbarConfig };
 });
 
 const options = computed(() => {
@@ -173,9 +193,19 @@ const options = computed(() => {
   return mergedOptions;
 });
 
+function onToolbarToolClick(event: VxeGridDefines.ToolbarToolClickEventParams) {
+  if (event.code === 'search') {
+    props.api?.toggleSearchForm?.();
+  }
+  (
+    gridEvents.value?.toolbarToolClick as VxeGridListeners['toolbarToolClick']
+  )?.(event);
+}
+
 const events = computed(() => {
   return {
     ...gridEvents.value,
+    toolbarToolClick: onToolbarToolClick,
   };
 });
 
@@ -304,7 +334,11 @@ onUnmounted(() => {
 
       <!-- form表单 -->
       <template #form>
-        <div v-if="formOptions" class="relative rounded py-3 pb-4">
+        <div
+          v-if="formOptions"
+          v-show="showSearchForm !== false"
+          class="relative rounded py-3 pb-4"
+        >
           <slot name="form">
             <Form>
               <template

+ 2 - 1
packages/locales/src/langs/en-US/common.json

@@ -9,5 +9,6 @@
   "noData": "No Data",
   "refresh": "Refresh",
   "loadingMenu": "Loading Menu",
-  "query": "Search"
+  "query": "Search",
+  "search": "Search"
 }

+ 2 - 1
packages/locales/src/langs/zh-CN/common.json

@@ -9,5 +9,6 @@
   "noData": "暂无数据",
   "refresh": "刷新",
   "loadingMenu": "加载菜单中",
-  "query": "查询"
+  "query": "查询",
+  "search": "搜索"
 }

+ 1 - 0
playground/src/views/examples/vxe-table/custom-cell.vue

@@ -82,6 +82,7 @@ const gridOptions: VxeGridProps<RowType> = {
       },
     },
   },
+  showOverflow: false,
 };
 
 const [Grid] = useVbenVxeGrid({ gridOptions });

+ 15 - 3
playground/src/views/examples/vxe-table/form.vue

@@ -1,6 +1,6 @@
 <script lang="ts" setup>
 import type { VbenFormProps } from '#/adapter/form';
-import type { VxeGridProps } from '#/adapter/vxe-table';
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
 import { Page } from '@vben/common-ui';
 
@@ -71,7 +71,7 @@ const formOptions: VbenFormProps = {
   submitOnEnter: false,
 };
 
-const gridOptions: VxeGridProps<RowType> = {
+const gridOptions: VxeTableGridOptions<RowType> = {
   checkboxConfig: {
     highlight: true,
     labelField: 'name',
@@ -85,6 +85,7 @@ const gridOptions: VxeGridProps<RowType> = {
     { field: 'price', title: 'Price' },
     { field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
   ],
+  exportConfig: {},
   height: 'auto',
   keepSource: true,
   pagerConfig: {},
@@ -100,9 +101,20 @@ const gridOptions: VxeGridProps<RowType> = {
       },
     },
   },
+  toolbarConfig: {
+    custom: true,
+    export: true,
+    refresh: true,
+    resizable: true,
+    search: true,
+    zoom: true,
+  },
 };
 
-const [Grid] = useVbenVxeGrid({ formOptions, gridOptions });
+const [Grid] = useVbenVxeGrid({
+  formOptions,
+  gridOptions,
+});
 </script>
 
 <template>