|
@@ -12,6 +12,18 @@
|
|
:content="addForm.parentTname"></el-page-header>
|
|
:content="addForm.parentTname"></el-page-header>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
+ <!-- tooltip -->
|
|
|
|
+ <div
|
|
|
|
+ v-if="tooltip.visible"
|
|
|
|
+ :style="`top:${tooltip.y}px;left:${tooltip.x}px;`"
|
|
|
|
+ class="custom-tooltip"
|
|
|
|
+ >
|
|
|
|
+ <div><b>开始时间:</b> {{ tooltip.task.start_date }}</div>
|
|
|
|
+ <div><b>结束时间:</b> {{ tooltip.task.end_date }}</div>
|
|
|
|
+ <div><b>计划工时:</b> {{ tooltip.task.dayDifference }} 天 {{ tooltip.task.time }} 小时</div>
|
|
|
|
+ <div><b>项目名称:</b> {{ tooltip.task.projectName }}</div>
|
|
|
|
+ <div><b>计划名称:</b> {{ tooltip.task.planName }}</div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
@@ -52,6 +64,12 @@ export default {
|
|
integrationTask: {},
|
|
integrationTask: {},
|
|
user: JSON.parse(sessionStorage.getItem("user")),
|
|
user: JSON.parse(sessionStorage.getItem("user")),
|
|
showMmeiLaiDeData: {},
|
|
showMmeiLaiDeData: {},
|
|
|
|
+ tooltip: {
|
|
|
|
+ visible: false,
|
|
|
|
+ task: null,
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ }
|
|
};
|
|
};
|
|
},
|
|
},
|
|
created: function () {
|
|
created: function () {
|
|
@@ -187,6 +205,93 @@ export default {
|
|
|
|
|
|
gantt.scrollTo(gantt.posFromDate(midDate) - 200, gantt.getScrollState().y);
|
|
gantt.scrollTo(gantt.posFromDate(midDate) - 200, gantt.getScrollState().y);
|
|
}
|
|
}
|
|
|
|
+ },
|
|
|
|
+ observeTaskLines(gantt) {
|
|
|
|
+ console.log(gantt, '<==== gantt')
|
|
|
|
+ const taskContainer = gantt.$task_data;
|
|
|
|
+
|
|
|
|
+ this.observer = new MutationObserver(() => {
|
|
|
|
+ this.bindTooltipEvents();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.observer.observe(taskContainer, {
|
|
|
|
+ childList: true,
|
|
|
|
+ subtree: true
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.bindTooltipEvents(); // 初次执行
|
|
|
|
+ },
|
|
|
|
+ bindTooltipEvents() {
|
|
|
|
+ console.log('开始执行')
|
|
|
|
+ const taskLines = this.$refs.ganttContainer.querySelectorAll(".gantt_task_line");
|
|
|
|
+
|
|
|
|
+ taskLines.forEach(line => {
|
|
|
|
+ const taskId = line.getAttribute("task_id");
|
|
|
|
+ if (!taskId || line.dataset.bound === "true") return;
|
|
|
|
+
|
|
|
|
+ line.dataset.bound = "true";
|
|
|
|
+
|
|
|
|
+ line.addEventListener("mouseenter", (e) => {
|
|
|
|
+ const rect = line.getBoundingClientRect();
|
|
|
|
+ const task = gantt.getTask(taskId);
|
|
|
|
+ if(!task.taskId) {
|
|
|
|
+ this.tooltip.visible = false;
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ console.log(task)
|
|
|
|
+ const list = task.text.split('/')
|
|
|
|
+ const d1 = this.dayjs(task.start_date);
|
|
|
|
+ const d2 = this.dayjs(task.end_date);
|
|
|
|
+ this.tooltip.task = {
|
|
|
|
+ ...task,
|
|
|
|
+ end_date: this.dayjs(task.end_date).format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
+ start_date: this.dayjs(task.start_date).format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
+ projectName: list[0],
|
|
|
|
+ planName: list[1],
|
|
|
|
+ dayDifference: d2.diff(d1, 'day'),
|
|
|
|
+ };
|
|
|
|
+ this.tooltip.x = rect.left + window.scrollX;
|
|
|
|
+ this.tooltip.y = (rect.top - 240) - 10 + window.scrollY;
|
|
|
|
+ this.tooltip.visible = true;
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ line.addEventListener("mouseleave", () => {
|
|
|
|
+ this.tooltip.visible = false;
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ bindTaskLineEvents() {
|
|
|
|
+ console.log("bindTaskLineEvents", this.$refs.ganttContainer)
|
|
|
|
+ if(!this.$refs.ganttContainer) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ const taskLines = this.$refs.ganttContainer.querySelectorAll(".gantt_task_line");
|
|
|
|
+ taskLines.forEach(line => {
|
|
|
|
+ const taskId = line.getAttribute("task_id");
|
|
|
|
+ if (!taskId) return;
|
|
|
|
+
|
|
|
|
+ // 避免重复绑定
|
|
|
|
+ if (line.dataset.tooltipBound) return;
|
|
|
|
+ line.dataset.tooltipBound = "true";
|
|
|
|
+
|
|
|
|
+ line.addEventListener("mouseenter", (e) => {
|
|
|
|
+ const task = gantt.getTask(taskId);
|
|
|
|
+ this.tooltip.task = task;
|
|
|
|
+ this.tooltip.visible = true;
|
|
|
|
+
|
|
|
|
+ const updateMouse = (moveEvent) => {
|
|
|
|
+ this.tooltip.x = moveEvent.pageX;
|
|
|
|
+ this.tooltip.y = moveEvent.pageY;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ document.addEventListener("mousemove", updateMouse);
|
|
|
|
+
|
|
|
|
+ line.addEventListener("mouseleave", () => {
|
|
|
|
+ this.tooltip.visible = false;
|
|
|
|
+ document.removeEventListener("mousemove", updateMouse);
|
|
|
|
+ }, { once: true });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
}
|
|
}
|
|
},
|
|
},
|
|
mounted: function () {
|
|
mounted: function () {
|
|
@@ -275,21 +380,6 @@ export default {
|
|
gantt.config.start_date = new Date(this.valueDate[0]);
|
|
gantt.config.start_date = new Date(this.valueDate[0]);
|
|
gantt.config.end_date = new Date(this.valueDate[1]);
|
|
gantt.config.end_date = new Date(this.valueDate[1]);
|
|
|
|
|
|
- //设置任务条样式
|
|
|
|
- // gantt.templates.task_class = function (start, end, item) {
|
|
|
|
- // const { taskPlan, taskStatus } = item
|
|
|
|
- // if(taskStatus == 5 || taskStatus == 6) {
|
|
|
|
- // return "reject_line"
|
|
|
|
- // }
|
|
|
|
- // if(taskPlan == 1 && taskStatus == 0) {
|
|
|
|
- // return "success_line"
|
|
|
|
- // }
|
|
|
|
- // if(taskPlan == 1 && taskStatus == 2) {
|
|
|
|
- // return "draft_line"
|
|
|
|
- // }
|
|
|
|
- // return item.taskPlanType == 3 ? "error_line" : "person_line"
|
|
|
|
- // };
|
|
|
|
-
|
|
|
|
const that = this
|
|
const that = this
|
|
// 设置任务条内容显示
|
|
// 设置任务条内容显示
|
|
gantt.templates.task_text = function (start, end, task) {
|
|
gantt.templates.task_text = function (start, end, task) {
|
|
@@ -321,38 +411,6 @@ export default {
|
|
</div>`;
|
|
</div>`;
|
|
}
|
|
}
|
|
|
|
|
|
- // 小组长
|
|
|
|
- // if (userInfo.projectLeaderType == 1) {
|
|
|
|
- // if (leaderOrManager == 1) {
|
|
|
|
- // return `<div class="task_text">
|
|
|
|
- // ${task.taskStatus == 3 ? `<div class="circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div> <div class="circle"></div>` : ''}
|
|
|
|
- // ${task.taskStatus == 4 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="circle"></div>` : ''}
|
|
|
|
- // ${task.taskStatus == 5 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div> <div class="circle"></div>` : ''}
|
|
|
|
- // ${task.taskStatus == 6 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div>` : ''}
|
|
|
|
- // <div>${task.text}</div>
|
|
|
|
- // </div>`;
|
|
|
|
- // }
|
|
|
|
-
|
|
|
|
- // 审核人
|
|
|
|
- // if (userInfo.projectLeaderType == 2) {
|
|
|
|
- // if (leaderOrManager == 2) {
|
|
|
|
- // const oneRight = `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="circle"></div>`
|
|
|
|
- // const twoPairs = `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="circle exclamation-circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div>`
|
|
|
|
- // const toExamine = `<div class="task_text statuss">
|
|
|
|
- // ${task.taskStatus == 3 || task.taskStatus == 4 ? `<div class="circle">
|
|
|
|
- // <div class="pendingReviewOfCornerMarkers">!</div>
|
|
|
|
- // </div>` : ''}`
|
|
|
|
- // const twoEmptyCircles = `<div class="circle"></div><div class="circle"></div>`
|
|
|
|
- // return `<div class="task_text">
|
|
|
|
- // ${(userIds == checkFirstId && task.taskStatus == 3) ? toExamine : (userIds == checkFirstId && task.taskStatus == 4) ? oneRight : ''}
|
|
|
|
- // ${(userIds == checkSecondId && task.taskStatus == 4) ? toExamine : (userIds == checkSecondId && task.taskStatus == 3) ? twoEmptyCircles : ''}
|
|
|
|
- // ${task.taskStatus == 5 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div> <div class="circle"></div>` : ''}
|
|
|
|
- // ${task.taskStatus == 6 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div>` : ''}
|
|
|
|
- // <div>${task.text}</div>
|
|
|
|
- // <div>${task.text}</div>
|
|
|
|
- // </div>`
|
|
|
|
- // }
|
|
|
|
-
|
|
|
|
// 正常人
|
|
// 正常人
|
|
return `<div class="task_text">
|
|
return `<div class="task_text">
|
|
<div>${task.text}</div>
|
|
<div>${task.text}</div>
|
|
@@ -464,9 +522,12 @@ export default {
|
|
this.containerRect = this.$refs.ganttContainer.getBoundingClientRect();
|
|
this.containerRect = this.$refs.ganttContainer.getBoundingClientRect();
|
|
gantt.parse(this.$props.tasks);
|
|
gantt.parse(this.$props.tasks);
|
|
|
|
|
|
|
|
+ // 等渲染完成后绑定每个任务条事件
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ this.observeTaskLines(gantt); // 开始监听任务条变化
|
|
|
|
+ }, 2000)
|
|
|
|
+
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
- // gantt.showTask('任务_2636_2339');
|
|
|
|
- // gantt.selectTask('任务_2636_2339');
|
|
|
|
const list = JSON.parse(localStorage.getItem('ganttChartTaskId') || '[]')
|
|
const list = JSON.parse(localStorage.getItem('ganttChartTaskId') || '[]')
|
|
if(list[0]) {
|
|
if(list[0]) {
|
|
this.focusAndSelectTaskFull(list[0])
|
|
this.focusAndSelectTaskFull(list[0])
|
|
@@ -586,4 +647,13 @@ export default {
|
|
word-break: break-all; */
|
|
word-break: break-all; */
|
|
white-space: pre-wrap;
|
|
white-space: pre-wrap;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+.custom-tooltip {
|
|
|
|
+ position: fixed;
|
|
|
|
+ z-index: 9999;
|
|
|
|
+ background: rgba(0, 0, 0, 0.7);
|
|
|
|
+ color: #fff;
|
|
|
|
+ padding: 20px;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+}
|
|
</style>
|
|
</style>
|