vxe-table 实现横向树列表

Traveller

开发过程中,很多产品经理都喜欢做些花里胡哨的表格展示,以下是一种常见的表格展示方式,看上去好像很复杂,实现起来很简单,下面看看代码怎么实现

1eb174040615421ec8ec2d105214d0f.png

组件实现主要围绕vxe-talble-v3,这款基于vue的表格框架能节省很大的功夫


template

<template>
  <vxe-table
    border
    height="600"
    :scroll-y="{ enabled: false }"
    :span-method="rowspanMethod"
    :data="tableData"
    align="center"
  >
    <vxe-column field="sort" width="150" title="序号"></vxe-column>
    <vxe-column field="type" width="250" title="类型" :formatter="formatterType"> </vxe-column>
    <vxe-colgroup title="验收项目"  v-if="deepLevel>0">
        <vxe-column v-for="(item,idx) in deepLevel" :key="idx" :field="`name${item}`" header-class-name="header"></vxe-column>
    </vxe-colgroup>

    <vxe-column field="content" type="html"  width="350" title="设计规范要求及规范规定">
       <template #default="{ row }">
         <div class="cellContent" v-if="XEUtils.isArray(row.content)"> 
           <p @click="cellLink(item)" v-for="(item,idx) in row.content" :key="idx"><i class="el-icon-paperclip icon"></i><span class="link">{{item.provisions_info}}</span></p>
         </div>
         <span v-else>{{row.content}}</span>
        </template>
    </vxe-column>
  </vxe-table>
</template>

js

