当前位置: 首页 > 知识库问答 >
问题:

element-plus - element plus和这种table合并的逻辑怎么写?

巩枫
2024-09-15

image.png

"Data": [
        {
            "PatientName": "导管室光盘刻录",
            "sm": 5376.0,
            "ct": 216.0,
            "t": "微信",
            "total": 7186.0
        },
        {
            "PatientName": "导管室光盘刻录",
            "sm": 405.0,
            "ct": 16.0,
            "t": "支付宝",
            "total": 7186.0
        },
        {
            "PatientName": "导管室光盘刻录",
            "sm": 1405.0,
            "ct": 119.0,
            "t": "聚合付",
            "total": 7186.0
        },
        {
            "PatientName": "小儿内科(二)",
            "sm": 561.1,
            "ct": 133.0,
            "t": "微信",
            "total": 576.1
        },
        {
            "PatientName": "小儿内科(二)",
            "sm": 15.0,
            "ct": 9.0,
            "t": "支付宝",
            "total": 576.1
        },
        {
            "PatientName": "医疗服务(病历复印)",
            "sm": 12040.0,
            "ct": 888.0,
            "t": "支付宝",
            "total": 12040.0
        },
        {
            "PatientName": "医疗服务(营养科)",
            "sm": 4935.4,
            "ct": 80.0,
            "t": "支付宝",
            "total": 4935.4
        },
        {
            "PatientName": "医疗服务费(急诊))",
            "sm": 3203.6,
            "ct": 162.0,
            "t": "微信",
            "total": 3344.8
        },
        {
            "PatientName": "医疗服务费(急诊))",
            "sm": 141.2,
            "ct": 5.0,
            "t": "支付宝",
            "total": 3344.8
        },
        {
            "PatientName": "合计",
            "sm": 28082.3,
            "ct": 1628.0,
            "t": "",
            "total": 28082.3
        }
    ],
<el-table  :span-method="objectSpanMethod" :data="data.list" border stripe>
      <el-table-column label="科室名称" prop="PatientName" align="center"></el-table-column>
      <el-table-column prop="ct" align="center" label="收费人数">
      </el-table-column>
      <el-table-column prop="t" align="center" label="支付方式">
      </el-table-column>
      <el-table-column prop="sm" align="center" label="收入金额">
      </el-table-column>
      <el-table-column prop="total" align="center" label="合计">
      </el-table-column>
    </el-table>

我在objectSpanMethod中写逻辑,写了半天写不成,最关键的是需要合并的行个数不定,1,2,3,4,。。行合并都有可能。

const objectSpanMethod = ({row,column,rowIndex,columnIndex}) => {
  let count=data.list.filter((item)=>item.PatientName===row.PatientName).length
  if (columnIndex === 0 || columnIndex === 4) {
    /*
    if (rowIndex % count === 0) {
      return {
        rowspan: 2,
        colspan: 1,
      }
    } else {
      return {
        rowspan: 0,
        colspan: 0,
      }
    }
    */
  }
}

共有4个答案

闻人宏盛
2024-09-15
<template>
  <el-table :span-method="objectSpanMethod"
            :data="tableData"
            border
            stripe>
    <el-table-column label="科室名称"
                     prop="PatientName"
                     align="center"></el-table-column>
    <el-table-column prop="sm"
                     align="center"
                     label="收入金额">
    </el-table-column>
    <el-table-column prop="total"
                     align="center"
                     label="合计">
    </el-table-column>
  </el-table>
</template>

