2023-02-07 10:10:36 +08:00

655 lines
18 KiB
Vue
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 style="height: 100%">
<div ref="gantt" style="height: 100%">
<template slot-scope="scope">
<el-popover
popper-class="area_popper"
offset="-150"
trigger="hover"
:open-delay="0"
:close-delay="0"
placement="top"
:disabled="isShowBox"
>
<!-- 提示的文字框显示所有的部门信息 -->
<p class="showText">{{ scope.row.text }}</p>
<!-- 利用三元表达式判断是否超过预期的长度 -->
<!-- <div slot="reference">{{ scope.row.address.length > 20? scope.row.address.slice(0, 20) + '...' : scope.row.address}}</div> -->
</el-popover>
</template>
</div>
</div>
</template>
<script>
import {
addProgressTaskApi, //增加
deleteTaskAlarmApi, //删除
editProgressTaskApi, //编辑
getParentChildListApi, //查询
} from "@/assets/js/api/scheduleInfo";
import $ from 'jquery'
import 'jquery-ui-dist/jquery-ui'
import 'jquery-ui-dist/jquery-ui.min.css'
import { gantt } from "dhtmlx-gantt";
import moment from "moment";
export default {
name: "gantt",
props: {
tasks: {
type: Object,
default() {
return {
data: [],
links: [],
};
},
},
},
data() {
return {
events:[],
dataLinks: [],
title: "",
width: 800,
visible: false,
disablesubmit: false,
projectSn: "", //项目sn
dataList: [], //
};
},
mounted: function () {
//日期格式化
gantt.config.xml_date = "%Y-%m-%d";
//左侧是否自适应
gantt.config.autofit = true;
//左侧宽
gantt.config.grid_width = 1000;
//取消连线
gantt.config.drag_links = true;
//只读
gantt.config.readonly = false;
//右侧显示列名
gantt.config.date_scale = "%Y-%m-%d";
//自动调整图表坐标轴区间用于适配task的长度
gantt.config.fit_tasks = true;
//弹窗宽
gantt.config.wide_form = false;
//汉化
gantt.locale = {
date: {
month_full: [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
],
month_short: [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月",
"7月",
"8月",
"9月",
"10月",
"11月",
"12月",
],
day_full: [
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
],
day_short: ["日", "一", "二", "三", "四", "五", "六"],
},
labels: {
dhx_cal_today_button: "今天",
day_tab: "日",
week_tab: "周",
month_tab: "月",
new_event: "新建日程",
icon_save: "保存",
icon_cancel: "关闭",
icon_details: "详细",
icon_edit: "编辑",
icon_delete: "删除",
confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?
confirm_deleting: "是否删除计划?",
section_description: "备注:",
section_time: "计划时间:",
section_time2: "开始时间:",
section_deadline: "实际时间:",
section_type: "类型",
section_text: "任务名称:",
section_color: "颜色:",
//-----
section_status: "完成状态:",
section_progress: "进度比例:",
section_taskTypeId: "任务模式:",
section_taskduration: "任务工期:",
/* grid columns */
column_text: "计划名称",
column_start_date: "开始时间",
column_duration: "持续时间",
column_add: "",
column_id: "",
column_predecessors: "",
column_duration: "",
/* link confirmation */
link: "关联",
confirm_link_deleting: "将被删除",
link_start: " (开始)",
link_end: " (结束)",
type_task: "任务",
type_project: "项目",
type_milestone: "里程碑",
minutes: "分钟",
hours: "小时",
days: "天",
weeks: "周",
months: "月",
years: "年",
},
};
gantt.plugins({ marker: true, tooltip: true }); // 开启marker插件
// 提示框内容
gantt.templates.tooltip_text = function (start, end, task) {
return (
"<b>任务名称:</b>" +
task.text +
"<br/><b>计划开始日期:</b> " +
moment(task.start_date).format("YYYY-MM-DD") +
"<br/><b>计划完成日期:</b> " +
moment(task.end_date).format("YYYY-MM-DD")
);
// "<br/><b>实际开始日期:</b> " + task.actual_start_date +
// "<br/><b>实际完成日期:</b> " + task.actual_end_date
};
//左侧显示列名
gantt.config.columns = [
{ name: "id", label: "id", width: "160", align: "center" },
{
name: "text",
label: "任务名称",
tree: true,
width: "150",
align: "center",
resize: true,
},
{
name: "predecessorIds",
label: "前置任务",
width: "140",
align: "center",
resize: true,
},
{
name: "start_date",
label: "计划开始日期",
align: "center",
width: "100",
resize: true,
},
{
name: "end_date",
label: "计划完成日期",
align: "center",
width: "100",
resize: true,
},
{
name: "planned_start",
label: "实际开始日期",
align: "center",
width: "100",
resize: true,
},
{
name: "planned_end",
label: "实际完成日期",
align: "center",
width: "100",
resize: true,
},
{ name: "duration", label: "任务工期", align: "center" },
{
name: "progressRatio",
label: "进度比例",
align: "center",
resize: true,
template: function (obj) {
return Math.floor(obj.progress * 100).toString() + "%";
},
},
{ name: "add", label: "" },
];
function startDatepicker(node){
return $(node).find("input[name='start']");
}
function endDateInput(node){
return $(node).find("input[name='end']");
}
gantt.form_blocks["datepicker"] = {
render(sns) { //sns - the section's configuration object
return "<div class='gantt-lb-datepicker'>"+
"<input type='text' name='start' placeholder='请选择实际开始时间' style='height:20px;margin:0 0px 0 10px'>"+'-'+
"<input type='text' name='end' placeholder='请选择实际结束时间' style='height:20px'>"+
"</div>";;
},
set_value(node, value, task, section) {
startDatepicker(node).datepicker({
dateFormat: "yy-mm-dd",
onSelect: () => {
}
});
startDatepicker(node).datepicker("setDate", task.planned_start);
endDateInput(node).datepicker({
dateFormat: "yy-mm-dd",
onSelect: function (dateStr) {
// gantt.ext.inlineEditors.save()
}
});
endDateInput(node).datepicker("setDate", task.planned_end);
},
get_value(node, task, section) {
if(task.planned_start && task.planned_end) {
var start = startDatepicker(node).datepicker('getDate');
var end = endDateInput(node).datepicker('getDate');
task.planned_start = start;
task.planned_end = end;
}
// task.duration = gantt.calculateDuration(task);
},
focus(node) {
}
}
//弹出层
gantt.config.lightbox.sections = [
//工程名称
{
name: "text",
height: 30,
map_to: "text",
type: "textarea",
focus: true,
width: 250,
},
//计划开始/结束时间
{
name: "time",
height: 30,
map_to: "auto",
type: "time",
time_format: ["%Y", "%m", "%d"],
},
//实际开始/结束时间
{
name: "deadline",
height: 30,
type: "datepicker",
map_to:"auto",
},
// 完成状态
{
name: "status",
height: 30,
map_to: "status",
type: "select",
options: [
{ key: 1, label: "未开始", color: "#4C87FF" },
{ key: 2, label: "进行中", color: "#54CF8" },
{ key: 3, label: "已完成", color: "#F2D026F" },
],
},
//任务模式
{
name: "taskTypeId",
height: 30,
map_to: "taskTypeId",
type: "select",
options: [
{ key: 1, label: "手动" },
{ key: 2, label: "自动" },
],
},
//任务工期
{
name: "taskduration",
height: 30,
map_to: "duration",
type: "textarea",
focus: true,
},
//进度
{
name: "progress",
height: 30,
map_to: "progress",
type: "textarea",
focus: true,
},
// //颜色
// {
// name: "color",
// height: 30,
// map_to: "color",
// type: "select",
// options: [
// { key: "#4C87FF", label: "紫色" },
// { key: "#54CF8E", label: "绿色" },
// { key: "#F2D026", label: "黄色" },
// { key: "#FF6C7F", label: "水红色" },
// ],
// },
//备注
{
name: "description",
height: 40,
map_to: "remark",
type: "textarea",
},
];
//弹窗标题 日期范围
gantt.templates.task_time = function (start, end, task) {
return (
moment(task.start_date).format("YYYY-MM-DD") +
" - " +
moment(task.end_date).format("YYYY-MM-DD")
);
};
//弹窗标题 计划名称
gantt.templates.task_text = function (start, end, task) {
return task.text;
};
gantt.init(this.$refs.gantt);
let this_ = this;
//添加后触发
gantt.attachEvent("onAfterTaskAdd", function (id, item) {
console.log("添加后触发", this_.dataList);
console.log("添加后触发 item", item);
if (item.parent != 0 && item.parent != null) {
this_.checkLinks(this_.dataList, item.parent);
} else {
console.log("父亲调用");
this_.dataList.forEach((res) => {
this_.dataLinks.push(res.id);
});
}
console.log("添加后触发 predecessorIds 2-- ", this_.dataLinks);
let data = {
children: [],
duration: Number(item.ck),
feedbackList: [],
parentId: item.parent,
predecessorIds: this_.dataLinks.join(","),
progressRatio: item.progress,
remark: item.remark,
startDate: moment(item.start_date).format("YYYY-MM-DD"),//计划开始
status: Number(item.status) - 1,
projectSn: this_.$store.state.projectSn,
createUserId: this_.$store.state.userInfo.userId,
taskName: item.text,
taskTypeId: Number(item.taskTypeId) - 1,
finishDate: moment(item.end_date).format("YYYY-MM-DD"),//计划结束
actualStartDate: moment(item.planned_start).format("YYYY-MM-DD"),//实际开始
actualFinishDate: moment(item.planned_end).format("YYYY-MM-DD"),//实际结束
};
addProgressTaskApi(data).then((res) => {
console.log("添加的数据", res);
this_.getParentChildList();
});
this_.dataLinks = [];
});
//移动进度后触发
gantt.attachEvent("onAfterTaskDrag", function (id, mode, e) {
// console.log("移动进度后触发mode", mode);
// this_.changeTask();
});
//移动任务后触发
gantt.attachEvent("onAfterTaskMove", function (id, parent, tindex) {
// console.log("移动任务后触发", mode);
// this_.changeTask();
});
//删除任务后触发
gantt.attachEvent("onAfterTaskDelete", function (id, item) {
console.log("删除任务后触发,", id);
deleteTaskAlarmApi({ id: id }).then((res) => {
console.log("添加的数据", res);
this_.getParentChildList();
});
});
//修改任务后触发
const onAfterTaskDrag =gantt.attachEvent("onAfterTaskUpdate", function (id, item) {
console.log("修改任务后触发", item);
let data = {
duration: Number(item.ck),
progressRatio: item.progress,
remark: item.remark,
startDate: moment(item.start_date).format("YYYY-MM-DD"),//计划开始
status: Number(item.status) - 1,
id: id,
projectSn: this_.$store.state.projectSn,
createUserId: this_.$store.state.userInfo.userId,
taskName: item.text,
taskTypeId: Number(item.taskTypeId) - 1,
finishDate: moment(item.end_date).format("YYYY-MM-DD"),//计划结束
actualStartDate: moment(item.planned_start).format("YYYY-MM-DD"),//实际开始
actualFinishDate: moment(item.planned_end).format("YYYY-MM-DD"),//实际结束
};
editProgressTaskApi(data).then((res) => {
console.log("修改的数据", res);
this_.getParentChildList();
});
});
this_.events.push(onAfterTaskDrag)
//拖拽任务后触发
gantt.attachEvent("onTaskDrag", function (id, mode, task, original) {
// console.log("拖拽任务后触发",id, mode, task, original);
});
//保存验证
gantt.attachEvent("onLightboxSave", function (id, item) {
// setTimeout(function () {
item.ck = item.duration;
console.log("保存验证,", item);
// if (!item.taskName) {
// gantt.message({ type: "error", taskName: "请填写任务名称!" });
// return false;
// }
// }, 2000);
return true;
});
},
created() {
this.projectSn = this.$store.state.projectSn;
this.getParentChildList();
},
beforeDestroy () {
this.events.forEach(ele => {
gantt.detachEvent(ele)
})
},
methods: {
//数据格式整理
changeTask(ganttValue) {
// return
const taskCount = ganttValue.length;
let taskData = [];
let openTask = [];
for (let i = 0; i < taskCount; i++) {
let taskOne = {};
const obj = ganttValue[i];
if (obj == null || typeof obj.id === "number") {
continue;
}
taskOne.taskName = obj.taskName;
//打开状态继续打开
if (obj.$open == true) {
openTask.push(obj.id);
}
//整理数据格式
taskOne.id = obj.id;
taskOne.text = obj.taskName || obj.text;
if (obj.startDate != null) {
taskOne.start_date = moment(obj.startDate).format("YYYY-MM-DD");
}
if (obj.finishDate != null) {
taskOne.end_date = moment(obj.finishDate).format("YYYY-MM-DD");
}
if (obj.actualStartDate != null) {
taskOne.planned_start = moment(obj.actualStartDate).format(
"YYYY-MM-DD"
);
}
if (obj.actualFinishDate != null) {
taskOne.planned_end = moment(obj.actualFinishDate).format("YYYY-MM-DD");
}
taskOne.duration = obj.duration;
taskOne.progress = obj.progressRatio;
taskOne.projectSn = obj.projectSn;
taskOne.description = obj.remark;
taskOne.predecessorIds = obj.predecessorIds;
taskOne.parent = obj.parent;
// 0未开始 ,1进行中2已完成
taskOne.color =
obj.status === 0 ? "#ccc" : obj.status === 1 ? "yellow" : "green";
taskOne.status = obj.status + 1;
taskOne.taskTypeId = obj.taskTypeId + 1;
if (obj.parentId) {
taskOne.parent = obj.parentId;
}
if(i == 0) {
console.log("第一条数据结构 ", JSON.stringify(taskOne));
}
taskData.push(taskOne);
}
this.$props.tasks.data = taskData;
//清空数据
gantt.clearAll();
//加载
gantt.parse(this.$props.tasks);
//遍历打开,使之前打开的父级继续打开
openTask.forEach((id) => {
gantt.open(id);
});
},
//获取甘特图父子节点数据
getParentChildList() {
this.tasks.data = [];
getParentChildListApi({ projectSn: this.projectSn }).then((res) => {
this.check(res.result);
this.dataList = res.result;
this.$props.tasks.data = this.tasks.data;
// gantt.parse(this.$props.tasks);
this.changeTask(this.tasks.data);
});
},
check(val) {
let arr = [];
val.forEach((res) => {
this.tasks.data.push(res);
if (res.predecessorIds != "" && res.predecessorIds != null) {
let dataLinks = res.predecessorIds.split(",");
let dataLink = {
source: dataLinks[dataLinks.length - 1],
target: res.id,
type: "1",
};
this.tasks.links.push(dataLink);
}
if (res.children.length >= 1) {
res.children.forEach((restwo) => {
arr.push(restwo);
});
}
});
if (arr.length >= 1) {
this.check(arr);
}
},
checkLinks(val, id) {
let arrLink = [];
val.forEach((res) => {
if (res.id === id) {
console.log(
"找到爸爸了 --" + id + "---- children -" + res.children
);
if (res.children != null && res.children.length >= 1) {
res.children.forEach((resLink) => {
this.dataLinks.push(resLink.id);
});
console.log("找到爸爸了 ,返回的数据 ", this.dataLinks);
}
} else {
if (res.children != null && res.children.length != 0) {
res.children.forEach((resLink) => {
arrLink.push(resLink);
});
}
}
});
if (arrLink.length >= 1) {
this.checkLinks(arrLink, id);
}
},
},
};
</script>
<style lang="less" scoped>
@import "~dhtmlx-gantt/codebase/dhtmlxgantt.css";
::v-deep .gantt_tree_content {
height: 100%;
white-space: nowrap;
min-width: 0;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
}
</style>