赞
踩
安装gantt
- npm install dhtmlx-gantt -save
- 复制代码
引入---组件
- `引入`
- <template>
- <div ref="gantt" class="container" />
- </template>
- <script>
- import { gantt } from 'dhtmlx-gantt'
- </script>
- 复制代码
使用
使用需要很多配置项,在原生版进行详情介绍,vue版只做基本使用
功能(收费) | 文档链接 | 简要说明 |
---|---|---|
动态加载 | Dynamic loading | 能通过接口更新甘特数据,gantt支持的接口方法 |
时间刻度隐藏 | Ability to hide time units on the time scale | 右边视图刻度可以不显示某时间内容 |
工作时间精度 | Assigning Calendar to Project | 精确工作时间到小时或小数点天数 |
自动调度 | Auto scheduling | 使甘特图能够根据任务之间的关系自动安排任务,自动调度时间 |
页面多个甘特图 | Enterprise and Ultimate licenses) | 单个页面创建多个甘特图 |
关键任务计算 | Critical path calculation | 关键任务不可延迟,项目标红,计算项目可预算时间 |
水平拖拽多个任务 | Decimal units for tasks durations | 可以同时修改多个任务的时间 |
项目,里程碑,任务类型 | Projects and Milestones task types | 区别显示图标,里程碑(菱形图案)---原生版可用 |
将项目拆分子任务 | Projects and Milestones task types | 项目收缩显示子任务 -----原生版可用 |
分组任务 | Tasks grouping | 细化数据分类,不做汇总分区基本用不上 |
以上内容只是部分收费内容,并非全部收费内容
引入
- `页面部分` ----#节点高度要给,gantt不根据内容撑开
- <div style="min-height:calc(78vh - 50px - 5px );width: 100%;overflow: hidden;" ref="gantt">
- </div>
-
- `引入部分`
- import {
- gantt
- } from '@/assets/js/dhtmlx';
- import "@/assets/css/dhtmlxgantt.css";
- 复制代码
使用
gantt加载数据格式
- `定义数据格式`
- data(){
- return {
- tasks: {
- data: [],//数据
- links: [],//关联项目数据
- },
- }
- }
- `甘特数据载入`
- gantt.parse(this.tasks);//parse方法加载数据
- gantt.render();//建议每一次修改配置项调用一次render方法
- 复制代码
tasks.data数据格式
- data=[
- {
- id: 1,//必填
- text: "标题",//必填
- type: "task",// 项目类型 task任务 project项目 milestone里程碑
- start_date: "2023/3/15",
- duration: 5,//任务持续时间
- parent: 11,//存在这个属性说明此数据为子任务数据,父任务id为11
- progress: 0.3,//项目任务滑块的进度
- open: true,//是否展开显示
- ....
- },
- {
- id: 2,
- text: "标题2",
- start_date: "2023/3/15",
- duration: 5,
- progress: 0,
- open: true
- ....
- },
- ]
- # data中有些数据可以直接被读取,其余数据都可以定义在左侧表格columns数据显示
- `甘特可直接读取属性
- type parent progress open ...
- `
- 复制代码

tasks.links数据格式
- links=[
- {
- id:'111',//数据id
- source:'1'
- target:'2'
- type:'0'
- },//
- {
- id:'222'
- source:'2'
- target:'1'
- type:'1'
- },//数据说明 滑块任务2 的头部 指向滑块任务1的头部
- ]
- #字段解释
- 格式 id:数据id
- source:开始链接的项目id ----为tasks.data中数据的id
- target:要链接项目的id ----为tasks.data中数据的id
- type: 0--进行-开始 `尾部链接头部`
- 1--开始-开始 `头部链接头部`
- 2--进行-进行 `尾部链接尾部`
- 3--开始-进行 `头部链接尾部`
- 复制代码

图例
配置项
基础config
- gantt.config.branch_loading = true; // 启用动态加载
- gantt.config.xml_date = "%Y-%m-%d"; //日期格式化
- gantt.config.order_branch = true;
- gantt.config.order_branch_free = true;
- gantt.config.autofit = true;//左侧是否自适应
- gantt.config.drag_links = true;//连线
- gantt.config.readonly = false; //只读
- gantt.config.smart_scales = true;
- gantt.config.date_scale = "%m月%d日"; //右侧显示列名
- gantt.config.layout = {//拖拽布局
- css: "gantt_container",
- rows: [
- {
- cols: [
- { view: "grid", id: "grid", scrollX: "scrollHor", scrollY: "scrollVer" },
- { resizer: true, width: 1 },
- { view: "timeline", id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer" },
- { view: "scrollbar", scroll: "y", id: "scrollVer" }
- ]
- },
- { view: "scrollbar", scroll: "x", id: "scrollHor", height: 20 }
- ]
- };
- gantt.config.start_on_monday = true;//是否从周一显示起始时间---右侧条形图
- gantt.config.work_time = true;//显示工作时间
- gantt.config.fit_tasks = true; //自动调整图表坐标轴区间用于适配task的长度
- 复制代码

local---本地汉化
说明
(1)直接引入dhtmlx甘特实现的图表操作描述全是英文的,所以要对现有的属性数据显示要进行汉化文字代替
(2)汉化分三种
日期汉化 | 属性汉化 | 自定义属性汉化 |
---|---|---|
gantt.locale.date | gantt.locale.labels | gantt.locale.labels |
- //汉化
- 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_type: "类型:",
- section_text: "计划名称:",
- section_test: "测试:",
- #自定义属性汉化----->
- section_projectClass: "项目类型:",
- taskProjectType_0: "项目任务",
- taskProjectType_1: "普通任务",
- section_head: "负责人:",
- section_priority: '优先级:',
- taskProgress: '任务状态',
- taskProgress_0: "未开始",
- taskProgress_1: "进行中",
- taskProgress_2: "已完成",
- taskProgress_3: "已延期",
- taskProgress_4: "搁置中",
- #<-----自定义属性汉化结束
- section_template: 'Details',
- /* grid columns */
- column_text: "计划名称",
- column_start_date: "开始时间",
- column_duration: "持续时间",
- column_add: "",
- column_priority: "难度",
- /* link confirmation */
- link: "关联",
- confirm_link_deleting: "将被删除",
- link_start: " (开始)",
- link_end: " (结束)",
- type_task: "任务",
- type_project: "项目",
- type_milestone: "里程碑",
-
- minutes: "分钟",
- hours: "小时",
- days: "天",
- weeks: "周",
- months: "月",
- years: "年"
- }
- }
- 复制代码

