瀏覽代碼

feat(table): support columns-change event

添加列改变事件(含排序、可见性、固定列)。该事件仅由表格设置组件中人为触发。
无木 3 年之前
父節點
當前提交
125a7d1483

+ 17 - 2
src/components/Table/src/BasicTable.vue

@@ -32,13 +32,19 @@
   </div>
 </template>
 <script lang="ts">
-  import type { BasicTableProps, TableActionType, SizeType } from './types/table';
+  import type {
+    BasicTableProps,
+    TableActionType,
+    SizeType,
+    ColumnChangeParam,
+  } from './types/table';
 
   import { defineComponent, ref, computed, unref, toRaw } from 'vue';
   import { Table } from 'ant-design-vue';
   import { BasicForm, useForm } from '/@/components/Form/index';
   import expandIcon from './components/ExpandIcon';
   import HeaderCell from './components/HeaderCell.vue';
+  import { InnerHandlers } from './types/table';
 
   import { usePagination } from './hooks/usePagination';
   import { useColumns } from './hooks/useColumns';
@@ -83,6 +89,7 @@
       'edit-change',
       'expanded-rows-change',
       'change',
+      'columns-change',
     ],
     setup(props, { attrs, emit, slots }) {
       const tableElRef = ref<ComponentRef>(null);
@@ -177,7 +184,15 @@
 
       const { getExpandOption, expandAll, collapseAll } = useTableExpand(getProps, tableData, emit);
 
-      const { getHeaderProps } = useTableHeader(getProps, slots);
+      const handlers: InnerHandlers = {
+        onColumnsChange: (data: ColumnChangeParam[]) => {
+          emit('columns-change', data);
+          // support useTable
+          unref(getProps).onColumnsChange?.(data);
+        },
+      };
+
+      const { getHeaderProps } = useTableHeader(getProps, slots, handlers);
 
       const { getFooterProps } = useTableFooter(
         getProps,

+ 12 - 4
src/components/Table/src/components/TableHeader.vue

@@ -6,11 +6,15 @@
   <div :class="`${prefixCls}__toolbar`">
     <slot name="toolbar"></slot>
     <Divider type="vertical" v-if="$slots.toolbar && showTableSetting" />
-    <TableSetting :setting="tableSetting" v-if="showTableSetting" />
+    <TableSetting
+      :setting="tableSetting"
+      v-if="showTableSetting"
+      @columns-change="handleColumnChange"
+    />
   </div>
 </template>
 <script lang="ts">
-  import type { TableSetting } from '../types/table';
+  import type { TableSetting, ColumnChangeParam } from '../types/table';
   import type { PropType } from 'vue';
 
   import { defineComponent } from 'vue';
@@ -42,9 +46,13 @@
         default: '',
       },
     },
-    setup() {
+    emits: ['columns-change'],
+    setup(_, { emit }) {
       const { prefixCls } = useDesign('basic-table-header');
-      return { prefixCls };
+      function handleColumnChange(data: ColumnChangeParam[]) {
+        emit('columns-change', data);
+      }
+      return { prefixCls, handleColumnChange };
     },
   });
 </script>

+ 22 - 7
src/components/Table/src/components/settings/ColumnSetting.vue

@@ -114,7 +114,7 @@
   import { getPopupContainer } from '/@/utils';
   import { omit } from 'lodash-es';
 
-  import type { BasicColumn } from '../../types/table';
+  import type { BasicColumn, ColumnChangeParam } from '../../types/table';
 
   interface State {
     checkAll: boolean;
@@ -141,8 +141,9 @@
       Divider,
       Icon,
     },
+    emits: ['columns-change'],
 
-    setup() {
+    setup(_, { emit }) {
       const { t } = useI18n();
       const table = useTableContext();
 
@@ -234,10 +235,10 @@
         const checkList = plainOptions.value.map((item) => item.value);
         if (e.target.checked) {
           state.checkedList = checkList;
-          table.setColumns(checkList);
+          setColumns(checkList);
         } else {
           state.checkedList = [];
-          table.setColumns([]);
+          setColumns([]);
         }
       }
 
@@ -257,7 +258,7 @@
         checkedList.sort((prev, next) => {
           return sortList.indexOf(prev) - sortList.indexOf(next);
         });
-        table.setColumns(checkedList);
+        setColumns(checkedList);
       }
 
       // reset columns
@@ -266,7 +267,7 @@
         state.checkAll = true;
         plainOptions.value = unref(cachePlainOptions);
         plainSortOptions.value = unref(cachePlainOptions);
-        table.setColumns(table.getCacheColumns());
+        setColumns(table.getCacheColumns());
       }
 
       // Open the pop-up window for drag and drop initialization
@@ -298,7 +299,7 @@
 
               plainSortOptions.value = columns;
               plainOptions.value = columns;
-              table.setColumns(columns);
+              setColumns(columns);
             },
           });
           initSortable();
@@ -335,7 +336,21 @@
           item.width = 100;
         }
         table.setCacheColumnsByField?.(item.dataIndex, { fixed: isFixed });
+        setColumns(columns);
+      }
+
+      function setColumns(columns: BasicColumn[] | string[]) {
         table.setColumns(columns);
+        const data: ColumnChangeParam[] = unref(plainOptions).map((col) => {
+          const visible =
+            columns.findIndex(
+              (c: BasicColumn | string) =>
+                c === col.value || (typeof c !== 'string' && c.dataIndex === col.value)
+            ) !== -1;
+          return { dataIndex: col.value, fixed: col.fixed, visible };
+        });
+
+        emit('columns-change', data);
       }
 
       return {

+ 9 - 4
src/components/Table/src/components/settings/index.vue

@@ -2,13 +2,13 @@
   <div class="table-settings">
     <RedoSetting v-if="getSetting.redo" />
     <SizeSetting v-if="getSetting.size" />
-    <ColumnSetting v-if="getSetting.setting" />
+    <ColumnSetting v-if="getSetting.setting" @columns-change="handleColumnChange" />
     <FullScreenSetting v-if="getSetting.fullScreen" />
   </div>
 </template>
 <script lang="ts">
   import type { PropType } from 'vue';
-  import type { TableSetting } from '../../types/table';
+  import type { TableSetting, ColumnChangeParam } from '../../types/table';
 
   import { defineComponent, computed } from 'vue';
 
@@ -33,7 +33,8 @@
         default: () => ({}),
       },
     },
-    setup(props) {
+    emits: ['columns-change'],
+    setup(props, { emit }) {
       const { t } = useI18n();
 
       const getSetting = computed((): TableSetting => {
@@ -46,7 +47,11 @@
         };
       });
 
-      return { getSetting, t };
+      function handleColumnChange(data: ColumnChangeParam[]) {
+        emit('columns-change', data);
+      }
+
+      return { getSetting, t, handleColumnChange };
     },
   });
 </script>

+ 7 - 2
src/components/Table/src/hooks/useTableHeader.ts

@@ -1,5 +1,5 @@
 import type { ComputedRef, Slots } from 'vue';
-import type { BasicTableProps } from '../types/table';
+import type { BasicTableProps, InnerHandlers } from '../types/table';
 
 import { unref, computed, h } from 'vue';
 import TableHeader from '../components/TableHeader.vue';
@@ -7,7 +7,11 @@ import TableHeader from '../components/TableHeader.vue';
 import { isString } from '/@/utils/is';
 import { getSlot } from '/@/utils/helper/tsxHelper';
 
-export function useTableHeader(propsRef: ComputedRef<BasicTableProps>, slots: Slots) {
+export function useTableHeader(
+  propsRef: ComputedRef<BasicTableProps>,
+  slots: Slots,
+  handlers: InnerHandlers
+) {
   const getHeaderProps = computed((): Recordable => {
     const { title, showTableSetting, titleHelpMessage, tableSetting } = unref(propsRef);
     const hideTitle = !slots.tableTitle && !title && !slots.toolbar && !showTableSetting;
@@ -26,6 +30,7 @@ export function useTableHeader(propsRef: ComputedRef<BasicTableProps>, slots: Sl
                 titleHelpMessage,
                 showTableSetting,
                 tableSetting,
+                onColumnsChange: handlers.onColumnsChange,
               } as Recordable,
               {
                 ...(slots.toolbar

+ 12 - 0
src/components/Table/src/types/table.ts

@@ -381,6 +381,8 @@ export interface BasicTableProps<T = any> {
    * @param expandedRows
    */
   onExpandedRowsChange?: (expandedRows: string[] | number[]) => void;
+
+  onColumnsChange?: (data: ColumnChangeParam[]) => void;
 }
 
 export type CellFormat =
@@ -427,3 +429,13 @@ export interface BasicColumn extends ColumnProps {
   // 业务控制是否显示
   ifShow?: boolean | ((column: BasicColumn) => boolean);
 }
+
+export type ColumnChangeParam = {
+  dataIndex: string;
+  fixed: boolean | 'left' | 'right' | undefined;
+  visible: boolean;
+};
+
+export interface InnerHandlers {
+  onColumnsChange: (data: ColumnChangeParam[]) => void;
+}

+ 8 - 1
src/views/demo/table/Basic.vue

@@ -11,6 +11,7 @@
       :bordered="border"
       showTableSetting
       :pagination="pagination"
+      @columns-change="handleColumnChange"
     >
       <template #toolbar>
         <a-button type="primary" @click="toggleCanResize">
@@ -29,7 +30,7 @@
 </template>
 <script lang="ts">
   import { defineComponent, ref } from 'vue';
-  import { BasicTable } from '/@/components/Table';
+  import { BasicTable, ColumnChangeParam } from '/@/components/Table';
   import { getBasicColumns, getBasicData } from './tableData';
 
   export default defineComponent({
@@ -56,6 +57,11 @@
       function toggleBorder() {
         border.value = !border.value;
       }
+
+      function handleColumnChange(data: ColumnChangeParam[]) {
+        console.log('ColumnChanged', data);
+      }
+
       return {
         columns: getBasicColumns(),
         data: getBasicData(),
@@ -68,6 +74,7 @@
         toggleLoading,
         toggleBorder,
         pagination,
+        handleColumnChange,
       };
     },
   });

+ 4 - 1
src/views/demo/table/UseTable.vue

@@ -20,7 +20,7 @@
 </template>
 <script lang="ts">
   import { defineComponent } from 'vue';
-  import { BasicTable, useTable } from '/@/components/Table';
+  import { BasicTable, ColumnChangeParam, useTable } from '/@/components/Table';
   import { getBasicColumns, getBasicShortColumns } from './tableData';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { demoListApi } from '/@/api/demo/table';
@@ -58,6 +58,9 @@
         rowSelection: {
           type: 'checkbox',
         },
+        onColumnsChange: (data: ColumnChangeParam[]) => {
+          console.log('ColumnsChanged', data);
+        },
       });
 
       function changeLoading() {