|
@@ -0,0 +1,644 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+
|
|
|
+ <div class="u-gantt-container u-flex">
|
|
|
+ <div>
|
|
|
+ <el-table
|
|
|
+ :data="tableData"
|
|
|
+ stripe border
|
|
|
+ :cell-class-name="tableCellClassName"
|
|
|
+ :header-cell-class-name="tableCellClassName"
|
|
|
+ @row-dblclick="rowDblclick"
|
|
|
+ row-key="id"
|
|
|
+ default-expand-all
|
|
|
+ :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
|
|
+ @expand-change="expandChange"
|
|
|
+ >
|
|
|
+ <template v-for="(item, index) in configColumns">
|
|
|
+ <el-table-column
|
|
|
+ :prop="item.name"
|
|
|
+ :label="item.label"
|
|
|
+ :width="item.width"
|
|
|
+ :align="item.align"
|
|
|
+ :key="index"
|
|
|
+ show-overflow-tooltip
|
|
|
+ ></el-table-column>
|
|
|
+ <!-- :fixed="item.fixed" -->
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <div class="u-gantt" ref="uGantt">
|
|
|
+ <div class="u-gantt-title u-flex" >
|
|
|
+ <div v-for="(item, index) in uGanttColumns" :key="index" class="item-title">{{ item.label}}</div>
|
|
|
+ </div>
|
|
|
+ <div class="u-gantt-content">
|
|
|
+ <div class="u-gantt-bg">
|
|
|
+ <div v-for="(item, tr) in ganttLists" :key="tr" class="item-tr u-flex">
|
|
|
+ <!-- :style="{'display': item.show}" -->
|
|
|
+ <div class="item-td" v-for="(item, td) in uGanttColumns" :key="td"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="u-gantt-task">
|
|
|
+
|
|
|
+ <div class="u-gantt-task-content uGanttTaskItem" ref="uGanttTaskItem" v-for="(item, index) in ganttLists" :key="index" :style="setStyle(item)">
|
|
|
+ <!-- <span class="resize" ref="`resize${index}}`" @mousedown="dragControllerDiv(index)"></span> -->
|
|
|
+ <div class="u-gantt-task-drag" ref="uGanttDrag"></div>
|
|
|
+ <div class="u-gantt-task-resize resize-left" ref="uGanttResizeL"></div>
|
|
|
+ <div class="u-gantt-task-text">{{ item.content }}</div>
|
|
|
+ <div class="u-gantt-task-resize resize-right" ref="uGanttResizeR"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 自定义内容:弹窗 -->
|
|
|
+ <slot/>
|
|
|
+
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ props: {
|
|
|
+ configColumns: {
|
|
|
+ type: Array,
|
|
|
+ default: []
|
|
|
+ },
|
|
|
+ taskLists: {
|
|
|
+ type: Array,
|
|
|
+ default: []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data(){
|
|
|
+ return {
|
|
|
+ // taskLists: [
|
|
|
+ // {
|
|
|
+ // id: 0,
|
|
|
+ // testItems: 'ceshi',
|
|
|
+ // sampleName: 'ceshi',
|
|
|
+ // task_start: '2023-07-03',
|
|
|
+ // task_end: '2023-07-04',
|
|
|
+ // statusC: '0',
|
|
|
+ // content: '111'
|
|
|
+ // }, {
|
|
|
+ // id: 1,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '0',
|
|
|
+ // }, {
|
|
|
+ // id: 2,
|
|
|
+ // testItems: 'ceshi',
|
|
|
+ // sampleName: 'ceshi',
|
|
|
+ // task_start: '2023-07-06',
|
|
|
+ // task_end: '2023-07-10',
|
|
|
+ // statusC: '1',
|
|
|
+ // }, {
|
|
|
+ // id: 3,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '1',
|
|
|
+ // },{
|
|
|
+ // id: 4,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '1',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // id: 5,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '1',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // id: 6,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '1',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // id: 7,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '1',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // id: 8,
|
|
|
+ // testItems: '测试',
|
|
|
+ // sampleName: '测试',
|
|
|
+ // task_start: '',
|
|
|
+ // task_end: '',
|
|
|
+ // statusC: '1',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // id: 21,
|
|
|
+ // testItems: 'ceshi1',
|
|
|
+ // sampleName: 'ceshi',
|
|
|
+ // task_start: '2023-07-05',
|
|
|
+ // task_end: '2023-07-08',
|
|
|
+ // statusC: '1',
|
|
|
+ // parentId: 2
|
|
|
+ // }, {
|
|
|
+ // id: 23,
|
|
|
+ // testItems: 'ceshi3',
|
|
|
+ // sampleName: 'ceshi',
|
|
|
+ // task_start: '2023-07-02',
|
|
|
+ // task_end: '2023-07-04',
|
|
|
+ // statusC: '1',
|
|
|
+ // parentId: 2
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // id: 22,
|
|
|
+ // testItems: 'ceshi2',
|
|
|
+ // sampleName: 'ceshi',
|
|
|
+ // task_start: '2023-07-06',
|
|
|
+ // task_end: '2023-07-10',
|
|
|
+ // statusC: '1',
|
|
|
+ // parentId: 2
|
|
|
+ // }
|
|
|
+ // ],
|
|
|
+ // 甘特图部分时间表头
|
|
|
+ uGanttColumns: [],
|
|
|
+ // 表格使用数据
|
|
|
+ tableData: [],
|
|
|
+ // 甘特图显示的
|
|
|
+ ganttLists: [],
|
|
|
+
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // computed: {
|
|
|
+ // // 甘特图标题日期分配
|
|
|
+ // uGanttColumns() {
|
|
|
+ // // 获取标准时间
|
|
|
+ // var nowdays = new Date()
|
|
|
+ // // 获取当年
|
|
|
+ // var currentYear = new Date().getFullYear()
|
|
|
+ // // 获取当月
|
|
|
+ // var currentMonth = new Date().getMonth() + 1
|
|
|
+ // // 获取当天
|
|
|
+ // var nowDay = new Date().getDate()
|
|
|
+ // // 获取当前月有多少天
|
|
|
+ // var currentMonthNum = new Date(currentYear, currentMonth, 0).getDate()
|
|
|
+ // console.log(nowDay, currentMonth, currentMonthNum)
|
|
|
+ // //
|
|
|
+ // // let now = new Date(nowDay)
|
|
|
+ // // console.log(nowdays, now)
|
|
|
+ // // 当前月份所有日期集合
|
|
|
+ // let currentMonthArr = []
|
|
|
+ // for (let i = 1; i <= currentMonthNum; i++) {
|
|
|
+ // // let day = nowdays.setDate(i);
|
|
|
+ // // console.log(day)
|
|
|
+ // // 年月日(yyyy-MM-dd)
|
|
|
+ // let dateLabel = (currentMonth < 10 ? '0' + currentMonth : currentMonth) + "月" + (i < 10 ? '0' + i : i) + "日";
|
|
|
+ // let dateName = currentYear + "-" + (currentMonth < 10 ? '0' + currentMonth : currentMonth) + "-" + (i < 10 ? '0' + i : i);
|
|
|
+ // // let day =
|
|
|
+ // currentMonthArr.push({label: dateLabel, name: dateName});
|
|
|
+ // }
|
|
|
+ // console.log(currentMonthArr)
|
|
|
+ // return currentMonthArr
|
|
|
+ // },
|
|
|
+
|
|
|
+ // },
|
|
|
+ created (){
|
|
|
+ this.changeTableTree()
|
|
|
+ // this.changeTaskSort()
|
|
|
+ this.getStartEndTime()
|
|
|
+ },
|
|
|
+ mounted () {
|
|
|
+ this.uGanttDrag()
|
|
|
+ this.uGanttResizeL()
|
|
|
+ this.uGanttResizeR()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 获取最开始和最末尾时间
|
|
|
+ getStartEndTime(){
|
|
|
+ // var setTimeData = JSON.parse(JSON.stringify(this.taskLists))
|
|
|
+ var setTimeData = this.taskLists.filter(res=> res.task_start)
|
|
|
+ setTimeData.sort(function(a, b) {
|
|
|
+ return b.task_start < a.task_start ? 1 : -1
|
|
|
+ })
|
|
|
+ console.log(setTimeData[0].task_start)
|
|
|
+ console.log(setTimeData[setTimeData.length - 1].task_end)
|
|
|
+ var end = this.addDate(setTimeData[setTimeData.length - 1].task_end, 2)
|
|
|
+ this.uGanttColumns = this.getBetweenDate(setTimeData[0].task_start, end)
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 计算某个日期几天后的日期
|
|
|
+ * @param {*} date 相加前的时间
|
|
|
+ * @param {*} days 需要相加的天数
|
|
|
+ */
|
|
|
+ addDate(date, days) {
|
|
|
+ var date = new Date(date);
|
|
|
+ date.setDate(date.getDate() + days);
|
|
|
+ var year = date.getFullYear();
|
|
|
+ var month = date.getMonth() + 1;
|
|
|
+ var day = date.getDate();
|
|
|
+ var mm = "'" + month + "'";
|
|
|
+ var dd = "'" + day + "'";
|
|
|
+ if(mm.length == 3) {
|
|
|
+ month = "0" + month;
|
|
|
+ }
|
|
|
+ if(dd.length == 3) {
|
|
|
+ day = "0" + day;
|
|
|
+ }
|
|
|
+ var time = year + "-" + month + "-" + day
|
|
|
+ return time;
|
|
|
+ },
|
|
|
+ /** 获取两个日期之间的间隔日期
|
|
|
+ * @param { Date | number | string } startTime 开始时间 标准时间格式 时间戳格式 字符串格式(2008-08-08,2008-8-8,2008-08-8,2008-8-08)
|
|
|
+ * @param { Date | number | string } endTime 结束时间 标准时间格式 时间戳格式 字符串格式(2008-08-08,2008-8-8,2008-08-8,2008-8-08)
|
|
|
+ * */
|
|
|
+ getBetweenDate(startTime, endTime){
|
|
|
+ // 校验时间格式
|
|
|
+ if (typeof startTime === 'string') {
|
|
|
+ const reg = /^\d{4}-(0?[1-9]|1[0-2])-((0?[1-9])|((1|2)[0-9])|30|31)$/g
|
|
|
+ if (!reg.test(startTime)) throw `开始时间:${startTime}时间格式错误`
|
|
|
+ }
|
|
|
+ if (typeof endTime === 'string') {
|
|
|
+ const reg = /^\d{4}-(0?[1-9]|1[0-2])-((0?[1-9])|((1|2)[0-9])|30|31)$/g
|
|
|
+ if (!reg.test(endTime)) throw `结束时间:${endTime}时间格式错误`
|
|
|
+ }
|
|
|
+ let start = new Date(startTime)
|
|
|
+ let end = new Date(endTime)
|
|
|
+ const resultTime = []
|
|
|
+ // 当 开始时间小于结束时间的时候进入循环
|
|
|
+ while (start <= end) {
|
|
|
+ let getDay = start.getDate()
|
|
|
+ // 月份需要加 1
|
|
|
+ let getMonth = start.getMonth() + 1
|
|
|
+ let getYear = start.getFullYear()
|
|
|
+ /**
|
|
|
+ * 拼接时间格式
|
|
|
+ * (getMonth >= 10 ? `${getMonth}` : `0${getMonth}`) 自动给 小于10的时间前面补0
|
|
|
+ */
|
|
|
+ let setTime =
|
|
|
+ `${getYear}-` +
|
|
|
+ (getMonth >= 10 ? `${getMonth}` : `0${getMonth}`) +
|
|
|
+ '-' +
|
|
|
+ (getDay >= 10 ? `${getDay}` : `0${getDay}`)
|
|
|
+ let dateLabel = (getMonth < 10 ? '0' + getMonth : getMonth) + "月" + (getDay < 10 ? '0' + getDay : getDay) + "日";
|
|
|
+ resultTime.push({label: dateLabel, name: setTime})
|
|
|
+ /**
|
|
|
+ * 重新设置开始时间
|
|
|
+ * 使用 setFullYear() 方法会自动将时间累加,返回的是时间戳格式
|
|
|
+ * 使用 new Date() 将时间重新设置为标准时间
|
|
|
+ * getMonth - 1 将月份时间重新还原
|
|
|
+ */
|
|
|
+ start = new Date(start.setFullYear(getYear, getMonth - 1, getDay + 1))
|
|
|
+ }
|
|
|
+ return resultTime
|
|
|
+ },
|
|
|
+ // 将一维数组改成多维数组
|
|
|
+ changeTableTree(){
|
|
|
+ this.tableData = this.handleTree(this.taskLists, 'id', "parentId")
|
|
|
+ this.changeTaskSort(this.tableData)
|
|
|
+ },
|
|
|
+ // 绘制甘特条
|
|
|
+ setStyle(item){
|
|
|
+ var startIndex = this.uGanttColumns.findIndex(res => res.name === item.task_start)
|
|
|
+ var endIndex = this.uGanttColumns.findIndex(res => res.name === item.task_end)
|
|
|
+ var trIndex = this.ganttLists.findIndex(res => res.id === item.id)
|
|
|
+ // console.log(trIndex, this.ganttLists)
|
|
|
+ var style = {
|
|
|
+ left: 70 * startIndex + 'px',
|
|
|
+ width: 70 * (endIndex - startIndex + 1) + 'px',
|
|
|
+ top: (34 * trIndex + 2) + 'px'
|
|
|
+ }
|
|
|
+ return style
|
|
|
+ },
|
|
|
+ // 将组好的多维数组转成一维数组--是为了左右对应
|
|
|
+ changeTaskSort(arr){
|
|
|
+ for(var i = 0; i < arr.length; i++){
|
|
|
+ // arr[i].show = 'flex'
|
|
|
+ if(Array.isArray(arr[i].children)){
|
|
|
+ this.ganttLists.push(arr[i]);
|
|
|
+ this.changeTaskSort(arr[i].children);
|
|
|
+ }else{
|
|
|
+ this.ganttLists.push(arr[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 位移事件
|
|
|
+ uGanttDrag(){
|
|
|
+ var _this = this
|
|
|
+ var uGanttDrag = this.$refs.uGanttDrag;
|
|
|
+ var uGanttTaskItem = this.$refs.uGanttTaskItem;
|
|
|
+ for (let i = 0; i < uGanttDrag.length; i++) {
|
|
|
+ // 鼠标按下
|
|
|
+ uGanttDrag[i].onmousedown = function (e) {
|
|
|
+ const offsetLeft = uGanttTaskItem[i].offsetLeft
|
|
|
+ const offsetWidth = uGanttTaskItem[i].offsetWidth
|
|
|
+ var startX = e.clientX;
|
|
|
+ var moveLen
|
|
|
+ // 向上取证获取当前是第几行
|
|
|
+ var ganttIndex = Math.trunc(uGanttTaskItem[i].offsetTop/34)
|
|
|
+ // 移动事件
|
|
|
+ document.onmousemove = function (e) {
|
|
|
+ var endX = e.clientX;
|
|
|
+ moveLen = offsetLeft + ( endX - startX )
|
|
|
+ // 设置当前甘特条距离左侧的距离(使得左侧移动,而宽度不变,右侧对应向右移,产生移动效果)
|
|
|
+ uGanttTaskItem[i].style.left = moveLen + 'px'
|
|
|
+ // 移动过程鼠标变成拖拽形状
|
|
|
+ uGanttDrag[i].style.cursor = 'move'
|
|
|
+
|
|
|
+ // 监听位置进行滚动条滚动--尚未完成
|
|
|
+ var uGantt = _this.$refs.uGantt
|
|
|
+ const offsetRight = uGantt.offsetWidth - (uGanttTaskItem[i].offsetLeft + uGanttTaskItem[i].offsetWidth)
|
|
|
+ console.log(offsetRight)
|
|
|
+ if(offsetRight<0){
|
|
|
+ uGantt.scrollLeft = uGanttTaskItem[i].offsetWidth
|
|
|
+ }
|
|
|
+ }
|
|
|
+ document.onmouseup = function (evt) {
|
|
|
+ // 同样:不能停在一段的中间位置,所以计算使其整段整段的形式显示
|
|
|
+ uGanttTaskItem[i].style.left = Math.round(moveLen/70) * 70 + 'px';
|
|
|
+ // 获取最终左侧停在第几列
|
|
|
+ var startNum = (uGanttTaskItem[i].offsetLeft)/70
|
|
|
+ // 获取最终右侧停在第几列
|
|
|
+ var endNum = (offsetWidth / 70) + startNum
|
|
|
+ // 找到对应的时间强制赋值刷新
|
|
|
+ _this.$set(_this.ganttLists[ganttIndex], 'task_start', _this.uGanttColumns[startNum].name)
|
|
|
+ _this.$set(_this.ganttLists[ganttIndex], 'task_end', _this.uGanttColumns[endNum - 1].name)
|
|
|
+ // 鼠标变回手型
|
|
|
+ uGanttDrag[i].style.cursor = 'pointer'
|
|
|
+ // 释放
|
|
|
+ document.onmousemove = null;
|
|
|
+ document.onmouseup = null;
|
|
|
+ document.releaseCapture && document.releaseCapture();
|
|
|
+ }
|
|
|
+ document.setCapture && document.setCapture();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 改变大小
|
|
|
+ uGanttResizeL(){
|
|
|
+ var _this = this
|
|
|
+ var resize = this.$refs.uGanttResizeL;
|
|
|
+ var uGanttTaskItem = this.$refs.uGanttTaskItem;
|
|
|
+ for (let i = 0; i < resize.length; i++) {
|
|
|
+ resize[i].onmousedown = function (e) {
|
|
|
+ var startX = e.clientX;
|
|
|
+ var ganttIndex = Math.trunc(uGanttTaskItem[i].offsetTop/34)
|
|
|
+ const offsetLeft = uGanttTaskItem[i].offsetLeft;
|
|
|
+ const offsetWidth = uGanttTaskItem[i].offsetWidth
|
|
|
+ var moveLen
|
|
|
+ var ganttWidth
|
|
|
+ document.onmousemove = function (e) {
|
|
|
+ var endX = e.clientX;
|
|
|
+ moveLen = offsetLeft - (startX - endX);
|
|
|
+ ganttWidth = (startX - endX) + offsetWidth
|
|
|
+ if (ganttWidth < 70){
|
|
|
+ ganttWidth = 70
|
|
|
+ moveLen = offsetLeft + offsetWidth - 70
|
|
|
+ }
|
|
|
+
|
|
|
+ uGanttTaskItem[i].style.left = moveLen + 'px';
|
|
|
+ uGanttTaskItem[i].style.width = ganttWidth + 'px';
|
|
|
+ }
|
|
|
+ document.onmouseup = function (evt) {
|
|
|
+ uGanttTaskItem[i].style.left = Math.round(moveLen/70) * 70 + 'px';
|
|
|
+ uGanttTaskItem[i].style.width = Math.round(ganttWidth/70) * 70 + 'px';
|
|
|
+ var num = (uGanttTaskItem[i].offsetLeft)/70
|
|
|
+ console.log(num)
|
|
|
+ // 普通赋值
|
|
|
+ // _this.ganttLists[0].task_end = _this.uGanttColumns[num - 1].name
|
|
|
+ // 强制赋值刷新
|
|
|
+ console.log(ganttIndex)
|
|
|
+ _this.$set(_this.ganttLists[ganttIndex], 'task_start', _this.uGanttColumns[num].name)
|
|
|
+ // 强制刷新
|
|
|
+ // _this.$forceUpdate()
|
|
|
+ document.onmousemove = null;
|
|
|
+ document.onmouseup = null;
|
|
|
+ document.releaseCapture && document.releaseCapture();
|
|
|
+ }
|
|
|
+ document.setCapture && document.setCapture();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 改变大小
|
|
|
+ uGanttResizeR(){
|
|
|
+ // 方法域(onmousedown等方法中有自己的this,所以在外面重新赋值this,让内部方法调用)
|
|
|
+ var _this = this
|
|
|
+ // 1.获取ref
|
|
|
+ var resize = this.$refs.uGanttResizeR;
|
|
|
+ var uGanttTaskItem = this.$refs.uGanttTaskItem;
|
|
|
+ // 2.循环监听获取当前点击的事件
|
|
|
+ // 上面设置onmousedown方法会出现第一次点击无法调用的问题,所以在mounted中写(不知道为什么有类似监听的效果)
|
|
|
+ // 因为ref有好几个,获取的数组,所以这里要循环
|
|
|
+ for (let i = 0; i < resize.length; i++) {
|
|
|
+ // 不可以设置var resize = resize[i] 下面统一使用resize的方式 =>这样会有问题
|
|
|
+ // 1.鼠标按下事件:
|
|
|
+ // 用[resize[i].],而不是全局document监听,这样才能监听到是哪儿一个甘特条触发了事件
|
|
|
+ resize[i].onmousedown = function (e) {
|
|
|
+ // 1.获取当前点击的甘特条是第几行的,也就是对应左侧项目组中的index
|
|
|
+ var ganttIndex = Math.trunc(uGanttTaskItem[i].offsetTop/34)
|
|
|
+ // 2.获取按下位置距离
|
|
|
+ var startX = e.clientX;
|
|
|
+ // 3.获取当前右侧拖拽区域距离父元素左侧距离(也就是右侧拖拽区域距离甘特图左边的距离:注意父子关系)
|
|
|
+ var offsetLeft = resize[i].offsetLeft;
|
|
|
+ // 转言之:上面那个就是当前甘特条的宽度--也就可以写作下面的方式
|
|
|
+ // var offsetLeft = uGanttTaskItem[i].offsetWidth;
|
|
|
+ // 4.定义拖拽参数--主要是为了onmouseup能调用
|
|
|
+ var moveLen
|
|
|
+ // 5.鼠标移动事件--注意:这里是document全局,这样就可以实现超出位置依旧可以控制拖拽
|
|
|
+ document.onmousemove = function (e) {
|
|
|
+ // 1.获取移动过程中实时位置
|
|
|
+ var endX = e.clientX;
|
|
|
+ // 2.设置当前甘特条的宽度:一开始甘特条的宽度 +(拖拽区域(鼠标点)末位置-初始位置)
|
|
|
+ moveLen = offsetLeft + (endX - startX);
|
|
|
+ // 3.判断如果小于1格,就不再减少
|
|
|
+ if (moveLen < 70) moveLen = 70;
|
|
|
+ // 这一步好像是没啥用啊?
|
|
|
+ // resize[i].style.left = moveLen;
|
|
|
+ // 设置甘特条随move变化:即实时宽度也为moveLen即可
|
|
|
+ uGanttTaskItem[i].style.width = moveLen + 'px';
|
|
|
+ }
|
|
|
+ // 鼠标抬起事件
|
|
|
+ document.onmouseup = function (evt) {
|
|
|
+ // 1.因为时间一段一段的,设置少于35(70的一半)最终结果向左靠,反之向右靠
|
|
|
+ uGanttTaskItem[i].style.width = Math.round(moveLen/70) * 70 + 'px';
|
|
|
+ // 2.获取当前甘特条最后位置在第几列--用于赋值
|
|
|
+ var num = (uGanttTaskItem[i].offsetLeft + uGanttTaskItem[i].offsetWidth)/70
|
|
|
+ // 普通赋值
|
|
|
+ // _this.ganttLists[0].task_end = _this.uGanttColumns[num - 1].name
|
|
|
+ // 3.强制赋值刷新--获取列对应的时间,赋值给左侧的第ganttIndex个项目的task_end
|
|
|
+ _this.$set(_this.ganttLists[ganttIndex], 'task_end', _this.uGanttColumns[num - 1].name)
|
|
|
+ // 强制刷新
|
|
|
+ // _this.$forceUpdate()
|
|
|
+ // 4.释放鼠标事件
|
|
|
+ document.onmousemove = null;
|
|
|
+ document.onmouseup = null;
|
|
|
+ // 5.从当前线程中的窗口释放鼠标捕获,并恢复通常的鼠标输入处理
|
|
|
+ document.releaseCapture && document.releaseCapture();
|
|
|
+ }
|
|
|
+ // 当前线程的给定窗口设置鼠标捕获
|
|
|
+ document.setCapture && document.setCapture();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ tableCellClassName({ row, column, rowIndex, columnIndex }){
|
|
|
+ //把每一行的索引放进row--可以用于获取index
|
|
|
+ // row.index = rowIndex;
|
|
|
+ return 'u-table-cell'
|
|
|
+ },
|
|
|
+ // 展开隐藏事件
|
|
|
+ expandChange(row, isExpend){
|
|
|
+ console.log(row, isExpend)
|
|
|
+ if(isExpend){
|
|
|
+ // 展开
|
|
|
+ // this.ganttLists.map((res, index) => {
|
|
|
+ // console.log(res)
|
|
|
+ // if(res.parentId === row.id){
|
|
|
+ // res.show = 'flex'
|
|
|
+ // }
|
|
|
+ // return res
|
|
|
+ // })
|
|
|
+ var index = this.ganttLists.findIndex(res=>res.id === row.id)
|
|
|
+ this.ganttLists.splice(index+1, 0, ...row.children)
|
|
|
+
|
|
|
+ this.$forceUpdate()
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 隐藏
|
|
|
+ // this.ganttLists.map((res, index) => {
|
|
|
+ // console.log(res)
|
|
|
+ // if(res.parentId === row.id){
|
|
|
+ // res.show = 'none'
|
|
|
+ // }
|
|
|
+ // return res
|
|
|
+ // })
|
|
|
+ this.ganttLists = this.ganttLists.filter(res=>res.parentId !== row.id)
|
|
|
+ this.$forceUpdate()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 双击事件
|
|
|
+ rowDblclick(row, column, event){
|
|
|
+ // console.log(row, column, event)
|
|
|
+ // 深拷贝:直接赋值会有还没点确定,甘特图部分就已经改变的bug
|
|
|
+ // this.currentDbEdit = JSON.parse(JSON.stringify(row))
|
|
|
+ this.$emit('dbclick', JSON.parse(JSON.stringify(row)))
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.u-flex{
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+.u-gantt-container{
|
|
|
+ // width: calc(100vw - 240px);
|
|
|
+ .el-table{
|
|
|
+ user-select: none;
|
|
|
+ // width: auto;
|
|
|
+ .u-table-cell{
|
|
|
+ padding: 0 !important;
|
|
|
+ height: 34px !important;
|
|
|
+ line-height: 34px !important;
|
|
|
+ box-sizing: border-box !important;
|
|
|
+ }
|
|
|
+ .el-table--enable-row-transition .el-table__body td.el-table__cell{
|
|
|
+ padding: 0 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ .u-gantt{
|
|
|
+ // width: calc(100% - 371px);
|
|
|
+ flex: 1;
|
|
|
+ border-top: 1px solid #ebebeb;
|
|
|
+ border-left: 1px solid #ebebeb;
|
|
|
+ overflow: auto;
|
|
|
+ }
|
|
|
+ .u-gantt-title{
|
|
|
+ .item-title{
|
|
|
+ width: 70px;
|
|
|
+ height: 34px;
|
|
|
+ line-height: 34px;
|
|
|
+ text-align: center;
|
|
|
+ border-right: 1px solid #ebebeb;
|
|
|
+ border-bottom: 1px solid #ebebeb;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #787878;
|
|
|
+ flex-shrink: 0; // 设置宽度不够时,元素不压缩而是超出滚动
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .u-gantt-content{
|
|
|
+ position: relative;
|
|
|
+ // 底层表格线框
|
|
|
+ .u-gantt-bg{
|
|
|
+ // position: absolute;
|
|
|
+ .item-tr{
|
|
|
+ height: 34px;
|
|
|
+ }
|
|
|
+ .item-td{
|
|
|
+ width: 70px;
|
|
|
+ height: 34px;
|
|
|
+ border-right: 1px solid #ebebeb;
|
|
|
+ border-bottom: 1px solid #ebebeb;
|
|
|
+ flex-shrink: 0; // 设置宽度不够时,元素不压缩而是超出滚动
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 项目甘特条
|
|
|
+ .u-gantt-task{
|
|
|
+ // position: absolute;
|
|
|
+ // top: 0;
|
|
|
+ // left: 0;
|
|
|
+ // right: 0;
|
|
|
+ // bottom: 0;
|
|
|
+ // background-color: #b72222;
|
|
|
+ .u-gantt-task-content{
|
|
|
+ position: absolute;
|
|
|
+ top: 36px;
|
|
|
+ left: 140px;
|
|
|
+ width: 140px;
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
+ background-color: #44c2e5;
|
|
|
+ border-radius: 2px;
|
|
|
+ .u-gantt-task-drag{
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 1px;
|
|
|
+ right: 1px;
|
|
|
+ bottom: 0;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .u-gantt-task-resize{
|
|
|
+ position: absolute;
|
|
|
+ width: 8px;
|
|
|
+ height: 30px;
|
|
|
+ top: 0;
|
|
|
+ cursor: w-resize;
|
|
|
+ }
|
|
|
+ .resize-left{
|
|
|
+ left: -7px;
|
|
|
+ }
|
|
|
+ .u-gantt-task-text{
|
|
|
+ color: #fff;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ }
|
|
|
+ .resize-right{
|
|
|
+ right: -7px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|