(4)图例注释
表格(左)配置
属性 | 说明 |
---|---|
name | 在tasks.data中定义的属性数据,add为例外,add为新增数据项触发gantt新增弹窗,显示为一个加号 |
label | 标记描述 |
align | 文字格式 |
resize | 布尔值,可以拉伸内容宽度 |
width | 宽度,可写max _width min_width |
height | 高度, 可写max _height min_height |
editor | 将表格内容设置为可编辑状态,官网描述 |
template | 自定义渲染内容 |
- //左侧显示列名
- gantt.config.columns = [
- //{ name: "add", width: 44 }
- { name: "text", min_width:100,max_width:200, label:"任务", align: "left",resize: true, tree: true, editor: { type: 'text', map_to: 'text' } },
- { name: "id", label: "", hide: true },
- { name: "start_date", label: "开始时间", width: 120, resize: true, align: "left" },
- {
- name: "head", width: 110, height: 40, label: "负责人",resize: true, align: "left",
- // editor: {
- // map_to: "head_id", type: "select", options: gantt.serverList("staff"),
- // },
- #这里的template渲染的是任务头像跟名称,this.genttDealById 是在methods定义的方法根据id获取名称,gantt.serverList()是甘特图获取数据集分发
- template: (item) => {
- if (this.ganttDealById(gantt.serverList('staff'), item.head_id)) {
- return `<span class='userIcon' style='background-color:${item.color ? item.color : "#6666"}'>${this.ganttDealById(gantt.serverList('staff'), item.head_id).slice(0, 1)}</span>${this.ganttDealById(gantt.serverList('staff'), item.head_id)}`
- }
- }
- },
- // { name: "end_date", label: "结束时间", align: "center" },
- {
- name: "taskProgress", label: "任务状态", align: "center", width: 130,editor: {
- type: "select", map_to: "taskProgress", options: [
- #这里的labels.taskProgress_0属性是自定义汉化属性描述
- { key: "0", label: gantt.locale.labels.taskProgress_0 },
- { key: "1", label: gantt.locale.labels.taskProgress_1 },
- { key: "2", label: gantt.locale.labels.taskProgress_2 },
- { key: "3", label: gantt.locale.labels.taskProgress_3 },
- { key: "4", label: gantt.locale.labels.taskProgress_4 },
- ],
- },
- #obj形参是单个的tasks.data中的数据
- template: function (obj) {
- let re = '';
- switch (obj.taskProgress) {
- case "0":
- #这里的样式类名只能通过css读取,写在less scss无法读取
- re = `<div class='taskProgress color_bg_1' >未开始</div>`
- break;
- case "1":
- re = `<div class='taskProgress color_bg_2' >进行中</div>`
- break;
- case "2":
- re = `<div class='taskProgress color_bg_3' >已完成</div>`
- break;
- case "3":
- re = `<div class='taskProgress color_bg_4'>已延期</div>`
- break;
- case "4":
- re = `<div class='taskProgress color_bg_5' >搁置中</div>`
- break;
- }
- return re
- }
- },
-
- ];
- 复制代码

弹窗表单----见汉化图例
- //弹出层
- gantt.config.lightbox.sections = [ { name: "text", height: 70, map_to: "text", type: "textarea", focus: true, width: "*" }, { name: "time", height: 40, map_to: "auto", type: "duration", time_format: ["%Y", "%m", "%d"],
- },
- {
- name: "projectClass", height: 30, map_to: "proTemplate", type: "template",
-
- },
- {
- name: "head", height: 22, map_to: "head_id", type: "select", options: gantt.serverList('staff',[]),
- },
- { name: "description", height: 70, map_to: "description", type: "textarea" },
- {
- name: "priority", height: 40, map_to: "priority", type: "radio", options: gantt.serverList("priority")
- },
-
- ];
- 复制代码

