Vue項目的甘特圖組件之dhtmlx-gantt使用教程和實現(xiàn)效果展示(推薦)
公司的甘特圖需求,研究了幾個組件后,選擇使用 dhtmlx-gantt 進行實現(xiàn),dhtmlx-gantt使用其實是偏簡單的,文檔雖然是英文,但配合翻譯也是可以看懂的,下面將公司需求的代碼實現(xiàn)粘貼出來,并簡單介紹一下使用方法,希望對你有幫助。
看一下目前實現(xiàn)的效果:

需求是不需要bar連線的,所以將bar連線注釋掉了,連線也是可以有的
組件官網(wǎng)地址: https://dhtmlx.com/
2024-11-13更新:
樣式不一致:
有朋友私信問我表格樣式不一樣,在第一項前面無法出現(xiàn)圖標,我看了一下發(fā)現(xiàn)是組件版本更新的問題,官方在新版內取消了默認的圖標,如果喜歡上圖的樣式,就安裝 dhtmlx-gantt 的 8 版本,如果 不需要圖標就安裝目前最新的 9 版本。
沒有細看,我將組件更新后,功能都是好用的,新版用法應該差不多,可能新增了一些api,有時間后我會去更新。目前發(fā)現(xiàn)的區(qū)別是:新版在樹節(jié)點前取消了默認圖標、tooltip新版為黑色背景,8版本為白色背景
下面正式進入教程:
一、首先 npm 安裝插件
npm i dhtmlx-gantt
二、創(chuàng)建一個vue組件
我這里命名為gantt.vue ,放在項目根目錄的 /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', //開始時間 日月年
end_date: '2021-10-15',
projectStatus: '進行中',
open: true, //默認打開=
number: '', //顯示字段
person: '韓鴻風',
post: 'BA',
department: '數(shù)字化一部',
task: '0/20'
},
{
// toolTipsTxt: '任務#101-001',
id: 21, //任務id
text: '任務1的撒的防守打法士大夫', //任務名稱
start_date: '2021-10-16', //開始時間 日月年
end_date: '2021-12-26',
parent: 1, //父級id
progress: 1, //完成度
open: true, //默認打開
status: '已完成',
},
{
// toolTipsTxt: '任務#101-001',
id: 22, //任務id
text: '第二個逾期階段', //任務名稱
start_date: '2021-12-16', //開始時間 日月年
end_date: '2022-01-26',
parent: 1, //父級id
progress: 1, //完成度
open: true, //默認打開
status: '逾期'
},
{
// toolTipsTxt: '任務#101-001',
id: 23, //任務id
text: '第三個進行中階段', //任務名稱
start_date: '2022-01-20', //開始時間 日月年
end_date: '2022-03-03',
parent: 1, //父級id
progress: 0.7, //完成度
open: true, //默認打開
status: '進行中'
},
{
id: 2,
text: 'DFB45113',
progress: 0.7, //完成度
start_date: '2021-10-16', //開始時間 日月年
projectStatus: '已完成',
end_date: '2021-10-15',
open: true, //默認打開
number: '哈哈哈' //顯示字段
},
{
// toolTipsTxt: '任務#101-001',
id: 11, //任務id
text: '項目啟動階段', //任務名稱
start_date: '2022-04-06', //開始時間 日月年
end_date: '2022-06-06',
parent: 2, //父級id
progress: 1, //完成度
open: true, //默認打開
status: '已完成'
},
{
// toolTipsTxt: '任務#101-001',
id: 12, //任務id
text: '設計階段', //任務名稱
start_date: '2022-04-20', //開始時間 日月年
end_date: '2022-06-26',
parent: 2, //父級id
progress: 0.9, //完成度
open: true, //默認打開
status: '進行中'
},
{
// toolTipsTxt: '任務#101-001',
id: 13, //任務id
text: '采購階段', //任務名稱
start_date: '2022-05-14', //開始時間 日月年
end_date: '2022-07-26',
parent: 2, //父級id
progress: 1, //完成度
open: true, //默認打開
status: '未開始'
}
],
// 任務之間連接線,目前注釋掉了,需要的話打開
// 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() {
// 設置時間識別格式
gantt.config.xml_date = "%Y-%m-%d"
// //表格列設置
gantt.config.columns = [
{ name: 'person', label: '項目成員', 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實例 按需開啟
// gantt.destructor()
// 初始化
gantt.init(this.$refs.gantt);
// 數(shù)據(jù)解析
gantt.parse(this.tasks);
},
}
</script>三、業(yè)務頁面內 引用自定義組件:
<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 的一些配置項,也可以說是我用到的配置項,更多的就要參考官方文檔了
四、dhtmlx-gantt 基本配置項
(注意,都要放在組件的 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: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
};甘特圖的尺寸自適應
指盡量不出現(xiàn)滾動條展示全部
gantt.config.autosize = false;
只讀模式
為false時支持編輯
gantt.config.readonly = true;
是否顯示左側表格
gantt.config.show_grid = true;
設置表頭高度
gantt.config.scale_height = 50;
設置bar的高度
gantt.config.bar_height = 26;
設置行的高度
gantt.config.row_height = 32;
設置時間識別格式
很重要,必須和你數(shù)據(jù)的格式一樣
gantt.config.xml_date = "%Y-%m-%d %H:%i"
表格列設置
(配置項不用細說了吧,template 可以自定義列模板)
gantt.config.columns = [
{ name: 'text', label: '項目名稱', 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: '項目成員', width: '100', align: 'center' },
// { name: 'post', label: '崗位名稱', width: '100', align: 'center' },
// { name: 'department', label: '部門名稱', width: '100', align: 'center' },
{ name: 'task', label: '項目任務', 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:"開始時間", align: "center" },
// {name:"end_date", label:"結束時間", align: "center" },
];為每個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': // 進行中
return 'gantt_primary';
case '300': // 暫停
return 'gantt_warning';
default: // 已終止 500
return 'gantt_info';
}
};然后在css內定義樣式就好啦
<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>自動延長時間刻度
gantt.config.fit_tasks = true;
允許拖放
gantt.config.drag_project = true;
定義x軸時間維度
做視圖切換
// 年 格式
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' }];自動調整坐標軸
當task的長度改變時,自動調整圖表坐標軸區(qū)間用于適配task的長度
gantt.config.fit_tasks = true;
啟用 tooltip 功能
gantt.plugins({
tooltip: true // 啟用 tooltip 插件
});
gantt.templates.tooltip_text = (start, end, task) => {
};性能提升
// 僅僅渲染在屏幕可見的那部分時間軸。在處理時間軸非常長的時候,可以提升性能 gantt.config.smart_scales = true // 按需渲染, 僅僅渲染在屏幕可見的那部分任務和依賴線。這個在顯示大量的任務時,性能比較高。 gantt.config.smart_rendering = true
增加事件
事件很多,具體看官方文檔,我這里加了雙擊事件
// 給每行增加雙擊事件 ,親測事件會重復注冊,用這個方法攔截一下
if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick);
// 雙擊bar任務事件(單擊會有問題,點擊展開時也會觸發(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é)點的開始結束設置為同一天,就可以實現(xiàn)隱藏父節(jié)點的bar
// # 字段解釋
// id: 數(shù)據(jù)id 必須是唯一值,父子也不能重復
// text: 會顯示在bar上的字段,如不顯示就設為 ''
// progress: 完成度, 0 - 1
// start_date: 開始的日期,格式在js里設置,
// end_date: 結束的日期 要時分秒! 只給日期會視為日期的 00:00:00 要特殊處理一下!!
// open: 如果是父節(jié)點,是否默認展開
// parent: 子節(jié)點必須有,設置為父節(jié)點的id,會自動處理,數(shù)據(jù)順序無所謂
// #=================================================================
]
// #字段解釋
// 格式 id:數(shù)據(jù)id
// source:開始鏈接的項目id ----為tasks.data中數(shù)據(jù)的id
// target:要鏈接項目的id ----為tasks.data中數(shù)據(jù)的id
// type: 0--進行-開始 `尾部鏈接頭部`
// 1--開始-開始 `頭部鏈接頭部`
// 2--進行-進行 `尾部鏈接尾部`
// 3--開始-進行 `頭部鏈接尾部`
// 任務之間連接線,目前注釋掉了,需要的話打開
// 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'); // 漢化 - 默認是英文
// 格式化日期
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: '關閉',
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: '優(yōu)先級:',
taskProgress: '任務狀態(tài)',
taskProgress_0: '未開始',
taskProgress_1: '進行中',
taskProgress_2: '已完成',
taskProgress_3: '已延期',
taskProgress_4: '擱置中',
section_template: 'Details',
/* grid columns */
column_text: '計劃名稱',
column_start_date: '開始時間',
column_duration: '持續(xù)時間',
column_add: '',
column_priority: '難度',
/* link confirmation */
link: '關聯(lián)',
confirm_link_deleting: '將被刪除',
message_ok: '確定',
message_cancel: '取消',
link_start: ' (開始)',
link_end: ' (結束)',
type_task: '任務',
type_project: '項目',
type_milestone: '里程碑',
minutes: '分鐘',
hours: '小時',
days: '天',
weeks: '周',
months: '月',
years: '年'
};
//自適應甘特圖的尺寸大小, 使得在不出現(xiàn)滾動條的情況下, 顯示全部任務
gantt.config.autosize = false;
//只讀模式
gantt.config.readonly = true;
//是否顯示左側樹表格
gantt.config.show_grid = true;
// 設置表頭高度
gantt.config.scale_height = 50;
// 設置bar的高度
gantt.config.bar_height = 26;
// 設置行的高度
gantt.config.row_height = 32;
// 設置時間識別格式
gantt.config.xml_date = "%Y-%m-%d %H:%i"
// //表格列設置
gantt.config.columns = [
{ name: 'text', label: '項目名稱', 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: '項目成員', width: '100', align: 'center' },
// { name: 'post', label: '崗位名稱', width: '100', align: 'center' },
// { name: 'department', label: '部門名稱', width: '100', align: 'center' },
{ name: 'task', label: '項目任務', 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:"開始時間", align: "center" },
// {name:"end_date", label:"結束時間", align: "center" },
];
// 為每個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': // 進行中
return 'gantt_primary';
case '300': // 暫停
return 'gantt_warning';
default: // 已終止 500
return 'gantt_info';
}
};
// 自動延長時間刻度
gantt.config.fit_tasks = true;
// 允許拖放
gantt.config.drag_project = true;
// 定義時間格式
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' }];
}
// //當task的長度改變時,自動調整圖表坐標軸區(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' }
];
// 給每行增加雙擊事件 ,親測事件會重復注冊,用這個方法攔截一下
if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick);
// 雙擊bar任務事件(單擊會有問題,點擊展開時也會觸發(fā))
this.onTaskDblClick = gantt.attachEvent("onTaskDblClick", (id, e) => {
this.$emit('rowDbClick',id)
return true;
}, { id: 'onTaskDblClick' })
// 清空舊數(shù)據(jù)
gantt.clearAll();
// 銷毀gantt實例 按需開啟
// 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è)務代碼:
<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="任務詳情" :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: '任務名稱',
prop: 'text',
width: 300
},
{
label: '項目名稱',
prop: 'project',
width: 300
},
{
label: '項目成員',
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: '結束日期',
prop: 'end_date',
width: 300,
formatter: (val) => {
return `<div>${ this.formatDate(val) }</div>`
}
},
{
label: '任務狀態(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': // 進行中
return `<div style="color: #3A84FF; font-weight: 700;">進行中</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: '項目名稱',
type: 'select',
key: 'ProjectId',
shortcut: true,
options: []
// namei18n: 'CommercialQuotationNumber',
},
{
label: '項目成員',
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('點擊了', 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é)點
arr.push({
id: item.id,
text: item.projectName, // 第一項 項目名稱
task: item.finishedCount + ' / ' + item.totalCount, // 項目任務數(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é)點
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>到此這篇關于Vue項目的甘特圖組件之dhtmlx-gantt使用教程和實現(xiàn)效果展示(推薦)的文章就介紹到這了,更多相關vue甘特圖dhtmlx-gantt使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue網(wǎng)頁html轉換PDF(最低兼容ie10)的思路詳解
這篇文章主要介紹了Vue網(wǎng)頁html轉換PDF(最低兼容ie10)的思路詳解,實現(xiàn)此功能需要引入兩個插件,需要的朋友可以參考下2017-08-08
微信小程序實戰(zhàn)基于vue2實現(xiàn)瀑布流的代碼實例
瀑布流,又稱瀑布流式布局,是比較流行的一種網(wǎng)站頁面布局,視覺表現(xiàn)為參差不齊的多欄布局,隨著頁面滾動條向下滾動,這種布局還會不斷加載數(shù)據(jù)塊并附加至當前尾部,這篇文章主要介紹了微信小程序實戰(zhàn),基于vue2實現(xiàn)瀑布流,需要的朋友可以參考下2022-12-12
Vue實現(xiàn)獲取后端接口API代碼片段(已封裝Service方法名)
Vue實現(xiàn)獲取后端接口API代碼片段(已封裝Service方法名),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
一文詳解如何在Vue網(wǎng)站中實現(xiàn)多語言支持
在當今全球化的互聯(lián)網(wǎng)環(huán)境中,為網(wǎng)站提供多語言支持已成為提升用戶體驗和擴大受眾范圍的關鍵策略,本文為大家介紹了如何在Vue網(wǎng)站中實現(xiàn)多語種支持功能,有需要的可以了解下2025-03-03

