demo2.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. <template>
  2.  <div style="height: 100%; width: 100%">
  3.     <div class="content">
  4.        <div style="margin: -5px 0px 5px;display: flex;justify-content: space-between;">
  5.            <a-input allowClear v-model="searchTitle" placeholder="请输入任务名称"></a-input>
  6.            <a-button icon="search" type="primary" @click="searchDataClick">搜索</a-button>
  7.        </div>
  8.        <!-- 中间 内容 -->
  9.        <div class="centerContent">
  10.          <!-- 甘特图 -->
  11.          <div class="selectDate">
  12.            <a-button @click="changeToday">今</a-button>
  13.            <!-- 日期切换 -->
  14.            <a-select  default-value="d" style="width: 55px;margin-left: 5px;" @change="ganttChangeDateView">
  15.              <a-select-option value="y">年</a-select-option>
  16.              <a-select-option value="m">月</a-select-option>
  17.              <a-select-option value="w">周</a-select-option>
  18.              <a-select-option value="d">日</a-select-option>
  19.            </a-select>
  20.            <a-button style="margin-left: 5px;" @click="changeFull"><a-icon type="fullscreen" /></a-button>
  21.          </div>
  22.          <div class="rightGatt" style="min-height:calc(78vh - 50px - 5px );width: 100%;overflow: hidden;" ref="gantt"></div>
  23.        </div>
  24.      </div>
  25.  </div>
  26. </div>
  27. </template>
  28. <script>
  29. import {gantt} from '@/assets/js/dhtmlx';
  30. import "@/assets/css/dhtmlxgantt.css";
  31. import moment from 'moment'​
  32. export default {
  33. name: "ganttChart",
  34. data() {
  35. return {
  36. moment,
  37. timer: null, //定时
  38. item: {}, //单行数据
  39. searchTitle: "", //搜索标题
  40. tasks: {
  41. data: [
  42. ], //数据
  43. links: [
  44. {
  45. id:'111',//数据id
  46.    source:'1'
  47.    target:'2'
  48.    type:'0'
  49. },//
  50. {
  51.    id:'222'
  52.    source:'2'
  53.    target:'1'
  54.    type:'1'
  55. },
  56. ], //关联项目数据
  57. },
  58. savetasks: {
  59. data: [],
  60. links: []
  61. }, //暂存空数据
  62. ganttServerStaff: [], //设置gantt成员数据
  63. selectStaff: [], //下拉成员
  64. staff: [], //成员
  65. ganttEvent: { //销毁事件
  66. },
  67. urls: {
  68. staff: "", //项目成员
  69. tasklinks: '', //gantt数据
  70. linksEdit: '', //修改和新增连接
  71. linksDelete: '', //删除连接
  72. addTask: '', //新增项目PUT
  73. editTask: '', //编辑项目put请求 tid
  74. deleteTask: '', //删除项目delete tid
  75. }
  76. }
  77. },
  78. watch: {
  79. searchTitle(newVal, oldVal) {
  80. this.searchTitle = newVal;
  81. }
  82. },
  83. mounted() {
  84. this.$nextTick(() => {
  85. this.ganttChangeEvent(); //交互事件
  86. this.initGantt(); //初始化
  87. this.createTodayLine(); //今日线
  88. // this.ganttServerList(); //服务数据
  89. })
  90. this.onQuery(); //查询数据
  91. this.ganttChangeDateView("d"); //默认日格式
  92. },
  93. methods: {
  94. /*
  95. 甘特图
  96. */
  97. // 初始化gantt
  98. initGantt() {
  99. // 清空之前的配置
  100. // gantt.clearAll();
  101. // 启用动态加载
  102. gantt.config.branch_loading = true
  103. //日期格式化
  104. gantt.config.xml_date = "%Y-%m-%d";
  105. gantt.config.order_branch = true;
  106. gantt.config.order_branch_free = true;
  107. //左侧是否自适应
  108. gantt.config.autofit = true;
  109. gantt.config.drag_links = true; //连线
  110. gantt.config.readonly = false; //只读
  111. gantt.config.date_scale = "%m月%d日"; //右侧显示列名
  112. gantt.config.layout = { //拖拽布局
  113. css: "gantt_container",
  114. rows: [{
  115. cols: [{
  116. view: "grid",
  117. id: "grid",
  118. scrollX: "scrollHor",
  119. scrollY: "scrollVer"
  120. },
  121. {
  122. resizer: true,
  123. width: 1
  124. },
  125. {
  126. view: "timeline",
  127. id: "timeline",
  128. scrollX: "scrollHor",
  129. scrollY: "scrollVer"
  130. },
  131. {
  132. view: "scrollbar",
  133. scroll: "y",
  134. id: "scrollVer"
  135. }
  136. ]
  137. },
  138. {
  139. view: "scrollbar",
  140. scroll: "x",
  141. id: "scrollHor",
  142. height: 20
  143. }
  144. ]
  145. };
  146. gantt.config.start_on_monday = true;
  147. gantt.config.work_time = true;
  148. gantt.config.fit_tasks = true; //自动调整图表坐标轴区间用于适配task的长度
  149. ​
  150. //汉化
  151. gantt.locale = {
  152. date: {
  153. month_full: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
  154. month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
  155. day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
  156. day_short: ["日", "一", "二", "三", "四", "五", "六"]
  157. },
  158. labels: {
  159. dhx_cal_today_button: "今天",
  160. day_tab: "日",
  161. week_tab: "周",
  162. month_tab: "月",
  163. new_event: "新建日程",
  164. icon_save: "保存",
  165. icon_cancel: "关闭",
  166. icon_details: "详细",
  167. icon_edit: "编辑",
  168. icon_delete: "删除",
  169. confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?
  170. confirm_deleting: "是否删除计划?",
  171. section_description: "描述:",
  172. section_time: "时间范围:",
  173. section_type: "类型:",
  174. section_text: "计划名称:",
  175. section_test: "测试:",
  176. section_projectClass: "项目类型:",
  177. taskProjectType_0: "项目任务",
  178. taskProjectType_1: "普通任务",
  179. section_head: "负责人:",
  180. section_priority: '优先级:',
  181. taskProgress: '任务状态',
  182. taskProgress_0: "未开始",
  183. taskProgress_1: "进行中",
  184. taskProgress_2: "已完成",
  185. taskProgress_3: "已延期",
  186. taskProgress_4: "搁置中",
  187. section_template: 'Details',
  188. /* grid columns */
  189. column_text: "计划名称",
  190. column_start_date: "开始时间",
  191. column_duration: "持续时间",
  192. column_add: "",
  193. column_priority: "难度",
  194. /* link confirmation */
  195. link: "关联",
  196. confirm_link_deleting: "将被删除",
  197. message_ok: '确定',
  198. message_cancel: '取消',
  199. link_start: " (开始)",
  200. link_end: " (结束)",
  201. ​
  202. type_task: "任务",
  203. type_project: "项目",
  204. type_milestone: "里程碑",
  205. ​
  206. minutes: "分钟",
  207. hours: "小时",
  208. days: "天",
  209. weeks: "周",
  210. months: "月",
  211. years: "年"
  212. }
  213. }
  214. gantt.serverList("priority", [{
  215. key: 0,
  216. label: "最高"
  217. },
  218. {
  219. key: 1,
  220. label: "较高"
  221. },
  222. {
  223. key: 2,
  224. label: "普通"
  225. },
  226. {
  227. key: 3,
  228. label: "较低"
  229. },
  230. {
  231. key: 4,
  232. label: "最低"
  233. },
  234. ]);
  235. //左侧显示列名
  236. gantt.config.columns = [{
  237. name: "text",
  238. min_width: 100,
  239. max_width: 200,
  240. label: "任务",
  241. align: "left",
  242. resize: true,
  243. tree: true,
  244. editor: {
  245. type: 'text',
  246. map_to: 'text'
  247. }
  248. },
  249. {
  250. name: "id",
  251. label: "",
  252. hide: true
  253. },
  254. {
  255. name: "start_date",
  256. label: "开始时间",
  257. width: 120,
  258. resize: true,
  259. align: "left"
  260. },
  261. {
  262. name: "head",
  263. min_width: 100,
  264. height: 40,
  265. label: "负责人",
  266. resize: true,
  267. align: "left",
  268. // editor: {
  269. //   map_to: "head_id", type: "select", options: gantt.serverList("staff"),
  270. // },
  271. template: (item) => {
  272. if (this.ganttDealById(gantt.serverList('staff'), item.head_id)) {
  273. 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)}`
  274. }
  275. }
  276. },
  277. // { name: "end_date", label: "结束时间", align: "center" },
  278. {
  279. name: "taskProgress",
  280. label: "任务状态",
  281. align: "center",
  282. min_width: 110,
  283. editor: {
  284. type: "select",
  285. map_to: "taskProgress",
  286. options: [{
  287. key: "0",
  288. label: gantt.locale.labels.taskProgress_0
  289. },
  290. {
  291. key: "1",
  292. label: gantt.locale.labels.taskProgress_1
  293. },
  294. {
  295. key: "2",
  296. label: gantt.locale.labels.taskProgress_2
  297. },
  298. {
  299. key: "3",
  300. label: gantt.locale.labels.taskProgress_3
  301. },
  302. {
  303. key: "4",
  304. label: gantt.locale.labels.taskProgress_4
  305. },
  306. ],
  307. },
  308. template: function(obj) {
  309. let re = '';
  310. switch (obj.taskProgress) {
  311. case "0":
  312. re = `<div class='taskProgress color_bg_1' >未开始</div>`
  313. break;
  314. case "1":
  315. re = `<div class='taskProgress color_bg_2' >进行中</div>`
  316. break;
  317. case "2":
  318. re = `<div class='taskProgress color_bg_3' >已完成</div>`
  319. break;
  320. case "3":
  321. re = `<div class='taskProgress color_bg_4'>已延期</div>`
  322. break;
  323. case "4":
  324. re = `<div class='taskProgress color_bg_5' >搁置中</div>`
  325. break;
  326. }
  327. return re​
  328. }
  329. }, ​
  330. ];​
  331. //弹出层
  332. gantt.config.lightbox.sections = [{
  333. name: "text",
  334. height: 70,
  335. map_to: "text",
  336. type: "textarea",
  337. focus: true,
  338. width: "*"
  339. },
  340. {
  341. name: "time",
  342. height: 40,
  343. map_to: "auto",
  344. type: "duration",
  345. time_format: ["%Y", "%m", "%d"],
  346. },
  347. {
  348. name: "projectClass",
  349. height: 30,
  350. map_to: "proTemplate",
  351. type: "template",
  352. },
  353. {
  354. name: "head",
  355. height: 22,
  356. map_to: "head_id",
  357. type: "select",
  358. options: gantt.serverList('staff', []),
  359. },
  360. {
  361. name: "description",
  362. height: 70,
  363. map_to: "description",
  364. type: "textarea"
  365. },
  366. {
  367. name: "priority",
  368. height: 40,
  369. map_to: "priority",
  370. type: "radio",
  371. options: gantt.serverList("priority")
  372. }, ​
  373. ];​
  374. gantt.config.smart_scales = true;
  375. gantt.plugins({
  376. click_drag: true,
  377. drag_timeline: true, // 拖动图
  378. marker: true, // 时间标记
  379. fullscreen: true, // 全屏
  380. tooltip: true, // 鼠标经过时信息
  381. undo: true // 允许撤销
  382. })
  383. gantt.init(this.$refs.gantt);
  384. },
  385. // gantt数据服务列表
  386. ganttServerList() {
  387. this.getProjectStaff(); //获取项目成员
  388. // 项目难度
  389. gantt.serverList("priority", [{
  390. key: 0,
  391. label: "最高"
  392. },
  393. {
  394. key: 1,
  395. label: "较高"
  396. },
  397. {
  398. key: 2,
  399. label: "普通"
  400. },
  401. {
  402. key: 3,
  403. label: "较低"
  404. },
  405. {
  406. key: 4,
  407. label: "最低"
  408. },
  409. ]);
  410. },
  411. // gantt交互事件注册
  412. ganttChangeEvent() {
  413. // gantt渲染
  414. this.ganttEvent.onGanttReady = gantt.attachEvent("onGanttReady", () => {
  415. //弹窗标题 日期范围
  416. gantt.templates.task_time = function(start, end, task) {
  417. return "周期:" + moment(start).format('YYYY-MM-DD') + " 至 " + moment(end).format('YYYY-MM-DD');
  418. };
  419. // 浮窗
  420. gantt.templates.tooltip_text = (start, end, task) => {
  421. return "<b>项目名称:</b> " + task.text + "<br><b>负责人:</b>" + task.head + "<br/><b>开始时间:</b> " +
  422. moment(start).format('YYYY-MM-DD') +
  423. "<br/><b>结束时间:</b> " +
  424. moment(new Date(end).valueOf() - 1000 * 60 * 60 * 24).format('YYYY-MM-DD');
  425. }
  426. //弹窗标题 计划名称
  427. gantt.templates.task_text = function(start, end, task) {
  428. return task.text;
  429. };
  430. gantt.templates.timeline_cell_class = function(task, date) {
  431. if (!gantt.isWorkTime({
  432. task: task,
  433. date: date
  434. })) {
  435. return "weekend";
  436. } else {
  437. return 'weekday'
  438. }
  439. };
  440. gantt.templates.task_end_date = (date) => {
  441. return gantt.templates.task_date(this.moment(new Date(date.valueOf() - 1000 * 60 * 60 * 24)).format(
  442. "YYYY-MM-DD"));
  443. };
  444. gantt.templates.grid_date_format = (date, column) => {
  445. if (column === "end_date") {
  446. return this.moment(new Date(date.valueOf() - 1000 * 60 * 60 * 24)).format("YYYY-MM-DD");
  447. } else {
  448. return this.moment(date).format("YYYY-MM-DD");
  449. }
  450. }
  451. });
  452. // 修改默认弹窗
  453. gantt.attachEvent("onBeforeLightbox", (id) => {
  454. var task = gantt.getTask(id);
  455. task.proTemplate = `${gantt.locale.labels.taskProjectType_0}`
  456. return true;
  457. });​
  458. //添加后触发
  459. this.ganttEvent.onAfterTaskAdd = gantt.attachEvent("onAfterTaskAdd", (id, item) => {
  460. clearTimeout(this.timer)
  461. this.timer = setTimeout(() => {
  462. this.dealProject("add", item)
  463. }, 500)​
  464. });
  465. // 修改任务
  466. this.ganttEvent.onAfterTaskUpdate = gantt.attachEvent("onAfterTaskUpdate", (id, data) => {
  467. clearTimeout(this.timer)
  468. this.timer = setTimeout(() => {
  469. this.dealProject("edit", data);
  470. gantt.render()
  471. }, 500)​
  472. });
  473. // 删除项目
  474. this.ganttEvent.onAfterTaskDelete = gantt.attachEvent("onAfterTaskDelete", (id, data) => {
  475. clearTimeout(this.timer)
  476. this.timer = setTimeout(() => {
  477. this.dealProject("delete", data);
  478. gantt.render();
  479. }, 500)
  480. });
  481. // 移动项目
  482. this.ganttEvent.onAfterTaskDrag = gantt.attachEvent("onAfterTaskDrag", (id, mode, e) => {
  483. clearTimeout(this.timer)
  484. this.timer = setTimeout(() => {
  485. var task = gantt.getTask(id);
  486. this.dealProject("edit", task);
  487. gantt.render()
  488. }, 500)
  489. });
  490. // 用户完成拖动并释放鼠标
  491. this.ganttEvent.onAfterTaskChanged = gantt.attachEvent("onAfterTaskChanged", (id, mode, task) => {
  492. clearTimeout(this.timer)
  493. this.timer = setTimeout(() => {
  494. gantt.render();
  495. }, 500)
  496. });​
  497. // 删除连接项目关系
  498. this.ganttEvent.onAfterLinkDelete = gantt.attachEvent("onAfterLinkDelete", (id, item) => {
  499. clearTimeout(this.timer)
  500. this.timer = setTimeout(() => {
  501. let param = Object.assign({}, {
  502. projectId: this.$store.state.project_data.id
  503. }, item)
  504. this.axios.$delete(this.urls.linksDelete, param).then(res => {
  505. res.code == 200 && this.$message.success("解除成功!")
  506. res.code != 200 && this.$message.error("解除失败!")
  507. })
  508. gantt.render();
  509. }, 500)
  510. });
  511. // 修改连接项目关系
  512. this.ganttEvent.onAfterLinkUpdate = gantt.attachEvent("onAfterLinkUpdate", (id, item) => {
  513. clearTimeout(this.timer)
  514. this.timer = setTimeout(() => {
  515. ​
  516. let param = Object.assign({}, {
  517. projectId: this.$store.state.project_data.id
  518. }, item)
  519. this.axios.$put(this.urls.linksEdit, param).then(res => {
  520. res.code == 200 && this.$message.success("关联成功!")
  521. res.code != 200 && this.$message.error("关联失败!")​
  522. })
  523. gantt.render()
  524. }, 500)
  525. });
  526. // 新增连接项目关系
  527. this.ganttEvent.onBeforeLinkAdd = gantt.attachEvent("onBeforeLinkAdd", (id, item) => {
  528. this.timer = setTimeout(() => {
  529. clearTimeout(this.timer)
  530. let param = Object.assign({}, {
  531. projectId: this.$store.state.project_data.id
  532. }, item)
  533. this.axios.$put(this.urls.linksEdit, param).then(res => {
  534. res.code == 200 && this.$message.success("关联成功!");
  535. res.code != 200 && this.$message.error("关联失败!");
  536. })
  537. gantt.render()
  538. }, 20)​
  539. });
  540. // 保存新增
  541. this.ganttEvent.onLightboxSave = gantt.attachEvent("onLightboxSave", (id, item) => {
  542. if (!item.text) {
  543. this.$message.error("请填写计划名称!");
  544. return false;
  545. }
  546. return true;
  547. });​
  548. },
  549. // 处理id 对应名称label
  550. ganttDealById(list, id) {
  551. for (let i = 0; i < list.length; i++) {
  552. if (list[i].key == id)
  553. return list[i].label;
  554. }
  555. return "";
  556. },
  557. // 切换 年 季 月 周 日视图
  558. ganttChangeDateView(type) {
  559. switch (type) {
  560. case 'y':
  561. gantt.config.scale_unit = "year";
  562. gantt.config.step = 1;
  563. gantt.config.subscales = null;
  564. gantt.config.date_scale = "%Y年";
  565. gantt.templates.date_scale = null;
  566. break;​
  567. case 'm':
  568. gantt.config.scale_unit = 'month';
  569. gantt.config.step = 1;
  570. gantt.config.date_scale = "%m月";
  571. gantt.templates.date_scale = null;
  572. break;
  573. case 'w':
  574. gantt.config.scale_unit = 'week';
  575. gantt.config.step = 1;
  576. gantt.config.date_scale = "第%w周";
  577. gantt.templates.date_scale = null;
  578. break;
  579. case 'd':
  580. gantt.config.scale_unit = 'day';
  581. gantt.config.step = 1;
  582. gantt.config.date_scale = "%m月%d日";
  583. gantt.templates.date_scale = null;
  584. gantt.config.subscales = null;
  585. break;
  586. }
  587. gantt.render();
  588. },
  589. // 今日线
  590. createTodayLine() {
  591. var dateToStr = gantt.date.date_to_str("%Y年%M%d日");
  592. var markerId = gantt.addMarker({
  593. id: 'markerLine',
  594. start_date: new Date(),
  595. css: "today",
  596. text: "今日",
  597. title: dateToStr(new Date())
  598. });
  599. gantt.updateMarker(markerId);
  600. },
  601. // 是否全屏
  602. changeFull() {
  603. gantt.ext.fullscreen.toggle();
  604. },
  605. // 定位到今日线
  606. changeToday() {
  607. this.$nextTick(() => {
  608. let ganTT = document.getElementsByClassName('gantt_marker today')
  609. gantt.scrollTo(ganTT[0].offsetLeft - 300, null);
  610. })
  611. },
  612. /*
  613.   操作
  614.   */
  615. // 获取项目成员
  616. getProjectStaff(projectID) {
  617. this.axios.get(this.urls.staff, {
  618. params: {
  619. projectId: projectID ? projectID : this.$store.state.project_data.id
  620. },
  621. }).then(res => {
  622. let staffArr = [];
  623. res.data.code = 200 && res.data.result.forEach((item, index) => {
  624. staffArr[index] = {};
  625. staffArr[index].key = item.id;
  626. staffArr[index].label = item.realname;
  627. })
  628. this.selectStaff = res.data.result;
  629. // 补充gantt数据
  630. this.ganttServerStaff = staffArr;
  631. gantt.updateCollection("staff", staffArr);
  632. gantt.render()
  633. })
  634. },
  635. //计算进度
  636. evalProgess(start, end, update) {
  637. if (start && end && update) {
  638. let start_date = this.moment(start).format("YYYY-MM-DD");
  639. let end_date = this.moment(end).format("YYYY-MM-DD");
  640. let update_date = this.moment(update).format("YYYY-MM-DD");
  641. if ((new Date(end_date) - new Date(update_date) > 0)) {
  642. let process = (new Date(update_date) - new Date(start_date)) / (new Date(end_date) - new Date(start_date));
  643. return process.toFixed(2)
  644. } else {
  645. return 0
  646. }
  647. }​
  648. return 0
  649. },
  650. // 获取数据
  651. onQuery(param) {
  652. gantt.clearAll();
  653. gantt.parse(this.savetasks);
  654. gantt.render();
  655. param = Object.assign({}, {
  656. projectId: this.$store.state.project_data.id ? this.$store.state.project_data.id : '1'
  657. }, param)
  658. this.axios.get(this.urls.tasklinks, {
  659. params: param
  660. }).then(res => {
  661. let result = res.data.result["taskList"];
  662. let pushArr = [];
  663. this.tasks.links = res.data.result["ganttchartList"]; //连接项目
  664. this.tasks.data = [];
  665. result.forEach((item, index) => {
  666. this.tasks.data[index] = {};
  667. this.tasks.data[index].id = item.tid ? item.tid : ''; //项目id
  668. this.tasks.data[index].text = item.title ? item.title : '空标题'; //标题
  669. this.tasks.data[index].start_date = item.startTime; //开始时间
  670. // 负责人--成员
  671. this.tasks.data[index].head_id = item.headRole?.id ? item.headRole?.id : ''; //负责人id
  672. this.tasks.data[index].head = item.headRole?.realname ? item.headRole?.realname : ''; //负责人
  673. this.tasks.data[index].progress = this.evalProgess(item.startTime, item.endTime, item
  674. .updateTime) //项目进展
  675. // 后台时间加一天 显示减一天 处理条形图时间左闭右开
  676. this.tasks.data[index].end_date = this.moment(new Date(item.endTime).valueOf() + 1000 * 60 * 60 *
  677. 24).format("YYYY-MM-DD"); //结束时间
  678. // this.tasks.data[index].end_date = item.endTime;//结束时间
  679. this.tasks.data[index].priority = item.priority ? item.priority : ''; //任务优先级
  680. this.tasks.data[index].projectClass = item.type ? item.type : ''; //类型 0项目任务 1 普通任务
  681. ​
  682. this.tasks.data[index].taskProgress = item.taskStatus.toString(); //任务状态
  683. this.tasks.data[index].description = item.describe ? item.describe : ''; //描述
  684. this.tasks.data[index].color = item.stateDictionary.color ? item.stateDictionary.color : ''; //颜色
  685. if (item.taskList && item.taskList.length != 0) {
  686. this.tasks.data[index].render = "split"; //显示在单行
  687. this.tasks.data[index].open = true; //展开
  688. item.taskList.forEach((_item) => {
  689. pushArr.push({
  690. id: _item.tid,
  691. text: _item.title ? _item.title : '空标题',
  692. start_date: _item.startTime,
  693. end_date: _item.endTime,
  694. head_id: _item.headId,
  695. head: _item.head,
  696. priority: _item.priority,
  697. projectClass: _item.type,
  698. taskProgress: _item.taskStatus.toString(),
  699. description: _item.describe,
  700. parent: _item.mainTaskId,
  701. });
  702. })
  703. }
  704. });
  705. this.tasks.data = this.tasks.data.concat(pushArr)
  706. this.$nextTick(() => {
  707. gantt.parse(this.tasks);
  708. gantt.render();
  709. gantt.refreshData();
  710. })​
  711. })
  712. },
  713. ​
  714. // 项目新增 修改tid 删除tid
  715. dealProject(type, data) {
  716. let param = {};
  717. if (type != 'add') {
  718. param.tid = data.id;
  719. param.title = data.text;
  720. param.startTime = this.moment(data.start_date).format("YYYY-MM-DD");
  721. param.endTime = this.moment(data.end_date).format("YYYY-MM-DD");
  722. param.describe = data.description;
  723. param.priority = data.priority;
  724. param.head = data.head_id;
  725. param.taskStatus = data.taskProgress;
  726. param.projectId = this.$store.state.project_data.id;
  727. } else {
  728. param.title = data.text;
  729. param.startTime = this.moment(data.start_date).format("YYYY-MM-DD");
  730. param.endTime = this.moment(data.end_date).format("YYYY-MM-DD");
  731. param.describe = data.description;
  732. param.priority = data.priority;
  733. param.head = data.head_id;
  734. param.taskStatus = data.taskProgress;
  735. param.projectId = this.$store.state.project_data.id;
  736. }
  737. let formdata = new FormData();
  738. for (let i in param) {
  739. formdata.append(i, param[i])
  740. }
  741. switch (type) {
  742. case "add": //新增
  743. this.axios.put(this.urls.addTask, formdata).then(res => {
  744. res.data.code == 200 && this.$message.success("新增成功!")
  745. res.data.code != 200 && this.$message.error("新增失败!")
  746. }).catch(err => {
  747. this.$message.error("请求失败!")
  748. })
  749. break;
  750. case "edit":
  751. this.axios.put(this.urls.editTask, formdata).then(res => {
  752. res.data.code == 200 && this.$message.success("修改成功!")
  753. res.data.code != 200 && this.$message.error("修改失败!")
  754. }).catch(err => {
  755. this.$message.error("请求失败!")
  756. })
  757. break;
  758. case "delete":
  759. this.axios.delete(this.urls.deleteTask, formdata).then(res => {
  760. res.data.code == 200 && this.$message.success("删除成功!")
  761. res.data.code != 200 && this.$message.error("删除失败!")
  762. }).catch(err => {
  763. this.$message.error("请求失败!")
  764. })
  765. break;​
  766. }
  767. },
  768. selecthead(val) {
  769. this.searchHead = val; //id
  770. },
  771. // 搜索判断数据
  772. hasSubstr(parentId, type) {
  773. let task = gantt.getTask(parentId);
  774. if (type == 'tilte') {
  775. if (task.text.toLowerCase().indexOf(this.searchTitle) !== -1)
  776. return true;
  777. }
  778. // }  
  779. },
  780. //点击按钮搜索
  781. searchDataClick() {
  782. if (this.searchTitle) {
  783. this.ganttEvent.onBeforeTaskDisplay = gantt.attachEvent("onBeforeTaskDisplay", (id, task) => {
  784. if (this.hasSubstr(id, 'tilte')) {
  785. return true;
  786. }
  787. return false;
  788. });
  789. gantt.refreshData()
  790. gantt.render()
  791. } else {
  792. this.ganttEvent.onBeforeTaskDisplay = gantt.attachEvent("onBeforeTaskDisplay", (id, task) => {
  793. return true
  794. })
  795. gantt.refreshData()
  796. gantt.render()
  797. }
  798. },
  799. },
  800. ​
  801. destroyed() {
  802. // 销毁gantt事件
  803. for (let i in this.ganttEvent) {
  804. gantt.detachEvent(this.ganttEvent[i])
  805. }
  806. gantt.ext.tooltips.tooltip.hide();
  807. }
  808. }
  809. </script>
  810. <style scoped lang="scss">
  811. @import url(./gantt.css);
  812. .ant-layout {
  813. background: #f8f9f9;
  814. }
  815. ​ .ant-layout-header {
  816. background: #fdffff;
  817. color: rgb(29, 28, 28);
  818. border: 1px solid #dee0e0;
  819. }
  820. ​ .header {
  821. // position: fixed;
  822. display: flex;
  823. justify-content: space-between;
  824. align-items: center;
  825. }
  826. ​ .content {
  827. background: #fdffff;
  828. height: 99vh;
  829. }
  830. ​ // 中间
  831. .centerContent {
  832. position: relative;
  833. background: #fdffff;
  834. width: 100%;
  835. overflow-y: auto;
  836. display: flex;
  837. justify-content: space-between;
  838. .selectDate {
  839. width: 100px;
  840. position: fixed;
  841. top: 18%;
  842. right: 9%;
  843. z-index: 99;
  844. display: flex;
  845. justify-content: space-between;
  846. }
  847. }
  848. </style>