【el-table 实现C# GridView控件 根据GroupIndex 进行分组功能 支持多级 不同参数】

el-table 实现C# GridView控件 根据GroupIndex 进行分组功能 支持多级 不同参数

目的

呦呦呦,又碰见一个需求,要实现一个类似 C# GridView控件 根据GroupIndex 进行分组功能,好好好 你winform直接设置groupIndex组件内部处理渲染了,没有办法只能我们自己处理数据了。
在这里插入图片描述

思路

原理很简单就是用el-table的展开行

row-key 行数据的 Key,用来优化 Table 的渲染;这个一定要设置哦,而且不能重复,不然会有渲染问题
tree-props 渲染嵌套数据的配置选项
span-method 合并行或列的计算方法

在这里插入图片描述

实现方法

第一个版本 暂时写一个方法先实现 后续再优化

<template>
  <el-table
    ref="tableRef"
    :data="state.tableData"
    show-overflow-tooltip
    row-key="regItrId"
    default-expand-all
    :tree-props="{ children: 'children', hasChildren: 'true' }"
    :span-method="tableSpanMethod"
    height="80vh"
    border
  >
    <el-table-column width="80" :show-overflow-tooltip="false" align="center"></el-table-column>
    <el-table-column prop="regRegisterDate" label="保养时间" align="left" :formatter="groupNameFormtter" />
    <el-table-column prop="regContent" label="保养操作" min-width="100" align="center" />
    <el-table-column prop="regExp" label="保养备注" min-width="100" align="center" />
    <el-table-column prop="userName" label="操作人" min-width="100" align="center" />
    <el-table-column prop="overIntervalTime" label="超出保养时间" min-width="100" align="center" />
  </el-table>
</template>
<script setup lang="ts">
import { MultilevelDataGrouping, data } from "@/utils/format";
import { ElMessage } from "element-plus";

const state = reactive({
  tableData: [] as any
});

/** ###################### 表格 ###################### */
const tableRef = ref();

const groupNameFormtter = (row: any, column: any, cellValue: any, index: number) => {
  if (!row.children) {
    return row.regRegisterDate;
  } else {
    return row.groupsLable;
  }
};
// 合并行
const tableSpanMethod = (data: { row: any; column: any; rowIndex: number; columnIndex: number }) => {
  const { columnIndex } = data;
  if (data.row.children && columnIndex == 1) {
    return [1, 5];
  } else {
    return [1, 1];
  }
};

onMounted(() => {
  const { nodeList, parentNodeKeyList } = MultilevelDataGrouping(data, {
    id: "regItrId",
    groups: ["maiContent", "itrEname", "proName"],
    groupLables: ["保养内容:", "仪器:", "实验组:"]
  });
  state.tableData = nodeList;
  state.tableDataKeyList = parentNodeKeyList;
});
</script>
// 初始化 format.ts
export function MultilevelDataGrouping(
  data: any[],
  { id, groups, groupLables }: { id: string; groups: string[]; groupLables: string[] }
) {
  let TransitData = data;
  groups.forEach((groupKey, groupIndex) => {
    const groupMap = new Map();
    const nodeList: any[] = [];
    TransitData.forEach((node: any) => {
      const nodeId = node[id];
      const nodeGroup = node[groupKey];
      if (!groupMap.has(nodeGroup)) {
        const length = nodeList.length;
        groupMap.set(nodeGroup, length);
        const cloneNode: any = { ...node };
        cloneNode[id] = groupKey + nodeId ?? length;
        cloneNode["children"] = [];
        const label = groupLables ? groupLables[groupIndex] : "";
        cloneNode["groupsLable"] = label + (nodeGroup ?? "");
        nodeList.push(cloneNode);
      }
      const index = groupMap.get(nodeGroup);
      nodeList[index].children.push(node);
    });
    TransitData = nodeList;
  });
  return TransitData;
}

主要优化点说明:
类型定义:通过IDataNode接口和IGroupingParams以及IGroupingResult接口的定义,增强了函数的输入和输出的类型安全性。
参数校验:在函数的开始处添加了简单的参数校验逻辑,确保必要的参数存在且有效。
性能考虑:虽然原始算法已经相对高效,对于类型转换和数据处理进行了最小化,这里主要通过增强类型检查和优化代码结构来提升可读性和可维护性,而不是性能。需要注意的是,对于大多数情况,原算法的性能已经是可接受的;如果处理极大规模数据集,可能需要考虑更专门的算法优化。
代码可维护性和可读性:通过使用接口和类型定义,以及合理的参数校验,提升了代码的可维护性和可读性。

// 优化后 format.ts
interface IDataNode {
  [id: string]: any; // 使用字符串作为键,值可以是任意类型
  children?: IDataNode[]; // 可选的子节点数组
  groupsLable?: string; // 可选的节点所属分组标签
}

interface IGroupingParams {
  id: string; // 用于标识节点的属性名
  groups: string[]; // 用于分组的属性名数组
  groupLables?: string[]; // 可选的分组标签数组,对应groups中的每个分组
}

interface IGroupingResult {
  nodeList: IDataNode[]; // 分组后的节点数组
  parentNodeKeyList: string[]; // 分组后所有父节点的键值数组
}

/**
 * 多级数据分组函数
 * @param data 要进行分组的数据节点数组,每个节点应包含指定的id属性
 * @param params 分组参数,包括需要分组的属性名和可选的分组标签
 * @return 返回一个对象,包含分组后的节点数组和父节点键值数组
 * @author: 
 */
export function MultilevelDataGrouping(data: IDataNode[], params: IGroupingParams): IGroupingResult {
  // 校验输入参数
  if (!params.id || !Array.isArray(params.groups)) {
    throw new Error("Invalid parameters: 'id' and 'groups' are required.");
  }

  const { id, groups, groupLables = [] } = params;
  const parentNodeKeyList: string[] = [];
  let TransitData = [...data]; // 用于分组操作的数据副本

  // 遍历每个分组条件,依次进行分组
  groups.forEach((groupKey, groupIndex) => {
    const groupMap = new Map<string, number>(); // 用于映射节点组到其在节点数组中的索引
    const nodeList: IDataNode[] = []; // 当前分组的节点数组

    // 遍历数据,为每个节点创建或找到对应的分组
    TransitData.forEach(node => {
      const nodeId = node[id];
      const nodeGroup = node[groupKey];

      // 如果节点组尚未存在于节点数组中,则添加新节点组
      if (!groupMap.has(nodeGroup)) {
        const length = nodeList.length;
        groupMap.set(nodeGroup, length);

        // 克隆节点,并适应分组信息
        const cloneNode: IDataNode = { ...node };
        cloneNode[id] = `${groupKey}${nodeId ?? length}`;
        cloneNode["children"] = [];
        cloneNode["groupsLable"] = `${groupLables[groupIndex] ?? ""}${nodeGroup ?? ""}`;

        nodeList.push(cloneNode);
        parentNodeKeyList.push(cloneNode[id]);
      }

      // 将节点添加到对应的分组中
      const index = groupMap.get(nodeGroup)!;
      nodeList[index].children!.push(node);
    });

    // 更新数据副本为当前分组的节点数组,以进行下一次分组
    TransitData = nodeList;
  });

  // 返回分组结果
  return { nodeList: TransitData, parentNodeKeyList };
}
  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值