Vue項(xiàng)目的甘特圖組件之dhtmlx-gantt使用教程和實(shí)現(xiàn)效果展示(推薦)
公司的甘特圖需求,研究了幾個(gè)組件后,選擇使用 dhtmlx-gantt 進(jìn)行實(shí)現(xiàn),dhtmlx-gantt使用其實(shí)是偏簡單的,文檔雖然是英文,但配合翻譯也是可以看懂的,下面將公司需求的代碼實(shí)現(xiàn)粘貼出來,并簡單介紹一下使用方法,希望對你有幫助。
看一下目前實(shí)現(xiàn)的效果:
需求是不需要bar連線的,所以將bar連線注釋掉了,連線也是可以有的
組件官網(wǎng)地址: https://dhtmlx.com/
2024-11-13更新:
樣式不一致:
有朋友私信問我表格樣式不一樣,在第一項(xiàng)前面無法出現(xiàn)圖標(biāo),我看了一下發(fā)現(xiàn)是組件版本更新的問題,官方在新版內(nèi)取消了默認(rèn)的圖標(biāo),如果喜歡上圖的樣式,就安裝 dhtmlx-gantt 的 8 版本,如果 不需要圖標(biāo)就安裝目前最新的 9 版本。
沒有細(xì)看,我將組件更新后,功能都是好用的,新版用法應(yīng)該差不多,可能新增了一些api,有時(shí)間后我會去更新。目前發(fā)現(xiàn)的區(qū)別是:新版在樹節(jié)點(diǎn)前取消了默認(rèn)圖標(biāo)、tooltip新版為黑色背景,8版本為白色背景
下面正式進(jìn)入教程:
一、首先 npm 安裝插件
npm i dhtmlx-gantt
二、創(chuàng)建一個(gè)vue組件
我這里命名為gantt.vue ,放在項(xiàng)目根目錄的 /components 目錄下
gantt.vue文件:
<template> <div> <div ref="gantt"/> </div> </template> <script> import gantt from 'dhtmlx-gantt'; // 引入包 import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'; // 引入自帶的css文件 export default { data() { return { tasks: { data: [ { id: 1, text: 'DFB24019', progress: 0.8, //完成度 start_date: '2021-10-16', //開始時(shí)間 日月年 end_date: '2021-10-15', projectStatus: '進(jìn)行中', open: true, //默認(rèn)打開= number: '', //顯示字段 person: '韓鴻風(fēng)', post: 'BA', department: '數(shù)字化一部', task: '0/20' }, { // toolTipsTxt: '任務(wù)#101-001', id: 21, //任務(wù)id text: '任務(wù)1的撒的防守打法士大夫', //任務(wù)名稱 start_date: '2021-10-16', //開始時(shí)間 日月年 end_date: '2021-12-26', parent: 1, //父級id progress: 1, //完成度 open: true, //默認(rèn)打開 status: '已完成', }, { // toolTipsTxt: '任務(wù)#101-001', id: 22, //任務(wù)id text: '第二個(gè)逾期階段', //任務(wù)名稱 start_date: '2021-12-16', //開始時(shí)間 日月年 end_date: '2022-01-26', parent: 1, //父級id progress: 1, //完成度 open: true, //默認(rèn)打開 status: '逾期' }, { // toolTipsTxt: '任務(wù)#101-001', id: 23, //任務(wù)id text: '第三個(gè)進(jìn)行中階段', //任務(wù)名稱 start_date: '2022-01-20', //開始時(shí)間 日月年 end_date: '2022-03-03', parent: 1, //父級id progress: 0.7, //完成度 open: true, //默認(rèn)打開 status: '進(jìn)行中' }, { id: 2, text: 'DFB45113', progress: 0.7, //完成度 start_date: '2021-10-16', //開始時(shí)間 日月年 projectStatus: '已完成', end_date: '2021-10-15', open: true, //默認(rèn)打開 number: '哈哈哈' //顯示字段 }, { // toolTipsTxt: '任務(wù)#101-001', id: 11, //任務(wù)id text: '項(xiàng)目啟動階段', //任務(wù)名稱 start_date: '2022-04-06', //開始時(shí)間 日月年 end_date: '2022-06-06', parent: 2, //父級id progress: 1, //完成度 open: true, //默認(rèn)打開 status: '已完成' }, { // toolTipsTxt: '任務(wù)#101-001', id: 12, //任務(wù)id text: '設(shè)計(jì)階段', //任務(wù)名稱 start_date: '2022-04-20', //開始時(shí)間 日月年 end_date: '2022-06-26', parent: 2, //父級id progress: 0.9, //完成度 open: true, //默認(rèn)打開 status: '進(jìn)行中' }, { // toolTipsTxt: '任務(wù)#101-001', id: 13, //任務(wù)id text: '采購階段', //任務(wù)名稱 start_date: '2022-05-14', //開始時(shí)間 日月年 end_date: '2022-07-26', parent: 2, //父級id progress: 1, //完成度 open: true, //默認(rèn)打開 status: '未開始' } ], // 任務(wù)之間連接線,目前注釋掉了,需要的話打開 // links: [ // { id: '10', source: '11', target: '12', type: '1' }, // { id: '11', source: '11', target: '13', type: '1' }, // { id: '12', source: '11', target: '14', type: '1' }, // { id: '13', source: '11', target: '15', type: '1' }, // { id: '14', source: '23', target: '16', type: '0' }, // { id: '15', source: '13', target: '17', type: '1' }, // { id: '16', source: '17', target: '18', type: '0' }, // { id: '17', source: '18', target: '19', type: '0' }, // { id: '18', source: '19', target: '20', type: '0' }, // { id: '19', source: '15', target: '21', type: '2' }, // { id: '20', source: '15', target: '22', type: '2' }, // { id: '21', source: '15', target: '23', type: '0' } // ] }, }; }, mounted() { this.init(); }, methods: { init() { // 設(shè)置時(shí)間識別格式 gantt.config.xml_date = "%Y-%m-%d" // //表格列設(shè)置 gantt.config.columns = [ { name: 'person', label: '項(xiàng)目成員', width: '100', align: 'center' } ]; gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y 年 %F' }, { unit: 'day', step: 1, date: '%d' }]; // 清空舊數(shù)據(jù) gantt.clearAll(); // 銷毀gantt實(shí)例 按需開啟 // gantt.destructor() // 初始化 gantt.init(this.$refs.gantt); // 數(shù)據(jù)解析 gantt.parse(this.tasks); }, } </script>
三、業(yè)務(wù)頁面內(nèi) 引用自定義組件:
<template> <!-- 使用甘特圖組件 --> <div style="padding: 10px;background-color: #fff;"> <gantt></gantt> </div> </template> <script> import gantt from '@/components/gantt.vue'; components: { gantt }, </script>
如果你的頁面能展示出來基本樣式,那么就成功啦,咱們繼續(xù)下一步
下面講一下 dhtmlx-gantt 的一些配置項(xiàng),也可以說是我用到的配置項(xiàng),更多的就要參考官方文檔了
四、dhtmlx-gantt 基本配置項(xiàng)
(注意,都要放在組件的 init方法中)
格式化表頭日期展示:
// 格式化日期 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: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'] };
甘特圖的尺寸自適應(yīng)
指盡量不出現(xiàn)滾動條展示全部
gantt.config.autosize = false;
只讀模式
為false時(shí)支持編輯
gantt.config.readonly = true;
是否顯示左側(cè)表格
gantt.config.show_grid = true;
設(shè)置表頭高度
gantt.config.scale_height = 50;
設(shè)置bar的高度
gantt.config.bar_height = 26;
設(shè)置行的高度
gantt.config.row_height = 32;
設(shè)置時(shí)間識別格式
很重要,必須和你數(shù)據(jù)的格式一樣
gantt.config.xml_date = "%Y-%m-%d %H:%i"
表格列設(shè)置
(配置項(xiàng)不用細(xì)說了吧,template 可以自定義列模板)
gantt.config.columns = [ { name: 'text', label: '項(xiàng)目名稱', tree: true, width: '200', align: 'left', template: (task)=>{ if(task.parent) { return task.text } else { return `<div style="font-weight: 700">${task.text}</div>` } }}, { name: 'person', label: '項(xiàng)目成員', width: '100', align: 'center' }, // { name: 'post', label: '崗位名稱', width: '100', align: 'center' }, // { name: 'department', label: '部門名稱', width: '100', align: 'center' }, { name: 'task', label: '項(xiàng)目任務(wù)', width: '100', align: 'center' }, // { name: 'number', label: '工單號', tree: false, width: '120', align: 'center', }, // { // name: 'duration', // label: '工期', // align: 'center', // template: function(obj) { // return obj.duration + '天'; // } // } // {name:"start_date", label:"開始時(shí)間", align: "center" }, // {name:"end_date", label:"結(jié)束時(shí)間", align: "center" }, ];
為每個(gè)bar增加class
(希望不同的bar展示不同的顏色)
gantt.templates.task_class = function(start, end, item) { switch (item.status) { case '400': // 已完成 return 'gantt_success'; case '100': // 未開始 return 'gantt_begined'; case '200': // 進(jìn)行中 return 'gantt_primary'; case '300': // 暫停 return 'gantt_warning'; default: // 已終止 500 return 'gantt_info'; } };
然后在css內(nèi)定義樣式就好啦
<style lang="less" scoped> /deep/ .gantt_success .gantt_task_progress { background: #13C400 !important; border: none !important; } /deep/ .gantt_primary .gantt_task_progress { background: #3A84FF!important; border: none !important; } /deep/ .gantt_begined .gantt_task_progress { background: #9a9a9a !important; border: none !important; } /deep/ .gantt_info .gantt_task_progress { background: #FE0000 !important; border: none !important; } /deep/ .gantt_warning .gantt_task_progress { background: #FF7700 !important; border: none !important; } </style>
自動延長時(shí)間刻度
gantt.config.fit_tasks = true;
允許拖放
gantt.config.drag_project = true;
定義x軸時(shí)間維度
做視圖切換
// 年 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }]; // 月 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }, { unit: 'month', step: 1, date: '%F' }]; // 日 格式 gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y 年 %F' }, { unit: 'day', step: 1, date: '%d' }];
自動調(diào)整坐標(biāo)軸
當(dāng)task的長度改變時(shí),自動調(diào)整圖表坐標(biāo)軸區(qū)間用于適配task的長度
gantt.config.fit_tasks = true;
啟用 tooltip 功能
gantt.plugins({ tooltip: true // 啟用 tooltip 插件 }); gantt.templates.tooltip_text = (start, end, task) => { };
性能提升
// 僅僅渲染在屏幕可見的那部分時(shí)間軸。在處理時(shí)間軸非常長的時(shí)候,可以提升性能 gantt.config.smart_scales = true // 按需渲染, 僅僅渲染在屏幕可見的那部分任務(wù)和依賴線。這個(gè)在顯示大量的任務(wù)時(shí),性能比較高。 gantt.config.smart_rendering = true
增加事件
事件很多,具體看官方文檔,我這里加了雙擊事件
// 給每行增加雙擊事件 ,親測事件會重復(fù)注冊,用這個(gè)方法攔截一下 if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick); // 雙擊bar任務(wù)事件(單擊會有問題,點(diǎn)擊展開時(shí)也會觸發(fā)) this.onTaskDblClick = gantt.attachEvent("onTaskDblClick", (id, e) => { this.$emit('rowDbClick',id) return true; }, { id: 'onTaskDblClick' })
五、完整代碼
ganttPerson.vue
<template> <div> <div ref="gantt" :style="'height:' + (tabheight - 80) + 'px'" /> </div> </template> <script> import gantt from 'dhtmlx-gantt'; import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'; // import { JeecgListMixin } from '@/mixins/JeecgListMixin' // import { getAction, putAction } from '@/api/manage' export default { name: 'ganttPerson', props: ['ganttData', 'dateType'], watch: { ganttData: { handler(val) { this.tasks = { data: val } this.init(); }, deep: true } }, mounted() { let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; this.tabheight = h - 170; if (this.height) { this.tabheight = this.height; } }, // mixins: [JeecgListMixin], data() { return { // 注冊事件攔截 onTaskDblClick: null, // 甘特圖配置 tasks: { data: [ // 把父節(jié)點(diǎn)的開始結(jié)束設(shè)置為同一天,就可以實(shí)現(xiàn)隱藏父節(jié)點(diǎn)的bar // # 字段解釋 // id: 數(shù)據(jù)id 必須是唯一值,父子也不能重復(fù) // text: 會顯示在bar上的字段,如不顯示就設(shè)為 '' // progress: 完成度, 0 - 1 // start_date: 開始的日期,格式在js里設(shè)置, // end_date: 結(jié)束的日期 要時(shí)分秒! 只給日期會視為日期的 00:00:00 要特殊處理一下!! // open: 如果是父節(jié)點(diǎn),是否默認(rèn)展開 // parent: 子節(jié)點(diǎn)必須有,設(shè)置為父節(jié)點(diǎn)的id,會自動處理,數(shù)據(jù)順序無所謂 // #================================================================= ] // #字段解釋 // 格式 id:數(shù)據(jù)id // source:開始鏈接的項(xiàng)目id ----為tasks.data中數(shù)據(jù)的id // target:要鏈接項(xiàng)目的id ----為tasks.data中數(shù)據(jù)的id // type: 0--進(jìn)行-開始 `尾部鏈接頭部` // 1--開始-開始 `頭部鏈接頭部` // 2--進(jìn)行-進(jìn)行 `尾部鏈接尾部` // 3--開始-進(jìn)行 `頭部鏈接尾部` // 任務(wù)之間連接線,目前注釋掉了,需要的話打開 // links: [ // { id: '10', source: '11', target: '12', type: '1' }, // { id: '11', source: '11', target: '13', type: '1' }, // { id: '12', source: '11', target: '14', type: '1' }, // { id: '13', source: '11', target: '15', type: '1' }, // { id: '14', source: '23', target: '16', type: '0' }, // { id: '15', source: '13', target: '17', type: '1' }, // { id: '16', source: '17', target: '18', type: '0' }, // { id: '17', source: '18', target: '19', type: '0' }, // { id: '18', source: '19', target: '20', type: '0' }, // { id: '19', source: '15', target: '21', type: '2' }, // { id: '20', source: '15', target: '22', type: '2' }, // { id: '21', source: '15', target: '23', type: '0' } // ] }, url: { // list: "/projectManage/projectPlan/queryProjectPlanGTT", // delete: "/projectManage/projectModule/delete", // deleteBatch: "/projectManage/projectModule/deleteBatch", // exportXlsUrl: "/projectManage/projectModule/exportXls", // importExcelUrl: "/projectManage/projectModule/importExcel", // budgetExportXlsUrl: "/projectManage/projectModule/budgetExportXls", // budgetImportUrl: "/projectManage/projectModule/budgetImportExcel", }, tabheight: 0 }; }, methods: { // 初始化 init() { gantt.i18n.setLocale('cn'); // 漢化 - 默認(rèn)是英文 // 格式化日期 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: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'] }; gantt.locale.labels = { dhx_cal_today_button: '今天', day_tab: '日', week_tab: '周', month_tab: '月', new_event: '新建日程', icon_save: '保存', icon_cancel: '關(guān)閉', icon_details: '詳細(xì)', icon_edit: '編輯', icon_delete: '刪除', confirm_closing: '請確認(rèn)是否撤銷修改!', //Your changes will be lost, are your sure? confirm_deleting: '是否刪除計(jì)劃?', section_description: '描述:', section_time: '時(shí)間范圍:', section_type: '類型:', section_text: '計(jì)劃名稱:', section_test: '測試:', section_projectClass: '項(xiàng)目類型:', taskProjectType_0: '項(xiàng)目任務(wù)', taskProjectType_1: '普通任務(wù)', section_head: '負(fù)責(zé)人:', section_priority: '優(yōu)先級:', taskProgress: '任務(wù)狀態(tài)', taskProgress_0: '未開始', taskProgress_1: '進(jìn)行中', taskProgress_2: '已完成', taskProgress_3: '已延期', taskProgress_4: '擱置中', section_template: 'Details', /* grid columns */ column_text: '計(jì)劃名稱', column_start_date: '開始時(shí)間', column_duration: '持續(xù)時(shí)間', column_add: '', column_priority: '難度', /* link confirmation */ link: '關(guān)聯(lián)', confirm_link_deleting: '將被刪除', message_ok: '確定', message_cancel: '取消', link_start: ' (開始)', link_end: ' (結(jié)束)', type_task: '任務(wù)', type_project: '項(xiàng)目', type_milestone: '里程碑', minutes: '分鐘', hours: '小時(shí)', days: '天', weeks: '周', months: '月', years: '年' }; //自適應(yīng)甘特圖的尺寸大小, 使得在不出現(xiàn)滾動條的情況下, 顯示全部任務(wù) gantt.config.autosize = false; //只讀模式 gantt.config.readonly = true; //是否顯示左側(cè)樹表格 gantt.config.show_grid = true; // 設(shè)置表頭高度 gantt.config.scale_height = 50; // 設(shè)置bar的高度 gantt.config.bar_height = 26; // 設(shè)置行的高度 gantt.config.row_height = 32; // 設(shè)置時(shí)間識別格式 gantt.config.xml_date = "%Y-%m-%d %H:%i" // //表格列設(shè)置 gantt.config.columns = [ { name: 'text', label: '項(xiàng)目名稱', tree: true, width: '200', align: 'left', template: (task)=>{ if(task.parent) { return task.text } else { return `<div style="font-weight: 700">${task.text}</div>` } }}, { name: 'person', label: '項(xiàng)目成員', width: '100', align: 'center' }, // { name: 'post', label: '崗位名稱', width: '100', align: 'center' }, // { name: 'department', label: '部門名稱', width: '100', align: 'center' }, { name: 'task', label: '項(xiàng)目任務(wù)', width: '100', align: 'center' }, // { name: 'number', label: '工單號', tree: false, width: '120', align: 'center', }, // { // name: 'duration', // label: '工期', // align: 'center', // template: function(obj) { // return obj.duration + '天'; // } // } // {name:"start_date", label:"開始時(shí)間", align: "center" }, // {name:"end_date", label:"結(jié)束時(shí)間", align: "center" }, ]; // 為每個(gè)bar增加class gantt.templates.task_class = function(start, end, item) { switch (item.status) { case '400': // 已完成 return 'gantt_success'; case '100': // 未開始 return 'gantt_begined'; case '200': // 進(jìn)行中 return 'gantt_primary'; case '300': // 暫停 return 'gantt_warning'; default: // 已終止 500 return 'gantt_info'; } }; // 自動延長時(shí)間刻度 gantt.config.fit_tasks = true; // 允許拖放 gantt.config.drag_project = true; // 定義時(shí)間格式 if(this.dateType === 'year') { // 年 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }]; } else if(this.dateType === 'month') { // 月 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }, { unit: 'month', step: 1, date: '%F' }]; } else { // 日 格式 gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y 年 %F' }, { unit: 'day', step: 1, date: '%d' }]; } // //當(dāng)task的長度改變時(shí),自動調(diào)整圖表坐標(biāo)軸區(qū)間用于適配task的長度 gantt.config.fit_tasks = true; // 添加彈窗屬性 gantt.config.lightbox.sections = [ { name: 'description', height: 70, map_to: 'text', type: 'textarea', focus: true }, { name: 'type', type: 'typeselect', map_to: 'type' }, { name: 'time', type: 'duration', map_to: 'auto' } ]; // 給每行增加雙擊事件 ,親測事件會重復(fù)注冊,用這個(gè)方法攔截一下 if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick); // 雙擊bar任務(wù)事件(單擊會有問題,點(diǎn)擊展開時(shí)也會觸發(fā)) this.onTaskDblClick = gantt.attachEvent("onTaskDblClick", (id, e) => { this.$emit('rowDbClick',id) return true; }, { id: 'onTaskDblClick' }) // 清空舊數(shù)據(jù) gantt.clearAll(); // 銷毀gantt實(shí)例 按需開啟 // gantt.destructor() // 初始化 gantt.init(this.$refs.gantt); // 數(shù)據(jù)解析 gantt.parse(this.tasks); }, } }; </script> <style lang="less" scoped> /deep/ .gantt_row.gantt_row_project:hover { background: #e4e4e4 !important; } /deep/ .gantt_row.gantt_row_task:hover { background: #e4e4e4 !important; } /deep/ .gantt_selected { background: #ececec !important; } /deep/ .gantt_task_row.gantt_selected .gantt_task_cell { background: #ececec !important; border-right-color: #ebebeb !important; } /deep/ .gantt_grid_head_cell { background-color: #f7f7f7; font-weight: 700; font-size: 13px; color: #000000; } /deep/ .gantt_scale_cell { background-color: #f7f7f7; font-weight: 700; color: #000000 !important; border-bottom: 1px solid #ebebeb; } /deep/ .gantt_task_line { border: none !important; box-shadow: none !important; } /deep/ .gantt_task_progress_wrapper { border: none !important; background-color: #E1E1E1; border-radius: 8px; } /deep/ .gantt_task_content { } /deep/ .gantt_task_line { border: none; border-radius: 8px; background-color: transparent; } /deep/ .gantt_success .gantt_task_progress { background: #13C400 !important; border: none !important; } /deep/ .gantt_primary .gantt_task_progress { background: #3A84FF!important; border: none !important; } /deep/ .gantt_begined .gantt_task_progress { background: #9a9a9a !important; border: none !important; } /deep/ .gantt_info .gantt_task_progress { background: #FE0000 !important; border: none !important; } /deep/ .gantt_warning .gantt_task_progress { background: #FF7700 !important; border: none !important; } </style>
業(yè)務(wù)代碼:
<template> <div style="padding: 10px"> <more-search :searchdata="searchdata" :searchform="searchform" @submit="submit" :needChangeCard="true"></more-search> <!-- 甘特圖組件 --> <div style="padding: 10px;background-color: #fff;"> <gantt v-loading="tableLoading" :ganttData="ganttData" :dateType="searchform.DataType" @rowDbClick="ganttDbClick"></gantt> <div style="margin-top: 10px;text-align: right;"> <el-pagination @current-change="handleCurrentChange" @size-change="handleSizeChange" :current-page="page" background layout="total, sizes,prev, pager, next" :page-size="pageSize" :total="total" :page-sizes="[30, 50, 100, 200]"> </el-pagination> </div> </div> <!-- 詳情彈窗 --> <el-drawer title="任務(wù)詳情" :visible.sync="leftDialogVisible" direction="rtl"> <div style="padding: 20px;border-top: 1px #ccc solid;"> <div style="display: flex;flex-wrap: wrap;"> <div v-for="propItem in detailProp" :style="propItem.width > 200 ? 'width:100%' : 'width: 50%'" :key="propItem.prop" class="text item"> <div style="width: 110px;text-align: center;color:#94999F; border: 1px #EBEEF5 solid;flex-shrink: 0;padding: 5px;background-color: #FAFAFA;padding-left: 10px; display: flex;align-items: center;"> {{ propItem.label }} </div> <div style="border: 1px #EBEEF5 solid;padding: 5px 0 5px 10px;overflow: hidden;width: 100%;"> <div class="wordhidden"> <span v-if="propItem.formatter"> <div v-html="propItem.formatter(detailData[propItem.prop])"></div> </span> <span v-else>{{ detailData[propItem.prop] }}</span> </div> </div> </div> </div> </div> </el-drawer> </div> </template> <script> import moreSearch from '@/components/moreSearch.vue'; import gantt from '@/components/ganttPerson.vue'; import { GetList, GetUsers, GetAllDepts, GetAllPosts, GetProjectList } from '@/api/personUtilSituation.js'; export default { components: { moreSearch, gantt }, data() { return { tableLoading: false, page: 1, total: 0, pageSize: 30, leftDialogVisible: false, detailData: {}, detailProp: [ { label: '任務(wù)名稱', prop: 'text', width: 300 }, { label: '項(xiàng)目名稱', prop: 'project', width: 300 }, { label: '項(xiàng)目成員', prop: 'personName', width: 300 }, { label: '成員部門', prop: 'departmentName', width: 300 }, { label: '成員崗位', prop: 'postName', width: 300 }, { label: '開始日期', prop: 'start_date', width: 300, formatter: (val) => { return `<div>${ this.formatDate(val) }</div>` } }, { label: '結(jié)束日期', prop: 'end_date', width: 300, formatter: (val) => { return `<div>${ this.formatDate(val) }</div>` } }, { label: '任務(wù)狀態(tài)', prop: 'status', width: 300, formatter: (val) => { switch (val) { case '400': // 已完成 return `<div style="color: #13C400; font-weight: 700;">已完成</div>`; case '100': // 未開始 return `<div style="color: #9a9a9a; font-weight: 700;">未開始</div>`; case '200': // 進(jìn)行中 return `<div style="color: #3A84FF; font-weight: 700;">進(jìn)行中</div>`; case '300': // 暫停 return `<div style="color: #FF7700; font-weight: 700;">暫停</div>`; default: // 已終止 500 return `<div style="color: #FE0000; font-weight: 700;">已終止</div>`; } } } ], ganttData: [], searchdata: [ { label: '展示形式', type: 'select', key: 'DataType', shortcut: true, options: [ { label: '年', value: 'year' }, { label: '月', value: 'month' }, { label: '日', value: 'day' } ] // namei18n: 'CommercialQuotationNumber', }, { label: '日期范圍', type: 'datepicker', options: [], key: 'Date', shortcut: true }, { label: '項(xiàng)目名稱', type: 'select', key: 'ProjectId', shortcut: true, options: [] // namei18n: 'CommercialQuotationNumber', }, { label: '項(xiàng)目成員', type: 'select', key: 'PersonId', shortcut: false, options: [] // namei18n: 'CommercialQuotationNumber', }, { label: '崗位名稱', type: 'select', key: 'PostName', shortcut: false, options: [] // namei18n: 'CommercialQuotationNumber', }, { label: '部門名稱', type: 'select', key: 'DepartmentName', shortcut: false, options: [] // namei18n: 'CommercialQuotationNumber', } ], searchform: { DataType: 'day', Date: [], ProjectId: '', PersonId: '', PostName: '', DepartmentName: '' }, page: 1 }; }, mounted() { this.getSelectList(); this.getList(); }, methods: { ganttDbClick(id) { console.log('接收到', id); let clickRow = this.ganttData.filter((item) => { return item.id === id; }); console.log('點(diǎn)擊了', clickRow); this.detailData = clickRow[0]; if(!this.detailData.project) return this.leftDialogVisible = true; }, submit(val) { this.searchform = val; this.page = 1; this.getList(); }, getList() { this.tableLoading = true this.ganttData = []; let para = { Start: this.searchform.Date ? this.searchform.Date[0] : '', End: this.searchform.Date ? this.searchform.Date[1] : '', ProjectId: this.searchform.ProjectId, PersonId: this.searchform.PersonId, PostName: this.searchform.PostName, SkipCount: (this.page -1) * this.pageSize, MaxResultCount: this.pageSize }; GetList(para).then((res) => { this.total = res.response.totalCount; let data = res.response.items; let arr = []; data.forEach((item) => { // 父節(jié)點(diǎn) arr.push({ id: item.id, text: item.projectName, // 第一項(xiàng) 項(xiàng)目名稱 task: item.finishedCount + ' / ' + item.totalCount, // 項(xiàng)目任務(wù)數(shù)字 start_date: item.tasks[0].planStartDate + ' 00:00', end_date: item.tasks[0].planStartDate + ' 00:00', progress: 1, open: true, person: item.personName }); // 子節(jié)點(diǎn) if (item.tasks) { item.tasks.forEach((task) => { arr.push({ id: task.id, text: task.taskName, start_date: task.planStartDate + ' 00:00', end_date: task.planFinishDate + ' 23:59', progress: 1, parent: item.id, status: task.status, project: item.projectName, departmentName: item.departmentName, personName: item.personName, postName: item.postName }); }); } }); this.ganttData = arr; this.tableLoading = false }).catch(rej=>{ this.tableLoading = false }); }, handleCurrentChange(val) { this.page = val this.getList() }, handleSizeChange(val) { this.page = 1 this.pageSize = val this.getList() }, getSelectList() { GetUsers().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'PersonId') { item.options = res.response.map((item) => { return { value: item.id, label: item.name }; }); } }); }); GetAllDepts().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'DepartmentName') { item.options = res.response.map((item) => { return { value: item.id, label: item.name }; }); } }); }); GetAllPosts().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'PostName') { item.options = res.response.map((item) => { return { value: item.id, label: item.name }; }); } }); }); GetProjectList().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'ProjectId') { item.options = res.response.map((item) => { return { value: item.id, label: item.projectName }; }); } }); }); }, formatDate(date) { if (!date) return ''; const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); // const hours = String(date.getHours()).padStart(2, '0'); // const minutes = String(date.getMinutes()).padStart(2, '0'); // const seconds = String(date.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day}`; } } }; </script> <style scoped> .text { font-size: 13px; } .item { display: flex; } </style>
到此這篇關(guān)于Vue項(xiàng)目的甘特圖組件之dhtmlx-gantt使用教程和實(shí)現(xiàn)效果展示(推薦)的文章就介紹到這了,更多相關(guān)vue甘特圖dhtmlx-gantt使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue實(shí)現(xiàn)指令式動態(tài)追加小球動畫組件的步驟
這篇文章主要介紹了Vue實(shí)現(xiàn)指令式動態(tài)追加小球動畫組件的步驟,幫助大家更好的理解和實(shí)用vue,感興趣的朋友可以了解下2020-12-12vue實(shí)現(xiàn)pdf文件發(fā)送到郵箱功能的示例代碼
這篇文章主要介紹了vue實(shí)現(xiàn)pdf文件發(fā)送到郵箱功能,實(shí)現(xiàn)代碼包括對郵箱格式內(nèi)容是否為空的驗(yàn)證方法,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05vue@cli3項(xiàng)目模板怎么使用public目錄下的靜態(tài)文件
這篇文章主要介紹了vue@cli3項(xiàng)目模板怎么使用public目錄下的靜態(tài)文件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07