demo.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <template>
  2.  <div style="height: 100%; width: 100%">
  3. <div>
  4. <el-select v-model="timer" placeholder="请选择">
  5. <el-option
  6. v-for="item in options"
  7. :key="item.value"
  8. :label="item.label"
  9. :value="item.value">
  10. </el-option>
  11. </el-select>
  12. </div>
  13. <div class="rightGatt" style="min-height:calc(78vh - 50px - 5px );width: 100%;overflow: hidden;" ref="gantt"></div>
  14. </div>
  15. </template>
  16. <script>
  17. // 引入 组件库
  18. import '@/assets/js/dhtmlx.js';
  19. import "@/assets/css/dhtmlxgantt.css";
  20. import demoData from './ganttData.json'
  21. export default {
  22. name: 'gantt',
  23. // 接受父级组件 传递的数据并规范类型
  24. data() {
  25. return {
  26. moment: '',
  27. timer: 'day', //定时
  28. item: {}, //单行数据
  29. searchTitle: "", //搜索标题
  30. tasks: {
  31. data: [
  32. {
  33.    id: 1,//必填
  34.    text: "这是任务",//必填
  35.    type: "task",// 项目类型 task任务 project项目 milestone里程碑  
  36. userName:'张',//人名
  37.    start_date: "2023-3-15",
  38. end_date: "2023-3-30",
  39.    progress: 0.3,//项目任务滑块的进度
  40.    open: true,//是否展开显示
  41. taskProgress:'0',
  42. },
  43. {
  44.    id: 2,
  45.    text: "这是项目",
  46. type: "project",// 项目类型 task任务 project项目 milestone里程碑  
  47. userName:'李',//人名
  48.    start_date: "2023-1-15",
  49. end_date: "2023-1-20",
  50.    progress: 0,
  51. taskProgress:'1',
  52. },
  53. {
  54.    id: 3,
  55.    text: "这是里程碑",
  56. type: "milestone",// 项目类型 task任务 project项目 milestone里程碑  
  57. userName:'陈',//人名
  58.    start_date: "2023-2-10",
  59. end_date: "2023-2-15",
  60.    progress: 0,
  61. taskProgress:'2',
  62. },
  63. ], //数据
  64. links: [
  65. // {
  66. // id:1,//数据id
  67. //    source:1,
  68. //    target:2,
  69. //    type:0
  70. // },
  71. // {
  72. //    id:3,
  73. //    source:2,
  74. //    target:3,
  75. //    type:2
  76. // },
  77. ],
  78. // 格式 id:数据id  
  79. // source:开始链接的项目id  ----为tasks.data中数据的id
  80. //    target:要链接项目的id  ----为tasks.data中数据的id
  81. // type: 0--进行-开始  `尾部链接头部`  
  82. // 1--开始-开始 `头部链接头部`
  83. // 2--进行-进行 `尾部链接尾部`
  84. // 3--开始-进行 `头部链接尾部`
  85. },
  86. ganttEvent: { //销毁事件
  87. },
  88. options: [{
  89. value: 'day',
  90. label: '日'
  91. }, {
  92. value: 'week',
  93. label: '周'
  94. }, {
  95. value: 'month',
  96. label: '月'
  97. }, {
  98. value: 'year',
  99. label: '年'
  100. }],
  101. zoomConfig:{
  102. levels: [
  103. {
  104. name: 'day',
  105. scale_height: 60,
  106. scales: [{ unit: 'day', step: 1, format: '%d %M' }]
  107. },
  108. {
  109. name: 'week',
  110. scale_height: 60,
  111. scales: [
  112. {
  113. unit: 'week',
  114. step: 1,
  115. format: function (date) {
  116. let dateToStr = gantt.date.date_to_str('%m-%d')
  117. let endDate = gantt.date.add(date, -6, 'day')
  118. let weekNum = gantt.date.date_to_str('%W')(date) //第几周
  119. return dateToStr(endDate) + ' 至 ' + dateToStr(date)
  120. }
  121. },
  122. {
  123. unit: 'day',
  124. step: 1,
  125. format: '%d', // + "周%D"
  126. css: function (date) {
  127. if (date.getDay() == 0 || date.getDay() == 6) {
  128. return 'day-item weekend weekend-border-bottom'
  129. } else {
  130. return 'day-item'
  131. }
  132. }
  133. }
  134. ]
  135. },
  136. {
  137. name: 'month',
  138. scale_height: 60,
  139. min_column_width: 18,
  140. scales: [
  141. { unit: 'month', format: '%Y-%m' },
  142. {
  143. unit: 'day',
  144. step: 1,
  145. format: '%d',
  146. css: function (date) {
  147. if (date.getDay() == 0 || date.getDay() == 6) {
  148. return 'day-item weekend weekend-border-bottom'
  149. } else {
  150. return 'day-item'
  151. }
  152. }
  153. }
  154. ]
  155. },
  156. {
  157. name: 'quarter',
  158. height: 60,
  159. min_column_width: 110,
  160. scales: [
  161. {
  162. unit: 'quarter',
  163. step: 1,
  164. format: function (date) {
  165. let yearStr = new Date(date).getFullYear() + '年'
  166. let dateToStr = gantt.date.date_to_str('%M')
  167. let endDate = gantt.date.add(gantt.date.add(date, 3, 'month'), -1, 'day')
  168. return yearStr + dateToStr(date) + ' - ' + dateToStr(endDate)
  169. }
  170. },
  171. {
  172. unit: 'week',
  173. step: 1,
  174. format: function (date) {
  175. let dateToStr = gantt.date.date_to_str('%m-%d')
  176. let endDate = gantt.date.add(date, 6, 'day')
  177. let weekNum = gantt.date.date_to_str('%W')(date)
  178. return dateToStr(date) + ' 至 ' + dateToStr(endDate)
  179. }
  180. }
  181. ]
  182. },
  183. {
  184. name: 'year',
  185. scale_height: 50,
  186. min_column_width: 150,
  187. scales: [
  188. { unit: 'year', step: 1, format: '%Y年' },
  189. { unit: 'month', format: '%Y-%m' }
  190. ]
  191. }
  192. ]
  193. }
  194. }
  195. },
  196. watch:{
  197. timer(val){
  198. this.changeTime(val); //默认日格式
  199. },
  200. },
  201. mounted() {
  202. this.initGantt();
  203. // this.ganttChangeDateView("d"); //默认日格式
  204. },
  205. methods: {
  206. // 切换 年 季 月 周 日视图
  207. ganttChangeDateView(type) {
  208. switch (type) {
  209. case 'y':
  210. gantt.config.scale_unit = "year";
  211. gantt.config.step = 1;
  212. gantt.config.subscales = null;
  213. gantt.config.date_scale = "%Y年";
  214. gantt.templates.date_scale = null;
  215. break ;
  216. case 'm':
  217. gantt.config.scale_unit = "month";
  218. gantt.config.step = 1;
  219. gantt.config.date_scale = "%m月";
  220. gantt.templates.date_scale = null;
  221. break;
  222. case 'w':
  223. gantt.config.scale_unit = "week";
  224. gantt.config.step = 1;
  225. gantt.config.date_scale = "第%w周";
  226. gantt.templates.date_scale = null;
  227. break;
  228. case 'd':
  229. gantt.config.scale_unit = "day";
  230. gantt.config.step = 1;
  231. gantt.config.date_scale = "%m月%d日";
  232. gantt.templates.date_scale = null;
  233. gantt.config.subscales = null;
  234. break;
  235. }
  236. gantt.render();
  237. },
  238. // 是否全屏
  239. changeFull() {
  240. gantt.ext.fullscreen.toggle();
  241. },
  242. changeTime(val){
  243. gantt.ext.zoom.setLevel(val)
  244. },
  245. // 定位到今日线
  246. changeToday() {
  247. this.$nextTick(() => {
  248. let ganTT = document.getElementsByClassName('gantt_marker today')
  249. gantt.scrollTo(ganTT[0].offsetLeft - 300, null);
  250. })
  251. },
  252. initGantt() {
  253. gantt.config.branch_loading = true
  254. //日期格式化
  255. gantt.config.date_format = "%Y-%m-%d";
  256. // gantt.config.order_branch = true;
  257. // gantt.config.order_branch_free = true;
  258. //左侧是否自适应
  259. gantt.config.autofit = true;
  260. gantt.config.drag_links = true; //连线
  261. gantt.config.readonly = false; //只读
  262. // gantt.config.layout = { //拖拽布局
  263. // css: "gantt_container",
  264. // rows: [{
  265. // cols: [{
  266. // view: "grid",
  267. // id: "grid",
  268. // scrollX: "scrollHor",
  269. // scrollY: "scrollVer"
  270. // },
  271. // {
  272. // resizer: true,
  273. // width: 1
  274. // },
  275. // {
  276. // view: "timeline",
  277. // id: "timeline",
  278. // scrollX: "scrollHor",
  279. // scrollY: "scrollVer"
  280. // },
  281. // {
  282. // view: "scrollbar",
  283. // scroll: "y",
  284. // id: "scrollVer"
  285. // }
  286. // ]
  287. // },
  288. // {
  289. // view: "scrollbar",
  290. // scroll: "x",
  291. // id: "scrollHor",
  292. // height: 20
  293. // }
  294. // ]
  295. // };
  296. gantt.config.start_on_monday = true;
  297. gantt.config.work_time = true;
  298. gantt.config.fit_tasks = true; //自动调整图表坐标轴区间用于适配task的长度
  299. // 汉化
  300. gantt.locale = {
  301. date: {
  302. month_full: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
  303. month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
  304. day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
  305. day_short: ["日", "一", "二", "三", "四", "五", "六"]
  306. },
  307. labels: {
  308. dhx_cal_today_button: "今天",
  309. day_tab: "日",
  310. week_tab: "周",
  311. month_tab: "月",
  312. new_event: "新建日程",
  313. icon_save: "保存",
  314. icon_cancel: "关闭",
  315. icon_details: "详细",
  316. icon_edit: "编辑",
  317. icon_delete: "删除",
  318. confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?
  319. confirm_deleting: "是否删除计划?",
  320. section_description: "描述:",
  321. section_time: "时间范围:",
  322. section_type: "类型:",
  323. section_text: "计划名称:",
  324. section_test: "测试:",
  325. section_projectClass: "项目类型:",
  326. taskProjectType_0: "项目任务",
  327. taskProjectType_1: "普通任务",
  328. section_head: "负责人:",
  329. section_priority: "优先级:",
  330. taskProgress: "任务状态",
  331. taskProgress_0: "未开始",
  332. taskProgress_1: "进行中",
  333. taskProgress_2: "已完成",
  334. taskProgress_3: "已延期",
  335. taskProgress_4: "搁置中",
  336. section_template: "Details",
  337. column_text: "计划名称",
  338. column_start_date: "开始时间",
  339. column_duration: "持续时间",
  340. column_add: "",
  341. column_priority: "难度",
  342. link: "关联",
  343. confirm_link_deleting: "将被删除",
  344. message_ok: "确定",
  345. message_cancel: "取消",
  346. link_start: "(开始)",
  347. link_end: "(结束)",
  348. type_task: "任务",
  349. type_project: "项目",
  350. type_milestone: "里程碑",
  351. minutes: "分钟",
  352. hours: "小时",
  353. days: "天",
  354. weeks: "周",
  355. months: "月",
  356. years: "年"
  357. }
  358. };
  359. gantt.serverList("priority", [{
  360. key: 0,
  361. label: "最高"
  362. },
  363. {
  364. key: 1,
  365. label: "较高"
  366. },
  367. {
  368. key: 2,
  369. label: "普通"
  370. },
  371. {
  372. key: 3,
  373. label: "较低"
  374. },
  375. {
  376. key: 4,
  377. label: "最低"
  378. },
  379. ]);
  380. // 左侧显示列名
  381. gantt.config.columns = [{
  382. name: "text",
  383. min_width: 100,
  384. max_width: 200,
  385. label: "任务",
  386. align: "left",
  387. resize: true,
  388. tree: true,
  389. editor: {
  390. type: 'text',
  391. map_to: 'text'
  392. },
  393. },
  394. {
  395. name: "id",
  396. label: "",
  397. hide: true
  398. },
  399. {
  400. name: "start_date",
  401. label: "开始时间",
  402. width: 120,
  403. resize: true,
  404. align: "left"
  405. },
  406. {
  407. name: "userName",
  408. min_width: 100,
  409. height: 40,
  410. label: "负责人",
  411. resize: true,
  412. align: "left",
  413. template: (item) => {
  414. // if (this.ganttDealById(gantt.serverList('staff'), item.head_id)) {
  415. // 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)}`
  416. // }
  417. }
  418. },
  419. {
  420. name: "taskProgress",
  421. label: "任务状态",
  422. align: "center",
  423. min_width: 110,
  424. editor: {
  425. type: "select",
  426. map_to: "taskProgress",
  427. options: [{
  428. key: "0",
  429. label: gantt.locale.labels.taskProgress_0
  430. },
  431. {
  432. key: "1",
  433. label: gantt.locale.labels.taskProgress_1
  434. },
  435. {
  436. key: "2",
  437. label: gantt.locale.labels.taskProgress_2
  438. },
  439. {
  440. key: "3",
  441. label: gantt.locale.labels.taskProgress_3
  442. },
  443. {
  444. key: "4",
  445. label: gantt.locale.labels.taskProgress_4,
  446. }
  447. ]
  448. },
  449. template: (obj) => {
  450. let val = '';
  451. switch (obj.taskProgress) {
  452. case "0":
  453. val = `<div class='taskProgress color_bg_1'>未开始</div>`;
  454. break;
  455. case "1":
  456. val = `<div class='taskProgress color_bg_2'>进行中</div>`;
  457. break;
  458. case "2":
  459. val = `<div class='taskProgress color_bg_3'>已完成</div>`;
  460. break;
  461. case "3":
  462. val = `<div class='taskProgress color_bg_4'>已延期</div>`;
  463. break;
  464. case "4":
  465. val = `<div class='taskProgress color_bg_5'>搁置中</div>`;
  466. break;
  467. };
  468. return val
  469. }
  470. }
  471. ]
  472. gantt.config.lightbox.sections = [
  473. {
  474. name: 'text',
  475. height: 70,
  476. map_to: 'text',
  477. type: 'textarea',
  478. focus: true,
  479. width: '*'
  480. },
  481. {
  482. name: 'time',
  483. height: 40,
  484. map_to: 'auto',
  485. type: 'duration',
  486. time_format: ["%Y", "%m", "%d"],
  487. },
  488. {
  489. name: 'projectClass',
  490. height: 30,
  491. map_to: 'proTemplate',
  492. type: 'template',
  493. },
  494. {
  495. name: 'head',
  496. height: 22,
  497. map_to: 'head_id',
  498. type: 'select',
  499. options: gantt.serverList("staff", []),
  500. },
  501. {
  502. name: 'description',
  503. height: 70,
  504. map_to: 'description',
  505. type: 'textarea'
  506. },
  507. {
  508. name: 'priority',
  509. height: 40,
  510. map_to: 'priority',
  511. type: 'radio',
  512. options: gantt.serverList("priority")
  513. },
  514. ]
  515. gantt.config.smart_scales = true;
  516. gantt.plugins({
  517. click_drag: true,
  518. drag_timeline: true, // 拖动图
  519. marker: true, // 时间标记
  520. fullscreen: true, // 全屏
  521. tooltip: true, // 鼠标经过时信息
  522. undo: true // 允许撤销
  523. })
  524. gantt.init(this.$refs.gantt);
  525. gantt.parse(this.tasks);
  526. },
  527. }
  528. };
  529. </script>
  530. <style scoped lang="scss">
  531. .ant-layout {
  532. background: #f8f9f9;
  533. }
  534. ​ .ant-layout-header {
  535. background: #fdffff;
  536. color: rgb(29, 28, 28);
  537. border: 1px solid #dee0e0;
  538. }
  539. ​ .header {
  540. // position: fixed;
  541. display: flex;
  542. justify-content: space-between;
  543. align-items: center;
  544. }
  545. ​ .content {
  546. background: #fdffff;
  547. height: 99vh;
  548. }
  549. ​ // 中间
  550. .centerContent {
  551. position: relative;
  552. background: #fdffff;
  553. width: 100%;
  554. overflow-y: auto;
  555. display: flex;
  556. justify-content: space-between;
  557. .selectDate {
  558. width: 100px;
  559. position: fixed;
  560. top: 18%;
  561. right: 9%;
  562. z-index: 99;
  563. display: flex;
  564. justify-content: space-between;
  565. }
  566. }
  567. /deep/ .color_bg_1{
  568.  background-color:#60a3bc !important;
  569. }
  570. .color_bg_2{
  571.  background-color:#079992 ;
  572. }
  573. .color_bg_3{
  574.  background-color:#78e08f ;
  575. }
  576. .color_bg_4{
  577.  background-color:#e55039 ;
  578. }
  579. .color_bg_5{
  580.  background-color:#f6b93b ;
  581. }
  582. </style>