From a3e27f5cab583debe11a9c62d8cc0115783b0791 Mon Sep 17 00:00:00 2001 From: Gary Gu <garygu@Garydebijibendiannao.local> Date: Wed, 28 May 2025 16:59:43 +0800 Subject: [PATCH] fix: 优化实况UI放大缩小 --- src/components/Gantt.vue | 660 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 660 insertions(+), 0 deletions(-) diff --git a/src/components/Gantt.vue b/src/components/Gantt.vue new file mode 100644 index 0000000..d65cee0 --- /dev/null +++ b/src/components/Gantt.vue @@ -0,0 +1,660 @@ +<template> + <div class="gantt-box"> + <div class="gantt-header"> + <div> + <el-button size="small" type="primary" @click="yearClick">年</el-button> + <el-button size="small" type="primary" @click="monthClick">月</el-button> + <el-button size="small" type="primary" @click="weekClick">周</el-button> + <!-- <el-button size="small" type="primary" @click="dayClick">日</el-button> --> + </div> + <div> + <el-button style="margin-right: 20px" size="small" type="primary" v-if="!columnsShow" @click="toggle('1')">展开详情</el-button> + <el-button style="margin-right: 20px" size="small" type="primary" v-else @click="toggle('2')">关闭详情</el-button> + <span>备注:</span> + <span>进行中</span><span class="color" style="background-color: rgb(211, 211, 0)"></span>, <span>待进行</span + ><span class="color" style="background-color: rgb(170, 170, 127)"></span>, <span>延期未完工</span + ><span class="color" style="background-color: rgb(255, 0, 0)"></span>, <span>延期已完工</span + ><span class="color" style="background-color: #8bc34a"></span>, <span>已完工/提前完工</span + ><span class="color" style="background-color: rgb(14, 172, 81)"></span> + </div> + </div> + <div ref="gantt" style="height: 400px; font-size: 12px"></div> + </div> +</template> + +<script> + import axios from "axios"; + import { gantt } from "dhtmlx-gantt"; + import "dhtmlx-gantt/codebase/dhtmlxgantt.css"; + + export default { + name: "Gantt", + components: {}, + data() { + return { + taskslist: [], + // 甘特图配置 + tasks: { + data: [], + }, + columnsShow: false, + }; + }, + mounted() { + this.init(); //初始化 + this.getProjectqryDataColl(); //获取数据 + }, + methods: { + // 将毫秒值转换为普通的日期格式 yyyy-MM-dd + formatDate(time) { + const myTime = new Date(time); + const yyyy = myTime.getFullYear(); + let MM = myTime.getMonth() + 1; + if (MM < 10) { + MM = "0" + MM; + } + let dd = myTime.getDate(); + if (dd < 10) { + dd = "0" + dd; + } + const str = yyyy + "-" + MM + "-" + dd; + return str; + }, + // 获取两个时间相减的天数 + getDays(strDateStart, strDateEnd) { + var strSeparator = "-"; + //日期分隔符 var oDate1; var oDate2; + var iDays; + var oDate1 = strDateStart.split(strSeparator); + var oDate2 = strDateEnd.split(strSeparator); + var strDateS = new Date(oDate1[0], oDate1[1] - 1, oDate1[2]); + var strDateE = new Date(oDate2[0], oDate2[1] - 1, oDate2[2]); + var iDays = parseInt(Math.abs(strDateS - strDateE) / 1000 / 60 / 60 / 24); + //把相差的毫秒数转换为天数 + return iDays; + }, + getIntervalDays(timestamp) { + const date1 = new Date(); + const date2 = new Date(timestamp); + const diff = Math.abs(date2.getTime() - date1.getTime()); // 计算时间差(毫秒) + return Math.floor(diff / (1000 * 60 * 60 * 24)); // 将时间差转换为天数 + }, + // 计算时间进度 + getIntervalDays2(timestamp1, timestamp2) { + const now = new Date(); + const date1 = new Date(timestamp1); + const date2 = new Date(timestamp2); + const diff = Math.abs(date2.getTime() - date1.getTime()); // 计算时间差(毫秒) + const total = Math.floor(diff / (1000 * 60 * 60 * 24)); // 将时间差转换为天数 + const diff2 = Math.abs(now.getTime() - date1.getTime()); // 计算时间差(毫秒) + const real = Math.floor(diff2 / (1000 * 60 * 60 * 24)); // 将时间差转换为天数 + return Math.floor((real / total) * 100); + }, + + clickdataAll() { + let clickdata = []; + let colors = ""; + this.taskslist.map((item) => { + var arr = this.formatDate(item.begin1).split("-"); + var arr1 = this.formatDate(item.over1).split("-"); + var startTime = arr[2] + "-" + arr[1] + "-" + arr[0]; + var endTime = arr1[2] + "-" + arr1[1] + "-" + arr1[0]; + + var arr2 = []; + var arr3 = []; + var startTime1 = ""; + var endTime1 = ""; + var duration1 = ""; + if (item.begin2 != null) { + startTime1 = this.formatDate(item.begin2); + } + if (item.over2 != null) { + endTime1 = this.formatDate(item.over2); + } + + if (startTime1 != "" && endTime1 != "") { + duration1 = this.getDays(startTime1, endTime1); + } + if (item.zt == "0") { + colors = "#aaaa7f"; + } + if (item.zt == "1") { + colors = "#d3d300"; + } + if (item.zt == "2" || item.zt == "3") { + colors = "#0eac51"; + } + if (item.zt == "5") { + colors = "#ff0000"; + } + if (item.zt == "4") { + colors = "#8bc34a"; + } + clickdata.push({ + id: item.id, + text: item.project, + start_date: startTime, + end_date: endTime, + parent: item.parent, + duration: "4", + start_date1: startTime1, + end_date1: endTime1, + duration1: duration1, + progress: 0, + open: true, + color: colors, + remark: item.remark, + }); + }); + gantt.clearAll(); + this.tasks.data = clickdata; + gantt.parse(this.tasks); + gantt.refreshData(); + this.ganttLoading = false; + }, + + clearDirtyData() { + let baseList = []; + let baseList2 = []; + let baseList3 = []; + this.taskslist.map((item) => { + item.used = false; + item.baseTitle = ""; + }); + // 先筛选父级 + this.taskslist.map((item) => { + if (!item.used && !item.parent) { + item.used = true; + item.baseTitle = "[" + item.project + "]"; + baseList.push(item); + } + }); + baseList.map((item) => { + this.taskslist.map((item2) => { + if (!item2.used && item2.parent == item.id) { + item2.used = true; + item2.baseTitle = item.baseTitle + "->[" + item2.project + "]"; + baseList2.push(item2); + } + }); + }); + + baseList2.map((item) => { + this.taskslist.map((item2) => { + if (!item2.used && item2.parent == item.id) { + item2.used = true; + item2.baseTitle = item.baseTitle + "->[" + item2.project + "]"; + baseList3.push(item2); + } + }); + }); + + baseList3.map((item) => { + this.taskslist.map((item2) => { + if (!item2.used && item2.parent == item.id) { + item2.used = true; + item2.baseTitle = item.baseTitle + "->[" + item2.project + "]"; + } + }); + }); + + let copyTaskslist = []; + this.taskslist.map((item) => { + if (item.baseTitle) { + copyTaskslist.push(item); + } + }); + this.taskslist = copyTaskslist; + }, + // 获取工程进度项目列表 + getProjectqryDataColl() { + axios.get("https://api.zhihuibuild.com/zuul/zuul/jinchan-device/project/qryProjectProgress").then(({ data }) => { + // 接口获取data + if (data.code == "200") { + if (data.body.length != 0) { + this.taskslist = data.body; + this.clearDirtyData(); + let cache = []; + + this.taskslist.map((item, index) => { + item.zIndex = index + 1; + // 重新判断状态 + let nowTime = new Date().getTime(); + if (!item.begin2) { + //未开始 + item.zt = 0; + } else { + if (!item.over2) { + //未结束 + if (item.over1 >= nowTime) { + //判断预计工期是否超过当前时间 + item.zt = 1; //进行中 + } else { + item.zt = 5; //延期未完工 + } + } else { + if (item.over1 >= item.over2) { + //判断预计工期是否超过实际工期 + item.zt = 3; //提前完工2、3 + } else { + item.zt = 4; //延期完工 + } + } + } + if (item.zt == "5") { + cache.push([cache.length + 1, item.project, this.getIntervalDays(item.over1)]); + } + }); + + cache.sort(function (a, b) { + return b[2] - a[2]; + }); + cache.map((item, index) => { + item[0] = index + 1; + item[2] = item[2] + "天"; + }); + + setTimeout(() => { + this.clickdataAll(); + }, 1000); + } + } + }); + }, + yearClick() { + gantt.config.scales = [ + { + unit: "year", + step: 1, + date: " %Y", + }, + ]; + gantt.init(this.$refs.gantt); + }, + monthClick() { + gantt.config.scales = [ + { + unit: "year", + step: 1, + date: " %Y", + }, + { + unit: "month", + step: 1, + date: "%F", + }, + ]; + gantt.init(this.$refs.gantt); + }, + weekClick() { + gantt.config.scales = [ + { + unit: "year", + step: 1, + date: " %Y", + }, + { + unit: "month", + step: 1, + date: "%F", + }, + { + unit: "week", + step: 1, + date: "%W周", + }, + ]; + gantt.init(this.$refs.gantt); + }, + dayClick() { + gantt.config.scales = [ + { + unit: "year", + step: 1, + date: " %Y", + }, + { + unit: "month", + step: 1, + date: "%F", + }, + { + unit: "day", + step: 1, + date: "%j日", + }, + ]; + gantt.init(this.$refs.gantt); + }, + riliClick() { + gantt.config.scales = [ + { + unit: "month", + step: 1, + date: " %Y - %F", + }, + { + unit: "day", + step: 1, + date: "%j日 周%D", + }, + ]; + gantt.init(this.$refs.gantt); + }, + toggle(val) { + if (val == 1) { + this.columnsShow = true; + } else { + this.columnsShow = false; + } + //左侧显示列名 + if (val == "1") { + gantt.config.columns = [ + { + name: "text", + label: "任务名称", + tree: true, + align: "left", + resize: true, + width: "*", + min_width: 220, + }, + { + name: "start_date", + label: "计划开始", + align: "center", + resize: true, + width: "*", + min_width: 100, + }, + { + name: "end_date", + label: "计划结束", + align: "center", + resize: true, + width: "*", + min_width: 100, + }, + { + name: "duration", + label: "工期", + align: "center", + }, + { + name: "start_date1", + label: "实际开始", + align: "center", + resize: true, + width: "*", + min_width: 100, + }, + { + name: "end_date1", + label: "实际结束", + align: "center", + resize: true, + width: "*", + min_width: 100, + }, + { + name: "duration1", + label: "实际工期", + align: "center", + }, + { + name: "zt", + label: "", + align: "center", + resize: false, + }, + ]; + } else { + gantt.config.columns = [ + { + name: "text", + label: "任务名称", + tree: true, + align: "left", + resize: true, + width: 250, + }, + ]; + } + + // 初始化 + gantt.init(this.$refs.gantt); + // 数据解析 + gantt.parse(this.tasks); + }, + // 初始化 + init() { + // 自动延长时间刻度 + gantt.config.fit_tasks = true; + gantt.config.show_links = false; + gantt.config.drag_progress = false; // 取消进度条 + gantt.config.row_height = 25; //进度条容器高 + gantt.config.scale_height = 50; + gantt.config.autofit = true; //左侧是否自适应 + gantt.i18n.setLocale("cn"); // 设置中文 + gantt.config.readonly = true; // 设置为只读 + //自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务 + gantt.config.autosize = false; + gantt.config.open_split_tasks = true; + // 允许拖放 + gantt.config.drag_project = true; + // 设置甘特图时间的起始结束时间,并允许显示超过时间刻度任务 + // gantt.config.start_date = new Date(`${new Date().getFullYear()-1}`,'01'); + // gantt.config.end_date = new Date(`${new Date().getFullYear()+1}`,'01'); + gantt.config.show_tasks_outside_timescale = true; + //开启提示:鼠标悬浮在gantt行上显示 + gantt.plugins({ + tooltip: true, + // quick_info: true,// 快速信息框 + multiselect: true, // 激活多任务选择 + }); + + gantt.templates.tooltip_text = function (start, end, task) { + return ( + "<b>项目: <span style='color:" + + task.color + + "'>" + + task.text + + "</span><br/><span>实际开始:" + + task.start_date1 + + "</span> " + + "</span><br/><span>实际结束:" + + task.end_date1 + + "</span> " + + "</span><br/><br/><span>计划开始:" + + gantt.templates.tooltip_date_format(start) + + "</span> " + + "<br/><span>计划结束:" + + gantt.templates.tooltip_date_format(end) + + "</span> " + + (task.remark ? `<br/><span>备注:${task.remark}</span>` : "") + ); + }; + // 按月 + gantt.config.scales = [ + { + unit: "year", + step: 1, + date: " %Y", + }, + { + unit: "month", + step: 1, + date: "%F", + }, + ]; + + //左侧显示列名 + gantt.config.columns = [ + { + name: "text", + label: "任务名称", + tree: true, + align: "left", + resize: true, + width: 250, + }, + ]; + // 初始化 + gantt.init(this.$refs.gantt); + + // 数据解析 + gantt.parse(this.tasks); + }, + }, + }; +</script> +<style lang="scss" scoped> + .gantt-box { + background-color: rgba(0, 0, 0, 0.2); + margin: 10px; + color: #fff; + + .gantt-header { + padding-top: 5px; + margin: 10px; + height: 40px; + display: flex; + justify-content: space-between; + align-items: center; + + .color { + width: 36px; + height: 16px; + vertical-align: text-top; + display: inline-block; + margin-right: 5px; + margin-left: 5px; + } + } + + /* 滚动条样式*/ + ::-webkit-scrollbar { + width: 10px; + height: 10px; + background-color: transparent; + } + + ::-webkit-scrollbar-thumb { + background-color: #73abb1; + border-radius: 6px; + } + + ::-webkit-scrollbar-track { + background-color: #373f4a; + opacity: 0.9; + } + } +</style> +<style lang="scss"> + body { + background-color: rgb(19, 90, 144); + } + + /* 自定义甘特图样式 */ + .gantt_grid_data .gantt_row.gantt_selected, + .gantt_grid_data .gantt_row.odd.gantt_selected, + .gantt_task_row.gantt_selected { + background-color: #409eff !important; + } + + .gantt_grid_data .gantt_row.odd:hover, + .gantt_grid_data .gantt_row:hover { + background-color: #409eff !important; + } + + .gantt_grid_scale .gantt_grid_head_cell { + color: #fff !important; + } + + .gantt_grid_scale, + .gantt_task_scale, + .gantt_task_vscroll { + background-color: transparent; + } + + /* 大背景透明 */ + .gantt_container { + background-color: transparent; + } + + /* 左标题文字白色 */ + .gantt_grid_data .gantt_cell { + color: #fff; + } + + /* 顶部日期白色 */ + .gantt_task .gantt_task_scale .gantt_scale_cell { + color: #fff; + } + + /* 偶数行背景透明 */ + .gantt_row.odd, + .gantt_task_row.odd { + background-color: transparent; + } + + /* 奇数行背景透明 */ + .gantt_row, + .gantt_task_row { + background-color: transparent; + } + + /* 表格边框*/ + .gantt_cell { + border-right: 1px solid #0de8ec; + } + .gantt_task_cell { + border-right: 1px solid #0de8ec; + } + + .gantt_row, + .gantt_task_row { + border-bottom: 1px solid #0de8ec; + } + + .gantt_grid_scale, + .gantt_task_scale { + border-bottom: 1px solid #0de8ec; + } + + .gantt_scale_line { + border-top: 1px solid #0de8ec; + } + + .gantt_layout_cell_border_right { + border-right: 1px solid #0de8ec; + } + + .gantt_layout_cell_border_bottom { + border-bottom: 1px solid #0de8ec; + } + + .gantt_layout_cell_border_left { + border-left: 1px solid #0de8ec; + } + + .gantt_layout_cell_border_top { + border-top: 1px solid #0de8ec; + } + + .gantt_task_content { + text-shadow: 0 0 4px #333; + overflow: visible; + transform: translateY(-12px); + } + + /* 进度条高度 */ + .gantt_task_line { + height: 10px !important; + transform: translateY(10px); + } + + .gantt_tooltip { + width: 180px; + } +</style> -- Gitblit v1.9.3