gantt.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. <template>
  2. <div class="ganttContainerBox">
  3. <div ref="ganttContainer" style="height: 100%;">
  4. </div>
  5. <!-- 任务详情信息弹出框 -->
  6. <el-dialog :class="''" :title="title" v-if="addFormVisible" append-to-body
  7. :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="840px" :top="'6vh'">
  8. <taskComponent ref="thskComponents" :integrationTask="integrationTask" :showOrNot="showOrNot"
  9. @closeBounced="closeBounced" :showMmeiLaiDe="true" :showMmeiLaiDeData="showMmeiLaiDeData"></taskComponent>
  10. <div slot="title" v-if="addForm.parentTid != null">
  11. <el-page-header @back="backToParentTask" :title="$t('parenttask')"
  12. :content="addForm.parentTname"></el-page-header>
  13. </div>
  14. </el-dialog>
  15. <!-- tooltip -->
  16. <div
  17. v-if="tooltip.visible"
  18. :style="`top:${tooltip.y}px;left:${tooltip.x}px;`"
  19. class="custom-tooltip-customize"
  20. >
  21. <div><b>类&#8195;&ensp;&nbsp;型:</b> {{ tooltip.task.taskPlanTypeName }}</div>
  22. <div><b>开始时间:</b> {{ tooltip.task.start_date }}</div>
  23. <div><b>结束时间:</b> {{ tooltip.task.end_date }}</div>
  24. <div><b>计划工时:</b> {{ tooltip.task.time }} 小时 ({{ tooltip.task.dayDifference }} 天 )</div>
  25. <div><b>项目名称:</b> {{ tooltip.task.projectName }}</div>
  26. <div><b>任务内容:</b> {{ tooltip.task.planName }}</div>
  27. </div>
  28. </div>
  29. </template>
  30. <script>
  31. import { gantt } from 'dhtmlx-gantt';
  32. // import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
  33. // import 'dhtmlx-gantt/codebase/locale/locale_cn' // 本地化
  34. import taskComponent from "@/components/taskComponent.vue"
  35. export default {
  36. name: 'gantt',
  37. components: {
  38. taskComponent
  39. },
  40. props: {
  41. tasks: {
  42. type: Object,
  43. default() {
  44. return { data: [], links: [] }
  45. }
  46. },
  47. stafforpro: '',
  48. valueDate: [],
  49. typeList: {
  50. type: Array,
  51. default() {
  52. return []
  53. }
  54. }
  55. },
  56. data() {
  57. return {
  58. containerRect: null,
  59. taskFormVisible: false,
  60. addForm: {},
  61. addLoading: false,
  62. title: '创建计划',
  63. commentList: [],
  64. dynamicTab: true,
  65. showOrNot: false,
  66. integrationTask: null,
  67. taskComponentFlg: false,
  68. addFormVisible: false,
  69. integrationTaskNingwai: {},
  70. integrationTask: {},
  71. user: JSON.parse(sessionStorage.getItem("user")),
  72. showMmeiLaiDeData: {},
  73. tooltip: {
  74. visible: false,
  75. task: null,
  76. x: 0,
  77. y: 0,
  78. }
  79. };
  80. },
  81. created: function () {
  82. // gantt.clearAll()
  83. // console.log("tasks",this.$props.tasks);
  84. },
  85. methods: {
  86. detaliTaskExposure(row) {
  87. const { taskId, ganttData } = row
  88. this.title = '编辑计划'
  89. this.showMmeiLaiDeData = JSON.parse(ganttData || '{}')
  90. setTimeout(() => {
  91. this.editTask({ taskId })
  92. }, 1000)
  93. },
  94. getDistanceToParent(element, parent) {
  95. let distance = 0;
  96. while (element && element !== parent) {
  97. distance += element.offsetTop; // 获取当前元素相对于父元素顶部的距离
  98. element = element.offsetParent; // 获取上一级父元素
  99. }
  100. return distance;
  101. },
  102. closeBounced(obj) {
  103. console.log(obj, '<======== 点击事件')
  104. if (!obj.backToParentTaskSub) {
  105. this.addFormVisible = false
  106. this.taskComponentFlg = false
  107. if (obj.submitInsert) {
  108. this.$emit('closeBounced', obj)
  109. }
  110. if(obj.deleteTask) {
  111. this.$emit('closeBounced', obj)
  112. }
  113. }
  114. },
  115. backToParentTask() {
  116. console.log('点击, <======== 点击了backToParentTask')
  117. },
  118. addTask(row) {
  119. this.showOrNot = true
  120. this.addForm = {
  121. projectId: '', groupId: '', stagesId: '', taskLevel: 0, planHours: 8, taskType: 0, startDate: row.date
  122. }
  123. const userIdList = (row.userId && row.userId.split(',')) || []
  124. const executorListFront = userIdList.map(item => {
  125. return {
  126. executorId: item,
  127. planHours: 8
  128. }
  129. })
  130. let obj = {
  131. create: true,
  132. addForm: this.addForm,
  133. executorListFront,
  134. stage: this.addForm,
  135. integrationTaskNingwai: this.integrationTaskNingwai,
  136. taskVue: true,
  137. meetingId: this.addForm.meetingId
  138. }
  139. this.integrationTask = obj
  140. this.addFormVisible = true
  141. },
  142. editTask(row) {
  143. this.showOrNot = true
  144. this.http.post('/task/getTask', { id: row.taskId },
  145. res => {
  146. if (res.code == "ok") {
  147. const data = res.data
  148. if(this.user.roleId != 2283 && !data.executorId) {
  149. this.$message({
  150. message: '这条数据只有区域经理才能分配',
  151. type: 'warning'
  152. });
  153. return
  154. }
  155. this.addForm = {
  156. id: data.id
  157. }
  158. this.integrationTask = {
  159. id: data.id,
  160. task: data,
  161. num: 1,
  162. curProjectId: data.projectId || '',
  163. create: false,
  164. integrationTaskNingwai: {
  165. groupId: data.groupId,
  166. isDesc: false,
  167. order: "seq",
  168. projectId: data.projectId || '',
  169. },
  170. taskVue: data.projectId ? false : true,
  171. meetingId: this.addForm.meetingId
  172. }
  173. this.addFormVisible = true
  174. } else {
  175. this.$message({ message: res.msg, type: "error" });
  176. }
  177. },
  178. error => {
  179. this.$message({ message: error, type: "error" });
  180. });
  181. },
  182. handleEmptyClick(row) {
  183. if (row.taskId) {
  184. // 编辑任务
  185. this.title = '编辑计划'
  186. this.editTask(row)
  187. } else {
  188. // 新增任务
  189. this.title = '创建计划'
  190. this.addTask(row)
  191. }
  192. },
  193. // 定位数据
  194. focusAndSelectTaskFull(taskId) {
  195. if (gantt.isTaskExists(taskId)) {
  196. var task = gantt.getTask(taskId);
  197. gantt.showTask(taskId);
  198. gantt.selectTask(taskId);
  199. // 检查日期有效性
  200. if (!(task.start_date instanceof Date) || !(task.end_date instanceof Date)) {
  201. console.error("Invalid date format in task:", task);
  202. return;
  203. }
  204. var midTime = (task.start_date.getTime() + task.end_date.getTime()) / 2;
  205. var midDate = new Date(midTime);
  206. gantt.scrollTo(gantt.posFromDate(midDate) - 200, gantt.getScrollState().y);
  207. }
  208. },
  209. observeTaskLines(gantt) {
  210. console.log(gantt, '<==== gantt')
  211. const taskContainer = gantt.$task_data;
  212. this.observer = new MutationObserver(() => {
  213. this.bindTooltipEvents();
  214. });
  215. this.observer.observe(taskContainer, {
  216. childList: true,
  217. subtree: true
  218. });
  219. this.bindTooltipEvents(); // 初次执行
  220. },
  221. bindTooltipEvents() {
  222. const taskLines = this.$refs.ganttContainer && this.$refs.ganttContainer.querySelectorAll(".gantt_task_line");
  223. (taskLines || []).forEach(line => {
  224. const taskId = line.getAttribute("task_id");
  225. if (!taskId || line.dataset.bound === "true") return;
  226. line.dataset.bound = "true";
  227. line.addEventListener("mouseenter", (e) => {
  228. const rect = line.getBoundingClientRect();
  229. const task = gantt.getTask(taskId);
  230. if(!task.taskId) {
  231. this.tooltip.visible = false;
  232. return
  233. }
  234. console.log(task)
  235. const list = task.text.split('/')
  236. const d1 = this.dayjs(task.start_date);
  237. const d2 = this.dayjs(task.end_date);
  238. this.tooltip.task = {
  239. ...task,
  240. end_date: this.dayjs(task.endDateStr).format('YYYY-MM-DD HH:mm:ss'),
  241. start_date: this.dayjs(task.startDateStr).format('YYYY-MM-DD HH:mm:ss'),
  242. projectName: list[0],
  243. planName: list[1],
  244. dayDifference: d2.diff(d1, 'day'),
  245. taskPlanTypeName: this.typeList.find(type => type.id == task.taskPlanType).name
  246. };
  247. this.tooltip.x = rect.left + window.scrollX;
  248. this.tooltip.y = (rect.top - 180) - 10 + window.scrollY;
  249. this.tooltip.visible = true;
  250. });
  251. line.addEventListener("mouseleave", () => {
  252. this.tooltip.visible = false;
  253. });
  254. });
  255. },
  256. bindTaskLineEvents() {
  257. console.log("bindTaskLineEvents", this.$refs.ganttContainer)
  258. if(!this.$refs.ganttContainer) {
  259. return
  260. }
  261. const taskLines = this.$refs.ganttContainer.querySelectorAll(".gantt_task_line");
  262. (taskLines || []).forEach(line => {
  263. const taskId = line.getAttribute("task_id");
  264. if (!taskId) return;
  265. // 避免重复绑定
  266. if (line.dataset.tooltipBound) return;
  267. line.dataset.tooltipBound = "true";
  268. line.addEventListener("mouseenter", (e) => {
  269. const task = gantt.getTask(taskId);
  270. this.tooltip.task = task;
  271. this.tooltip.visible = true;
  272. const updateMouse = (moveEvent) => {
  273. this.tooltip.x = moveEvent.pageX;
  274. this.tooltip.y = moveEvent.pageY;
  275. };
  276. document.addEventListener("mousemove", updateMouse);
  277. line.addEventListener("mouseleave", () => {
  278. this.tooltip.visible = false;
  279. document.removeEventListener("mousemove", updateMouse);
  280. }, { once: true });
  281. });
  282. });
  283. }
  284. },
  285. mounted: function () {
  286. const userInfo = JSON.parse(sessionStorage.getItem("user"));
  287. gantt.clearAll()
  288. gantt.locale = {
  289. date: {
  290. month_full: [this.$t('yiYue'), this.$t('erYue'), this.$t('sanYue'), this.$t('siYue'), this.$t('thisTWuyue'), this.$t('liuYue'), this.$t('qiYue'), this.$t('baYue'), this.$t('jiuYue'), this.$t('shiYue'), this.$t('shiYiYue'), this.$t('shiErYue')],
  291. month_short: [this.$t('1Yue'), this.$t('2Yue'), this.$t('3Yue'), this.$t('4Yue'), this.$t('5Yue'), this.$t('6Yue'), this.$t('7Yue'), this.$t('8Yue'), this.$t('9Yue'), this.$t('10Yue'), this.$t('11Yue'), this.$t('12Yue')],
  292. day_full: [this.$t('xingQiRi'), this.$t('xingQiYi'), this.$t('xingQiEr'), this.$t('xingQiSan'), this.$t('xingQiSi'), this.$t('xingQiWu'), this.$t('xingQiLiu')],
  293. day_short: [this.$t('ri'), "一", "二", "三", "四", "五", "六"]
  294. },
  295. labels: {
  296. dhx_cal_today_button: this.$t('jinTian'),
  297. day_tab: this.$t('weekDay.day'),
  298. week_tab: this.$t('zhou'),
  299. month_tab: this.$t('weekDay.month'),
  300. new_event: this.$t('xinJianRiCheng'),
  301. icon_save: this.$t('save'),
  302. icon_cancel: this.$t('Shutdown'),
  303. icon_details: this.$t('xiangXi'),
  304. icon_edit: this.$t('bian-ji'),
  305. icon_delete: this.$t('btn.delete'),
  306. confirm_closing: this.$t('qingQueRenShiFouCheXiaoXiuGai'), //Your changes will be lost, are your sure?
  307. confirm_deleting: this.$t('shiFouShanChuRiCheng'),
  308. section_description: this.$t('other.describe'),
  309. section_time: this.$t('shiJianFanWei'),
  310. section_type: this.$t('types'),
  311. /* grid columns */
  312. column_text: this.$t('renWuMing'),
  313. column_start_date: this.$t('starttimes'),
  314. column_duration: this.$t('chiXuShiJian'),
  315. column_add: "",
  316. /* link confirmation */
  317. link: this.$t('guanLian'),
  318. confirm_link_deleting: this.$t('jiangBeiShanChu'),
  319. link_start: this.$t('kaiShi'),
  320. link_end: this.$t('jieShu'),
  321. type_task: this.$t('other.task'),
  322. type_project: this.$t('other.project'),
  323. type_milestone: this.$t('other.milestone'),
  324. minutes: this.$t('fenZhong'),
  325. hours: this.$t('time.hour'),
  326. days: this.$t('time.day'),
  327. weeks: this.$t('zhou'),
  328. months: this.$t('weekDay.month'),
  329. years: this.$t('nian')
  330. }
  331. };
  332. // gantt.config.autosize = true;
  333. // gantt.config.duration_unit = "hour";
  334. gantt.config.fit_tasks = true;
  335. gantt.config.drag_move = false;
  336. gantt.config.xml_date = "%Y-%m-%d";
  337. gantt.config.columns = [
  338. { name: "text", label: (this.stafforpro == this.$t('anRenYuanChaKan') ? this.$t('lable.name') : this.$t('headerTop.projectName')), align: "left", tree: true },
  339. // {name:"time",label:"计划工时(h)", align: "center" }
  340. // {name:"start_date", label:"开始时间", width:'*' , align: "center" },
  341. // {name:"duration", label:"工时(天)", width:'*' , align: "center" }
  342. ];
  343. gantt.config.scale_unit = "month"; //按月显示
  344. gantt.config.date_scale = "%F, %Y"; //设置时间刻度的格式(X轴) 多个尺度
  345. gantt.config.scale_height = 50; //设置时间刻度的高度和网格的标题
  346. gantt.config.open_tree_initially = true;
  347. gantt.config.subscales = [
  348. { unit: "day", step: 1, date: "周%D,%d" }
  349. ];
  350. gantt.config.buttons_left = []
  351. gantt.config.buttons_right = ["gantt_cancel_btn"]
  352. gantt.config.drag_links = false
  353. gantt.config.drag_resize = false
  354. gantt.config.drag_progress = false
  355. gantt.config.details_on_dblclick = false
  356. gantt.config.lightbox.sections = [
  357. { name: "description", height: 76, map_to: "text", type: "textarea", focus: true }
  358. ];
  359. gantt.config.start_date = new Date(this.valueDate[0]);
  360. gantt.config.end_date = new Date(this.valueDate[1]);
  361. const that = this
  362. // 设置任务条内容显示
  363. gantt.templates.task_text = function (start, end, task) {
  364. const { leaderOrManager, taskPlan, taskStatus, checkFirstId, checkSecondId, startDateStr, endDateStr, time, text } = task
  365. const userIds = that.user.id
  366. const d1 = that.dayjs(task.start_date);
  367. const d2 = that.dayjs(task.end_date);
  368. const texts = `${startDateStr.split(' ')[0].split('-').join('')} - ${endDateStr.split(' ')[0].split('-').join('')} ${time}h(${ d2.diff(d1, 'day')}天) ${text}`
  369. // 都审核通过
  370. if(taskPlan == 1 && taskStatus == 0 && task.text == '请假') {
  371. return `<div class="task_text">
  372. <div style="background: '#ff5757'">${texts}</div>
  373. </div>`
  374. }
  375. if(taskPlan == 1 && taskStatus == 0) {
  376. return `<div class="task_text">
  377. <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div>
  378. <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div>
  379. <div>${texts}</div>
  380. </div>`
  381. }
  382. // 更改为统一的
  383. if([0,2,3,4,5,6].includes(taskStatus)) {
  384. return `<div class="task_text">
  385. ${task.taskStatus == 0 ? `<div class="exclamation-circle circle greenStr" style="color: #8ecaf8">V</div><div class="exclamation-circle circle greenStr" style="color: #8ecaf8">V</div>` : ''}
  386. ${task.taskStatus == 2 ? `<div class="circle greyStr"></div>` : ''}
  387. ${task.taskStatus == 3 ? `<div class="circle orangeStr"></div> <div class="circle"></div>` : ''}
  388. ${task.taskStatus == 4 ? `<div class="exclamation-circle circle greenStr" style="color: #8ecaf8">V</div> <div class="circle orangeStr"></div>` : ''}
  389. ${task.taskStatus == 5 ? `<div class="exclamation-circle circle redStr" style="color: #f56c6c">!</div> <div class="circle"></div>` : ''}
  390. ${task.taskStatus == 6 ? `<div class="exclamation-circle circle greenStr" style="color: #8ecaf8">V</div> <div class="exclamation-circle circle redStr" style="color: #f56c6c">!</div>` : ''}
  391. <div style="margin-left: 6px;">${texts}</div>
  392. </div>`;
  393. }
  394. // 正常人
  395. return `<div class="task_text" style="justify-content: center;">
  396. <div style="color: ${!task.taskId ? '#333' : '#fff'}">${task.text}</div>
  397. </div>`;
  398. };
  399. gantt.config.grid_width = 350;
  400. gantt.plugins({ tooltip: true });
  401. gantt.templates.tooltip_text = function (start, end, task) {
  402. return
  403. };
  404. gantt.ext.tooltips.attach({
  405. selector: '.gantt_grid [' + gantt.config.task_attribute + ']',
  406. onmouseenter: (event, node) => {
  407. if (node.textContent.length > 19) {
  408. let sdom = document.createElement('span')
  409. sdom.innerText = node.innerText
  410. sdom.className = 'tooltiptext'
  411. node.appendChild(sdom)
  412. }
  413. },
  414. onmousemove: () => { },
  415. onmouseleave: (event, node) => {
  416. let sdom = document.getElementsByClassName('tooltiptext')[0]
  417. if (sdom) { node.removeChild(sdom) }
  418. },
  419. global: true
  420. })
  421. // 双击事件
  422. this.$refs.ganttContainer.addEventListener('dblclick', (event) => {
  423. const taskIdStr = gantt.locate(event);
  424. // if(userInfo.projectLeaderType != 1 && userInfo.projectLeaderType != 2 && userInfo.projectLeaderType != 3) {
  425. // return
  426. // }
  427. this.showMmeiLaiDeData = {}
  428. if (taskIdStr && gantt.isTaskExists(taskIdStr)) {
  429. // 编辑任务
  430. const rows = gantt.getTask(taskIdStr)
  431. if (rows.id.indexOf('任务') != '-1') {
  432. const value = taskIdStr.split('任务_')[1]
  433. const taskId = value.split('_')[0]
  434. this.showMmeiLaiDeData = rows
  435. this.handleEmptyClick({ taskId })
  436. }
  437. } else {
  438. if(userInfo.projectLeaderType == 2) {
  439. return
  440. }
  441. // 获取 gantt_grid_data 容器
  442. const ganttGrid = document.querySelector('.gantt_grid_data');
  443. if (!ganttGrid) return;
  444. // // 计算点击位置
  445. const gridRect = ganttGrid.getBoundingClientRect();
  446. // const clickY = event.clientY - gridRect.top; // 相对 gantt_grid_data 的 Y 轴偏移量
  447. // // 获取任务行
  448. // const rows = ganttGrid.querySelectorAll('.gantt_row');
  449. // const rowHeight = rows.length > 0 ? rows[0].offsetHeight : 34; // 获取行高 (默认 40px)
  450. // // 计算索引
  451. // const rowIndex = Math.floor(clickY / rowHeight);
  452. // if (rowIndex >= rows.length || rowIndex < 0) return;
  453. // // 获取任务 ID
  454. // const rowElement = rows[rowIndex];
  455. // 新写的
  456. const rows = ganttGrid.querySelectorAll('.gantt_row');
  457. const clickedElement = event.toElement; // 当前点击的元素
  458. const parentElement = clickedElement.closest('.gantt_task_row');
  459. const yzhozhi = this.getDistanceToParent(parentElement) - 219 // 219 固定值
  460. const yCoordinate = +((yzhozhi / 35).toFixed(0)) * 35
  461. let rowIndexs = 0
  462. for(const em in rows) {
  463. const str = (rows[em].style && rows[em].style.top) || '-1px'
  464. const nums = str.split('px')[0]
  465. if(nums == yCoordinate) {
  466. rowIndexs = em
  467. }
  468. }
  469. const rowElement = rows[rowIndexs]
  470. console.log(yCoordinate, rowIndexs)
  471. console.log(rowElement, '<,,,,,,,,,,=============== rowElement')
  472. const taskIdFromRow = rowElement.getAttribute('task_id'); // 获取任务 ID
  473. if (taskIdFromRow && gantt.isTaskExists(taskIdFromRow)) {
  474. const taskData = gantt.getTask(taskIdFromRow);
  475. console.log(taskData, '<=== taskData')
  476. if (taskData.userId) {
  477. // 新增任务
  478. let rollingDistance = 0
  479. const scrollElement = this.$refs.ganttContainer.querySelector('.gantt_hor_scroll');
  480. if (scrollElement) {
  481. rollingDistance = scrollElement.scrollLeft || 0
  482. }
  483. const userId = taskData.userId;
  484. const gridX = event.clientX - gridRect.left; // 相对 gantt_grid_data 的 X 轴偏移量
  485. const date = gantt.dateFromPos((gridX - 349) + rollingDistance);
  486. console.log('点击的日期:', date, this.dayjs(date).format('YYYY-MM-DD'));
  487. this.handleEmptyClick({ userId, date: this.dayjs(date).format('YYYY-MM-DD') })
  488. }
  489. }
  490. }
  491. });
  492. gantt.init(this.$refs.ganttContainer);
  493. this.containerRect = this.$refs.ganttContainer.getBoundingClientRect();
  494. gantt.parse(this.$props.tasks);
  495. // 等渲染完成后绑定每个任务条事件
  496. setTimeout(() => {
  497. this.observeTaskLines(gantt); // 开始监听任务条变化
  498. }, 2000)
  499. setTimeout(() => {
  500. const list = JSON.parse(localStorage.getItem('ganttChartTaskId') || '[]')
  501. if(list[0]) {
  502. this.focusAndSelectTaskFull(list[0])
  503. }
  504. localStorage.removeItem('ganttChartTaskId')
  505. }, 1000)
  506. }
  507. }
  508. </script>
  509. <style>
  510. @import "~dhtmlx-gantt/codebase/dhtmlxgantt.css";
  511. .person_line {
  512. background: #8ecaf8;
  513. border: 1px solid;
  514. @include border_color("border_color");
  515. }
  516. .error_line {
  517. background: #ff5757;
  518. border: 1px solid;
  519. border-color: #ff5757;
  520. }
  521. .success_line {
  522. background: #5cb87a;
  523. border: 1px solid;
  524. border-color: #5cb87a;
  525. }
  526. .draft_line {
  527. background: #909399;
  528. border: 1px solid;
  529. border-color: #909399;
  530. }
  531. .reject_line {
  532. background: #FFBD4D;
  533. border: 1px solid;
  534. border-color: #FFBD4D;
  535. }
  536. .task_text {
  537. display: flex;
  538. flex-direction: row;
  539. align-items: center;
  540. white-space: nowrap;
  541. overflow: hidden;
  542. text-overflow: ellipsis;
  543. width: 100%;
  544. }
  545. .task_text>div {
  546. flex: 0 0 auto;
  547. }
  548. .circle {
  549. width: 10px;
  550. height: 10px;
  551. border-radius: 50%;
  552. border: 2px solid #fff;
  553. margin-left: 4px;
  554. display: flex;
  555. justify-content: center;
  556. align-items: center;
  557. }
  558. .exclamation-circle {
  559. background: #fff;
  560. font-size: 12px;
  561. font-weight: bold;
  562. }
  563. .pendingReviewOfCornerMarkers {
  564. width: 100%;
  565. height: 100%;
  566. border-radius: 50%;
  567. display: flex;
  568. justify-content: center;
  569. align-items: center;
  570. background: #fdba6e;
  571. font-weight: bold;
  572. }
  573. .statuss .circle {
  574. border-color: #fdba6e;
  575. }
  576. /* .gantt_tooltip{
  577. z-index: 10000;
  578. top: 10px !important;
  579. left: 10px !important;
  580. } */
  581. .tooltiptext {
  582. visibility: visible;
  583. background-color: #fff;
  584. color: #454545;
  585. box-shadow: 3px 3px 3px rgba(0, 0, 0, .07);
  586. border-left: 1px solid rgba(0, 0, 0, .07);
  587. border-top: 1px solid rgba(0, 0, 0, .07);
  588. font-size: 8pt;
  589. line-height: 20px;
  590. padding: 10px;
  591. /* opacity: 0;
  592. transition: 0.5s; */
  593. position: absolute;
  594. z-index: 10000;
  595. bottom: 120%;
  596. left: 25px;
  597. max-width: 300px;
  598. /* word-wrap: break-word;
  599. word-break: break-all; */
  600. white-space: pre-wrap;
  601. }
  602. .custom-tooltip-customize {
  603. position: fixed;
  604. z-index: 9999;
  605. background: rgba(0, 0, 0, 0.7);
  606. color: #fff;
  607. padding: 20px;
  608. border-radius: 6px;
  609. }
  610. .custom-tooltip-customize div {
  611. margin-bottom: 10px;
  612. line-height: 20px;
  613. }
  614. .custom-tooltip-customize div:last-child {
  615. margin-bottom: 0;
  616. }
  617. .orangeStr {
  618. background: #ffa500;
  619. }
  620. .greenStr {
  621. background: #32cd32;
  622. }
  623. .redStr {
  624. background: #ff0000;
  625. }
  626. .greyStr {
  627. background: #e0e0e0;
  628. }
  629. </style>