gantt功能插件挂载
- gantt.plugins({
- click_drag: true,
- drag_timeline: true,// 拖动图
- marker: true,// 时间标记
- fullscreen: true,// 全屏
- tooltip: true,// 鼠标经过时信息
- undo: true // 允许撤销
- })
- 复制代码
收费的甘特图功能一般在这放开
事件 | 参数 | 说明 (参数:id:数据id,item:当个数据对象,mode:拖拽模式,e:事件event) |
---|---|---|
onGanttReady | 无 | 在 dhtmlx甘特图初始化完成后触发,但甘特图尚未在页面上呈现 |
onBeforeLightbox | id | 打开弹窗之前修改 |
onAfterTaskAdd | id, item | 在用户将任务添加到甘特图后触发 |
onAfterTaskUpdate | id, item | 在用户将修改甘特图任务后触发 |
onAfterTaskDelete | id, item | 在用户删除甘特图任务后触发 |
onAfterTaskDrag | id, mode, e | 在用户完成拖动并释放鼠标按钮后触发,移动滑块 |
onAfterLinkDelete | id, item | 删除连接任务的联系 |
onAfterLinkUpdate | id, item | 修改连接项目关系 |
onBeforeLinkAdd | id, item | 新增连接项目关系 |
onLightboxSave | id, item | 弹窗新增修改 |
方法 | 用例 | 说明 |
---|---|---|
gantt.serverList(‘数据集名称’,'数据集') | gantt,serverList("数据集名称") 返回的数据集 | 在甘特实例定义数据集,方便在甘特配置修改是调用 |
gantt.updateCollection('数据集名称',更新数据) | gantt.updateCollection("staff", staffArr); | 更新数据集数据 |
gantt.render() | 更新gantt配置 | |
gantt.clearAll() | 清空gantt配置 | |
gantt.detachEvent(’事件名) | 重点 | 因为切换页面甘特不会销毁,调用销毁后阻止事件反复调用 |
gantt.scrollTo(x,y) | 定位今日线功能需要,定位到某个位置 | |
gantt.init() | gantt.init(this.$refs.gantt); | gantt初始化挂载节点 |
gantt.parse() | gantt.parse({ data: [],links: [] }) | gantt挂载数据 |
gantt.getTask() | gantt.getTask(id) | gantt获取单个数据 |
今日线与定位
- // 今日线
- createTodayLine() {
- var dateToStr = gantt.date.date_to_str("%Y年%M%d日");
- var markerId = gantt.addMarker({
- id: 'markerLine',
- start_date: new Date(),
- css: "today",
- text: "今日",
- title: dateToStr(new Date())
- });
- gantt.updateMarker(markerId);
- }
- //定位到今日线
- changeToday() {
- this.$nextTick(() => {
- let ganTT = document.getElementsByClassName('gantt_marker today')
- gantt.scrollTo(ganTT[0].offsetLeft-300, null);
- })
- },
- 复制代码

全屏(类F11)
- // 是否全屏
- changeFull() {
- gantt.ext.fullscreen.toggle();
- },
- 复制代码
- //
- <a-input allowClear v-model="searchTitle" placeholder="请输入任务名称"></a-input>
- <a-button icon="search" type="primary" @click="searchDataClick">搜索</a-button>
- //点击按钮搜索
- #methods
- // 搜索判断数据
- hasSubstr(parentId,type){
- let task = gantt.getTask(parentId);
- if(type=='tilte'){
- if(task.text.toLowerCase().indexOf(this.searchTitle) !== -1)
- return true;
- }
- // }
- },
- searchDataClick(){
- if(this.searchTitle ){
- this.ganttEvent.onBeforeTaskDisplay=gantt.attachEvent("onBeforeTaskDisplay", (id, task)=>{
- if (this.hasSubstr(id,'tilte') ){ return true;}
- return false;
- });
- gantt.refreshData()
- gantt.render()
- }else{
- this.ganttEvent.onBeforeTaskDisplay=gantt.attachEvent("onBeforeTaskDisplay", (id, task)=>{
- return true
- })
- gantt.refreshData()
- gantt.render()
- }
- },
- 复制代码

日期切换
- // 切换 年 季 月 周 日视图
- ganttChangeDateView(type) {
- switch (type) {
- case 'y':
- gantt.config.scale_unit = "year";
- gantt.config.step = 1;
- gantt.config.subscales = null;
- gantt.config.date_scale = "%Y年";
- gantt.templates.date_scale = null;
- break;
-
- case 'm':
- gantt.config.scale_unit = 'month';
- gantt.config.step = 1;
- gantt.config.date_scale = "%m月";
- gantt.templates.date_scale = null;
-
- break;
- case 'w':
- gantt.config.scale_unit = 'week';
- gantt.config.step = 1;
- gantt.config.date_scale = "第%w周";
- gantt.templates.date_scale = null;
-
- break;
- case 'd':
- gantt.config.scale_unit = 'day';
- gantt.config.step = 1;
- gantt.config.date_scale = "%m月%d日";
- gantt.templates.date_scale = null;
- gantt.config.subscales = null;
-
- break;
- }
- gantt.render();
- },
- 复制代码

