前端数据处理 , 数据排序 , table 数据整理 ,el-table根据数据动态合并单元格

最近被一个小小的前端数据处理脑子整的有点糊了,就是在大脑里整个的思路很简单,但是写完代码一跑确有问题,顿时陷入了思路和代码实现的对抗,改来改去最终是我总结的是对嵌套的for 循环不仔细分析是很容易出问题的。记录一下脑子糊了之后走不动的感受,教训是要慢下来,对自己的每一部分代码进行思路对应的检查。

第一版需求:

Select 病种选择,选择的数据在table 中进行展示,一类病种只能选择同一个医院,因此选择后的同类病种要放在一行中,数据展示按照选择的顺序展示,每一个病种可以单独删除。最终的效果图如下

实现思路,选择框选择的病种会选择到一个集合中,根据选择的集合,根据病种分类整理适合table 展示的数据,监听select控件的change时间,实现选择数据和下方table 的联动。每次change 都会按照当前的选择重新整合table 数据。

以上思路增加选择项的时候确实没有问题,按照选择的顺序 逆序删除也没有问题,但是选择框中的数据是按照选择顺序加入的,但是同类病种如果最先加入的被删除,change 时间触发后再整理table 数据,会导致table 原有数据上下行的交替,这种效果显然不符合正常的显示逻辑。

解决思路:

在整理table 数据之前,首先要把table 中已有的数据放在最前面,之后把新增的数据放在后面,再按照顺序整理table 数据

具体代码如下:

<template>
  <div class="containerbox">
    <el-select
      v-model="selectedDiseases"
      @change="changeDisease"
      value-key="diseaseNo"
      multiple
      collapse-tags
      style="margin-left: 20px;"
      placeholder="请选择申请病重"
      :multiple-limit="8"
      popper-class="sort_select"
    >
      <el-option v-for="item in allDisease" :key="item.diseaseNo" :label="item.diseaseName" :value="item"> </el-option>
    </el-select>

    <el-table :data="tableData" style="width: 100%" border center>
      <el-table-column label="选择申请病种" :min-width="180" align="center">
        <template slot-scope="scope">
          <!--  -->
          <span class="diseaseItem" v-for="item in scope.row.itemInfo" :key="item.diseaseNo"
            >{{ item.diseaseName }}
            <el-button type="text" class="el-icon-remove-outline" @click="removeDisease(item)"></el-button>
          </span>
        </template>
      </el-table-column>
      <el-table-column prop="fixhospitalName" label="选择医院" :min-width="180" align="center"> </el-table-column>
      <el-table-column label="操作" align="center">
        <template slot-scope="scope">
          <el-button type="primary" @click="chooseHospital(scope.row)">请选择医院</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