import XEUtils from "xe-utils";
export default {
  data() {
    return {
      tableData: [],
      acceptance_item: [],
      deepLevel:0,
      XEUtils:XEUtils
    };
  },
  created() {
    
    setTimeout(() => {
      // 获取api数据
      this.acceptance_item = this.getData();
      this.acceptance_item.forEach((item,idx)=>{
        item.sort = idx+1+''
      })
      let that = this;
      // 遍历api树形结构层数,标记最深层
      function arrLevel(arr,lv){
        if(!arr || !arr.length) return;
        arr.forEach(item=>{
          that.deepLevel = lv>that.deepLevel?lv:that.deepLevel;
          if(item.children && item.children.length){
            arrLevel(item.children,lv+1)
          }
        })
      }
      // 标记最深层赋值,vxetable在渲染出去
      arrLevel(this.acceptance_item,1)
      console.log(this.deepLevel)
      this.toColTreeData(this.acceptance_item)
    }, 2000); 
  },
  methods: {
    // 将普通树结构转换为横向树列表
    toColTreeData(treeData) {
      const options = { children: "children" };
      const list = [];
      const keyMap = {};
      XEUtils.eachTree(
        treeData,
        (item, index, result, paths, parent) => {
          item, index, result, paths, parent;
          keyMap[item.uid] = item;
          item.keys = parent ? parent.keys.concat([item.uid]) : [item.uid];
          if (!item.children || !item.children.length) {
            const row = {};
            item.keys.forEach((key, index) => {
              const level = index + 1;
              const obj = keyMap[key];
              row[`id${level}`] = obj.uid;
              // 第1层赋值序号和类型
              if(level==1){
                row.sort = obj.sort
                row.type = obj.type
              }
              // content里面层会覆盖外面层
              let content = obj.content?obj.content:obj.provisions
              row.content = content;
              // name遍历整个结构的所有name
              row[`name${level}`] = obj.name

            });
            list.push(row);
          }
        },
        options
      );
      this.keyMap = keyMap;
      console.log(list)
      this.tableData = list
    },
    formatterType ({ cellValue }) {
      return cellValue==1?"主控项目": cellValue == 2? "一般项目":""
    },
    cellLink(e){
      debugger
    },
    // 通用行合并函数(将相同多列数据合并为一行)
    rowspanMethod({ row, _rowIndex, column,_columnIndex, visibleData }) {
      let that = this;
      let arr = []
      for(let i=0;i<this.deepLevel;i++){
        arr.push(`name${i+1}`)
      }
      const fields =[...arr,...["type","sort"]];
      const cellValue = row[column.property];
      if (cellValue && fields.includes(column.property)) {
        const prevRow = visibleData[_rowIndex - 1];
        let nextRow = visibleData[_rowIndex + 1];
        if (prevRow && prevRow[column.property] === cellValue) {
          return { rowspan: 0, colspan: 0 };
        } else {
          let countRowspan = 1;
          while (nextRow && nextRow[column.property] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex];
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 };
          }
        }
      }
      // 用point标记name+'n'
      let point = ''
      Object.keys(row).forEach(item=>{
        if(item.indexOf('name')>-1 && item != `name${that.deepLevel}`){
          point = item;
        }
      })
      // point 与 column.property 相等时,操作当前单元格横移拉伸
      if(point == column.property && !row[`name${that.deepLevel}`]){
          return { rowspan: 1, colspan: this.deepLevel - ( parseInt(point.split('name')[1]) - 1 ) }
      }
      // 将undefined的单元格隐藏
      if(cellValue==undefined){
        return { rowspan: 0, colspan: 0 }
      }

    },
    getData(){
      const  data = [{
          id: 10,
          uid: "317218091849220096",
          puid: "0",
          type: 1,
          name: "1",
          content: "钢筋",
          provisions: [
            {
              provisions_id: "",
              provisions_info: "",
              specification_id: "",
            },
          ],
          children: [
            {
              id: 9,
              uid: "317218091849220097",
              puid: "317218091849220096",
              type: 0,
              name: "1.1",
              content: "",
              provisions: [
                {
                  provisions_id: "1",
                  provisions_info: "钢筋",
                  specification_id: "1",
                },
                {
                  provisions_id: "2",
                  provisions_info: "混凝土",
                  specification_id: "1",
                },
              ],
              children: [],
            },
            {
              id: 9,
              uid: "317218091849220200",
              puid: "317218091849220096",
              type: 0,
              name: "1.2",
              content: "",
              provisions: [
                {
                  provisions_id: "3",
                  provisions_info: "钢筋1",
                  specification_id: "1",
                },
                {
                  provisions_id: "4",
                  provisions_info: "混凝土1",
                  specification_id: "1",
                },
              ],
              children: [],
            },
            {
              id: 10,
              uid: "317218091849220201",
              puid: "317218091849220096",
              type: 0,
              name: "1.3",
              content: "",
              provisions: [
                {
                  provisions_id: "5",
                  provisions_info: "钢筋2",
                  specification_id: "1",
                },
                {
                  provisions_id: "6",
                  provisions_info: "混凝土2",
                  specification_id: "1",
                },
              ],
              children: [
                // {
                //   id: 11,
                //   uid: "317218091849220202",
                //   puid: "317218091849220201",
                //   type: 0,
                //   name: "1.3.1",
                //   content: "一般323",
                //   provisions: [
                //     {
                //       provisions_id: "",
                //       provisions_info: "",
                //       specification_id: "",
                //     },
                //   ],
                //   children: [],
                // },
              ],
            },
          ],
        },
        {
          id: 13,
          uid: "317218091849220098",
          puid: "0",
          type: 2,
          name: "2",
          content: "",
          provisions: [
            {
              provisions_id: "",
              provisions_info: "",
              specification_id: "",
            },
          ],
          children: [
            {
              id: 12,
              uid: "317218091849220099",
              puid: "317218091849220098",
              type: 0,
              name: "2.1",
              content: "",
              provisions: [
                {
                  provisions_id: "",
                  provisions_info: "",
                  specification_id: "",
                },
              ],
              children: [
                {
                  id: 11,
                  uid: "317218091849220100",
                  puid: "317218091849220099",
                  type: 0,
                  name: "2.1.1",
                  content: "一般",
                  provisions: [
                    {
                      provisions_id: "",
                      provisions_info: "",
                      specification_id: "",
                    },
                  ],
                  children: [],
                },
                {
                  id: 11,
                  uid: "317218091849220101",
                  puid: "317218091849220099",
                  type: 0,
                  name: "2.1.2",
                  content: "一般",
                  provisions: [
                    {
                      provisions_id: "",
                      provisions_info: "",
                      specification_id: "",
                    },
                  ],
                  children: [],
                },
              ],
            },
          ],
        }]
        return data
    }
  },
};

scss

.vxe-table{
  // 隐藏空表头
  &::v-deep .header {
    display: none;
  }
  &::v-deep .cellContent {
    .link{
      border-bottom: 1px solid #7ca8fb;
      color: #7ca8fb;
      cursor: pointer;
      margin-left: 5px;
      &:hover{
        border-bottom: 1px solid blue;
        color: blue;
      }
    }
  }
} 
阅读 1.8k
3 声望
1 粉丝
0 条评论
3 声望
1 粉丝
文章目录
宣传栏