阅读量:0
引言
在玻璃加工行业,高效管理切割、磨边、洗、钢化、丝印等复杂工序对于提升生产效率至关重要。本文将介绍如何利用Vue.js框架结合Element UI组件库,自定义实现一个工序甘特图,以可视化展示各道工序的时间线与进度,为生产调度带来便利。
目录
渲染效果
同产品高亮
拖拽滚动,同产品高亮
小时高度,宽度改变动态效果
全部代码:
优化
优化内容:减少timeInterval的调用,拖动滚动效果,同产品高亮效果。
<template> <div class="home group"> <el-card :span="24" :xs="24" class="box-card" id="boxCard" ref="tableBox" append-to-body > <el-row> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-view" size="mini" @click.native="switchView" >切换视图</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-s-tools" size="mini" @click.native="startSchedulingProductionFun" >开始排产</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-s-tools" size="mini" @click.native="proposalFun" >负荷调整建议</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain size="mini" icon="el-icon-document" >查看物料到货计划</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain size="mini" icon="el-icon-upload2" >导出</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-printer" size="mini" >打印</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-lock" size="mini" >锁定排产</el-button > </el-col> <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-unlock" size="mini" >解锁排产</el-button ></el-col > <!-- <el-col :span="1.5" style="margin-right: 10px"> <el-button type="primary" plain icon="el-icon-rank" size="mini" >拖拽排产</el-button ></el-col > --> </el-row> <el-table @mousedown.native="startDrag" @mousemove.native="handleDrag" @mouseup.native="endDrag" @mouseleave.native="endDrag" v-loading="loading" element-loading-text="正在加载处理数据...." v-if="isView" :virtual-scroll="true" class="ganteTable" :class="isFillScreen ? 'fullscreen-table ganteTable' : 'ganteTable'" ref="ganTeTable" :height="tableHeight" :style=" timeArr.length > 0 ? 'width:' + tableWidth + 'px;' : 'width:239px;height:100%' " :key="tableKey" :cell-style="iCellStyle" :fit="false" :data="tableData" border align="center" size="mini" :span-method="tableSpanMethod" > <el-table-column fixed align="center" prop="index1" label="工作中心" class="index1" > <template slot-scope="scope"> <el-popover placement="top-start" title="工作中心" trigger="hover" :content="scope.row.index1.label" > <div slot="reference" :class="rowHeight < 36 ? 'oneLineCls' : 'twoLineCls'" > {{ scope.row.index1.label }} </div> </el-popover> </template> </el-table-column> <el-table-column fixed align="center" prop="index2" label="产线名称" class="index1" > <template slot-scope="scope"> <!-- {{ scope.row.index2.label }} --> <el-popover placement="top-start" title="产线名称" width="200" trigger="hover" :content="scope.row.index3.label" > <div slot="reference" :class="rowHeight < 36 ? 'oneLineCls' : 'twoLineCls'" > {{ scope.row.index2.label }} </div> </el-popover> </template> </el-table-column> <el-table-column fixed height="47px" align="center" prop="index3" label="设备名称" class="index1" > <template slot-scope="scope"> <!-- {{ scope.row.index3.label }} --> <el-popover placement="top-start" title="设备名称" width="200" trigger="hover" :content="scope.row.index3.label" > <div slot="reference" :class="rowHeight < 36 ? 'oneLineCls' : 'twoLineCls'" > {{ scope.row.index3.label }} </div> </el-popover> </template> </el-table-column> <!-- 表头遍历日期 --> <div v-for="(timeArrItem, index1) in timeArr" :key="timeArrItem + index1 + ''" > <el-table-column height="47px" align="center" :label="timeArrItem.substr(0, 10)" > <!-- 表头遍历时间 --> <template v-for="(hourArrItem, index2) in hourArr"> <el-table-column height="47px" align="center" class="pc-box" :label="hourArrItem + ''" :key="index1 + '-' + index2 + 5 + timeArrItem + hourArrItem" :width="latticeWidth + 'px;'" > <template slot="header"> <div class="hour-item" @mousemove="updateXY"> <span>{{ hourArrItem }}</span> <div class="hour-ten-scale-box"> <div class="hour-ten-scale" v-for="x in 5" :key="x"></div> </div> <div class="hour-ten-side-box"> <div class="hour-ten-side-box-left"></div> <div class="hour-ten-side-box-right"></div> </div> </div> <div class="minute-scale" v-if="index2 === 0 && index1 === 0" :style="{ width: tableWidth + 'px' }" ></div> <div ref="pointBox" id="pointBox" v-if="index2 === 0 && index1 === 0" ></div> </template> <template slot-scope="scope" v-if="index2 === 0 && index1 === 0" > <div id="content-box" @mousemove="updateXY" class="content-box" :ref="index1 + '-' + index2 + 5" :style=" 'width:' + timeArr.length * 24 * latticeWidth + 'px;overflow:hidden;' " > <el-tooltip :draggable="true" v-for="workItem in scope.row.workPlanList.data" :key="workItem.onlyId" class="item" style="z-index: 99999" effect="dark" content="Bottom Right 提示文字" placement="bottom-end" > <div slot="content"> <p>信息</p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 工序:{{ workItem.workOrder }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 产品名称:{{ workItem.materialName }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 产品编码:{{ workItem.materialNo }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 产线名称:{{ workItem.productLineName }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 产线编码:{{ workItem.productLineSn }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 设备名称:{{ scope.row.index3.label }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 开始时间:{{ workItem.startTime }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 结束时间:{{ workItem.endTime }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 交期时间:{{ workItem.deliverTime }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 工作中心描述:{{ workItem.workCenterDesc }} </p> <p v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " > 工作中心编码:{{ workItem.workCenterSn }} </p> <p v-if="workItem.lineChangeFlag === true"> 状态:换线 </p> <p v-if="workItem.restFlag === true">状态:休息</p> </div> <div v-if=" workItem.lineChangeFlag === null && workItem.restFlag === null " @click=" highlightSimilarElements( 'A' + workItem.materialNo + workItem.deliverTime ) " :draggable="true" :class=" 'AAA A' + workItem.materialNo + workItem.deliverTime + '' " :style=" 'background-color:' + workItem.color + ';' + ' position: absolute;' + timeInterval( workItem.startTime, workItem.endTime, workItem.onlyId ) " ></div> <div v-if="workItem.lineChangeFlag === true" @click=" highlightSimilarElements( 'A' + workItem.materialNo + workItem.deliverTime ) " :draggable="true" :class=" 'AAA A' + workItem.materialNo + workItem.deliverTime + '' " :style=" ' position: relative; top: 50%; bottom: 50%;height: 3px' + ';' + 'background-color:' + '#FF0000' + ';' + ' position: absolute;' + timeInterval( workItem.startTime, workItem.endTime, workItem.onlyId ) " ></div> <div v-if="workItem.restFlag === true" @click=" highlightSimilarElements( 'A' + workItem.materialNo + workItem.deliverTime ) " :draggable="true" :class=" 'AAA A' + workItem.materialNo + workItem.deliverTime + '' " :style=" 'background-color:' + '#cedcf0;' + ' position: absolute;' + timeInterval( workItem.startTime, workItem.endTime, workItem.onlyId ) " ></div> </el-tooltip> </div> </template> </el-table-column> </template> </el-table-column> </div> </el-table> <day-table-view v-if="!isView"></day-table-view> <scheduling-window ref="schedulingWindow" @openSchedulingResultsWindow="openSchedulingResultsWindow" ></scheduling-window> <scheduling-results-window ref="schedulingResultsWindow" @switchView="switchView" ></scheduling-results-window> <suggestions-load-adjustment ref="suggestionsLoadAdjustment" @reScheduleProduction="getGanttChartData" ></suggestions-load-adjustment> <div class="slider-block" v-if="isView"> <div class="slider-block-text">小时高度:</div> <el-slider @change="sliderHeightChange" style="width: 200px" v-model="rowHeight" :min="24" :max="72" :step="12" show-stops > </el-slider> </div> <div class="slider-block1" v-if="isView"> <div v-if="isSlider" class="slider-block-text">小时宽度:</div> <el-slider v-if="isSlider" @change="sliderWidthChange" style="width: 200px" v-model="latticeWidth" :min="minWidth" :max="maxWidth" :step="12" show-stops > </el-slider> </div> <!-- <div class="slider-block1-btn" v-show="isView"> <el-button @click="fullScreenFunc" size="mini"> {{ isFillScreen ? "退出全屏" : "全屏" }} </el-button> </div> --> </el-card> </div> </template> <script> import { getGanttChart } from "@/api/ganttChart/ganttChart"; import dayTableView from "./gentterTable.vue"; import schedulingWindow from "./startSchedulingWindow.vue"; import schedulingResultsWindow from "./schedulingResultsWindow.vue"; import suggestionsLoadAdjustment from "./suggestionsLoadAdjustment.vue"; export default { name: "dailyScheduling", components: { dayTableView, schedulingWindow, schedulingResultsWindow, suggestionsLoadAdjustment, }, data() { return { styleCache: {}, //存放缓存结果 highlightedClass: null, dragging: false, startX: 0, startY: 0, scrollLeft: 0, scrollTop: 0, ganTeTable: null, // 初始化表格引用 isFillScreen: false, // 是否全屏 loading: false, //表格数据处理 isView: true, content: "内容", isSlider: true, //是否显示缩放和拉长 minWidth: 24, //最小缩放 maxWidth: 72, //最大缩放 rowHeight: 24, //每一行的高度 tableWidth: 0, pointObj: { pointX: 340, pointBoxLeft: 0, //指针盒子距离左侧的偏移量 }, eleData: { dayList: [], startTime: "", // 开始时间 endTime: "", // 结束时间 workcenterList: [], }, tableHeight: 0, //table的高度 oneHourPx: 24, //一小时间隔15px 一分钟间隔0.25px oneMinutePx: 0.4, //一分钟0.4px tableData: null, //表格数据 latticeWidth: 30, //一个单元格的宽度最小24px timeArr: [], //天数集合 hourArr: [ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", ], tableKey: 0, //值改变更新table earliestTime: "", //最早时间 latestTime: "", //最晚时间 conWidth: 0, usedKeys: new Set(), }; }, created() { window.onload = function () { document.addEventListener("touchstart", function (event) { if (event.touches.length > 1) { event.preventDefault(); } }); document.addEventListener("gesturestart", function (event) { event.preventDefault(); }); }; //初始化表格高度,和初始化指针数据 this.$set(this.pointObj, "pointX", 0); this.$nextTick(() => { this.tableHeight = this.$refs.tableBox.offsetHeight - 110; }); }, mounted() { this.getGanttChartData(); //禁止ctrl+滚轮缩放 let scrollFunc = function (e) { e = e || window.event; if (e.wheelDelta && event.ctrlKey) { //IE/Opera/Chrome event.returnValue = false; } else if (e.detail) { //Firefox event.returnValue = false; } }; /*注册事件*/ if (document.addEventListener) { document.addEventListener("DOMMouseScroll", scrollFunc, false); } //W3C window.onmousewheel = document.onmousewheel = scrollFunc; //IE/Opera/Chrome/Safari //设置表格最大高度沾满全屏 this.$nextTick(() => { this.tableHeight = document.getElementById("boxCard").offsetHeight - 110; window.addEventListener("scroll", this.handleScroll, true); //获取标针盒子距离浏览器左侧的距离 // this.pointObj.pointBoxLeft = document.getElementById("pointBox").getBoundingClientRect().left //监听浏览器窗口变化 const that = this; window.onresize = () => { return (() => { //计算装有指针的盒子距离浏览器左侧的距离,指针减去这个盒子距离浏览器左侧的偏移量得到正确时间指针 this.pointObj.pointBoxLeft = 0; console.log("窗口改变了"); })(); }; //如果日期小于2天 则官渡为39 if (this.timeArr.length <= 2) { this.latticeWidth = 24; this.minWidth = 24; this.maxWidth = 72; } // console.log("我被执行了", this.timeArr.length); if (this.timeArr.length >= 2) { this.latticeWidth = 24; this.minWidth = 24; this.maxWidth = 72; } if (this.timeArr.length == 1) { this.latticeWidth = 66; this.isSlider = false; } this.widthAA = this.timeArr.length * 24 * this.latticeWidth; this.tableWidth = this.widthAA + 240; }); this.ganTeTable = this.$refs.ganTeTable.$el.querySelector( ".el-table__body-wrapper" ); }, computed: { // timeInterval() { // return (startTime, endTime,id) => { // console.log("我被执行了", startTime, endTime,id); // let time = new Date(endTime) - new Date(startTime); // 获取任务开始时间和任务结束时间的相差时间戳 // let minuteDiff = Math.floor(time / (60 * 1000)); // 相差时间间隔 // let initialTime = new Date(startTime) - new Date(this.timeArr[0]); // 获取距离最开始的距离 // let inittiDiff = Math.floor(initialTime / (60 * 1000)); // let obj = { // widthPx: minuteDiff * (this.latticeWidth / 60), // startPx: inittiDiff * (this.latticeWidth / 60), // }; // return "width:" + obj.widthPx + "px;left:" + obj.startPx + "px;"; // }; // }, }, methods: { timeInterval(startTime, endTime, id) { // Check cache first const cacheKey = `${startTime}_${endTime}_${id}`; if (this.styleCache[cacheKey]) { return this.styleCache[cacheKey]; } console.log("我被执行了", startTime, endTime, id); let time = new Date(endTime) - new Date(startTime); // 获取任务开始时间和任务结束时间的相差时间戳 let minuteDiff = Math.floor(time / (60 * 1000)); // 相差时间间隔 let initialTime = new Date(startTime) - new Date(this.timeArr[0]); // 获取距离最开始的距离 let inittiDiff = Math.floor(initialTime / (60 * 1000)); let obj = { widthPx: minuteDiff * (this.latticeWidth / 60), startPx: inittiDiff * (this.latticeWidth / 60), }; const style = `width:${obj.widthPx}px;left:${obj.startPx}px;`; // Store in cache this.styleCache[cacheKey] = style; return style; }, generateRandomKey() { let key; do { key = Math.random().toString(36).substr(2, 9); // Generate a random string key } while (this.usedKeys.has(key)); // Ensure key is unique this.usedKeys.add(key); // Add key to usedKeys set return key; }, // 负荷调整建议 proposalFun() { this.$refs.suggestionsLoadAdjustment.open(); }, // 开始排产弹窗 openSchedulingResultsWindow() { this.showDialogVisible = false; this.$refs.schedulingResultsWindow.open(); }, highlightSimilarElements(targetClass) { // 先移除所有元素的高亮状态 if (this.highlightedClass) { document.querySelectorAll(`.${this.highlightedClass}`).forEach((el) => { el.classList.remove("highlighted"); }); } // 更新当前要高亮的类名 this.highlightedClass = targetClass; // 查找所有具有目标类名的元素并应用高亮 document.querySelectorAll(`.${targetClass}`).forEach((el) => { el.classList.add("highlighted"); }); }, // 开始排程的英文 startSchedulingProductionFun() { this.$refs.schedulingWindow.showDialogVisible = true; }, // 当鼠标按下时触发,记录起始位置和滚动条位置。 startDrag(e) { this.dragging = true; this.startX = e.pageX; this.startY = e.pageY; this.scrollLeft = this.ganTeTable.scrollLeft; this.scrollTop = this.ganTeTable.scrollTop; }, // 当鼠标移动时触发,计算鼠标移动距离并更新滚动条位置。 handleDrag: _.throttle(function (e) { if (this.dragging) { const dx = e.pageX - this.startX; const dy = e.pageY - this.startY; this.ganTeTable.scrollLeft = this.scrollLeft - dx; this.ganTeTable.scrollTop = this.scrollTop - dy; } }, 16), // 使用节流函数,16ms对应60fps的更新频率 // 鼠标松开,移出 endDrag() { this.dragging = false; }, //全屏退出全屏 fullScreenFunc() { if (!document.fullscreenElement) { this.enterFullScreen(); this.isFillScreen = true; this.latticeWidth = 72; this.sliderWidthChange(); } else { this.exitFullScreen(); this.latticeWidth = 39; this.sliderWidthChange(); this.isFillScreen = false; } }, //进入全屏 enterFullScreen() { let element = document.documentElement; if (element.requestFullscreen) { element.requestFullscreen(); } else if (element.mozRequestFullScreen) { /* Firefox */ element.mozRequestFullScreen(); } else if (element.webkitRequestFullscreen) { /* Chrome, Safari & Opera */ element.webkitRequestFullscreen(); } else if (element.msRequestFullscreen) { /* IE/Edge */ element.msRequestFullscreen(); } }, //退出全屏 exitFullScreen() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { /* Firefox */ document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { /* Chrome, Safari and Opera */ document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { /* IE/Edge */ document.msExitFullscreen(); } this.isFillScreen = false; }, async getGanttChartData() { this.loading = true; console.log("开始"); //判断是否传递过来id let id = null; if (typeof this.$route.query.id !== "undefined") { id = JSON.parse(this.$route.query.id); } let repos = null; await getGanttChart() .then((res) => { repos = res; this.processGanttData(repos); this.loading = false; }) .catch((error) => { // 请求失败的处理 console.error("请求数据失败:", error); this.loading = false; // 可选:设置加载状态为false // 可以进行错误处理或者用户提示 }); }, processGanttData(repos) { // 在获取到数据后进行处理 this.timeArr = repos.data.dayList.map((element) => element + " 00:00:00"); this.eleData.workcenterList = repos.data.workcenterList; this.treeToTableData(); for (let i = 0; i < this.tableData.length; i++) { for (let j = 0; j < this.tableData[i].workPlanList.data.length; j++) { this.tableData[i].workPlanList.data[j].onlyId = this.generateRandomKey(); // this.tableData[i].workPlanList.data[j].pxObj={...this.timeInterval(this.tableData[i].workPlanList.data[j].startTime,this.tableData[i].workPlanList.data[j].endTime)} } } // 根据时间长度设置 latticeWidth if (this.timeArr.length <= 2) { this.latticeWidth = 24; this.minWidth = 24; this.maxWidth = 72; } else if (this.timeArr.length >= 3) { this.latticeWidth = 21; this.minWidth = 21; this.maxWidth = 72; } else if (this.timeArr.length == 1) { this.latticeWidth = 66; this.minWidth = 66; this.maxWidth = 66; this.isSlider = false; } // 计算表格宽度 this.widthAA = this.timeArr.length * 24 * this.latticeWidth; this.tableWidth = this.widthAA + 240; // 更新表格布局 this.$nextTick(() => { if (this.$refs.ganTeTable) { this.$refs.ganTeTable.doLayout(); } this.$forceUpdate(); }); }, //切换视图 switchView() { this.isView = !this.isView; if (this.isView === true) { this.getGanttChartData(); } }, //物料信息展开 //行高回调 iCellStyle() { return "height:" + this.rowHeight + "px"; }, //改变行高 sliderHeightChange() { //重新布局表格 this.$nextTick(() => { this.styleCache = {}; this.iCellStyle(); this.$refs.ganTeTable.doLayout(); // this.tableKey = Math.random(); }); }, //改变行宽 sliderWidthChange() { //重新布局表格 this.$nextTick(() => { this.styleCache = {}; this.widthAA = this.timeArr.length * 24 * this.latticeWidth; this.tableWidth = this.widthAA + 240; this.$refs.ganTeTable.doLayout(); // this.tableKey = Math.random(); }); }, // 当鼠标移动时触发 updateXY(e) { let x = e.clientX; //计算装有指针的盒子距离浏览器左侧的距离,指针减去这个盒子距离浏览器左侧的偏移量得到正确时间指针 this.pointObj.pointBoxLeft = document .getElementById("pointBox") .getBoundingClientRect().left; this.$nextTick(() => { this.boble = false; document.querySelector( "#pointBox" ).innerHTML = `<div style="width: 1px; height: 225px; position: absolute; background: red;top:-18px; left:${ x - this.pointObj.pointBoxLeft }px;" id="head-pointer" class="head-pointer"> </div>`; }); this.boble = false; }, parentW(index1, index2) { if (this.$refs[index1 + "-" + index2 + 5]) { // console.log(this.$refs[index1 + "-" + index2 + 5][0].clientWidth); return this.$refs[index1 + "-" + index2 + 5][0].clientWidth; } else { return 0; } }, parentH(index1, index2) { if (this.$refs[index1 + "-" + index2 + 5]) { // console.log(this.$refs[index1 + "-" + index2 + 5][0].clientHeight); return this.$refs[index1 + "-" + index2 + 5][0].clientHeight; } else { return 0; } }, draggableStart() { // console.log(this.tableData[0].workPlanList.data); }, draggableEnd() { // console.log(this.tableData[0].workPlanList.data); }, /** * 计算两个时间的间隔 * 入参 开始时间,结束时间 * 回参 返回一个任务距离最开始时间的分钟[距离],和一个任务开始时间和结束时间的分钟[距离], */ // timeInterval(startTime, endTiem) { // console.log("我被执行了",startTime, endTiem) // let time = new Date(endTiem) - new Date(startTime); //获取任务开始时间和任务结束时间的相差时间戳 // let minuteDiff = Math.floor(time / (60 * 1000)); //相差时间间隔 // let initialTime = new Date(startTime) - new Date(this.timeArr[0]); //获取距离最开始的距离 // // ,new Date(startTime),new Date(this.timeArr[0]) // // console.log("~~~~~~~~~~~", this.timeArr[0]) // let inittiDiff = Math.floor(initialTime / (60 * 1000)); // // console.log("latticeWidth",inittiDiff) // return { // widthPx: minuteDiff * (this.latticeWidth / 60), // startPx: inittiDiff * (this.latticeWidth / 60), // }; // }, treeToTableData() { // console.log("this.eleData.workcenterList", this.eleData.workcenterList); //将树状结构格式转换成二维数组表格形式 let ewArr = this.parseTreeToRow(this.eleData.workcenterList); let tableData = []; ewArr.map((item) => { let obj = {}; item.map((itemc, indexb) => { obj["index" + (indexb + 1)] = { id: itemc.id, label: itemc.label, }; if (typeof itemc.workPlanList !== "undefined") { // for(let i=0;i<itemc.workPlanList.length;i++){ // itemc.workPlanList[i].pxObj = null; // itemc.workPlanList[i].pxObj = this.timeInterval(itemc.workPlanList[i].startTime,itemc.workPlanList[i].endTime) // } obj.workPlanList = { data: itemc.workPlanList }; } }); tableData.push(obj); }); this.tableData = tableData; }, /** * 递归-----将树结构数据格式,转化为,二维数组 表格形式 * @param node 树的源数据 * @param data 树转化为二维数组的数据 * @param row 临时存储数据 * @returns {*[]} */ parseTreeToRow(node, data = [], row = []) { console.log("parseTreeToRow执行中"); node.map((item) => { let obj = { id: item.workCenterId || item.lineId || item.machineId, label: item.workCenterName || item.lineName || item.machineDescribe, }; if (typeof item.workPlanList !== "undefined") { obj.workPlanList = item.workPlanList.length > 0 ? item.workPlanList : []; } if (item.children && item.children.length != 0) { this.parseTreeToRow(item.children, data, [...row, obj]); } else { data.push([...row, obj]); } }); return data; }, /** * 合并行或列的计算方法 */ tableSpanMethod({ row, column, rowIndex, columnIndex }) { // console.log("row, column, rowIndex, columnIndex"); // console.log( // "row, column, rowIndex, columnIndex", // columnIndex, // row, // column, // rowIndex, // columnIndex // ); return { rowspan: columnIndex < 3 ? this.mergeRows( row[column.property], this.tableData, rowIndex, column.property ) : 1, colspan: 1, }; }, /** * 表格单元格合并-----行 * @param {Object} value 当前单元格的值 * @param {Object} data 当前表格所有数据 * @param {Object} index 当前单元格的值所在 行 索引 * @param {Object} property 当前列的property * @returns {number} 待合并单元格数量 */ mergeRows(value, data, index, property) { // 判断 当前行的该列数据 与 上一行的该列数据 是否相等 if (index !== 0 && value.label === data[index - 1][property].label) { // 返回 0 使表格被跨 行 的那个单元格不会渲染 return 0; } // 判断 当前行的该列数据 与 下一行的该列数据 是否相等 let rowSpan = 1; for (let i = index + 1; i < data.length; i++) { if (value.label !== data[i][property].label) { break; } rowSpan++; } return rowSpan; }, }, }; </script> <style> .highlighted { box-shadow: inset 0 0 0 3px yellow !important; /* 内置阴影,用作边框 */ } </style> <style lang="less" scoped> .hour-item span { position: relative; bottom: -9px; } .hour-ten-side-box { width: 100%; height: 10px; position: relative; bottom: -6px; .hour-ten-side-box-left { width: 1px; height: 14px; background: #263c59; position: relative; left: -1px; float: left; } .hour-ten-side-box-right { width: 1px; height: 14px; background: #263c59; position: relative; right: -1px; float: right; } } .hour-ten-scale-box { width: 100%; display: flex; justify-content: space-evenly; position: relative; bottom: -16px; } .hour-ten-scale { height: 5px; width: 1px; background: #263c59; } #pointBox { position: relative; z-index: 2 !important; } .aaaaa { width: 20px; background: red; height: 25px; position: relative; } //表头指针 .head-pointer { width: 1px; height: 18px; position: absolute; background: red; z-index: 2 !important; } //表头清楚内容 /deep/ .el-table th.el-table__cell { overflow: visible !important; } //占满屏幕 .box-card { height: calc(100vh - 100px); /*示例中顶部区域固定高度190px*/ } /deep/ .el-table--enable-row-transition .el-table__body td.el-table__cell { // height: 47px; } /deep/ .el-table_1_column_1 .el-table_1_column_2 .el-table_1_column_3 { z-index: 300 !important; } /deep/ .el-table_1_column_4_column_5_column_6 > .cell { // width: 3120px !important; padding: 0; } .content-box { // width: 2000px !important; z-index: 2 !important; text-align: left; position: absolute; top: 0; bottom: 0; } .AAA { // left: -10px; // height: 30px; position: relative; width: 15px; height: 100%; z-index: 2 !important; } /deep/ .el-table_1_column_4_column_5_column_6 .is-center .el-table__cell { // width: 3060px !important; display: flex !important; // z-index: 1 !important; } //去除鼠标移入 /deep/ .group > .el-table--enable-row-hover .el-table__body tr:hover > td { background-color: white !important; height: 100%; } /deep/ .group > .el-table--enable-row-hover .el-table__body tr:hover > td > div { height: 100%; } /deep/ .el-table .cell { overflow: visible !important; padding-left: 0px !important; display: flex; //横向排列 padding-right: 0px !important; width: 100%; text-align: center; } /deep/ .el-table--mini .el-table__cell { // z-index: 1 !important; padding: 0 !important; } ::v-deep .el-table th.el-table__cell > .cell { display: contents; line-height: 15px; } .timeItemBox { display: flex; width: 500px; margin-left: -10px; z-index: 1; z-index: 200 !important; } .timeItem { height: 37.9px; width: 30px; } .wl-real-start { left: 50%; &:after { position: absolute; top: 0; // left: -5px; left: 0; z-index: 1; content: ""; width: 8px; height: 36px; // border-radius: 50%; background: #fcc300; } } .wl-real-start1 { left: 50%; &:after { position: absolute; top: 0; left: 0; z-index: 200 !important; content: ""; } } //伸缩加长 .slider-block { margin-top: 5px; margin-left: 20px; float: right; position: fixed; z-index: 10002; bottom: 0; right: 20px; display: flex; line-height: 33px; .slider-block-text { margin-right: 5px; font-size: 16px; } } .slider-block1 { margin-top: 5px; margin-left: 20px; z-index: 10002; float: right; position: fixed; bottom: 0; right: 344px; display: flex; line-height: 33px; .slider-block-text { margin-right: 5px; font-size: 16px; } } .slider-block1-btn { margin-top: 5px; margin-left: 20px; z-index: 10002; float: right; position: fixed; display: flex; line-height: 33px; bottom: 9px; right: 639px; } //超过一行显示 .oneLineCls { text-overflow: -o-ellipsis-lastline; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; line-clamp: 1; -webkit-box-orient: vertical; } .twoLineCls { text-overflow: -o-ellipsis-lastline; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; } .ganteTable { margin-top: 20px; } .minute-scale { position: absolute; z-index: 2 !important; } /* 在你的全局样式或组件的<style>标签内 */ .fullscreen-table { position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; margin: 0 auto; z-index: 1002; } </style>