import diseaseData from './disease.json'
export default {
  data() {
    return {
      tableData: [],
      allDisease: [],
      selectedDiseases: [],
      diseasesDto: []
    }
  },
  methods: {
    changeDisease(arr) {
      // 执行分组显示的问题
      // console.log(arr)
      // 根据当前选中的和之前选中的数据整合新的table 中应该展示的数据
      const tempTableData = this.tableData
      this.diseasesDto = []
      const oldDatas = []
      const newAdds = []
      this.tableData.forEach(row => {
        row.itemInfo.forEach(item => {
          oldDatas.push(item)
        })
      })
      // 先在新的选项中找到原来讯在的保留
      oldDatas.forEach(item => {
        const index = arr.findIndex(newItem => {
          return item.diseaseNo == newItem.diseaseNo
        })
        if (index != -1) {
          this.diseasesDto.push(item)
        }
      })
      // 把原来没加进去新增的加进入
      arr.forEach(item => {
        const index = this.diseasesDto.findIndex(inItem => {
          return inItem.diseaseNo == item.diseaseNo
        })
        if (index == -1) {
          this.diseasesDto.push(JSON.parse(JSON.stringify(item)))
        }
      })
      //从当前选中的病中深拷贝 1、如果已经是已经选择了医院的 保留医院 如果
      this.tableData = []
      this.diseasesDto.forEach(deepObj => {
        // 创建深拷贝的对象
        // const deepObj = JSON.parse(JSON.stringify(item))
        // 先判断tableData 中是否有这类数据 如果没有创建新的对象加入table data ,如果有的话在对应的itemInfo 中加入对应的item
        if (this.tableData.length == 0) {
          //还没加入过数据
          this.tableData.push({ fixhospitalName: deepObj.fixhospitalName, itemInfo: [deepObj] })
        } else {
          // 已经有数据 遍历里面的数据判断是否有这样的一类
          let inTable = false
          this.tableData.some(row => {
            //
            if (row.itemInfo[0].categoryNo == deepObj.categoryNo) {
              row.itemInfo.push(deepObj)
              inTable = true
            }
          })
          if (!inTable) {
            //如果没有在table 中 创建一个对象计入
            console.log('======')
            this.tableData.push({ fixhospitalName: deepObj.fixhospitalName, itemInfo: [deepObj] })
          }
        }
      })
      // console.log(this.tableData)
    },
    removeDisease(disease) {
      //删除选中集合中对应的数据
      const index = this.selectedDiseases.findIndex(item => {
        return item.diseaseNo == disease.diseaseNo
      })
      console.log(index)
      this.selectedDiseases.splice(index, 1)
      this.changeDisease(this.selectedDiseases)
      // this.tableData.some((item, rowIndex) => {
      //   const findedIndex = item.itemInfo.findIndex((ii, index) => {
      //     //判断如果有的话直接删除 删除后如果
      //     if (ii.diseaseNo == disease.diseaseNo) {
      //       item.itemInfo.splice(index, 1)
      //     }
      //     return ii.diseaseNo == disease.diseaseNo
      //   })
      //   if (findedIndex != -1) {
      //     // 判断删除后的row 是否还有信息
      //     if (item.itemInfo.length == 0) {
      //       this.tableData.splice(rowIndex, 1)
      //     }
      //     return true
      //   }
      // })
      // 删除table 中对应的数据
    }
  },
  mounted() {
    this.allDisease = diseaseData
    //生成模拟数据
    // const categoryNos = ['01', '02', '03', '04']
    // const categoryNames = ['精神类', '皮肤类', '结核类', '其他']
    // for (let i = 0; i < 20; i++) {
    //   const random = Math.floor(Math.random() * 4)
    //   const disease = {}
    //   disease.diseaseNo = '0' + i
    //   disease.diseaseName = '疾病' + i
    //   disease.categoryNo = categoryNos[random]
    //   disease.categoryName = categoryNames[random]
    //   this.allDisease.push(disease)
    // }
  }
}
</script>
<style lang="scss">
.containerbox {
  padding: 30px;
  text-align: center;
  .el-select {
    margin-top: 50px;
  }
  .el-table {
    margin-top: 200px;
  }
  .diseaseItem {
    margin-right: 20px;
    .el-button {
      color: red;
      // i {
      //   color: red;
      // }
    }
  }
}
</style>

需求改版:

需求刚写完的两天,因为要增加备足需求有变,改变后的需求涉及到单元格的合并单元格的需求,每个兵种占一行,增加备注列,其他操作和医院同一类的合并单元格,我的思路是,合并单元格仍然需要原来整理的tale 数据,因此保留,稍微改下页面渲染的数据结构,增加单元格合并的操作,效果图类似如下:

最终代码如下:

<template>
  <div class="containerbox">
    <el-select
      v-model="selectedDiseases"
      @change="changeDisease"
      value-key="diseaseNo"
      multiple
      collapse-tags
      style="margin-left: 20px;"
      placeholder="请选择申请病重"
      :multiple-limit="8"
      popper-class="sort_select"
    >
      <el-option v-for="item in allDisease" :key="item.diseaseNo" :label="item.diseaseName" :value="item"> </el-option>
    </el-select>

    <el-table :data="tableDataList" style="width: 100%" border center :span-method="tableSpanMethod">
      <el-table-column label="选择申请病种" :min-width="180" align="center">
        <template slot-scope="scope">
          <!--  -->
          <span class="diseaseItem" :key="scope.row.diseaseNo"
            >{{ scope.row.diseaseName }}
            <el-button type="text" class="el-icon-remove-outline" @click="removeDisease(scope.row)"></el-button>
          </span>
        </template>
      </el-table-column>
      <el-table-column prop="fixhospitalName" label="选择医院" :min-width="180" align="center"> </el-table-column>
      <el-table-column label="操作" align="center">
        <template slot-scope="scope">
          <el-button type="primary" @click="chooseHospital(scope.row)">请选择医院</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