<script lang="ts">
  import { computed, ref } from 'vue'

  /**
   * 合并单元格
   * @param rows 数据
   * @param field 以此字段合并
   * @returns 合并单元格 [起始, 长度]
   */
  function getMergeList(rows: Record<string, any>[], field: string): [number, number][] {
    const result: [number, number][] = [];
    let start = 0;
    let currentValue = rows[0]?.[field];

    for (let i = 1; i <= rows.length; i++) {
      if (i === rows.length || rows[i][field] !== currentValue) {
        result.push([start, i - start]);
        start = i;
        currentValue = rows[i]?.[field];
      }
    }

    return result;
  }

  export default {
    setup() {
      const tableData = ref([
        {
          "PatientName": "导管室光盘刻录",
          "sm": 5376.0,
          "total": 7186.0
        },
        {
          "PatientName": "导管室光盘刻录",
          "sm": 405.0,
          "total": 7186.0
        },
      ]);

      // 合并信息
      const dateMerges = computed(() => getMergeList(tableData.value, 'PatientName'));

      const objectSpanMethod = ({ column, rowIndex }) => {
        if (['PatientName', 'total'].includes(column.property)) {
          for (const [start, span] of dateMerges.value) {
            if (rowIndex === start) {
              return { rowspan: span, colspan: 1 }
            } else if (rowIndex > start && rowIndex < start + span) {
              return { rowspan: 0, colspan: 0 }
            }
          }
        }
        return { rowspan: 1, colspan: 1 }
      }

      return {
        tableData,
        objectSpanMethod,
      }
    },
  }
</script>
云京
2024-09-15
let arr = [
    {
        "PatientName": "导管室光盘刻录",
        "sm": 5376.0,
        "ct": 216.0,
        "t": "微信",
        "total": 7186.0
    },
    {
        "PatientName": "导管室光盘刻录",
        "sm": 405.0,
        "ct": 16.0,
        "t": "支付宝",
        "total": 7186.0
    },
    {
        "PatientName": "导管室光盘刻录",
        "sm": 1405.0,
        "ct": 119.0,
        "t": "聚合付",
        "total": 7186.0
    },
    {
        "PatientName": "小儿内科(二)",
        "sm": 561.1,
        "ct": 133.0,
        "t": "微信",
        "total": 576.1
    },
    {
        "PatientName": "小儿内科(二)",
        "sm": 15.0,
        "ct": 9.0,
        "t": "支付宝",
        "total": 576.1
    },
    {
        "PatientName": "医疗服务(病历复印)",
        "sm": 12040.0,
        "ct": 888.0,
        "t": "支付宝",
        "total": 12040.0
    },
    {
        "PatientName": "医疗服务(营养科)",
        "sm": 4935.4,
        "ct": 80.0,
        "t": "支付宝",
        "total": 4935.4
    },
    {
        "PatientName": "医疗服务费(急诊))",
        "sm": 3203.6,
        "ct": 162.0,
        "t": "微信",
        "total": 3344.8
    },
    {
        "PatientName": "医疗服务费(急诊))",
        "sm": 141.2,
        "ct": 5.0,
        "t": "支付宝",
        "total": 3344.8
    },
    {
        "PatientName": "合计",
        "sm": 28082.3,
        "ct": 1628.0,
        "t": "",
        "total": 28082.3
    }
];

// 统计每个 PatientName 出现的次数
let counts = arr.reduce((acc, item) => {
    acc[item.PatientName] = (acc[item.PatientName] || 0) + 1;
    return acc;
}, {});

// 为每个 PatientName 添加 index 和 sum
let indexMap = {};

arr.forEach(item => {
    const name = item.PatientName;
    
    // 如果还没有该 PatientName 的索引计数器,则初始化
    if (!indexMap[name]) {
        indexMap[name] = 1;
    }

    // 添加 sum 和 index 属性
    item.sum = counts[name];
    item.index = indexMap[name];

    // 更新该 PatientName 的索引计数器
    indexMap[name]++;
});

console.log(arr);

我用gpt弄好了

