关于布局这里不多说,上篇为此发过一篇,因需求布局稍微改动一下。移步至布局篇。如产品所说,一些数据是已封装好的,最后不要轻易动,既然这样、原本简单的需求必须由多接口返回数据,前端进行拼接并填充。后端提供3个接口供提取数据,分别是顶部任务对象,左侧树形结构,中间填充区域。
完整代码
<template><div class="box"><div class="leftSide"><el-row><el-col :span="24" class="general">项目名</el-col><el-col :span="24" class="general">操作</el-col><el-col :span="24" class="general">问题数</el-col></el-row><div class="tableHead"><template v-for="(i,j) in tableHead"><el-row :key="j"><el-col :span="i.children ? 12 : 24" :style="i.children ? extent(i.children) : 'height:50px'">{{i.name}}</el-col><el-col v-if="i.children" :span="12"><template v-for="(g,k) in i.children"><el-row :key="k">{{g.name}}</el-row></template></el-col></el-row></template></div></div><div class="rightSide"><div class="conceal"><div class="tableBody"><template v-for="(i,j) in tableBody"><el-row :key="j" class="singleRow"><el-col :span="24" class="column"><div style="width:190px;" :class="i.name.length > 10 ? 'linHet' : ''">{{i.name}}</div></el-col><el-col :span="24" class="column"><div style="width:190px;"><iclass="el-icon-circle-check"title="审核"></i></div></el-col><el-col :span="24" class="column"><div style="width:190px;">{{i.issue}}</div></el-col></el-row></template></div><div class="tableBody" ref="content"><template v-for="(item,index) in acrossRule"><el-row class="singleRow" :key="index"><template v-for="(j,i) in endlongRule"><el-col class="column" :key="i"><div style="width:190px;"></div></el-col></template></el-row></template></div></div></div></div></template><script>export default {data(){return {endlongRule: 0,acrossRule: 0,tableHead:[{name: "投标文件分析",id:'2',children:[{name: "相同创建人",id:'2-0'},{name: "相同修改人",id:'2-1'}]},{name: "投标行为审查",id:'3',children:[{name: "IP地址相同",id:'3-0'},{name: "MAC地址相同",id:'3-1'}, {name: "存在股权关系",id:'3-2'}, ]},{name: "内容异常审查",id:'4',children:[{name: "投标人、授权人重复",id:'4-0'},{name: "出现其他投标人信息",id:'4-1'}, {name: "错误、异常信息一致",id:'4-2'},{name: "报价阶梯规律性",id:'4-3'}, ]},{name: "其他",id:'5'},],tableBody:[{name:'投标1投标2投标2投标2投标2投标2投标2投标2投标2投标2投标2',issue:5,id:111,},{name:'博识知识图谱系列产品-安装部署手册v3.2.pdf',issue:10,id:211,},{name:'投标1',issue:5,id:311,},{name:'博识知识图谱系列产品-安装部署手册v3.2.pdf',issue:10,id:411,},{name:'投标1',issue:5,id:511,},],list:[{ruleInfoId:'2-0',taskId:111,text:'老虎'},{ruleInfoId:'2-1',taskId:211,text:'狮子'},{ruleInfoId:'3-0',taskId:311,text:'鬣狗'},{ruleInfoId:'3-1',taskId:211,text:'长颈鹿'},{ruleInfoId:'3-2',taskId:111,text:'野猪'},]}},created(){this.settleData();},methods:{settleData(){let endlongRule = 0;let headArr = []; let eachData = []; this.tableHead.forEach(e => {if(e.children){endlongRule += e.children.length;e.children.forEach(p => {headArr.push(p);})}else {endlongRule ++;headArr.push(e);}})this.endlongRule = endlongRule;this.acrossRule = this.tableBody.length;this.list.forEach( i => {let ruleCoord = headArr.findIndex(e => e.id == i.ruleInfoId); //查找规则idlet teskCoord = this.tableBody.findIndex(e => e.id == i.taskId); // 查找任务idif(ruleCoord != -1 && teskCoord != -1){let tempObj = {teskCoord: teskCoord,ruleCoord: ruleCoord,text: i.text,}eachData.push(tempObj);}})this.$nextTick(()=>{// 此处需 dom 加载完毕后调用,否则 HTMLCollection 对象返回nullthis.endow(eachData);})},endow(data){data.forEach(e => {let label = this.$refs.content.children;let row = label.item(e.teskCoord).children; // 获取指定行row.item(e.ruleCoord).children.item(0).innerHTML = '00'; // 找到指定单元格赋值})},extent(list){var height = 50 * list.lengthreturn `height: ${height}px; line-height: ${height}px;`},}}</script><style scoped>.leftSide {width:300px;float:left;}.rightSide {float:left;}.tableHead {width:300px;}.conceal {overflow: hidden;overflow-x: auto;width:1000px;}.tableBody {display: flex;}.singleRow{width: 200px;}.el-row {margin: 0px -1px -1px -1px; /*解决边框重叠*/text-align: center;font-size: 14px;line-height:50px;border:1px solid #e6e6e6;}.column {border:1px solid #f1eded;height:50.97px;border-top: none;border-left:none;display: flex;justify-content: center;}.linHet {text-align: center;line-height: 25px;overflow: hidden;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}.general {border:1px solid #e6e6e6;margin: 0px 0px -1px 0px; /*解决边框重叠*/}</style>
this.tableHead.forEach(e => {if(e.children){endlongRule += e.children.length;e.children.forEach(p => {headArr.push(p);})}else {endlongRule ++;headArr.push(e);}})this.endlongRule = endlongRule;this.acrossRule = this.tableBody.length;
循环左侧数据结构解析获取其子级数量,数量用于循环填充区域高度,获取任务对象数量用于循环填充区域宽度。
this.list.forEach( i => {let ruleCoord = headArr.findIndex(e => e.id == i.ruleInfoId); //查找规则idlet teskCoord = this.tableBody.findIndex(e => e.id == i.taskId); // 查找任务idif(ruleCoord != -1 && teskCoord != -1){let tempObj = {teskCoord: teskCoord,ruleCoord: ruleCoord,text: i.text,}eachData.push(tempObj);}})
双循环遍历填充区域的数组通过对比 id 找出当前对应规则的下标以及任务对象下标并push到新数组。
this.$nextTick(()=>{// 此处需 dom 加载完毕后调用,否则 HTMLCollection 对象返回nullthis.endow(eachData);})
在调用赋值方法前使用 nextTick 方法,确保 dom 加载完毕后再获取其dom,因返回的是 HTMLCollection 对象,可能造成获取某元素为 null 的情况发生。
endow(data){let label = this.$refs.content.children;data.forEach(e => {let row = label.item(e.teskCoord).children; // 获取指定行row.item(e.ruleCoord).children.item(0).innerHTML = e.text; // 向指定单元格赋值})},
利用 ref 获取填充区域父元素找出其子元素返回 HTMLCollection 对象(并非数组),使用 item 自带方法获取指定 dom 元素。通过以上逻辑获取到某行某列对应的下标,遍历其dom进行赋值即可。目前可以满足当前的需求。
缓慢成长中,有过错地方或更好的建议可留言。