图例
- <template>
- <div style="height: 100%; width: 100%">
- <a-layout>
- <div class="content">
- <div style="margin: -5px 0px 5px;display: flex;justify-content: space-between;">
- <a-input allowClear v-model="searchTitle" placeholder="请输入任务名称"></a-input>
- <a-button icon="search" type="primary" @click="searchDataClick">搜索</a-button>
- </div>
- <!-- 中间 内容 -->
- <div class="centerContent">
- <!-- 甘特图 -->
- <div class="selectDate">
- <a-button @click="changeToday">今</a-button>
- <!-- 日期切换 -->
- <a-select default-value="d" style="width: 55px;margin-left: 5px;" @change="ganttChangeDateView">
- <a-select-option value="y">年</a-select-option>
- <a-select-option value="m">月</a-select-option>
- <a-select-option value="w">周</a-select-option>
- <a-select-option value="d">日</a-select-option>
- </a-select>
- <a-button style="margin-left: 5px;" @click="changeFull"><a-icon type="fullscreen" /></a-button>
- </div>
- <div class="rightGatt" style="min-height:calc(78vh - 50px - 5px );width: 100%;overflow: hidden;" ref="gantt">
- </div>
- </div>
- </div>
- </a-layout>
- </div>
- </template>
- <script>
-
- import {
- gantt
- } from '@/assets/js/dhtmlx';
- import "@/assets/css/dhtmlxgantt.css";
- import { util } from "@/components/utils/util.js"
- import moment from 'moment'
-
- export default {
- name: "ganttChart",
- data() {
- return {
- moment,
- timer: null,//定时
- item: {},//单行数据
- searchTitle: "",//搜索标题
- tasks: {
- data: [],//数据
- links: [],//关联项目数据
- },
- savetasks: {
- data: [],
- links: []
- },//暂存空数据
- ganttServerStaff:[],//设置gantt成员数据
- selectStaff: [],//下拉成员
- staff: [],//成员
- ganttEvent: {//销毁事件
- },
- urls: {
- staff: "",//项目成员
- tasklinks: '',//gantt数据
- linksEdit: '',//修改和新增连接
- linksDelete: '',//删除连接
- addTask: '',//新增项目PUT
- editTask: '',//编辑项目put请求 tid
- deleteTask: '',//删除项目delete tid
- }
- }
- },
- watch: {
- searchTitle(newVal,oldVal){
- this.searchTitle = newVal;
- }
- },
- mounted() {
- this.axios.get(this.urls.staff, {
- params: { projectId: this.$store.state.project_data.id },
- }).then(res => {
- let staffArr = [];
- res.data.code = 200 && res.data.result.forEach((item, index) => {
- staffArr[index] = {};
- staffArr[index].key = item.id;
- staffArr[index].label = item.realname;
- })
- this.selectStaff = res.data.result;
- // 补充gantt数据
- this.ganttServerStaff=staffArr;
-
- })
- this.$nextTick(()=>{
- this.ganttChangeEvent();//交互事件
- this.initGantt();//初始化
-
- this.createTodayLine();//今日线
- this.ganttServerList();//服务数据
- })
- this.onQuery();//查询数据
- this.ganttChangeDateView("d");//默认日格式
- },
- methods: {
- /*
- 甘特图
- */
- // 初始化gantt
- initGantt() {
- // 清空之前的配置
- // gantt.clearAll();
-
- // 启用动态加载
- gantt.config.branch_loading = true
- //日期格式化
- gantt.config.xml_date = "%Y-%m-%d";
- gantt.config.order_branch = true;
- gantt.config.order_branch_free = true;
- //左侧是否自适应
- gantt.config.autofit = true;
- gantt.config.drag_links = true;//连线
- gantt.config.readonly = false; //只读
- gantt.config.date_scale = "%m月%d日"; //右侧显示列名
- gantt.config.layout = {//拖拽布局
- css: "gantt_container",
- rows: [
- {
- cols: [
- { view: "grid", id: "grid", scrollX: "scrollHor", scrollY: "scrollVer" },
- { resizer: true, width: 1 },
- { view: "timeline", id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer" },
- { view: "scrollbar", scroll: "y", id: "scrollVer" }
- ]
- },
- { view: "scrollbar", scroll: "x", id: "scrollHor", height: 20 }
- ]
- };
- gantt.config.start_on_monday = true;
- gantt.config.work_time = true;
- gantt.config.fit_tasks = true; //自动调整图表坐标轴区间用于适配task的长度
-
-
- //汉化
- 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_type: "类型:",
- section_text: "计划名称:",
- section_test: "测试:",
- section_projectClass: "项目类型:",
- taskProjectType_0: "项目任务",
- taskProjectType_1: "普通任务",
- section_head: "负责人:",
- section_priority: '优先级:',
- taskProgress: '任务状态',
- taskProgress_0: "未开始",
- taskProgress_1: "进行中",
- taskProgress_2: "已完成",
- taskProgress_3: "已延期",
- taskProgress_4: "搁置中",
- section_template: 'Details',
- /* grid columns */
- column_text: "计划名称",
- column_start_date: "开始时间",
- column_duration: "持续时间",
- column_add: "",
- column_priority: "难度",
- /* link confirmation */
- link: "关联",
- confirm_link_deleting: "将被删除",
- message_ok:'确定',
- message_cancel:'取消',
- link_start: " (开始)",
- link_end: " (结束)",
-
- type_task: "任务",
- type_project: "项目",
- type_milestone: "里程碑",
-
- minutes: "分钟",
- hours: "小时",
- days: "天",
- weeks: "周",
- months: "月",
- years: "年"
- }
- }
- gantt.serverList("priority", [
- { key: 0, label: "最高" },
- { key: 1, label: "较高" },
- { key: 2, label: "普通" },
- { key: 3, label: "较低" },
- { key: 4, label: "最低" },
- ]);
- //左侧显示列名
- gantt.config.columns = [
- { name: "text", min_width:100,max_width:200, label:"任务", align: "left",resize: true, tree: true, editor: { type: 'text', map_to: 'text' } },
- { name: "id", label: "", hide: true },
- { name: "start_date", label: "开始时间", width: 120, resize: true, align: "left" },
- {
- name: "head", min_width: 100, height: 40, label: "负责人",resize: true, align: "left",
- // editor: {
- // map_to: "head_id", type: "select", options: gantt.serverList("staff"),
- // },
- template: (item) => {
- if (this.ganttDealById(gantt.serverList('staff'), item.head_id)) {
- return `<span class='userIcon' style='background-color:${item.color ? item.color : "#6666"}'>${this.ganttDealById(gantt.serverList('staff'), item.head_id).slice(0, 1)}</span>${this.ganttDealById(gantt.serverList('staff'), item.head_id)}`
- }
- }
- },
- // { name: "end_date", label: "结束时间", align: "center" },
- {
- name: "taskProgress", label: "任务状态", align: "center", min_width: 110,editor: {
- type: "select", map_to: "taskProgress", options: [
- { key: "0", label: gantt.locale.labels.taskProgress_0 },
- { key: "1", label: gantt.locale.labels.taskProgress_1 },
- { key: "2", label: gantt.locale.labels.taskProgress_2 },
- { key: "3", label: gantt.locale.labels.taskProgress_3 },
- { key: "4", label: gantt.locale.labels.taskProgress_4 },
- ],
- },
- template: function (obj) {
- let re = '';
- switch (obj.taskProgress) {
- case "0":
- re = `<div class='taskProgress color_bg_1' >未开始</div>`
- break;
- case "1":
- re = `<div class='taskProgress color_bg_2' >进行中</div>`
- break;
- case "2":
- re = `<div class='taskProgress color_bg_3' >已完成</div>`
- break;
- case "3":
- re = `<div class='taskProgress color_bg_4'>已延期</div>`
- break;
- case "4":
- re = `<div class='taskProgress color_bg_5' >搁置中</div>`
- break;
- }
- return re
-
- }
- },
-
- ];
-
- //弹出层
- gantt.config.lightbox.sections = [
- { name: "text", height: 70, map_to: "text", type: "textarea", focus: true, width: "*" },
- {
- name: "time", height: 40, map_to: "auto", type: "duration",
- time_format: ["%Y", "%m", "%d"],
- },
- {
- name: "projectClass", height: 30, map_to: "proTemplate", type: "template",
-
- },
- {
- name: "head", height: 22, map_to: "head_id", type: "select", options: gantt.serverList('staff',[]),
- },
- { name: "description", height: 70, map_to: "description", type: "textarea" },
- {
- name: "priority", height: 40, map_to: "priority", type: "radio", options: gantt.serverList("priority")
- },
-
- ];
-
- gantt.config.smart_scales = true;
- gantt.plugins({
- click_drag: true,
- drag_timeline: true,// 拖动图
- marker: true,// 时间标记
- fullscreen: true,// 全屏
- tooltip: true,// 鼠标经过时信息
- undo: true // 允许撤销
- })
- gantt.init(this.$refs.gantt);
-
- },
-
-
- // gantt数据服务列表
- ganttServerList() {
- this.getProjectStaff();//获取项目成员
- // 项目难度
- gantt.serverList("priority", [
- { key: 0, label: "最高" },
- { key: 1, label: "较高" },
- { key: 2, label: "普通" },
- { key: 3, label: "较低" },
- { key: 4, label: "最低" },
- ]);
-
- },
- // gantt交互事件注册
- ganttChangeEvent() {
- // gantt渲染
- this.ganttEvent.onGanttReady= gantt.attachEvent("onGanttReady", ()=>{
-
- //弹窗标题 日期范围
- gantt.templates.task_time = function (start, end, task) {
- return "周期:" + moment(start).format('YYYY-MM-DD') + " 至 " + moment(end).format('YYYY-MM-DD');
- };
- // 浮窗
- gantt.templates.tooltip_text = (start, end, task) => {
- return "<b>项目名称:</b> " + task.text + "<br><b>负责人:</b>" + task.head + "<br/><b>开始时间:</b> "
- + moment(start).format('YYYY-MM-DD')
- + "<br/><b>结束时间:</b> "
- + moment(new Date(end).valueOf() - 1000*60*60*24 ).format('YYYY-MM-DD');
- }
- //弹窗标题 计划名称
- gantt.templates.task_text = function (start, end, task) {
- return task.text;
- };
- gantt.templates.timeline_cell_class = function (task, date) {
- if (!gantt.isWorkTime({ task: task, date: date })) {
- return "weekend";
- } else {
- return 'weekday'
- }
- };
- gantt.templates.task_end_date = (date)=>{
- return gantt.templates.task_date(this.moment(new Date(date.valueOf() - 1000*60*60*24)).format("YYYY-MM-DD"));
- };
- gantt.templates.grid_date_format = (date, column)=>{
- if(column === "end_date"){
- return this.moment(new Date(date.valueOf() - 1000*60*60*24)).format("YYYY-MM-DD");
- }else{
- return this.moment(date).format("YYYY-MM-DD");
- }
- }
- });
- // 修改默认弹窗
- gantt.attachEvent("onBeforeLightbox", (id)=> {
- var task = gantt.getTask(id);
- task.proTemplate = `${gantt.locale.labels.taskProjectType_0}`
- return true;
- });
-
- //添加后触发
- this.ganttEvent.onAfterTaskAdd = gantt.attachEvent("onAfterTaskAdd", (id, item) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
- this.dealProject("add",item)
- }, 500)
-
- });
- // 修改任务
- this.ganttEvent.onAfterTaskUpdate = gantt.attachEvent("onAfterTaskUpdate", (id, data) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
- this.dealProject("edit", data);
- gantt.render()
- }, 500)
-
- });
- // 删除项目
- this.ganttEvent.onAfterTaskDelete = gantt.attachEvent("onAfterTaskDelete", (id, data) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
-
- this.dealProject("delete", data);
- gantt.render();
- }, 500)
- });
- // 移动项目
- this.ganttEvent.onAfterTaskDrag = gantt.attachEvent("onAfterTaskDrag", (id, mode, e) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
- var task = gantt.getTask(id);
- this.dealProject("edit", task);
- gantt.render()
- }, 500)
- });
- // 用户完成拖动并释放鼠标
- this.ganttEvent.onAfterTaskChanged = gantt.attachEvent("onAfterTaskChanged", (id, mode, task) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
- gantt.render();
- }, 500)
- });
-
- // 删除连接项目关系
- this.ganttEvent.onAfterLinkDelete = gantt.attachEvent("onAfterLinkDelete", (id, item) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
-
- let param = Object.assign({}, { projectId:this.$store.state.project_data.id }, item)
- this.axios.$delete(this.urls.linksDelete, param).then(res => {
- res.code == 200 && this.$message.success("解除成功!")
- res.code != 200 && this.$message.error("解除失败!")
- })
- gantt.render();
- }, 500)
- });
- // 修改连接项目关系
- this.ganttEvent.onAfterLinkUpdate = gantt.attachEvent("onAfterLinkUpdate", (id, item) => {
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
-
- let param = Object.assign({}, { projectId:this.$store.state.project_data.id }, item)
- this.axios.$put(this.urls.linksEdit, param).then(res => {
- res.code == 200 && this.$message.success("关联成功!")
- res.code != 200 && this.$message.error("关联失败!")
-
- })
- gantt.render()
- }, 500)
- });
- // 新增连接项目关系
- this.ganttEvent.onBeforeLinkAdd = gantt.attachEvent("onBeforeLinkAdd", (id, item) => {
- this.timer = setTimeout(() => {
- clearTimeout(this.timer)
- let param = Object.assign({}, { projectId: this.$store.state.project_data.id }, item)
- this.axios.$put(this.urls.linksEdit, param).then(res => {
- res.code == 200 && this.$message.success("关联成功!");
- res.code != 200 && this.$message.error("关联失败!");
-
- })
- gantt.render()
- }, 20)
-
- });
- // 保存新增
- this.ganttEvent.onLightboxSave = gantt.attachEvent("onLightboxSave", (id, item) => {
- if (!item.text) {
- this.$message.error("请填写计划名称!");
- return false;
- }
- return true;
- });
-
- },
- // 处理id 对应名称label
- ganttDealById(list, id) {
- for (let i = 0; i < list.length; i++) {
- if (list[i].key == id)
- return list[i].label ;
- }
- return "";
- },
- // 切换 年 季 月 周 日视图
- ganttChangeDateView(type) {
- switch (type) {
- case 'y':
- gantt.config.scale_unit = "year";
- gantt.config.step = 1;
- gantt.config.subscales = null;
- gantt.config.date_scale = "%Y年";
- gantt.templates.date_scale = null;
- break;
-
- case 'm':
- gantt.config.scale_unit = 'month';
- gantt.config.step = 1;
- gantt.config.date_scale = "%m月";
- gantt.templates.date_scale = null;
-
- break;
- case 'w':
- gantt.config.scale_unit = 'week';
- gantt.config.step = 1;
- gantt.config.date_scale = "第%w周";
- gantt.templates.date_scale = null;
-
- break;
- case 'd':
- gantt.config.scale_unit = 'day';
- gantt.config.step = 1;
- gantt.config.date_scale = "%m月%d日";
- gantt.templates.date_scale = null;
- gantt.config.subscales = null;
-
- break;
- }
- gantt.render();
- },
- // 今日线
- createTodayLine() {
- var dateToStr = gantt.date.date_to_str("%Y年%M%d日");
- var markerId = gantt.addMarker({
- id: 'markerLine',
- start_date: new Date(),
- css: "today",
- text: "今日",
- title: dateToStr(new Date())
- });
- gantt.updateMarker(markerId);
- },
- // 是否全屏
- changeFull() {
- gantt.ext.fullscreen.toggle();
- },
- // 定位到今日线
- changeToday() {
- this.$nextTick(() => {
- let ganTT = document.getElementsByClassName('gantt_marker today')
- gantt.scrollTo(ganTT[0].offsetLeft-300, null);
- })
- },
- /*
- 操作
- */
- // 获取项目成员
- getProjectStaff(projectID) {
- this.axios.get(this.urls.staff, {
- params: { projectId: projectID ? projectID : this.$store.state.project_data.id },
- }).then(res => {
- let staffArr = [];
- res.data.code = 200 && res.data.result.forEach((item, index) => {
- staffArr[index] = {};
- staffArr[index].key = item.id;
- staffArr[index].label = item.realname;
- })
- this.selectStaff = res.data.result;
- // 补充gantt数据
- this.ganttServerStaff=staffArr;
- gantt.updateCollection("staff", staffArr);
- gantt.render()
- })
- },
- //计算进度
- evalProgess(start,end,update) {
- if (start && end && update) {
- let start_date = this.moment(start).format("YYYY-MM-DD");
- let end_date = this.moment(end).format("YYYY-MM-DD");
- let update_date = this.moment(update).format("YYYY-MM-DD");
-
- if((new Date(end_date) - new Date(update_date)>0)){
- let process= (new Date(update_date) - new Date(start_date)) / (new Date(end_date) - new Date(start_date));
- return process.toFixed(2)
- }else {
- return 0
- }
- }
-
- return 0
- },
- // 获取数据
- onQuery(param) {
- gantt.clearAll();
- gantt.parse(this.savetasks);
- gantt.render();
- param = Object.assign({}, { projectId:
- this.$store.state.project_data.id ? this.$store.state.project_data.id :'1'
- }, param)
- this.axios.get(this.urls.tasklinks, {
- params: param
- }).then(res => {
- let result = res.data.result["taskList"];
- let pushArr = [];
- this.tasks.links = res.data.result["ganttchartList"];//连接项目
- this.tasks.data = [];
- result.forEach((item, index) => {
- this.tasks.data[index] = {};
- this.tasks.data[index].id = item.tid ? item.tid : '';//项目id
- this.tasks.data[index].text = item.title ? item.title : '空标题';//标题
- this.tasks.data[index].start_date = item.startTime;//开始时间
- // 负责人--成员
- this.tasks.data[index].head_id = item.headRole?.id?item.headRole?.id:'';//负责人id
- this.tasks.data[index].head = item.headRole?.realname ? item.headRole?.realname : '';//负责人
- this.tasks.data[index].progress = this.evalProgess(item.startTime,item.endTime,item.updateTime)//项目进展
- // 后台时间加一天 显示减一天 处理条形图时间左闭右开
- this.tasks.data[index].end_date = this.moment(new Date(item.endTime).valueOf() + 1000*60*60*24).format("YYYY-MM-DD");//结束时间
- // this.tasks.data[index].end_date = item.endTime;//结束时间
- this.tasks.data[index].priority = item.priority ? item.priority : '';//任务优先级
- this.tasks.data[index].projectClass = item.type ? item.type : '';//类型 0项目任务 1 普通任务
-
- this.tasks.data[index].taskProgress = item.taskStatus.toString();//任务状态
- this.tasks.data[index].description = item.describe ? item.describe : '';//描述
- this.tasks.data[index].color = item.stateDictionary.color ? item.stateDictionary.color : '';//颜色
- if (item.taskList && item.taskList.length != 0) {
- this.tasks.data[index].render = "split";//显示在单行
- this.tasks.data[index].open = true;//展开
- item.taskList.forEach((_item) => {
- pushArr.push(
- {
- id: _item.tid,
- text: _item.title ? _item.title : '空标题',
- start_date: _item.startTime,
- end_date: _item.endTime,
- head_id: _item.headId,
- head: _item.head,
- priority: _item.priority,
- projectClass: _item.type,
- taskProgress: _item.taskStatus.toString(),
- description: _item.describe,
- parent: _item.mainTaskId,
- }
- );
- })
- }
- });
- this.tasks.data = this.tasks.data.concat(pushArr)
-
- this.$nextTick(() => {
- gantt.parse(this.tasks);
- gantt.render();
- gantt.refreshData();
- })
-
- })
- },
-
- // 项目新增 修改tid 删除tid
- dealProject(type, data) {
- let param = {};
- if (type != 'add') {
- param.tid = data.id;
- param.title = data.text;
- param.startTime = this.moment(data.start_date).format("YYYY-MM-DD");
- param.endTime = this.moment(data.end_date).format("YYYY-MM-DD");
-
- param.describe = data.description;
- param.priority = data.priority;
-
- param.head = data.head_id;
- param.taskStatus = data.taskProgress;
- param.projectId = this.$store.state.project_data.id;
- } else {
-
- param.title = data.text;
- param.startTime = this.moment(data.start_date).format("YYYY-MM-DD");
- param.endTime = this.moment(data.end_date).format("YYYY-MM-DD");
-
- param.describe = data.description;
- param.priority = data.priority;
-
- param.head = data.head_id;
- param.taskStatus = data.taskProgress;
- param.projectId = this.$store.state.project_data.id;
- }
- let formdata=new FormData();
- for(let i in param){
- formdata.append(i,param[i])
- }
- switch (type) {
- case "add"://新增
- this.axios.put(this.urls.addTask, formdata).then(res => {
-
- res.data.code == 200 && this.$message.success("新增成功!")
- res.data.code != 200 && this.$message.error("新增失败!")
- }).catch(err => {
- this.$message.error("请求失败!")
- })
- break;
- case "edit":
- this.axios.put(this.urls.editTask, formdata).then(res => {
- res.data.code == 200 && this.$message.success("修改成功!")
- res.data.code != 200 && this.$message.error("修改失败!")
- }).catch(err => {
- this.$message.error("请求失败!")
- })
- break;
- case "delete":
- this.axios.delete(this.urls.deleteTask, formdata).then(res => {
- res.data.code == 200 && this.$message.success("删除成功!")
- res.data.code != 200 && this.$message.error("删除失败!")
- }).catch(err => {
- this.$message.error("请求失败!")
- })
- break;
-
- }
- },
- selecthead(val){
-
- this.searchHead=val;//id
- },
- // 搜索判断数据
- hasSubstr(parentId,type){
- let task = gantt.getTask(parentId);
- if(type=='tilte'){
- if(task.text.toLowerCase().indexOf(this.searchTitle) !== -1)
- return true;
- }
- // }
- },
- //点击按钮搜索
- searchDataClick(){
-
- if(this.searchTitle ){
- this.ganttEvent.onBeforeTaskDisplay=gantt.attachEvent("onBeforeTaskDisplay", (id, task)=>{
- if (this.hasSubstr(id,'tilte') ){ return true;}
- return false;
- });
- gantt.refreshData()
- gantt.render()
- }else{
- this.ganttEvent.onBeforeTaskDisplay=gantt.attachEvent("onBeforeTaskDisplay", (id, task)=>{
- return true
- })
- gantt.refreshData()
- gantt.render()
- }
- },
- // 提交弹框
- handleOk() {
-
- if (this.modalTitle === 1) {
- this.editForm.validateFields((err, values) => {
- if (!err) {
- Array.isArray(values.participants) && (values.participants = values.participants.join());
- values = util.transformFields(values);
- let formdata = new FormData();
- for (let key in values) {
- formdata.append(key, values[key] ? values[key] : '');
- }
- this.axios.put(this.urls.addTask, formdata).then((res) => {
- if (res.data.code === 200) {
- this.visible = false;
- let msg = res.data.message
- this.$message.success(msg)
- this.editForm.resetFields()
- this.onQuery();
- }
- })
- }
- })
- }
- },
- },
-
- destroyed() {
- // 销毁gantt事件
- for (let i in this.ganttEvent) {
- gantt.detachEvent(this.ganttEvent[i])
- }
- gantt.ext.tooltips.tooltip.hide();
- }
- }
- </script>
- <style scoped lang="less">
- @import url(./gantt.css);
- .ant-layout {
- background: #f8f9f9;
- }
-
- .ant-layout-header {
- background: #fdffff;
- color: rgb(29, 28, 28);
- border: 1px solid #dee0e0;
- }
-
- .header {
- // position: fixed;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
-
- .content {
- background: #fdffff;
- height: 99vh;
- }
-
- // 中间
- .centerContent {
- position: relative;
- background: #fdffff;
- width: 100%;
- overflow-y: auto;
- display: flex;
- justify-content: space-between;
- .selectDate {
- width: 100px;
- position: fixed;
- top: 18%;
- right: 9%;
- z-index: 99;
- display: flex;
- justify-content: space-between;
- }
- }
- </style>
- 复制代码

自定义修改gantt样式文件
- .weekend {
- background: #fafafa !important;
- }
- .weekday{
- background: #fff;
- }
- .gantt_resource_task .gantt_task_content {
- color: inherit;
- }
-
- .gantt_resource_task .gantt_task_progress {
- background-color: rgba(33, 33, 33, 0.3);
- }
- .gantt_tree_content{
- color: #808080;
- }
- .gantt_cell:nth-child(1) .gantt_tree_content {
- border-radius: 16px;
- width: 100%;
- height: 80%;
- margin: 5% 0;
- line-height: 230%;
- }
- /* 今日线 */
- .gantt_marker.today{
- background: #ffb121;
- }
- .gantt_cell,.gantt_grid_head_cell,.gantt_grid_data,.gantt_data_area,.gantt_scale_cell{
- background-color:#fff ;
- }
- /* 滑块 */
- .gantt_task_content{
- color: #fff;
- font-size: 13px;
- font-weight: bold;
- outline: none;
- }
- /* 右边单元格 */
- .gantt_task_line,.gantt_task_inline_color{
- border-radius: 10px;
- box-sizing: border-box;
- border-color: #fff !important;
- }
- .gantt_task_scale .gantt_scale_line{
- /* border-bottom: 1px solid #e6ebf2; */
- }
- .gantt_row, .gantt_task_row{
- /* border-bottom: none; */
- }
- /* 覆盖进度条 */
- .gantt_task_line.gantt_task_inline_color .gantt_task_progress{
- opacity: none;
- /* background: repeating-linear-gradient(70deg, #666 0px, #666 10px, #fff 0px,#fff 20px); */
- /* animation: ani 1.5s ease-in-out 6; */
- }
- @keyframes ani {
- 0%{
- background: repeating-linear-gradient(70deg, #666 0px, #666 10px, #fff 0px,#fff 20px);
- }
- 100%{
- background: repeating-linear-gradient(70deg, #fff 0px, #fff 10px, #666 0px,#666 20px);
- }
- }
- .taskProgress{
- margin: 0 auto;
- margin-top: 5px;
- height: 24px;
- width: 65px;
- font-size: 12px;
- line-height: 24px;
- font-weight: bold;
- color: #f7fbfe;
- border-radius: 20px;
- }
- .color_bg_1{
- background-color:#60a3bc ;
- }
- .color_bg_2{
- background-color:#079992 ;
- }
- .color_bg_3{
- background-color:#78e08f ;
- }
- .color_bg_4{
- background-color:#e55039 ;
- }
- .color_bg_5{
- background-color:#f6b93b ;
- }
- .gantt_task_row .gantt_task_cell,.weekday{
- outline: none;
- }
- .gantt_grid_scale{
- background-color: #f7fbfe !important;
- }
- .gantt_task_row .gantt_selected .gantt_task_cell{
- background-color: none;
- border-right-color:none;
- }
- .gantt_grid_scale .gantt_grid_head_cell{
- font-weight: bold;
- font-size: 14px;
- border: none;
- color:#506270;
- }
- /* 滑动栏 */
- /* 项目icon标 */
- .gantt_tree_icon{
- width: 14px;
- margin-right: 2px;
- margin-left: -8px;
- }
- .gantt_tree_icon.gantt_file {
- /* 文件icon */
- background-image: url(../../assets/img/file.png);
- }
-
- .gantt_tree_icon.gantt_folder_open{
- /* 文件夹icon */
- background-image: none;
- }
-
- .gantt_tree_icon.gantt_open{
- /* 加号 */
- background-image: url(../../assets//img/project.png);
- }
-
- .gantt_tree_icon.gantt_close{
- /* 减号 */
- background-image: none;
- }
-
- .userIcon{
- display: inline-block;
- width: 25px;
- height: 25px;
- margin-right: 5px;
- text-align: center;
- line-height: 25px;
- color: #fafafa;
- border-radius: 50%;
- }
- #search{
- margin-left: 10px;
- outline: none;
- border: none;
- font-size: 12px;
- color: #666666;
- }
- /*定义滚动条宽高及背景,宽高分别对应横竖滚动条的尺寸*/
- *::-webkit-scrollbar {
- width: 10px;
- height: 10px;
- background-color: rgba(255, 255, 255, 0);
- }
-
- /*定义滚动条的轨道,内阴影及圆角*/
- *::-webkit-scrollbar-track {
- border-radius: 10px;
- background-color: rgba(230, 230, 230, 0.05);
- }
-
- *:hover::-webkit-scrollbar-track {
- background-color: rgba(230, 230, 230, 0.5);
- }
-
- /*定义滑块,内阴影及圆角*/
-
- *::-webkit-scrollbar-thumb {
- height: 20px;
- border-radius: 10px;
- -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
- background-color: rgba(216, 216, 216, 0.4);
- transition: background-color 1s;
- }
-
- *:hover::-webkit-scrollbar-thumb {
- background-color: rgba(216, 216, 216, 1);
- }
-
- *::-webkit-scrollbar-thumb:hover {
- background-color: rgba(190, 190, 190, 1);
- }
-
- *::-webkit-scrollbar-thumb:active {
- background-color: rgba(160, 160, 160, 1);
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。