vue2.X 中使用 echarts5.4.0实现项目进度甘特图

vue2.X 中使用 echarts5.4.0实现项目进度甘特图

效果图:
在这里插入图片描述
左侧都是名称上面时间,当中的内容是日志内容

  1. 组件: gantt.vue
<template><div id="main" style="width: 100%; height: 100%"></div></template><script>import * as echarts from "echarts";export default {name: "Gantt",props: {baseDate: {type: String,default: "",},ganttData: {type: Array,default: () => [],},roomData: {type: Array,default: () => [],},},data() {return {minHours: '08:00',maxHours: '24:00',// colors: ['#5c2223','#346c9c', '#525288', '#87723e', '#d1c2d3','#f07c82', '#835e1d', '#d99156', '#954416', '#ee8055', '#126e82', '#61649f', '#a7a8bd']};},created() {},mounted() {this.myEcharts();},watch: {ganttData(newVal) {this.myEcharts();},},methods: {getTimes() {let baseDate = `${this.baseDate}`;// 获取日志的最早和最晚时间,这样防止两边出现空白,比如00:00-09:00;this.$http.post(`/sys/task/times`, {taskDate: baseDate}).then(({ data: res }) => {if (res.code !== 0) {return this.$message.error(res.msg)}this.minHours = res.data.minTimethis.maxHours = res.data.maxTime}).catch(() => {})},myEcharts() {this.getTimes();// 基于准备好的dom,初始化echarts实例const container = document.getElementById("main");this.$echarts.init(container).dispose();var myChart = this.$echarts.init(container);// 用于随机颜色var colors= ['#8dddfa','#f98e72', '#f7b84f', '#a872f9', '#d6a9d1','#a7e56d', '#ff73c7', '#d6a9d1', '#b1e7fb', '#d3b3af', '#2859b1', '#1f6cb0']//let min = `${this.$moment().format("YYYY-MM-DD")} 00:00:00`;//let max1 = `${this.$moment().add(1, "day").format("YYYY-MM-DD")} 00:00:00`;// 指定图表的配置项和数据var option = {color: "#0A8BFF",backgroundColor: "#fff",title: {},tooltip: {// enterable: true,trigger: "item",show: true,// axisPointer: { // 坐标轴指示器,坐标轴触发有效//   type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'// },// alwaysShowContent: true,hideDelay: 100,backgroundColor: "rgba(255,255,255,1)", // 背景颜色(此时为默认色)borderRadius: 5, // 边框圆角confine: true,textStyle: {color: "#000"},// 悬浮的时候展示对应的数据formatter: function (params) {for(var i = 0; i < params.data.value.length; i++) {var content = (params.data.value[i].content +// "<br/>" +// (params.data.value[i].status === "1" ? '<span style="color:#4dc394;">已完成</span>' : '<span style="color:#e5835b;">进行中</span>') +"<br/>" +params.data.value[i].stime +" - " +params.data.value[i].etime);// 作用:鼠标悬浮在内容,出现弹窗显示内容详情,这里限制了宽,以防止宽度过长var tooltipHtml = '<div style="width:fit-content; max-width: 500px; white-space: wrap;">'+content+'</div>';return tooltipHtml;//return content;}},},legend: {// left: '90px',top: "1%",itemWidth: 16,itemHeight: 16,show: true,// selectedMode: false, // 图例设为不可点击textStyle: {color: "rgba(0, 0, 0, 0.45)",fontSize: 14,},},grid: {// 绘图网格left: "2%",right: "3%",top: "10%",bottom: "10%",containLabel: true,},xAxis: {type: "time",position: "top",//  interval: 3600 * 1000, // 以一个小时递增// 以一小时的时间递增minInterval: 3600 * 1000 ,maxInterval: 3600 * 1000 ,min: `${this.baseDate} ` + this.minHours,max: `${this.baseDate} ` + this.maxHours,//max:`${this.baseDate} 24:00`,//max: `${this.baseDate} 19:00`, // 设置最大时间为18点//min:`${this.baseDate} 00:00`, //将data里最小时间的整点时间设为min,否则min会以data里面的min为开始进行整点递增//min: `${this.baseDate} 08:00`, // 将data里最小时间的整点时间设为min,否则min会以data里面的min为开始进行整点递增axisLabel: {// 设置最后一个数据显示showMaxLabel: true,formatter: function (value, index) {var data = new Date(value);var hours = data.getHours();var minutes = data.getMinutes();if ((index !== 0 && hours === 0) || index === 25){return "23:59"} else {//return hours + ":00";if (minutes === 0) {return hours + ":00";} else {return hours + ":" + minutes;}}},textStyle: {color: "rgba(0,0,0,0.65)", // 更改坐标轴文字颜色fontSize: 14, // 更改坐标轴文字大小},},axisLine: {lineStyle: {color: "#e5e5e5",},onZero: false,},splitLine: {show: true,lineStyle: {type: "dashed",},},},// dataZoom: [//   // 给x轴设置滚动条//   {//     type: 'slider',//     show: true,//     yAxisIndex: [0, 1],//     left: '96%',//     start: 1,//     end: 100,//     fiterMode: 'filter'//   },//   {//     type: 'inside',//     fiterMode: 'filter',//     yAxisIndex: [0, 1],//     start: 1,//     end: 100//   }// ],yAxis: {inverse: true, // 是否反转type: "category",axisTick:{show: true //不显示坐标轴刻度线},splitLine: {     //网格线"show": true},axisLine: {show: true,lineStyle: {color: "#e5e5e5",},},data: this.roomData,axisLabel: {textStyle: {color: "rgba(0, 0, 0, 0.65)", // 刻度颜色fontSize: 14, // 刻度大小},},},series: [{type: "custom",clickable: false,renderItem: function (params, api) {// 开发者自定义的图形元素渲染逻辑,是通过书写 renderItem 函数实现的var categoryIndex = api.value(0).index; // 这里使用 api.value(0) 取出当前 dataItem 中第一个维度的数值。var start = api.coord([api.value(0).startTime, categoryIndex]); // 这里使用 api.coord(...) 将数值在当前坐标系中转换成为屏幕上的点的像素值。var end = api.coord([api.value(0).endTime, categoryIndex]);var height = 26;return {type: "rect", // 表示这个图形元素是矩形。还可以是 'rect', 'circle', 'sector', 'polygon' 等等。shape: echarts.graphic.clipRectByRect({// 矩形的位置和大小。x: start[0],y: start[1] - height / 2,width: end[0] - start[0],height: 27,},{// 当前坐标系的包围盒。x: params.coordSys.x,y: params.coordSys.y,width: params.coordSys.width,height: params.coordSys.height,}),style: api.style(),};},label: {normal: {show: true,position: "insideBottom",formatter: function (params) {//return params.value[0].content;let value =  params.value[0].content;if (!value) return "";if (value.length > 6) {return value.slice(0, 6) + "...";}return value;},textStyle: {align: "center",fontSize: 14,fontWeight: "400",lineHeight: "20",},},},encode: {x: 1, // data 中『维度1』对应到 X 轴y: 0, // 把"维度0"映射到 Y 轴。},itemStyle: {normal: {color: function (params) {const randomIndex = Math.floor(Math.random() * colors.length);return colors[randomIndex];},},},// dataZoom: [//   {//     show: true,//     realtime: true,//     start: 0,//     end: 50//   }// ],data: this.ganttData,},],};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);window.onresize = function () {myChart.resize();};// myChart.getZr().on("mousemove", (param) => {//   var pointInPixel = [param.offsetX, param.offsetY];//   if (myChart.containPixel("grid", pointInPixel)) {//     // 若鼠标滑过区域位置在当前图表范围内 鼠标设置为小手//     // myChart.getZr().setBackgroundColor('red')//     myChart.getZr().setCursorStyle("pointer");//   } else {//     myChart.getZr().setCursorStyle("default");//   }// });// 任意位置点击事件----注册双击// myChart.getZr().on("click", (params) => {//   if (!params.target) {//     // 点击在了空白处,做些什么。//     const point = [params.offsetX, params.offsetY];//     if (myChart.containPixel("grid", point)) {//       // 获取被点击的点在y轴上的索引//       const idxArr = myChart.convertFromPixel({ seriesIndex: 0 }, point);//       const xValue = new Date(+idxArr[0]).getHours();//       const yValue = idxArr[1];//       const sendData = [xValue, yValue];//       this.$emit("getInfoCallback", sendData);//     }//   }// });// // 图例点击事件-返回数据给父组件---单击事件// myChart.on("click", (params) => {//   this.$emit("getInfoCallback", params.data.value);// });},},computed: {},};</script><style scoped lang="less"></style>
  1. js文件
import Gantt from './src/gantt'Gantt.install = function (Vue) {Vue.component(Gantt.name, Gantt)
}
export default Gantt
  1. main.js中组件引用组件
    在这里插入图片描述
    在这里插入图片描述
  2. log页面
<template><div class="appointment"><div class="a-gantt"><el-row style="padding: 12px 10px; background-color: #fff"><el-col :span="12" align="left" style="font-weight: 700">日志</el-col><el-col :span="12" align="right"><el-date-pickerv-model="baseDate"type="date"@change="handleSelect"placeholder="选择日期"value-format="yyyy-MM-dd"></el-date-picker></el-col></el-row></div><div class="f-gantt"><Gantt:baseDate="baseDate"ref="gantt":ganttData="ganttData"@getInfoCallback="getGanttInfo":roomData="roomData"></Gantt></div><!-- 新增编辑框 --><!-- <el-dialog :title="formTitle" :visible.sync="dialogVisible" width="30%"><el-form :model="form" :label-width="formLabelWidth"><el-form-item label="会议室"><el-inputdisabledv-model="usernameData[form.index]"autocomplete="off"></el-input></el-form-item><el-form-item label="内容"><el-input v-model="form.content" autocomplete="off"></el-input></el-form-item><el-form-item label="时间" :label-width="formLabelWidth"><el-date-pickerv-model="form.startTime"type="datetime"placeholder="选择日期"value-format="yyyy-MM-dd HH:mm"></el-date-picker>-<el-date-pickerv-model="form.endTime"type="datetime"placeholder="选择日期"value-format="yyyy-MM-dd HH:mm"></el-date-picker></el-form-item><el-form-item label="状态" :label-width="formLabelWidth"><el-select v-model="form.status" style="width: 100%"><el-option label="进行中" value="0"></el-option><el-option label="已完成" value="1"></el-option></el-select></el-form-item></el-form><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="saveData">确 定</el-button></span></el-dialog> --></div>
</template><script>export default { data() {return {baseDate: `${new Date().getFullYear()}-${new Date().getMonth() + 1}-${new Date().getDate()}`,roomData: [],ganttData: [],dialogVisible: false,formLabelWidth: "120px",formTitle: "",form: {id: "",index: "",content: "",endTime: "",status: "",startTime: "",},};},created() {this.getDataList()// this.ganttData = [//   {//     value: [//       {//         index: 1,//         roomName: "会议室二",//         RoomId: "123",//         id: "333",//         startTime: '2023-09-05 08:28', //`${this.baseDate} 8:28`,//         endTime: '2023-09-05 09:28', // `${this.baseDate} 9:28`,//         status: "1",//         content: "睡觉",//       }//     ],//   },//   {//     value: [//     {//         index: 1,//         roomName: "会议室二",//         RoomId: "123",//         id: "333",//         startTime: '2023-09-05 12:28', //`${this.baseDate} 8:28`,//         endTime: '2023-09-05 15:28', // `${this.baseDate} 9:28`,//         status: "1",//         content: "工作",//       },//     ]//   },//   {//     value: [//       {//         index: 0,//         roomName: "会议室一",//         RoomId: "2234",//         id: "444",//         startTime: `2023-09-05 10:28`,//         endTime: `2023-09-05 12:28`,//         status: "0",//         content: "吃饭",//       },//     ],//   },//   {//     value: [//     {//         index: 0,//         roomName: "会议室一",//         RoomId: "123",//         id: "333",//         startTime: '2023-09-05 13:28', //`${this.baseDate} 8:28`,//         endTime: '2023-09-05 15:28', // `${this.baseDate} 9:28`,//         status: "1",//         content: "工作111",//       },//     ]//   }// ];//this.roomData = ['会议室一', '会议室二', '会议室三', '会议室四'];},mounted() {this.getDataList();},methods: {handleSelect() {this.getDataList()this.$refs.gantt.myEcharts();},getDataList() {this.$http.post(`/sys/task/ganteLog`, {taskDate: this.baseDate}).then(({ data: res }) => {if (res.code !== 0) {return this.$message.error(res.msg)}this.roomData = res.data.usernameListthis.ganttData = res.data.data}).catch(() => {})},getGanttInfo(data) {this.dialogVisible = true;// 根据data的长度判断是新增还是编辑// 新增if (data.length === 2) {this.formTitle = "新增";this.form = this.$options.data().form;this.$set(this.form, "index", data[1]);} else {this.formTitle = "修改";this.form = data[0];}},saveData() {if (this.formTitle === "修改") {this.ganttData = this.ganttData.filter((item) => {return item.value[0].id !== this.form.id;});} else {this.$set(this.form, "status", "0");}const obj = Object.assign({}, this.form);this.ganttData.push({ value: [obj] });this.$refs.gantt.myEcharts();this.dialogVisible = false;},},
};
</script><style scoped>
/* .a-gantt {position: absolute;top: 0;height: 60px;width: 100%;box-sizing: border-box;text-align: center;
} *//* .appointment {position: relative;height: 100%;overflow-y: hidden;border: 1px solid #ddd;color: #0f1419;box-sizing: border-box;
} */
.f-gantt {position: absolute;bottom: 10px;top: 80px;width: 100%;/*height: 600px;*/box-sizing: border-box;
}
</style>

注意数据结构
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/78228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ansys Zemax | 用于照明设计中的光源

本课程提供照明系统中光源的介绍&#xff0c;作为照明系统光源的信息中心。本课是照明学习路径的第二课。在这一课中&#xff0c;将描述照明系统中的各种光源类型以及如何这些使用光源。光源是照明系统的起点和支点&#xff0c;可以说是照明设计中最关键的部分。 简介&#xff…

华为云云耀云服务器L实例评测|基于云耀云服务器部署Samba服务

本实验将使用华为云云耀云服务器L实例&#xff0c;使用CentOS 7.9系统&#xff0c;搭建部署Samba服务器&#xff0c;并在本地Windows端进行访问。 文章目录 1、samba介绍2、环境准备3、安装samba软件包4、修改smb.conf配置文件5、添加访问samba的用户6、Windows下访问Samba服务…

使用 multiprocessing 多进程处理批量数据

示例代码 import multiprocessingdef process_data(data):# 这里是处理单个数据的过程return data * 2# 待处理的数据 data [1, 2, 3, 4, 5]def normal_func():# 普通处理方式result []for obj in data:result.append(process_data(obj)return resultdef parallel_func():# …

【FAQ】视频监控管理平台/视频汇聚平台EasyCVR安全检查相关问题及解决方法3.0

智能视频监控系统/视频云存储/集中存储/视频汇聚平台EasyCVR具备视频融合汇聚能力&#xff0c;作为安防视频监控综合管理平台&#xff0c;它支持多协议接入、多格式视频流分发&#xff0c;视频监控综合管理平台EasyCVR支持海量视频汇聚管理&#xff0c;可应用在多样化的场景上&…

Flink、Spark、Hive集成Hudi

环境描述: hudi版本:0.13.1 flink版本:flink-1.15.2 spark版本:3.3.2 Hive版本:3.1.3 Hadoop版本:3.3.4 一.Flink集成Hive 1.拷贝hadoop包到Flink lib目录 hadoop-client-api-3.3.4.jar hadoop-client-runtime-3.3.4.jar 2.下载上传flink-hive的jar包 flink-co…

算法 数据结构 递归冒泡算法 java冒泡算法 优化递归冒泡 数据结构(九)

使用递归算法实现冒泡&#xff1a; package com.nami.algorithm.study.day06;import java.util.Arrays;/*** beyond u self and trust u self.** Author: lbc* Date: 2023-09-05 15:36* email: 594599620qq.com* Description: keep coding*/ public class BubbleSort2 {// p…

大数据-玩转数据-Flink状态后端(下)

一、状态后端 每传入一条数据&#xff0c;有状态的算子任务都会读取和更新状态。由于有效的状态访问对于处理数据的低延迟至关重要&#xff0c;因此每个并行任务(子任务)都会在本地维护其状态&#xff0c;以确保快速的状态访问。 状态的存储、访问以及维护&#xff0c;由一个…

【深入解读Redis系列】(五)Redis中String的认知误区,详解String数据类型

有时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步&#xff0c;请认准https://blog.zysicyj.top 首发博客地址 系列文章地址 需求描述 现在假设有这样一个需求&#xff0c;我们要开发一个图像存储系统。要求如下&#xff1a; 该系统能快…

PbootCMS在搭建网站

1、打开网站 https://www.pbootcms.com/ 2、点击 “本站” 下载最新的网站代码 3、在本地laragon/www下创建目录&#xff08;hejuwuye&#xff09;&#xff0c;并将代码放进去 4、创建本地数据库&#xff0c;数据库名称为&#xff1a; hejuwuye&#xff0c;然后将static/bac…

快速傅里叶变换

引言 目标 傅里叶变化&#xff08;Fourier transform&#xff09;是一种信号处理技术&#xff0c;它可以将时间信号转换为频率信号&#xff0c;即将一组具有相同数量频率的正弦波叠加在一起&#xff0c;形成一组新的正弦波。如果我们把时间信号从频域转换到时域&#xff0c;那么…

SLAM ORB-SLAM2(1)总体框架

SLAM ORB-SLAM2(1)总体框架 1. 简介2. 框架3. TRACKING4. LOCAL MAPPING5. LOOP CLOSING6. MAP1. 简介 ORB-SLAM2 是一个实时和完整的视觉SLAM系统(包括闭环检测、重定位、地图重用等功能) 提供了利用单目、双目以及RGB-D相机完成稀疏三维重建的功能和接口 2. 框架 总体来说…

python项目制作docker镜像,加装引用模块,部署运行!

一、创建Dockerfile # 基于python:3.10.4版本创建容器 FROM python:3.10.4 # 在容器中创建工作目录 RUN mkdir /app # 将当前Dockerfile目录下的所有文件夹和文件拷贝到容器/app目录下 COPY . /app# 由于python程序用到了requests模块和yaml模块&#xff0c; # python:3.10.4基…

二叉树进阶练习

目录 一、根据二叉树创建字符串 二、二叉树的最近公共祖先 三、二叉搜索树与双向链表 四、从前序与中序遍历序列构造二叉树 五、从中序与后序遍历序列构造二叉树 六、二叉树的前序遍历&#xff08;非递归实现&#xff09; 七、二叉树的中序遍历&#xff08;非递归实现&a…

紫光展锐5G芯T820 解锁全新应用场景,让机器人更智能

数字经济的持续发展正推动机器人产业成为风口赛道。工信部数据显示&#xff0c;2023年上半年&#xff0c;我国工业机器人产量达22.2万套&#xff0c;同比增长5.4%&#xff1b;服务机器人产量为353万套&#xff0c;同比增长9.6%。 作为国内商用服务机器人领先企业&#xff0c;云…

应用在儿童平板防蓝光中的LED防蓝光灯珠

现在电子产品多&#xff0c;手机、平板电脑、电子书等等&#xff0c;由于蓝光有害眼睛健康&#xff0c;于是市场上有很多防蓝光的眼镜、防蓝光的手机膜、防蓝光的平板&#xff0c;这些材料和设备到底有没有用&#xff1f;如何正确预防蓝光危害呢&#xff1f; 我们现在所用的灯…

NCTF-2019-Crypto部分 复现

文章目录 SorechildRSAeasyRSAbabyRSA Sore 题目描述&#xff1a; task.py from string import ascii_letters from flag import flagctoi lambda x: ascii_letters.index(x) # 获得所有字母的字符串 itoc lambda x: ascii_letters[x] # 将索引值转换为字母key flag.strip…

关于 Resolution(分辨率、解析力)各单位的意义及相互之间的换算

1、问题背景 最近在调试的项目&#xff0c;有关于对解析力的要求&#xff0c;用 imatest 软件测试 MTF50 的值&#xff0c;如下图所示&#xff0c;可以看到他有不同的单位表示&#xff0c;LW/PH、Cycles/pixel 。另外关于解析力的单位还有LP/mm、L/mm、Cycles/mm、LP/PH&#…

MySQL安装validate_password_policy插件

功能介绍 validate_password_policy 是插件用于验证密码强度的策略。该参数可以设定三种级别&#xff1a;0代表低&#xff0c;1代表中&#xff0c;2代表高。 validate_password_policy 主要影响密码的强度检查级别&#xff1a; 0/LOW&#xff1a;只检查密码长度。 1/MEDIUM&am…

IO流(IO Stream)

​ 一、概述 我们已经系统学习了File 类&#xff0c;并且已经知道 File 类的实例用于表示文件或目录的路径 名。 虽然我们可以通过 File 实例来访问文件或目录的元数据&#xff0c;甚至可以创建、删除文件或目 录&#xff0c;但是&#xff0c;我们却不能通过File实例来访问文…

春秋云镜 CVE-2015-1427

春秋云镜 CVE-2015-1427 ElasticSearch RCE 靶标介绍 ElasticSearch RCE 启动场景 漏洞利用 因查询时至少要求es中有一条数据&#xff0c;所以发送如下数据包&#xff0c;增加一个数据&#xff1a; POST /website/blog/ HTTP/1.1 Host: eci-2zedttamjkr80i9iubel.cloudeci…