hberp/hb_client/src/components/Gantt/index.vue

1375 lines
39 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div class="left" style=" width: 400px ;float: left;border-right: 1px solid #f7f7f7">
<leftMenu
:list="list"
ref="leftMenu"
:BGScrollTop.sync="BGScrollTop"
@TableScrollTop="TableScrollTop"
@handlerRowClick="handlerRowClick"
@handlerGroup="handlerGroup"
@handlerExpand="handlerExpand"
></leftMenu>
<div class="rightLine" :style="{ left: rightLineX + 'px' }"></div>
<div
class="rightLine"
:style="{ left: rightLineX + 'px' }"
ref="rightLine"
@mousedown="rightLineMousedown"
></div>
</div>
<div class="chart" ref="chart">
<!--<div class="left" :style="{ width: rightLineX + 'px' }">
<leftMenu
:list="list"
ref="leftMenu"
:BGScrollTop.sync="BGScrollTop"
@TableScrollTop="TableScrollTop"
@handlerRowClick="handlerRowClick"
@handlerGroup="handlerGroup"
@handlerExpand="handlerExpand"
></leftMenu>
<div class="rightLine" :style="{ left: rightLineX + 'px' }"></div>
<div
class="rightLine"
:style="{ left: rightLineX + 'px' }"
ref="rightLine"
@mousedown="rightLineMousedown"
></div>
</div>-->
<div class="date">
<div class="years" v-for="item in allDays" :key="item.year">
<div
class="month"
v-for="(value, key) in item.month[0]"
:key="value + 'aa' + key"
:style="{ width: value.length * currentDaySize.value + 'px' }"
>
<div class="month-top">{{ item.year }}{{ key }}</div>
</div>
</div>
<div class="topMonth" v-if="showFixdTopMonth">{{ fixdTopMonth }}</div>
<div class="allDaysArray">
<div class="alldays">
<div
v-for="(j, index) in days"
:key="j + 'bb' + index"
class="day"
:style="{ width: currentDaySize.value + 'px' }"
>
<template v-if="currentDaySize.value === 20">
<span
v-if="j.today"
class="dateNum todayDateNum"
style="border-left:1px solid #d7d7d7;"
>
今天
</span>
<span
v-else
class="dateNum"
:style="{
borderLeft: index == 0 ? 'none' : '1px solid #d7d7d7'
}"
:class="{
weekday: j.weekday == 0 || j.weekday == 6,
isHover:
j.width >= currentLineDay.start &&
j.width <= currentLineDay.end
}"
>{{ j.date }}</span>
<span
class="dateBG"
:class="{
weekday2: j.weekday == 0,
weekday1: j.weekday == 6,
today: j.today
}"
:style="{
width: currentDaySize.value + 'px',
height:j.weekday == 0 || j.weekday == 6 ? lineBGHeight : '0px'
}"
></span>
</template>
<template v-if="currentDaySize.value == 10">
<span
class="dateNum"
:class="{
weekday: j.weekday == 0 || j.weekday == 6,
isHover:
j.width >= currentLineDay.start &&
j.width <= currentLineDay.end,
nodBorder:
j.width >= currentLineDay.start &&
j.width <= currentLineDay.end
}"
>
<div
v-show="
(j.width === currentLineDay.end &&isHover &&j.weekday !== 1) ||
(j.width === currentLineDay.start &&isHover &&j.weekday !== 1) ||
j.weekday === 1
"
style="width:100%;height:100%;"
:style="{
borderLeft: index === 0 ? 'none' : '1px solid #d7d7d7'
}"
>
{{ j.date }}
</div>
</span>
<span
class="dateBG"
:class="{
weekday2: j.weekday === 0,
weekday1: j.weekday === 6,
today: j.today
}"
:style="{
width: currentDaySize.value + 'px',
height:j.weekday === 0 || j.weekday === 6 ? lineBGHeight : '0px'
}"
></span>
</template>
<template v-if="currentDaySize.value === 2">
<span
class="dateNum"
:class="{
isHover:
j.width >= currentLineDay.start &&
j.width <= currentLineDay.end,
nodBorder:
j.width >= currentLineDay.start &&
j.width <= currentLineDay.end
}"
>
<div
v-show="
(j.width === currentLineDay.end && isHover && j.date !== 1) ||
(j.width === currentLineDay.start &&isHover &&j.date !== 1) ||
j.date === 1
"
style="width:100%;height:100%;font-size:10px!important;"
:style="{
borderLeft: index === 0 ? 'none' : '1px solid #d7d7d7'
}"
>
{{ j.date }}
</div>
</span>
<span
class="dateBG weekday2"
:class="{today: j.today}"
style="border-right:none;"
:style="{
width: currentDaySize.value + 'px',
height:j.weekday === 0 || j.weekday === 6 ? lineBGHeight : '0px'
}"
></span>
</template>
</div>
</div>
<div class="lineBG" @scroll="handlerBGScroll" ref="lineBG">
<template v-for="(item, index) in computedList">
<!--<div :key="item.id" class="tetst">{{item.isShow}}</div>-->
<div
v-show="item.isShow"
:ref="'line' + item.id"
:key="item.id + 'cc'+ index"
class="line"
:style="{
left: item.left + 'px',
width: item.widthMe + 'px',
top: item.top + 'px'
}"
@mouseover="
lineMouseover(
`line${item.id}`,
$event,
item.id,
item.parentId,
index
)"
@mouseleave="lineMouseleave"
@mouseenter="
lineMouseenter(
`line${item.id}`,
$event,
item.id,
item.parentId,
index
)"
>
<slider
v-show="item.type == 1"
:id="item.id"
v-model="item.per"
:min="0"
:max="item.per"
:per1="item.per1"
:disabled="disable"
:widths="item.widthChild"
></slider>
</div>
<div
v-if="item.type == 3"
:key="item.id+'dd'+index"
class="group"
:style="{
top: item.top + 'px',
left: item.left + 'px',
width: item.widthMe + 'px'
}"
>
<div class="progress" :style="{ width: item.per + '%' }"></div>
</div>
</template>
</div>
</div>
<div class="toolTip">
<!--<div class="today base" @click="handleGoToday">今天</div>-->
<el-dropdown trigger="click">
<span class="base">
{{currentDaySize.label}}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu
slot="dropdown"
:style="{ left: this.left + 'px !important' }"
>
<el-dropdown-item
v-for="item in currentDaySizeOptions"
:key="item.value + 'ee'"
@click.native="handleSetDaySize(item)"
>
{{ item.label }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<transition name="el-zoom-in-center">
<div
v-show="isShowMsg"
:style="{
left: currentProjectMsg.left + 'px',
top: currentProjectMsg.top + 'px'
}"
class="projectMsg"
>
<div class="lineMsg projectName">
{{ currentProjectMsg.name }}
</div>
<div class="lineMsg">
<span class="title">工作周期</span>
<span>{{ currentProjectMsg.allTime }}</span>
</div>
<div class="lineMsg">
<span class="title">当前进度</span>
<span>{{ currentProjectMsg.per }}</span>
</div>
<div class="lineMsg">
<span class="title">合格数量</span>
<span>{{ currentProjectMsg.per1 }}</span>
</div>
<div class="lineMsg">
<span class="title">开始时间</span>
<span>{{ currentProjectMsg.startTime }}</span>
</div>
<div class="lineMsg">
<span class="title">结束时间</span>
<span>{{ currentProjectMsg.endTime }}</span>
</div>
</div>
</transition>
</div>
</div>
</div>
</template>
<script>
import slider from "./components/slider";
import leftMenu from "./components/leftMenu";
export default {
components: {
slider,
leftMenu,
},
props: {
proList:{
type:Array,
default: () => {
return []
}} ,
},
data() {
return {
timeRange: [],
disable: true,
//当前项是否是子集
isChildren: false,
dialogVal: false,
//title
title: "新建",
//定时器
timer: null,
//leftMenu的右侧伸缩线
rightLineX: 400,
fixdTopMonth: "",
//近三年的所有年月日
allDays: [],
//所有的天数
days: [],
//月数
monthArr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
//当前hover的项目起止时间
currentLineDay: {
start: 0,
end: 0
},
//当前的时间大小
currentDaySize: {
label: "",
value: 20
},
currentDaySizeOptions: [
{
label: "",
value: 20
},
{
label: "",
value: 10
},
{
label: "",
value: 2
}
],
//是否显示信息
isShowMsg: false,
//当前hover的项目信息
currentProjectMsg: {
name: "",
allTime: 0,
per: 0,
per1: 0,
startTime: 0,
endTime: 0,
left: 0,
top: 0
},
isHover: false,
showFixdTopMonth: false,
currentListIndex: "",
//正在编辑的row
editRow: [],
currentRow: null,
// BG滚动高度
BGScrollTop: 0,
// 背景高度
lineBGHeight: 0,
expandArr: [],
list:[],
};
},
mounted(){
debugger;
this.list = [...this.proList];
document.addEventListener("scroll", this.handleScroll);
this.list=[...this.list];
this.handlerCheckList(this.list);
this.getDay();
this.setStoneLine();
},
computed: {
computedList() {
let arr = [];
this.list.forEach(item => {
if (!item.children || item.children.length < 1) {
arr.push(item);
} else if (item.children && item.children.length >= 1) {
arr.push(item);
arr = arr.concat(item.children);
}
});
return arr;
},
left() {
return window.innerWidth - 30;
},
//当前年份
currentYear() {
return new Date().getFullYear();
},
//当前月份
currentMonth() {
return new Date().getMonth() + 1;
},
//当前日
currentDay() {
return new Date().getDate();
}
},
methods: {
TableScrollTop(val) {
let lineBG = this.$refs.lineBG;
lineBG.scrollTo(0, val);
// lineBG.scrollTo({
// top: val,
// left: 0,
// behavior: "smooth"
// });
},
handlerBGScroll(e) {
this.BGScrollTop = this.$refs.chart.scrollTop;
},
//过滤导入的数据
handlerCheckList(list) {
list.forEach((item, index) => {
item.planTime = [item.startTime, item.endTime];
item.left = this.computedTimeWidth(item.startTime);
item.widthMe = item.widthChild = this.computedTimeWidth(item.startTime, item.endTime);
item.isShow = true;
if (index - 1 < 0) {
item.top = 15;
if (item.type == 3) {
item.isexpand = true;
if (item.children.length > 0) {
item.children.forEach((k, i) => {
k.planTime = [k.startTime, k.endTime];
k.top = item.top + i * 40 + 40;
k.isShow = true;
k.left = this.computedTimeWidth(k.startTime);
k.widthMe = k.widthChild = this.computedTimeWidth(k.startTime, k.endTime, k);
});
}
}
} else {
if (list[index - 1].type == 3) {
item.top =
list[index - 1].top + list[index - 1].children.length * 40 + 40;
if (item.type == 3) {
item.isexpand = true;
if (item.children.length > 0) {
item.children.forEach((z, o) => {
z.planTime = [z.startTime, z.endTime];
z.top = item.top + o * 40 + 40;
z.isShow = true;
z.left = this.computedTimeWidth(z.startTime);
z.widthMe = z.widthChild = this.computedTimeWidth(z.startTime, z.endTime, z);
});
}
}
} else {
item.top = list[index - 1].top + 40;
}
}
});
list.forEach(item => {
if (item.type == 3) {
this.setGroupWidth(item.id, list);
this.setGroupPer(item.id, list);
}
});
this.list = list;
this.setStoneLine(list);
window.scrollTo({
top: 0,
left: 400,
behavior: "smooth"
});
},
//设置左侧leftmenu高亮
handlerSelect(row) {
this.$refs.leftMenu.handlerSelect(row);
},
//分组是否展开
handlerExpand(row, expand) {
let rowIndex = this.list.findIndex(item => {
return item.id == row.id;
});
this.list[rowIndex].expand = expand;
if (
this.list[rowIndex].children &&
this.list[rowIndex].children.length > 0
) {
this.list[rowIndex].children.forEach(k => {
k.isShow = expand;
});
}
this.resetTop(rowIndex, !expand, true);
},
// 根据时间计算距离
computedTimeWidth(startTime, endTime) {
debugger;
if (!endTime) {
let left =
(Math.floor(startTime - new Date(`${this.currentYear - 1}/01/01`).getTime()) /
(1000 * 60 * 60 * 24)) * this.currentDaySize.value;
return left;
} else {
let width = (Math.floor(endTime - startTime) / (1000 * 60 * 60 * 24)) * this.currentDaySize.value + this.currentDaySize.value;
console.log(width);
return width;
}
},
//修改后续高度
resetTop(zindex, reduce, isexpand) {
// console.log(zindex, reduce, isexpand);
let num = reduce ? -40 : 40;
if (!reduce && !isexpand) {
// console.log(2);
this.list.forEach((item, index) => {
if (index > zindex) {
item.top = item.top + 40;
if (item.children && item.children.length > 0) {
item.children.forEach((k, i) => {
k.top = item.top + 40 * i + 40;
});
}
}
});
} else {
// console.log(1);
this.list.forEach((item, index) => {
if (index > zindex) {
item.top = item.top + num * this.list[zindex].children.length;
if (item.children && item.children.length > 0) {
item.children.forEach((k, i) => {
k.top = item.top + 40 * i + 40;
});
}
}
});
}
},
retDelTop(zindex, length) {
this.list.forEach((item, index) => {
if (index >= zindex) {
item.top = item.top - 40 * length;
if (item.children && item.children.length > 0) {
item.children.forEach((k, i) => {
k.top = item.top + 40 * i + 40;
});
}
}
});
},
//根据id设置group的宽度
setGroupWidth(id, lists) {
let parent;
if (lists) {
parent = lists.find(item => {
return item.id == id;
});
} else {
parent = this.list.find(item => {
return item.id == id;
});
}
let left = Math.min.apply(
Math,
parent.children.map(o => {
return o.left;
})
);
let arr = [];
parent.children.forEach(item => {
arr.push(item.left + item.widthMe);
});
let width = Math.max.apply(Math, arr);
let widthMe = width - left;
parent.widthMe = parent.widthChild = widthMe;
parent.left = left;
// return parent;
},
// 转为分组
handlerGroup(row) {
let index = this.list.findIndex(item => {
return item.id == row.id;
});
this.list[index].type = "3";
this.list[index].per = 0;
this.list[index].id = new Date().getTime();
this.list[index].left = 0;
this.list[index].widthMe = this.list[index].widthChild = 0;
this.$set(this.list, index, this.list[index]);
},
//leftMenu宽度设置
rightLineMousedown(e) {
let cx = e.clientX;
let result;
document.onmousemove = event => {
result = event.clientX - cx;
if (cx + result <= 441) return;
this.$refs.rightLine.style.left = cx + result + "px";
};
document.onmouseup = () => {
document.onmousemove = document.onmouseup = null;
if (cx + result <= 441) {
this.rightLineX = 441;
return;
}
this.rightLineX = cx + result;
};
},
//rowClick事件
handlerRowClick(row) {
this.currentRow = row;
this.$refs.chart.scrollTo({
top: 0,
left: row.left - 100,
behavior: "smooth"
});
},
//更改daySize-----按天/按周/按月
handleSetDaySize(item) {
this.currentDaySize = item;
this.days.forEach((item, index) => {
item.width = (index + 1) * this.currentDaySize.value;
});
this.handleScroll();
if (this.currentRow) {
let rs = this.computedList.find(o => {
return o.id == this.currentRow.id;
});
this.$nextTick(() => {
});
}
},
//滑动进度条事件
thunkMousemove() {
this.isShowMsg = false;
},
//滑动进度条事件
thunkMousedown() {
this.isShowMsg = false;
},
//滑动进度条事件
thunkMouseup(per, e, id, parentId) {
// console.log(per, id, parentId);
let cindex = this.computedList.findIndex(z => {
return z.id == id;
});
if (parentId) {
let index = this.list.findIndex(k => {
return k.id == parentId;
});
// console.log(parentId);
this.list.forEach(item => {
if (item.id == parentId) {
// console.log(item, this.list);
item.children.forEach(k => {
if (k.id == id) {
k.per = per;
}
});
}
});
this.setGroupPer(parentId);
this.$set(this.list, index, this.list[index]);
} else {
this.list.forEach(item => {
if (item.id == id) {
item.per = per;
}
});
}
this.checkIsin(`line${id}`, e, id, parentId, cindex);
},
//设置分组百分比
setGroupPer(id, lists) {
let z;
if (lists) {
z = lists.find(o => {
return o.id == id;
});
} else {
z = this.list.find(o => {
return o.id == id;
});
}
let count = 0;
let length = z.children.length;
z.children.forEach(item => {
count = count + (item.per / 100) * (1 / length);
});
z.per = Math.round(count * 100);
},
//回到今天
handleGoToday() {
let s =
Math.round(window.innerWidth / this.currentDaySize.value / 2) *
this.currentDaySize.value - this.rightLineX;
let width =
(Math.floor(
new Date(
`${this.currentYear}/${this.currentMonth}/${this.currentDay}`
).getTime() - new Date(`${this.currentYear - 1}/01/01`).getTime()
) /
(1000 * 60 * 60 * 24)) *
this.currentDaySize.value - s;
window.scrollTo({
top: 0,
left: width,
behavior: "smooth"
});
},
//根据距离计算时间
/**
* @param {Number} width
* @param {Boolean|String} time
*/
computedWithTime(width, time) {
let startTime = (width / this.currentDaySize.value) * (1000 * 60 * 60 * 24) +
new Date(`${this.currentYear - 1}/01/01`).getTime();
let s = new Date(startTime);
if (time && time == true) {
return s.getTime();
} else if (time && time == "YD") {
return `${s.getFullYear()}/${s.getMonth() + 1}`;
} else {
return `${s.getFullYear()}/${s.getMonth() + 1}/${s.getDate()}`;
}
},
//根据index值和e判断是否在当前line的范围里是否展示时间和msg框
/**
* @param {String} dom ref
* @param {Object} events $event
* @param {Number} id id
* @param {Number} parentId parentId
* @param {Number} index index
*/
checkIsin(dom, events, id, parentId, index) {
let line = this.$refs[dom][0];
let lineTop = parseInt(line.style.top);
let lineDown = lineTop + 16;
let lineLeft = parseInt(line.style.left);
let lineRight = parseInt(this.computedList[index].widthMe) + lineLeft;
if (
events.pageX - this.rightLineX >= lineLeft &&
events.pageX - this.rightLineX <= lineRight &&
events.y - 40 >= lineTop &&
events.y - 40 <= lineDown
) {
this.lineMouseover(dom, events, id, parentId, index);
this.lineMouseenter(dom, events, id, parentId, index);
} else {
this.isShowMsg = false;
this.currentLineDay = {
start: 0,
end: 0
};
}
},
/**
* @param {String} dom ref
* @param {Object} events $event
* @param {Number} id id
* @param {Number} parentId parentId
* @param {Number} index index
*/
//鼠标悬停展示上部日期
lineMouseover(dom, e, id, parentId, index) {
let start =
Math.round(
parseInt(this.$refs[dom][0].style.left) / this.currentDaySize.value
) *
this.currentDaySize.value +
this.currentDaySize.value;
let end =
parseInt(this.$refs[dom][0].style.left) +
parseInt(this.$refs[dom][0].style.width);
end =
Math.round(end / this.currentDaySize.value) * this.currentDaySize.value;
this.currentLineDay = {
start,
end
};
this.isHover = true;
this.handlerSelect(this.computedList[index]);
this.lineMouseenter(dom, e, id, parentId, index);
},
/**
* @param {String} dom ref
* @param {Object} events $event
* @param {Number} id id
* @param {Number} parentId parentId
* @param {Number} index index
*/
//鼠标进入显示当前项目的基本信息框
lineMouseenter(dom, e, id, parentId, index) {
let start =
Math.round(
parseInt(this.$refs[dom][0].style.left) / this.currentDaySize.value
) * this.currentDaySize.value;
let end =
parseInt(this.$refs[dom][0].style.left) +
parseInt(this.$refs[dom][0].style.width);
end =
Math.round(end / this.currentDaySize.value) *
this.currentDaySize.value -
this.currentDaySize.value;
this.currentProjectMsg = {
name: this.computedList[index].name,
allTime: (end - start) / this.currentDaySize.value + 1,
per: this.computedList[index].per,
per1: this.computedList[index].per1,
startTime: this.computedWithTime(start),
endTime: this.computedWithTime(end),
left: e.clientX,
top: e.clientY + 20
};
/*
* left:
e.clientX + 220 - this.$refs.chart.scrollLeft >= this.$refs.chart.clientWidth
? e.clientX - 220 - 400
: e.clientX ,
* */
this.isShowMsg = true;
},
//鼠标离开信息消失时间显示消失
/**
* @param {Object} e $event
* @param {Boolean} move 是否移动状态
*/
lineMouseleave(e, move) {
if (move) {
this.isShowMsg = false;
this.currentProjectMsg = {
name: "",
allTime: 0,
per: 0,
startTime: 0,
endTime: 0,
left: 0,
top: 0
};
// this.handlerSelect();
return;
}
this.currentLineDay = {
start: 0,
end: 0
};
this.isHover = false;
this.isShowMsg = false;
this.currentProjectMsg = {
name: "",
allTime: 0,
per: 0,
startTime: 0,
endTime: 0,
left: 0,
top: 0
};
this.handlerSelect();
},
//获取要显示的所有天数
getDay() {
this.getAllDate();
},
//判断是否为闰年
/**
* @param {Number} year 传入年份
*/
isLeapYear(year) {
if (year % 4 > 0) {
return true;
}
return false;
},
getAllDate() {
let obj = {}, arr = [];
/* let start = new Date(this.timeRange[0]).getFullYear();
let end = new Date(this.timeRange[1]).getFullYear();*/
/*for (let i = start; i < end + 1; i++) {
arr.push(i)
}*/
arr = [this.currentYear - 1, this.currentYear, this.currentYear + 1];
arr.forEach(item => {
obj.year = item;
obj.days = this.isLeapYear(item) ? 365 : 366;
this.allDays.push(obj);
obj = {};
});
this.checkDate();
},
//根据年份天数创建月份及月份天数数组
checkDate() {
this.allDays.forEach(item => {
item.month = this.handleMonthDay(item.days, item.year);
});
this.allDays.forEach(element => {
if (element.year == this.currentYear) {
element.month[0][this.currentMonth].forEach(k => {
if (k.date == this.currentDay) {
k.today = true;
}
});
}
});
let arr = [];
this.allDays.forEach(item => {
arr = arr.concat(item.month);
});
arr.forEach(item => {
for (var j in item) {
this.days = this.days.concat(item[j]);
}
});
this.days.forEach((item, index) => {
item.width = (index + 1) * this.currentDaySize.value;
});
},
/**
* @param {Number} days
* @param {Number} year
*/
handleMonthDay(days, year) {
let arr = [];
let obj = {};
this.monthArr.forEach(item => {
obj[item] = this.checkMonthDays(item, days);
});
arr.push(obj);
let s = arr[0];
for (let item in s) {
s[item] = this.addNum(s[item], item, year);
}
// console.log(arr);
return arr;
},
/**
* @param {number} num 天数
* @param {number} month 月份
* @param {number} year 年份
*/
addNum(num, month, year) {
let arr = [];
let obj = {};
for (let i = 1; i <= num; i++) {
obj.date = i;
obj.weekday = new Date(`${year}/ ${month} / ${i}`).getDay();
arr.push(obj);
obj = {};
}
return arr;
},
//根据月份返回天数
/**
* @param {Number} month 月份
* @param {Number} days 天数
*/
checkMonthDays(month, days) {
let day;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
// eslint-disable-next-line no-unreachable
break;
case 4:
case 6:
case 9:
case 11:
return 30;
// eslint-disable-next-line no-unreachable
break;
case 2:
day = days == 365 ? 28 : 29;
return day;
// eslint-disable-next-line no-unreachable
break;
}
},
//设置里程碑线的高度
setStoneLine(isFirst) {
this.$nextTick(() => {
let height = window.getComputedStyle(
document.getElementsByClassName("lineBG")[0]
).height;
this.lineBGHeight = height;
});
},
//顶部固定时间
handleScroll() {
let w = window.scrollX;
if (w <= 62) {
this.showFixdTopMonth = false;
} else {
this.showFixdTopMonth = true;
}
let time = this.computedWithTime(w, "YD");
this.fixdTopMonth = time;
}
},
watch: {
currentDaySize(newValue, oldValue) {
this.list.forEach(item => {
item.left = (item.left / oldValue.value) * newValue.value;
item.widthMe = item.widthChild =
(item.widthMe / oldValue.value) * newValue.value;
if (item.children && item.children.length > 0) {
item.children.forEach(k => {
k.left = (k.left / oldValue.value) * newValue.value;
k.widthMe = k.widthChild =
(k.widthMe / oldValue.value) * newValue.value;
});
}
});
}
},
beforeDestroy() {
window.removeEventListener("scroll", this.handleScroll);
document.onmousemove = document.onmouseup = null;
}
};
</script>
<style lang="scss" scoped>
.chart {
height: 40vh;
user-select: none;
position: relative;
overflow: hidden;
overflow-x: scroll;
background: #ffffff;
.header {
height: 40px;
position: relative;
.header-left {
margin-left: 10px;
box-sizing: border-box;
padding-top: 5px;
height: 40px;
position: fixed;
top: 0;
left: 0;
background-color: #fff;
}
}
.left {
position: absolute;
height: 89vh;
background-color: #fff;
z-index: 999;
border-right: 1px solid #d7d7d7;
.rightLine {
z-index: 999;
position: absolute;
top: 0;
height: 100%;
width: 2px;
background-color: #d7d7d7;
box-shadow: 4px 2px 12px 0 rgba(0, 0, 0, 0.2);
cursor: col-resize;
&:hover {
background-color: #409eff;
}
}
}
.showCurrentLineDate {
position: fixed;
top: 0;
background-color: #409eff;
color: #fff;
height: 20px;
font-size: 16px;
display: flex;
align-items: center;
justify-content: space-between;
}
.projectMsg {
box-sizing: border-box;
padding: 20px;
position: fixed;
width: 230px;
/*height: 230px;*/
z-index: 12000;
background-color: #fff;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
border: 1px solid #ebeef5;
.lineMsg {
margin-bottom: 10px;
&.projectName {
font-size: 22px;
color: #333333;
text-align: center;
border-bottom: 1px solid #999999;
}
span {
font-size: 14px;
color: #909090;
}
.title {
margin-right: 5px;
color: #666666
}
}
}
.date {
display: flex;
height: 100%;
position: relative;
/*overflow: scroll;*/
.topMonth {
// width: 100px;
background-color: #fff;
position: fixed;
top: 40px;
height: 21px;
line-height: 21px;
font-size: 12px !important;
font-weight: 600 !important;
color: #909090 !important;
}
.toolTip {
position: fixed;
right: 0;
top: 90px;
z-index: 999;
.base {
display: inline-block;
text-align: center;
height: 30px;
line-height: 30px;
padding: 0 15px;
background-color: #fff;
font-size: 14px;
cursor: pointer;
user-select: none;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
font-weight: 400;
color: #303030;
border-radius: 3px;
box-shadow: 0 3px 12px 0 rgba(48, 48, 48, 0.05),
0 3px 6px 0 rgba(48, 48, 48, 0.1);
margin-right: 20px;
&:hover {
color: #409eff;
}
}
}
.group {
position: absolute;
background-color: #909090 !important;
border: none !important;
border-radius: 0 !important;
height: 14px !important;
line-height: 14px !important;
// margin-top: 5px;
clip-path: polygon(
100% 0,
100% 100%,
calc(100% - 8px) 60%,
8px 60%,
0 100%,
0 0
);
// > div {
// -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
// }
.progress {
// width: 50px;
background-color: #606060 !important;
height: 100%;
}
}
}
.line {
position: absolute;
height: 20px;
background: #abf7f7;
.rightCurDrag {
cursor: e-resize;
width: 10px;
background-color: #000;
height: 16px;
position: absolute;
right: -15px;
transform: translateY(-50%);
top: 50%;
border-radius: 3px;
user-select: none;
}
.leftCurDrag {
cursor: e-resize;
width: 10px;
background-color: #000;
height: 16px !important;
position: absolute;
left: -15px;
transform: translateY(-50%);
top: 50%;
border-radius: 3px;
user-select: none;
}
.stoneLine {
position: absolute;
top: 0px;
left: 50%;
margin-left: -1px;
width: 2px;
background-color: #24b47e;
}
.milestone {
position: absolute;
left: 50%;
// transform: translateX(-50%);
cursor: move;
margin-left: -10px;
width: 20px;
height: 20px;
background-color: #24b47e;
transform: rotate(-45deg);
display: flex;
justify-content: center;
align-items: center;
i {
transform: rotate(45deg);
color: #fff;
z-index: 1;
}
}
}
.years {
display: flex;
height: 100%;
.month {
height: 100%;
.month-top {
height: 21px;
line-height: 21px;
font-size: 12px !important;
font-weight: 600 !important;
color: #909090 !important;
}
}
}
.allDaysArray {
position: absolute;
left: 0px;
top: 21px;
height: calc(100% - 21px);
.alldays {
display: flex;
}
.lineBG {
width: 100%;
height: 100%;
position: relative;
overflow: scroll;
}
.weekday {
color: #c7c7c7;
}
.weekday1 {
border-left: 1px solid #d7d7d7;
background-image: linear-gradient(to bottom, #f8f8f8, #f8f8f8);
}
.weekday2 {
border-right: 1px solid #d7d7d7;
background-image: linear-gradient(to bottom, #f8f8f8, #f8f8f8);
width: 100%;
}
.day {
// width: 40px;
position: relative;
display: inline-block;
height: calc(100% - 21px);
box-sizing: border-box;
text-align: center;
.isHover {
background-color: #409eff;
color: #fff;
}
.nodBorder {
div {
border-left: none !important;
}
}
.dateNum {
font-size: 12px;
line-height: 20px;
display: block;
height: 20px;
// border-left: 1px solid #d7d7d7;
border-bottom: 1px solid #d7d7d7;
box-sizing: border-box;
}
.todayDateNum {
background-color: #f0a100;
color: #fff;
}
.dateBG {
position: absolute;
top: 20px;
left: 0px;
display: block;
// height: 100%;
}
.today {
position: relative;
}
.today::after {
content: "";
height: 100%;
width: 2px;
background-color: #f0a100;
position: absolute;
// left: 20px;
top: 0px;
}
}
}
}
</style>