import diseaseData from './disease.json'
export default {
  data() {
    return {
      tableDataList :[],
      tableData: [],
      allDisease: [],
      selectedDiseases: [],
      diseasesDto: []
    }
  },
  methods: {
    changeDisease(arr) {
      // 执行分组显示的问题
      // console.log(arr)
      // 根据当前选中的和之前选中的数据整合新的table 中应该展示的数据
      // const tempTableData = this.tableData
      this.diseasesDto = []
      const oldDatas = []
      const newAdds = []
      // this.tableData.forEach(row => {
      //   row.itemInfo.forEach(item => {
      //     oldDatas.push(item)
      //   })
      // })
      // 先在新的选项中找到原来讯在的保留
      this.tableDataList.forEach(item => {
        const index = arr.findIndex(newItem => {
          return item.diseaseNo == newItem.diseaseNo
        })
        if (index != -1) {
          this.diseasesDto.push(item)
        }
      })
      // 把原来没加进去新增的加进入
      arr.forEach(item => {
        const index = this.diseasesDto.findIndex(inItem => {
          return inItem.diseaseNo == item.diseaseNo
        })
        if (index == -1) {
          this.diseasesDto.push(JSON.parse(JSON.stringify(item)))
        }
      })
      //从当前选中的病中深拷贝 1、如果已经是已经选择了医院的 保留医院 如果
      this.tableData = []
      this.diseasesDto.forEach(deepObj => {
        // 创建深拷贝的对象
        // const deepObj = JSON.parse(JSON.stringify(item))
        // 先判断tableData 中是否有这类数据 如果没有创建新的对象加入table data ,如果有的话在对应的itemInfo 中加入对应的item
        if (this.tableData.length == 0) {
          //还没加入过数据
          this.tableData.push({ fixhospitalName: deepObj.fixhospitalName, itemInfo: [deepObj] })
        } else {
          // 已经有数据 遍历里面的数据判断是否有这样的一类
          let inTable = false
          this.tableData.some(row => {
            //
            if (row.itemInfo[0].categoryNo == deepObj.categoryNo) {
              row.itemInfo.push(deepObj)
              inTable = true
            }
          })
          if (!inTable) {
            //如果没有在table 中 创建一个对象计入
            console.log('======')
            this.tableData.push({ fixhospitalName: deepObj.fixhospitalName, itemInfo: [deepObj] })
          }
        }
      })
      
      // 修改策略 需要单独按照顺序拿出来每一个数据 之后再合并单元格
      this.tableDataList = []
      this.tableData.forEach(row=>{
        row.itemInfo.forEach(item=>{
          this.tableDataList.push(item)
        })
      })

      // console.log(this.tableData)
    },
    removeDisease(disease) {
      //删除选中集合中对应的数据
      const index = this.selectedDiseases.findIndex(item => {
        return item.diseaseNo == disease.diseaseNo
      })
      console.log(index)
      this.selectedDiseases.splice(index, 1)
      this.changeDisease(this.selectedDiseases)
      // this.tableData.some((item, rowIndex) => {
      //   const findedIndex = item.itemInfo.findIndex((ii, index) => {
      //     //判断如果有的话直接删除 删除后如果
      //     if (ii.diseaseNo == disease.diseaseNo) {
      //       item.itemInfo.splice(index, 1)
      //     }
      //     return ii.diseaseNo == disease.diseaseNo
      //   })
      //   if (findedIndex != -1) {
      //     // 判断删除后的row 是否还有信息
      //     if (item.itemInfo.length == 0) {
      //       this.tableData.splice(rowIndex, 1)
      //     }
      //     return true
      //   }
      // })
      // 删除table 中对应的数据
    },
    tableSpanMethod({row,column,rowIndex,columnIndex}){
      //合并单元格
      let spanList = []
      this.tableData.forEach(row=>{
        spanList.push({spanLen:row.itemInfo.length,spanIndex:0})
      })
      // 需要合并单元格的列
      if(columnIndex==1||columnIndex==2){
        let spanStartIndex = 0;
        spanList.forEach(item=>{
          item.spanIndex = spanStartIndex
          spanStartIndex +=item.spanLen
        })
      let spaned = false
      for(let i = 0;i<spanList.length;i++){
        if(rowIndex === spanList[i].spanIndex){
          spaned = true
          return {
            rowspan:spanList[i].spanLen,
            colspan:1
          }
        }
      }
      }
    }
  },
  mounted() {
    this.allDisease = diseaseData
    //生成模拟数据
    // const categoryNos = ['01', '02', '03', '04']
    // const categoryNames = ['精神类', '皮肤类', '结核类', '其他']
    // for (let i = 0; i < 20; i++) {
    //   const random = Math.floor(Math.random() * 4)
    //   const disease = {}
    //   disease.diseaseNo = '0' + i
    //   disease.diseaseName = '疾病' + i
    //   disease.categoryNo = categoryNos[random]
    //   disease.categoryName = categoryNames[random]
    //   this.allDisease.push(disease)
    // }
  }
}
</script>
<style lang="scss">
.containerbox {
  padding: 30px;
  text-align: center;
  .el-select {
    margin-top: 50px;
  }
  .el-table {
    margin-top: 200px;
  }
  .diseaseItem {
    margin-right: 20px;
    .el-button {
      color: red;
      // i {
      //   color: red;
      // }
    }
  }
}
</style>

以上记录一次有印象的数据处理 github 完整代码在demo 中 sortDemo.vue 文件

代码地址 :https://github.com/sandyzhi/mydemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值