最近在做大屏展示,其中一个需求是展示生产过程中投料情况,效果类似甘特图。
思路:1.先得到整个过程的开始时间startTime和结束时间endTime。计算出整个过长经历的时长。
2.计算横向坐标的开始时间start和结束时间end,坐标的开始时间为生产开始时间-百分之十的生产时长,即start = startTime - 0.1h;坐标的结束时间为生产结束时间+百分之十的生产时长,即end = endTime + 0.1h.
3.确定横纵坐标值,先计算横计算坐标间隔,我固定了横坐标的打点数,直接用横坐标结束时间-坐标开始时间除以点数+1,即 (end-start) / (number +1)。得到间隔之后就可以计算出横坐标值。纵坐标值直接使用物料名称
4.显示每个料的投放情况显示出来。显示是用的div,每种物料的投料时长就是div的长度。
注意:计算宽度的时候需要依据自己的实际情况进行调整
效果
代码
<template>
<div class="Gantt">
<div class="content" ref="scrollbar">
<!-- <el-scrollbar> -->
<div
class="info"
style="margin-top: 2px; overflow: scroll; overflow-x: hidden;height: calc(100vh * 220 / 1080);"
>
<div id="gui-content" class="gui-content">
<div
class="gui-list clear room-gui-list"
v-for="task in taskList"
:key="task.materialId"
>
<div id="name" class="fasten ellipsis" :title="task.name">
{{ task.name }}
</div>
<div class="gui-tab">
<li
v-for="(o, i) in config.xAxis"
:key="i"
:style="{
width: 100 / (number + 1) + '%',
cursor: 'pointer',
}"
></li>
</div>
<template v-if="task.materialId">
<div
v-for="(item, index) in task.materialData"
:key="index"
class="meet-item-one"
v-bind:class="[
!item.status ? 'meet-color-having' : 'meet-color-finished',
]"
:style="{
left: getLeftTime(item.startTime) + '%',
width: getWidth(item) + '%',
backgroundColor: item.color,
// opacity:0.8
}"
v-show="getWidth(item) != 0"
@click="edit(item)"
>
<el-popover
placement="top-start"
trigger="hover"
:style="{fontSize:'10px',padding:'0px'}"
>
<p>{{'开始:'+item.startTime}}</p>
<p>{{'结束:'+item.endTime}}</p>
<div slot="reference" class="meet-item-one-content">
<p class="ellipsis" >{{ item.content }}</p>
</div>
</el-popover>
</div>
</template>
</div>
</div>
</div>
<!-- </el-scrollbar> -->
<div class="time-bar clear">
<div class="gui-table clear">
<li
:style="{
width: 100 / (number + 1) +'%',
}"
v-for="(item, index) in config.xAxis"
:key="index"
>
<div class="gui-cle"></div>
<div class="gui-lit"></div>
<div class="gui-title"><span class="">{{item.xAxis}}</span></div>
</li>
</div>
</div>
</div>
</div>
</template>
<script>
import {Popover,Scrollbar} from 'element-ui'
export default {
name: "GanttDemo",
data() {
return {
date: "",
number:6,
xInterval:0.1,
config: {xAxis:[]},
taskList: [
{
materialId: "1",
name: "物料一",
startTime: "2022-11-16 08:00:00",
endTime: "2022-11-16 20:00:00",
materialData: [
{
materialId: "1",
id: "14444",
status: 0,
startTime: '2022-11-16 08:00:00',
endTime: '2022-11-16 12:00:00',
color:"#32c5e9",
content:"800",
},
{
materialId: "1",
id: "15555",
status: 0,
startTime: '2022-11-16 18:30:10',
endTime: '2022-11-16 20:00:00',
color:"#32c5e9",
content:"600",
},
],
},
{
materialId: "2",
name: "物料二",
startTime: "2022-11-16 20:00:00",
endTime: "2022-11-16 23:30:00",
materialData:[{
materialId: "2",
id: "223865",
status: 0,
startTime: '2022-11-16 20:00:00',
endTime: '2022-11-16 23:30:00',
color:"#eb865e",
content:"800",
},
]
},{
materialId: "3",
name: "物料三",
startTime: "2022-11-16 15:00:00",
endTime: "2022-11-16 16:30:00",
materialData:[{
materialId: "3",
id: "31",
status: 0,
startTime: '2022-11-16 15:00:00',
endTime: '2022-11-16 16:30:00',
color:"#eb865e",
content:"500",
},
]
},{
materialId: "4",
name: "物料四",
startTime: "2022-11-16 12:00:00",
endTime: "2022-11-16 16:30:00",
materialData:[{
materialId: "4",
id: "41",
status: 0,
startTime: '2022-11-16 12:00:00',
endTime: '2022-11-16 16:30:00',
color:"#eb865e",
content:"450",
},
]
},{
materialId: "5",
name: "物料五",
startTime: "2022-11-16 11:00:00",
endTime: "2022-11-16 15:30:00",
materialData:[{
materialId: "5",
id: "51",
status: 0,
startTime: '2022-11-16 11:00:00',
endTime: '2022-11-16 15:30:00',
color:"#eb865e",
content:"300",
},
]
},{
materialId: "6",
name: "物料六",
startTime: "2022-11-16 11:00:00",
endTime: "2022-11-16 12:30:00",
materialData:[{
materialId: "6",
id: "61",
status: 0,
startTime: '2022-11-16 11:00:00',
endTime: '2022-11-16 12:30:00',
color:"#eb865e",
content:"200",
},
]
},{
materialId: "7",
name: "物料七",
startTime: "2022-11-16 09:00:00",
endTime: "2022-11-16 10:30:00",
materialData:[{
materialId: "7",
id: "71",
status: 0,
startTime: '2022-11-16 09:00:00',
endTime: '2022-11-16 10:30:00',
color:"#eb865e",
content:"300",
},
]
},
]
};
},
components:{
elPopover: Popover,
elScrollbar:Scrollbar,
},
props:{
},
watch:{
},
mounted(){
this.getConfig();
},
methods: {
getLeftTime(cTime) {
const dTime = new Date(cTime).getTime();
const leftTime = new Date(this.config.startTime).getTime();
const time = (dTime - leftTime) / (1000 * 60 * 60); // 小时数
const leftPercent = 0.88 * (time * 100) / (this.xInterval * (this.number+1)) ;
return leftPercent + 12;
},
getWidth(item) {
const _left1 = this.getLeftTime(item.startTime);
const _left2 = this.getLeftTime(item.endTime);
return _left2 - _left1;
},
edit(item) {
console.log(item);
},
getConfig(){
if(this.taskList.length>0){
let startTime = this.taskList[0].startTime;
let endTime = this.taskList[0].endTime;
console.log(endTime)
for(let index in this.taskList){
let task = this.taskList[index];
let start1 = startTime?new Date(startTime):new Date();
let start2 = new Date(task.startTime);
if(start1 > start2 && null != task.startTime){
startTime = task.startTime;
}
let end1 = new Date(endTime);
let end2 = new Date(task.endTime?task.endTime:start2);
if(end1 < end2){
endTime = task.endTime;
}
}
let hour =((new Date(endTime)).getTime() - (new Date(startTime)).getTime());
this.config.start = startTime;
this.config.end = endTime;
this.config.startTime = this.getDateTime(new Date((new Date(startTime)).getTime()-0.1*hour));
this.config.endTime = this.getDateTime(new Date((new Date(endTime)).getTime()+0.1*hour));
hour = ((new Date(this.config.endTime)).getTime() - (new Date(this.config.startTime)).getTime());
this.config.hour = hour;
if(hour){
this.xInterval = (hour / (this.number+1)) / (1000*60*60);
}
this.config.xAxis = []
let hh = (new Date(this.config.startTime)).getHours() < 10 ? '0' + (new Date(this.config.startTime)).getHours() : (new Date(this.config.startTime)).getHours();
let mm = (new Date(this.config.startTime)).getMinutes() < 10 ? '0' + (new Date(this.config.startTime)).getMinutes() : (new Date(this.config.startTime)).getMinutes();
let xOne = hh +":" +mm;
this.config.xAxis.push({xAxis:xOne});
for(let i = 0;i < this.number;i++){
console.log();
let node = (new Date(this.config.startTime)).getTime()+(this.xInterval * 60 *60 * 1000 * ( i + 1 ));
let nodeHh = (new Date(node)).getHours() < 10 ? '0' + (new Date(node)).getHours() : (new Date(node)).getHours();
let nodeMm = (new Date(node)).getMinutes() < 10 ? '0' + (new Date(node)).getMinutes() : (new Date(node)).getMinutes();
let nodeX = nodeHh + ":" + nodeMm;
this.config.xAxis.push({xAxis:nodeX});
}
}
},
getDateTime(time){
let year = time.getFullYear(); //获取年 2021
let month = time.getMonth() + 1; // 获取月 5
let day = time.getDate(); // 获取天 11
let h = time.getHours() < 10 ? '0' + time.getHours() : time.getHours(); // 获取小时 18
let m = time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes(); // 获取分钟 42
let s = time.getSeconds() < 10 ? '0' + time.getSeconds() : time.getSeconds(); // 获取秒 51
let dataTime = year + '-' + month + '-' + day + ' ' + h + ':' + m + ':' + s;
return dataTime;
},
}
};
</script>
<style lang="scss" scoped >
.Gantt {
padding: calc(100vw * 20 / 1920 );;
border-radius: 3px;
/* border: 1px solid red; */
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column-reverse;
position: relative;
}
.content {
padding-top: calc(100vw * 20 / 1920 );
}
.content /deep/ .el-scrollbar{
height: calc(100vh * 220 / 1080);
.el-scrollbar__wrap {
overflow-x: hidden;
}
}
.content /deep/ .el-scrollbar__view {
height: 100%;
// display: flex;
// flex-direction: column-reverse;
}
.Gantt .gui-table,
.gui-tab {
font-size: calc(100vw * 12 / 1920 );
color: #333;
margin: 0;
width: 88%;
float: right;
white-space: nowrap;
height: calc(100vh * 48 / 1080 );
}
.Gantt .gui-table li {
position: relative;
border-top: solid 1px #1ba5fa;
z-index: 666;
word-wrap: break-word;
}
.Gantt .gui-table li {
cursor: default;
}
.Gantt .gui-table li{
float: left;
text-align: left;
width: 8.9%;
height: calc(100vh * 48 / 1080 );
line-height: calc(100vh * 48 / 1080 );
/* cursor: pointer; */
white-space: pre-wrap;
}
.Gantt .gui-table .gui-title{
line-height: calc(100vh * 24 / 1080 );
position: relative;
width: 100%;
}
.Gantt .gui-table .gui-title span{
line-height: calc(100vh * 24 / 1080 );
color: rgba(255,255,255,.7);
position: absolute;
left: -50%;
text-align: center;
width: 100%;
}
.gui-tab li {
float: left;
text-align: left;
width: 8.9%;
height: calc(100vh * 28 / 1080 );
line-height: calc(100vh * 28 / 1080 );
/* cursor: pointer; */
white-space: pre-wrap;
}
.Gantt .gui-cle {
position: absolute;
left: -5px;
top: -5px;
width: 6px;
height: 6px;
background: #fff;
border-radius: 50%;
border: solid 2px #1ba5fa;
z-index: 666;
}
.Gantt .gui-lit {
position: absolute;
left: 0;
top: -3px;
width: 3px;
height: 3px;
background: #fff;
border-radius: 50%;
border: solid 1px #1ba5fa;
margin-left: 50%;
z-index: 666;
}
.clear {
*zoom: 1;
}
.clear:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
font-size: 0;
}
.Gantt .fasten {
width: 12%;
float: left;
height: calc(100vh * 28 / 1080 );
text-align: center;
line-height: calc(100vh * 28 / 1080 );
font-size: calc(100vw * 12 / 1920 );
color: rgba(255, 255, 255, .7);
border-right: solid 1px #1ba5fa;
/* word-break: break-word;
white-space: pre-line; */
}
.Gantt .gui-table{
font-size: calc(100vw * 12 / 1920 );
color: #333;
margin: 0;
width: 88%;
float: right;
white-space: nowrap;
height: calc(100vh * 48 / 1080 );
}
.gui-tab {
font-size: calc(100vw * 12 / 1920 );
color: #333;
margin: 0;
width: 88%;
float: right;
white-space: nowrap;
height: calc(100vh * 28 / 1080 );
}
/* .Gantt .gui-list:first-child {
background: #fff;
} */
.Gantt .gui-list {
position: relative;
display: flex;
}
.Gantt .meet-color-finished {
background: #4dc394;
}
.Gantt .meet-color-having {
background: #eb865e;
}
.Gantt .meet-item-one {
color: #000;
text-align: center;
position: absolute;
height: calc(100vh * 26 / 1080 );
left: 12%;
top: 1px;
color: #fafafa;
font: 14px/60px microsoft yahei;
/* padding: 0 5px; */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
overflow: hidden;
cursor: pointer;
width: 20%;
line-height: calc(100vh * 26 / 1080 );
}
li {
list-style: none;
}
.Gantt .meet-item-one-content{
height: 100%;
}
.ellipsis {
overflow: hidden;
margin-top: 0;
white-space: nowrap;
text-overflow: ellipsis;
line-height: calc(100vh * 28 / 1080 );
}
.info,.gui-content{
display: flex;
flex-direction: column-reverse;
}
.info::-webkit-scrollbar {
width : 5px;
height: 1px;
}
.info::-webkit-scrollbar-thumb {
box-shadow: 0px 1px 3px rgba(144,147,153,.3) inset; /*滚动条的内阴影*/
border-radius: 10px; /*滚动条的圆角*/
background-color: rgba(144,147,153,.3); /*滚动条的背景颜色*/
}
.info::-webkit-scrollbar-track {
box-shadow: 0px 1px 3px #071e4a inset; /*滚动条的背景区域的内阴影*/
border-radius: 10px; /*滚动条的背景区域的圆角*/
background-color: #071e4a; /*滚动条的背景颜色*/
}
/* .gui-yAxis{
position: absolute;
height: 100%;
border: solid 1px #1ba5fa;
} */
</style>