寇景明
2024-09-15
const data = [
  {
    "PatientName": "导管室光盘刻录",
    "sm": 5376.0,
    "ct": 216.0,
    "t": "微信",
    "total": 7186.0
  },
  {
    "PatientName": "导管室光盘刻录",
    "sm": 405.0,
    "ct": 16.0,
    "t": "支付宝",
    "total": 7186.0
  },
  {
    "PatientName": "导管室光盘刻录",
    "sm": 1405.0,
    "ct": 119.0,
    "t": "聚合付",
    "total": 7186.0
  },
  {
    "PatientName": "小儿内科(二)",
    "sm": 561.1,
    "ct": 133.0,
    "t": "微信",
    "total": 576.1
  },
  {
    "PatientName": "小儿内科(二)",
    "sm": 15.0,
    "ct": 9.0,
    "t": "支付宝",
    "total": 576.1
  },
  {
    "PatientName": "医疗服务(病历复印)",
    "sm": 12040.0,
    "ct": 888.0,
    "t": "支付宝",
    "total": 12040.0
  },
  {
    "PatientName": "医疗服务(营养科)",
    "sm": 4935.4,
    "ct": 80.0,
    "t": "支付宝",
    "total": 4935.4
  },
  {
    "PatientName": "医疗服务费(急诊))",
    "sm": 3203.6,
    "ct": 162.0,
    "t": "微信",
    "total": 3344.8
  },
  {
    "PatientName": "医疗服务费(急诊))",
    "sm": 141.2,
    "ct": 5.0,
    "t": "支付宝",
    "total": 3344.8
  },
  {
    "PatientName": "合计",
    "sm": 28082.3,
    "ct": 1628.0,
    "t": "",
    "total": 28082.3
  }
];

const findAdjacentDuplicates = arr => {
  let results = []; // 用于存储结果的数组

  for (let i = 0; i < arr.length - 1; i++) { // 遍历数组,直到倒数第二个元素
    if (arr[i].PatientName === arr[i + 1].PatientName) { // 检查当前元素是否与下一个元素相同
      let count = 1; // 至少有两个相同的元素
      let start = i; // 记录起始位置
      // 继续向后检查,直到找到不同的元素
      while (i + 1 < arr.length && arr[i].PatientName === arr[i + 1].PatientName) {
        count++;
        i++;
      }
      // 将结果添加到数组中
      results.push({ start: start, length: count });
    }
  }

  return results;
}

console.log(findAdjacentDuplicates(data))

objectSpanMethod里面判断在不在范围内就行了

陈业
2024-09-15

在你的情况中,由于合并的行数可能不同,你需要为每个PatientName分组动态地计算需要合并的行数。这里的关键是使用一个辅助结构(如Map或对象)来存储每个PatientName最后一次出现的索引,以及到当前为止遇到的相同PatientName的数量。

下面是一个示例实现,该实现假设你的数据已经按PatientName分组排序(如果不是,你可能需要先对数据进行排序)。

<script>
export default {
  data() {
    return {
      data: {
        list: [
          // 你的数据数组
        ]
      },
      // 用于记录每个PatientName的合并信息
      spanMap: new Map()
    };
  },
  created() {
    // 初始化spanMap
    this.data.list.forEach((item, index) => {
      if (!this.spanMap.has(item.PatientName)) {
        // 第一个遇到此PatientName时,初始化计数和索引
        this.spanMap.set(item.PatientName, { count: 1, lastIndex: index });
      } else {
        // 更新计数
        const { count } = this.spanMap.get(item.PatientName);
        this.spanMap.set(item.PatientName, { count: count + 1, lastIndex: index });
      }
    });
  },
  methods: {
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0 || columnIndex === 4) { // 假设你想要合并第一列和第五列
        const patientName = row.PatientName;
        const spanInfo = this.spanMap.get(patientName);
        if (rowIndex === spanInfo.lastIndex) {
          // 这是当前PatientName组的最后一行,设置rowspan
          return {
            rowspan: spanInfo.count,
            colspan: 1
          };
        } else {
          // 对于组内的其他行,不渲染这些单元格
          return {
            rowspan: 0,
            colspan: 0
          };
        }
      }
    }
  }
};
</script>

在这个示例中,spanMap是一个Map,其键是PatientName,值是一个对象,包含count(当前PatientName的总行数)和lastIndex(该PatientName最后一次出现的索引)。在objectSpanMethod中,我们检查当前行是否是该PatientName组的最后一行,并据此设置rowspan。如果是组内的其他行,我们将rowspancolspan都设置为0,以便这些单元格不会被渲染。

注意:确保你的数据在传递给表格之前已经按照PatientName进行了排序,否则这种方法将不会按预期工作。如果数据未排序,你可能需要在处理之前先对其进行排序。

 类似资料: