Browse Source

feat(BasicTable): table enable accordion expand (#3533). resolve #3525

xachary 1 year ago
parent
commit
abae7f3295

+ 3 - 5
src/components/Table/src/BasicTable.vue

@@ -22,6 +22,7 @@
       v-show="getEmptyDataIsShowTable"
       @change="handleTableChange"
       @resize-column="setColumnWidth"
+      @expand="handleTableExpand"
     >
       <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
         <slot :name="item" v-bind="data || {}"></slot>
@@ -207,11 +208,8 @@
 
   const { getRowClassName } = useTableStyle(getProps, prefixCls);
 
-  const { getExpandOption, expandAll, expandRows, collapseRows, collapseAll } = useTableExpand(
-    getProps,
-    tableData,
-    emit,
-  );
+  const { getExpandOption, expandAll, expandRows, collapseRows, collapseAll, handleTableExpand } =
+    useTableExpand(getProps, tableData, emit);
 
   const handlers: InnerHandlers = {
     onColumnsChange: (data: ColumnChangeParam[]) => {

+ 69 - 8
src/components/Table/src/hooks/useTableExpand.ts

@@ -1,6 +1,6 @@
 import type { ComputedRef, Ref } from 'vue';
 import type { BasicTableProps } from '../types/table';
-import { computed, unref, ref, toRaw } from 'vue';
+import { computed, unref, ref, toRaw, nextTick } from 'vue';
 import { ROW_KEY } from '../const';
 
 export function useTableExpand(
@@ -20,8 +20,8 @@ export function useTableExpand(
   });
 
   const getExpandOption = computed(() => {
-    const { isTreeTable } = unref(propsRef);
-    if (!isTreeTable) return {};
+    const { isTreeTable, expandRowByClick } = unref(propsRef);
+    if (!isTreeTable && !expandRowByClick) return {};
 
     return {
       expandedRowKeys: unref(expandedRowKeys),
@@ -43,15 +43,15 @@ export function useTableExpand(
 
   function expandRows(keys: (string | number)[]) {
     // use row ID expands the specified table row
-    const { isTreeTable } = unref(propsRef);
-    if (!isTreeTable) return;
+    const { isTreeTable, expandRowByClick } = unref(propsRef);
+    if (!isTreeTable && !expandRowByClick) return;
     expandedRowKeys.value = [...expandedRowKeys.value, ...keys];
   }
 
   function collapseRows(keys: (string | number)[]) {
     // use row ID collapses the specified table row
-    const { isTreeTable } = unref(propsRef);
-    if (!isTreeTable) return;
+    const { isTreeTable, expandRowByClick } = unref(propsRef);
+    if (!isTreeTable && !expandRowByClick) return;
     expandedRowKeys.value = unref(expandedRowKeys).filter((key) => !keys.includes(key));
   }
 
@@ -68,5 +68,66 @@ export function useTableExpand(
     return keys;
   }
 
-  return { getExpandOption, expandAll, collapseAll, expandRows, collapseRows };
+  // 获取展开路径 keys
+  function getKeyPaths(
+    records: Recordable[],
+    rowKey: string,
+    childrenColumnName: string,
+    key: string | number,
+    paths: Array<string | number>,
+  ): boolean {
+    if (records.findIndex((record) => record[rowKey] === key) > -1) {
+      paths.push(key);
+      return true;
+    } else {
+      for (const record of records) {
+        const children = record[childrenColumnName];
+        if (
+          Array.isArray(children) &&
+          getKeyPaths(children, rowKey, childrenColumnName, key, paths)
+        ) {
+          paths.push(record[rowKey]);
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  // 手风琴展开
+  function expandRowAccordion(key: string | number, rowKey: string) {
+    const { childrenColumnName } = unref(propsRef);
+    const paths: Array<string | number> = [];
+    getKeyPaths(tableData.value, rowKey, childrenColumnName || 'children', key, paths);
+    expandedRowKeys.value = paths;
+  }
+
+  // 监听展开事件,用于支持手风琴展开效果
+  function handleTableExpand(expanded, record) {
+    // 手风琴开关
+    // isTreeTable 或 expandRowByClick 时支持
+    // rowKey 是字符串时支持
+    // 展开操作
+    if (
+      propsRef.value.accordion &&
+      (propsRef.value.isTreeTable || propsRef.value.expandRowByClick) &&
+      typeof getRowKey.value === 'string' &&
+      expanded
+    ) {
+      const rowKey = getRowKey.value as string;
+      nextTick(() => {
+        expandRowAccordion(record[rowKey], rowKey);
+      });
+    }
+  }
+
+  return {
+    getExpandOption,
+    expandAll,
+    collapseAll,
+    expandRows,
+    collapseRows,
+    expandRowAccordion,
+    handleTableExpand,
+  };
 }

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

@@ -148,6 +148,7 @@ export interface BasicTableProps<T = any> {
   // 点击行选中
   clickToRowSelect?: boolean;
   isTreeTable?: boolean;
+  accordion?: boolean; // isTreeTable 或 expandRowByClick 时支持
   // 自定义排序方法
   sortFn?: (sortInfo: SorterResult) => any;
   // 排序方法

+ 1 - 0
src/views/demo/table/ExpandTable.vue

@@ -48,6 +48,7 @@
     rowKey: 'id',
     canResize: false,
     expandRowByClick: true,
+    accordion: true, // 手风琴效果
     actionColumn: {
       width: 160,
       title: 'Action',

+ 1 - 0
src/views/demo/table/TreeTable.vue

@@ -17,6 +17,7 @@
   const [register, { expandAll, collapseAll, expandRows, collapseRows }] = useTable({
     title: '树形表格',
     isTreeTable: true,
+    accordion: true, // 手风琴效果
     rowSelection: {
       type: 'checkbox',
       getCheckboxProps(record: Recordable) {

+ 51 - 2
src/views/demo/table/tableData.tsx

@@ -294,13 +294,62 @@ export function getTreeTableData() {
         endTime: new Date().toLocaleString(),
         children: [
           {
-            id: `l2-${index}`,
+            id: `l2-${index}-1`,
             name: 'John Brown',
-            age: `1${index}`,
+            age: `1`,
             no: `${index + 10}`,
             address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
             beginTime: new Date().toLocaleString(),
             endTime: new Date().toLocaleString(),
+            children: [
+              {
+                id: `l3-${index}-1-1`,
+                name: 'John Brown',
+                age: `11`,
+                no: `11`,
+                address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
+                beginTime: new Date().toLocaleString(),
+                endTime: new Date().toLocaleString(),
+              },
+              {
+                id: `l3-${index}-1-2`,
+                name: 'John Brown',
+                age: `12`,
+                no: `12`,
+                address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
+                beginTime: new Date().toLocaleString(),
+                endTime: new Date().toLocaleString(),
+              },
+            ],
+          },
+          {
+            id: `l2-${index}-2`,
+            name: 'John Brown',
+            age: `2`,
+            no: `${index + 10}`,
+            address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
+            beginTime: new Date().toLocaleString(),
+            endTime: new Date().toLocaleString(),
+            children: [
+              {
+                id: `l3-${index}-2-1`,
+                name: 'John Brown',
+                age: `21`,
+                no: `21`,
+                address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
+                beginTime: new Date().toLocaleString(),
+                endTime: new Date().toLocaleString(),
+              },
+              {
+                id: `l3-${index}-2-2`,
+                name: 'John Brown',
+                age: `22`,
+                no: `22`,
+                address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
+                beginTime: new Date().toLocaleString(),
+                endTime: new Date().toLocaleString(),
+              },
+            ],
           },
         ],
       });