vxe-gantt 3.4.2 → 3.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +53 -53
  3. package/es/gantt/src/gantt.js +1 -1
  4. package/es/ui/index.js +1 -1
  5. package/es/ui/src/log.js +1 -1
  6. package/lib/gantt/src/gantt.js +1 -1
  7. package/lib/gantt/src/gantt.min.js +1 -1
  8. package/lib/index.umd.js +50 -50
  9. package/lib/index.umd.min.js +1 -1
  10. package/lib/ui/index.js +1 -1
  11. package/lib/ui/index.min.js +1 -1
  12. package/lib/ui/src/log.js +1 -1
  13. package/lib/ui/src/log.min.js +1 -1
  14. package/package.json +88 -88
  15. package/packages/components.ts +22 -22
  16. package/packages/gantt/index.ts +32 -32
  17. package/packages/gantt/src/gantt-body.ts +323 -323
  18. package/packages/gantt/src/gantt-chart.ts +542 -542
  19. package/packages/gantt/src/gantt-footer.ts +73 -73
  20. package/packages/gantt/src/gantt-header.ts +162 -162
  21. package/packages/gantt/src/gantt-view.ts +1954 -1954
  22. package/packages/gantt/src/gantt.ts +2827 -2827
  23. package/packages/gantt/src/static.ts +35 -35
  24. package/packages/gantt/src/util.ts +47 -47
  25. package/packages/index.ts +8 -8
  26. package/packages/ui/index.ts +119 -119
  27. package/packages/ui/src/comp.ts +3 -3
  28. package/packages/ui/src/depend.ts +14 -14
  29. package/packages/ui/src/dom.ts +196 -196
  30. package/packages/ui/src/log.ts +8 -8
  31. package/packages/ui/src/utils.ts +67 -67
  32. package/packages/ui/src/vn.ts +13 -13
  33. package/styles/all.scss +3 -3
  34. package/styles/base.scss +2 -2
  35. package/styles/components/gantt-module/gantt-chart.scss +261 -261
  36. package/styles/components/gantt.scss +707 -707
  37. package/styles/helpers/baseMixin.scss +95 -95
  38. package/styles/helpers/baseVar.scss +3 -3
  39. package/styles/helpers/placement.scss +38 -38
  40. package/styles/theme/base.scss +14 -14
  41. package/styles/theme/dark.scss +8 -8
  42. package/styles/theme/light.scss +8 -8
  43. package/types/all.d.ts +16 -16
  44. package/types/index.d.ts +4 -4
@@ -1,1954 +1,1954 @@
1
- import { VNode, CreateElement } from 'vue'
2
- import { defineVxeComponent } from '../../ui/src/comp'
3
- import { VxeUI } from '@vxe-ui/core'
4
- import { setScrollTop, setScrollLeft, removeClass, addClass, hasClass } from '../../ui/src/dom'
5
- import { getRefElem, getStandardGapTime, getTaskBarLeft, getTaskBarWidth, hasMilestoneTask, getTaskType, hasSubviewTask } from './util'
6
- import XEUtils from 'xe-utils'
7
- import GanttViewHeaderComponent from './gantt-header'
8
- import GanttViewBodyComponent from './gantt-body'
9
- import GanttViewFooterComponent from './gantt-footer'
10
-
11
- import type { TableReactData, TableInternalData, VxeTableConstructor, VxeTableMethods, VxeTablePrivateMethods } from 'vxe-table'
12
- import type { VxeGanttViewConstructor, GanttViewReactData, VxeGanttDefines, VxeGanttViewPrivateMethods, GanttViewInternalData, VxeGanttConstructor, VxeGanttPrivateMethods } from '../../../types'
13
-
14
- const { globalEvents } = VxeUI
15
-
16
- const sourceType = 'gantt'
17
- const minuteMs = 1000 * 60
18
- const dayMs = minuteMs * 60 * 24
19
-
20
- function createInternalData (): GanttViewInternalData {
21
- return {
22
- xeTable: null,
23
- visibleColumn: [],
24
- startMaps: {},
25
- endMaps: {},
26
- chartMaps: {},
27
- todayDateMaps: {},
28
- elemStore: {},
29
- // 存放横向 X 虚拟滚动相关的信息
30
- scrollXStore: {
31
- preloadSize: 0,
32
- offsetSize: 0,
33
- visibleSize: 0,
34
- visibleStartIndex: 0,
35
- visibleEndIndex: 0,
36
- startIndex: 0,
37
- endIndex: 0
38
- },
39
- // 最后滚动位置
40
- lastScrollTop: 0,
41
- lastScrollLeft: 0
42
- }
43
- }
44
-
45
- function createReactData (): GanttViewReactData {
46
- return {
47
- // 是否启用了横向 X 可视渲染方式加载
48
- scrollXLoad: false,
49
- // 是否启用了纵向 Y 可视渲染方式加载
50
- scrollYLoad: false,
51
- // 是否存在纵向滚动条
52
- overflowY: true,
53
- // 是否存在横向滚动条
54
- overflowX: true,
55
- // 纵向滚动条的宽度
56
- scrollbarWidth: 0,
57
- // 横向滚动条的高度
58
- scrollbarHeight: 0,
59
-
60
- // 最后滚动时间戳
61
- lastScrollTime: 0,
62
- lazScrollLoading: false,
63
-
64
- scrollVMLoading: false,
65
- scrollYHeight: 0,
66
- scrollYTop: 0,
67
- isScrollYBig: false,
68
- scrollXLeft: 0,
69
- scrollXWidth: 0,
70
- isScrollXBig: false,
71
-
72
- minViewDate: null,
73
- maxViewDate: null,
74
- tableData: [],
75
- tableColumn: [],
76
- headerGroups: [],
77
-
78
- viewCellWidth: 40
79
- }
80
- }
81
-
82
- const maxYHeight = 5e6
83
- // const maxXWidth = 5e6
84
-
85
- function parseStringDate ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, dateValue: any) {
86
- const $xeGantt = $xeGanttView.$xeGantt
87
-
88
- const taskOpts = $xeGantt.computeTaskOpts
89
- const { dateFormat } = taskOpts
90
- return XEUtils.toStringDate(dateValue, dateFormat || null)
91
- }
92
-
93
- function updateTodayData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
94
- const $xeGantt = $xeGanttView.$xeGantt
95
- const internalData = $xeGanttView.internalData
96
-
97
- const ganttReactData = $xeGantt.reactData
98
- const { taskScaleList } = ganttReactData
99
- const minScale = $xeGantt.computeMinScale
100
- if (minScale) {
101
- const weekScale = taskScaleList.find(item => item.type === 'week')
102
- const isMinWeek = minScale.type === 'week'
103
- const itemDate = new Date()
104
- let [yyyy, M, MM, dd, HH, mm, ss] = XEUtils.toDateString(itemDate, 'yyyy-M-MM-dd-HH-mm-ss').split('-')
105
- const e = itemDate.getDay()
106
- const E = e + 1
107
- const q = Math.ceil((itemDate.getMonth() + 1) / 3)
108
- const W = `${XEUtils.getYearWeek(itemDate, weekScale ? weekScale.startDay : undefined)}`
109
- if (isMinWeek && checkWeekOfsetYear(W, M)) {
110
- yyyy = `${Number(yyyy) + 1}`
111
- M = '1'
112
- MM = '0' + M
113
- }
114
- ganttReactData.nowTime = itemDate.getTime()
115
- internalData.todayDateMaps = {
116
- year: yyyy,
117
- quarter: `${yyyy}_q${q}`,
118
- month: `${yyyy}_${MM}`,
119
- week: `${yyyy}_W${W}`,
120
- day: `${yyyy}_${MM}_${dd}_E${E}`,
121
- date: `${yyyy}_${MM}_${dd}`,
122
- hour: `${yyyy}_${MM}_${dd}_${HH}`,
123
- minute: `${yyyy}_${MM}_${dd}_${HH}_${mm}`,
124
- second: `${yyyy}_${MM}_${dd}_${HH}_${mm}_${ss}`
125
- }
126
- }
127
- }
128
-
129
- function handleColumnHeader ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
130
- const $xeGantt = $xeGanttView.$xeGantt
131
-
132
- const ganttReactData = $xeGantt.reactData
133
- const { taskScaleList } = ganttReactData
134
- const scaleUnit = $xeGantt.computeScaleUnit
135
- const minScale = $xeGantt.computeMinScale
136
- const weekScale = $xeGantt.computeWeekScale
137
- const scaleDateList = $xeGanttView.computeScaleDateList
138
- const fullCols: VxeGanttDefines.ViewColumn[] = []
139
- const groupCols: VxeGanttDefines.GroupColumn[] = []
140
-
141
- if (minScale && scaleUnit && scaleDateList.length) {
142
- const renderListMaps: Record<VxeGanttDefines.ColumnScaleType, VxeGanttDefines.ViewColumn[]> = {
143
- year: [],
144
- quarter: [],
145
- month: [],
146
- week: [],
147
- day: [],
148
- date: [],
149
- hour: [],
150
- minute: [],
151
- second: []
152
- }
153
- const tempTypeMaps: Record<VxeGanttDefines.ColumnScaleType, Record<string, VxeGanttDefines.ViewColumn>> = {
154
- year: {},
155
- quarter: {},
156
- month: {},
157
- week: {},
158
- day: {},
159
- date: {},
160
- hour: {},
161
- minute: {},
162
- second: {}
163
- }
164
- const isMinWeek = minScale.type === 'week'
165
-
166
- const handleData = (type: VxeGanttDefines.ColumnScaleType, colMaps: Record<VxeGanttDefines.ColumnScaleType, VxeGanttDefines.ViewColumn>, minCol: VxeGanttDefines.ViewColumn) => {
167
- if (minScale.type === type) {
168
- return
169
- }
170
- const currCol = colMaps[type]
171
- const currKey = `${currCol.field}`
172
- let currGpCol = tempTypeMaps[type][currKey]
173
- if (!currGpCol) {
174
- currGpCol = currCol
175
- tempTypeMaps[type][currKey] = currGpCol
176
- renderListMaps[type].push(currGpCol)
177
- }
178
- if (currGpCol) {
179
- if (!currGpCol.children) {
180
- currGpCol.children = []
181
- }
182
- currGpCol.children.push(minCol)
183
- }
184
- }
185
-
186
- for (let i = 0; i < scaleDateList.length; i++) {
187
- const itemDate = scaleDateList[i]
188
- let [yy, yyyy, M, MM, d, dd, H, HH, m, mm, s, ss] = XEUtils.toDateString(itemDate, 'yy-yyyy-M-MM-d-dd-H-HH-m-mm-s-ss').split('-')
189
- const e = itemDate.getDay()
190
- const E = e + 1
191
- const q = Math.ceil((itemDate.getMonth() + 1) / 3)
192
- const W = `${XEUtils.getYearWeek(itemDate, weekScale ? weekScale.startDay : undefined)}`
193
- const WW = XEUtils.padStart(W, 2, '0')
194
- if (isMinWeek && checkWeekOfsetYear(W, M)) {
195
- yyyy = `${Number(yyyy) + 1}`
196
- M = '1'
197
- MM = '0' + M
198
- }
199
- const dateObj: VxeGanttDefines.ScaleDateObj = { date: itemDate, yy, yyyy, M, MM, d, dd, H, HH, m, mm, s, ss, q, W, WW, E, e }
200
- const colMaps: Record<VxeGanttDefines.ColumnScaleType, VxeGanttDefines.ViewColumn> = {
201
- year: {
202
- field: yyyy,
203
- title: yyyy,
204
- dateObj
205
- },
206
- quarter: {
207
- field: `${yyyy}_q${q}`,
208
- title: `${q}`,
209
- dateObj
210
- },
211
- month: {
212
- field: `${yyyy}_${MM}`,
213
- title: MM,
214
- dateObj
215
- },
216
- week: {
217
- field: `${yyyy}_W${W}`,
218
- title: `${W}`,
219
- dateObj
220
- },
221
- day: {
222
- field: `${yyyy}_${MM}_${dd}_E${E}`,
223
- title: `${E}`,
224
- dateObj
225
- },
226
- date: {
227
- field: `${yyyy}_${MM}_${dd}`,
228
- title: dd,
229
- dateObj
230
- },
231
- hour: {
232
- field: `${yyyy}_${MM}_${dd}_${HH}`,
233
- title: HH,
234
- dateObj
235
- },
236
- minute: {
237
- field: `${yyyy}_${MM}_${dd}_${HH}_${mm}`,
238
- title: mm,
239
- dateObj
240
- },
241
- second: {
242
- field: `${yyyy}_${MM}_${dd}_${HH}_${mm}_${ss}`,
243
- title: ss,
244
- dateObj
245
- }
246
- }
247
- const minCol = colMaps[minScale.type]
248
- if (minScale.level < 19) {
249
- handleData('year', colMaps, minCol)
250
- }
251
- if (minScale.level < 17) {
252
- handleData('quarter', colMaps, minCol)
253
- }
254
- if (minScale.level < 15) {
255
- handleData('month', colMaps, minCol)
256
- }
257
- if (minScale.level < 13) {
258
- handleData('week', colMaps, minCol)
259
- }
260
- if (minScale.level < 11) {
261
- handleData('day', colMaps, minCol)
262
- }
263
- if (minScale.level < 9) {
264
- handleData('date', colMaps, minCol)
265
- }
266
- if (minScale.level < 7) {
267
- handleData('hour', colMaps, minCol)
268
- }
269
- if (minScale.level < 5) {
270
- handleData('minute', colMaps, minCol)
271
- }
272
- if (minScale.level < 3) {
273
- handleData('second', colMaps, minCol)
274
- }
275
-
276
- fullCols.push(minCol)
277
- }
278
-
279
- taskScaleList.forEach(scaleItem => {
280
- if (scaleItem.type === minScale.type) {
281
- groupCols.push({
282
- scaleItem,
283
- columns: fullCols
284
- })
285
- return
286
- }
287
- const list = renderListMaps[scaleItem.type] || []
288
- if (list) {
289
- list.forEach(item => {
290
- item.childCount = item.children ? item.children.length : 0
291
- item.children = undefined
292
- })
293
- }
294
- groupCols.push({
295
- scaleItem,
296
- columns: list
297
- })
298
- })
299
- }
300
-
301
- return {
302
- fullCols,
303
- groupCols
304
- }
305
- }
306
-
307
- /**
308
- * 判断周的年份是否跨年
309
- */
310
- function checkWeekOfsetYear (W: number | string, M: number | string) {
311
- return `${W}` === '1' && `${M}` === '12'
312
- }
313
-
314
- /**
315
- * 周维度,由于年份和第几周是冲突的行为,所以需要特殊处理,判断是否跨年,例如
316
- * '2024-12-31' 'yyyy-MM-dd W' >> '2024-12-31 1'
317
- * '2025-01-01' 'yyyy-MM-dd W' >> '2025-01-01 1'
318
- */
319
- function parseWeekObj (date: any, firstDay?: 0 | 5 | 1 | 2 | 3 | 4 | 6) {
320
- const currDate = XEUtils.toStringDate(date)
321
- let yyyy = currDate.getFullYear()
322
- const month = currDate.getMonth()
323
- const weekNum = XEUtils.getYearWeek(currDate, firstDay)
324
- if (checkWeekOfsetYear(weekNum, month + 1)) {
325
- yyyy++
326
- }
327
- return {
328
- yyyy,
329
- W: weekNum
330
- }
331
- }
332
-
333
- function createChartRender ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, fullCols: VxeGanttDefines.ViewColumn[]) {
334
- const $xeGantt = $xeGanttView.$xeGantt
335
- const reactData = $xeGanttView.reactData
336
-
337
- const { minViewDate } = reactData
338
- const minScale = $xeGantt.computeMinScale
339
- const scaleUnit = $xeGantt.computeScaleUnit
340
- const weekScale = $xeGantt.computeWeekScale
341
- if (minScale) {
342
- switch (scaleUnit) {
343
- case 'year': {
344
- const indexMaps: Record<string, number> = {}
345
- fullCols.forEach(({ dateObj }, i) => {
346
- const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy')
347
- indexMaps[yyyyMM] = i
348
- })
349
- return (startValue: any, endValue: any) => {
350
- const startDate = parseStringDate($xeGanttView, startValue)
351
- const endDate = parseStringDate($xeGanttView, endValue)
352
- const startStr = XEUtils.toDateString(startDate, 'yyyy')
353
- const startFirstDate = XEUtils.getWhatYear(startDate, 0, 'first')
354
- const endStr = XEUtils.toDateString(endDate, 'yyyy')
355
- const endFirstDate = XEUtils.getWhatYear(endDate, 0, 'first')
356
- const dateSize = Math.floor((XEUtils.getWhatYear(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / dayMs)
357
- const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
358
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
359
- const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
360
- return {
361
- offsetLeftSize,
362
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
363
- }
364
- }
365
- }
366
- case 'quarter': {
367
- const indexMaps: Record<string, number> = {}
368
- fullCols.forEach(({ dateObj }, i) => {
369
- const q = XEUtils.toDateString(dateObj.date, 'yyyy-q')
370
- indexMaps[q] = i
371
- })
372
- return (startValue: any, endValue: any) => {
373
- const startDate = parseStringDate($xeGanttView, startValue)
374
- const endDate = parseStringDate($xeGanttView, endValue)
375
- const startStr = XEUtils.toDateString(startDate, 'yyyy-q')
376
- const startFirstDate = XEUtils.getWhatQuarter(startDate, 0, 'first')
377
- const endStr = XEUtils.toDateString(endDate, 'yyyy-q')
378
- const endFirstDate = XEUtils.getWhatQuarter(endDate, 0, 'first')
379
- const dateSize = Math.floor((XEUtils.getWhatQuarter(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / dayMs)
380
- const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
381
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
382
- const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
383
- return {
384
- offsetLeftSize,
385
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
386
- }
387
- }
388
- }
389
- case 'month': {
390
- const indexMaps: Record<string, number> = {}
391
- fullCols.forEach(({ dateObj }, i) => {
392
- const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM')
393
- indexMaps[yyyyMM] = i
394
- })
395
- return (startValue: any, endValue: any) => {
396
- const startDate = parseStringDate($xeGanttView, startValue)
397
- const endDate = parseStringDate($xeGanttView, endValue)
398
- const startStr = XEUtils.toDateString(startDate, 'yyyy-MM')
399
- const startFirstDate = XEUtils.getWhatMonth(startDate, 0, 'first')
400
- const endStr = XEUtils.toDateString(endDate, 'yyyy-MM')
401
- const endFirstDate = XEUtils.getWhatMonth(endDate, 0, 'first')
402
- const dateSize = Math.floor((XEUtils.getWhatMonth(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / dayMs)
403
- const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
404
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
405
- const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
406
- return {
407
- offsetLeftSize,
408
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
409
- }
410
- }
411
- }
412
- case 'week': {
413
- const indexMaps: Record<string, number> = {}
414
- fullCols.forEach(({ dateObj }, i) => {
415
- const yyyyW = `${dateObj.yyyy}-${dateObj.W}`
416
- indexMaps[yyyyW] = i
417
- })
418
- return (startValue: any, endValue: any) => {
419
- const startDate = parseStringDate($xeGanttView, startValue)
420
- const endDate = parseStringDate($xeGanttView, endValue)
421
- const startWeekObj = parseWeekObj(startDate, weekScale ? weekScale.startDay : undefined)
422
- const startStr = `${startWeekObj.yyyy}-${startWeekObj.W}`
423
- const startFirstDate = XEUtils.getWhatWeek(startDate, 0, weekScale ? weekScale.startDay : undefined, weekScale ? weekScale.startDay : undefined)
424
- const endWeekObj = parseWeekObj(endDate, weekScale ? weekScale.startDay : undefined)
425
- const endStr = `${endWeekObj.yyyy}-${endWeekObj.W}`
426
- const endFirstDate = XEUtils.getWhatWeek(endDate, 0, weekScale ? weekScale.startDay : undefined, weekScale ? weekScale.startDay : undefined)
427
- const dateSize = Math.floor((XEUtils.getWhatWeek(endDate, 1, weekScale ? weekScale.startDay : undefined, weekScale ? weekScale.startDay : undefined).getTime() - endFirstDate.getTime()) / dayMs)
428
- const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
429
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
430
- const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
431
- return {
432
- offsetLeftSize,
433
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
434
- }
435
- }
436
- }
437
- case 'day':
438
- case 'date': {
439
- const indexMaps: Record<string, number> = {}
440
- fullCols.forEach(({ dateObj }, i) => {
441
- const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM-dd')
442
- indexMaps[yyyyMM] = i
443
- })
444
- return (startValue: any, endValue: any) => {
445
- const startDate = parseStringDate($xeGanttView, startValue)
446
- const endDate = parseStringDate($xeGanttView, endValue)
447
- const startStr = XEUtils.toDateString(startDate, 'yyyy-MM-dd')
448
- const startFirstDate = XEUtils.getWhatDay(startDate, 0, 'first')
449
- const endStr = XEUtils.toDateString(endDate, 'yyyy-MM-dd')
450
- const endFirstDate = XEUtils.getWhatDay(endDate, 0, 'first')
451
- const minuteSize = Math.floor((XEUtils.getWhatDay(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / minuteMs)
452
- // 开始和结束时间是否存在偏移时
453
- const startSubtract = (startDate.getTime() - startFirstDate.getTime()) / minuteMs / minuteSize
454
- const endSubtract = (endDate.getTime() - endFirstDate.getTime()) / minuteMs / minuteSize
455
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / minuteMs + 1) / minuteSize
456
- const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtract
457
- // 如果最小轴为天,当存在时分秒时,在当前单元格内渲染维度;如果不存在,则填充满单元格
458
- return {
459
- offsetLeftSize,
460
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize + (startSubtract || endSubtract ? 0 : 1)
461
- }
462
- }
463
- }
464
- case 'hour': {
465
- const indexMaps: Record<string, number> = {}
466
- fullCols.forEach(({ dateObj }, i) => {
467
- const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM-dd HH')
468
- indexMaps[yyyyMM] = i
469
- })
470
- return (startValue: any, endValue: any) => {
471
- const startDate = parseStringDate($xeGanttView, startValue)
472
- const endDate = parseStringDate($xeGanttView, endValue)
473
- const startStr = XEUtils.toDateString(startDate, 'yyyy-MM-dd HH')
474
- const startFirstDate = XEUtils.getWhatHours(startDate, 0, 'first')
475
- const endStr = XEUtils.toDateString(endDate, 'yyyy-MM-dd HH')
476
- const endFirstDate = XEUtils.getWhatHours(endDate, 0, 'first')
477
- const minuteSize = Math.floor((XEUtils.getWhatHours(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / minuteMs)
478
- // 开始和结束时间是否存在偏移时
479
- const startSubtract = (startDate.getTime() - startFirstDate.getTime()) / minuteMs / minuteSize
480
- const endSubtract = (endDate.getTime() - endFirstDate.getTime()) / minuteMs / minuteSize
481
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / minuteMs + 1) / minuteSize
482
- const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtract
483
- return {
484
- offsetLeftSize,
485
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize + (startSubtract || endSubtract ? 0 : 1)
486
- }
487
- }
488
- }
489
- case 'minute': {
490
- const indexMaps: Record<string, number> = {}
491
- fullCols.forEach(({ dateObj }, i) => {
492
- const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM-dd HH:mm')
493
- indexMaps[yyyyMM] = i
494
- })
495
- return (startValue: any, endValue: any) => {
496
- const startDate = parseStringDate($xeGanttView, startValue)
497
- const endDate = parseStringDate($xeGanttView, endValue)
498
- const startStr = XEUtils.toDateString(startDate, 'yyyy-MM-dd HH:mm')
499
- const startFirstDate = XEUtils.getWhatMinutes(startDate, 0, 'first')
500
- const endStr = XEUtils.toDateString(endDate, 'yyyy-MM-dd HH:mm')
501
- const endFirstDate = XEUtils.getWhatMinutes(endDate, 0, 'first')
502
- const minuteSize = Math.floor((XEUtils.getWhatMinutes(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / minuteMs)
503
- const subtract = (startDate.getTime() - startFirstDate.getTime()) / minuteMs / minuteSize
504
- const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / minuteMs + 1) / minuteSize
505
- const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
506
- return {
507
- offsetLeftSize,
508
- offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
509
- }
510
- }
511
- }
512
- case 'second': {
513
- const gapTime = getStandardGapTime(minScale.type)
514
- return (startValue: any, endValue: any) => {
515
- const startDate = parseStringDate($xeGanttView, startValue)
516
- const endDate = parseStringDate($xeGanttView, endValue)
517
- let offsetLeftSize = 0
518
- let offsetWidthSize = 0
519
- if (minViewDate) {
520
- offsetLeftSize = (startDate.getTime() - minViewDate.getTime()) / gapTime
521
- offsetWidthSize = ((endDate.getTime() - startDate.getTime()) / gapTime)
522
- }
523
- return {
524
- offsetLeftSize,
525
- offsetWidthSize
526
- }
527
- }
528
- }
529
- }
530
- }
531
- return () => {
532
- return {
533
- offsetLeftSize: 0,
534
- offsetWidthSize: 0
535
- }
536
- }
537
- }
538
-
539
- function handleParseColumn ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
540
- const $xeGantt = $xeGanttView.$xeGantt
541
- const reactData = $xeGanttView.reactData
542
- const internalData = $xeGanttView.internalData
543
-
544
- const ganttProps = $xeGantt
545
- const { treeConfig } = ganttProps
546
- const { minViewDate, maxViewDate } = reactData
547
- const { fullCols, groupCols } = handleColumnHeader($xeGanttView)
548
- if (minViewDate && maxViewDate) {
549
- const $xeTable = internalData.xeTable
550
- if ($xeTable) {
551
- const startField = $xeGantt.computeStartField
552
- const endField = $xeGantt.computeEndField
553
- const typeField = $xeGantt.computeTypeField
554
- const tableReactData = $xeTable as unknown as TableReactData
555
- const { isRowGroupStatus } = tableReactData
556
- const tableInternalData = $xeTable as unknown as TableInternalData
557
- const { afterFullData, afterTreeFullData, afterGroupFullData } = tableInternalData
558
- const aggregateOpts = $xeTable.computeAggregateOpts
559
- const treeOpts = $xeTable.computeTreeOpts
560
- const { transform } = treeOpts
561
- const childrenField = treeOpts.children || treeOpts.childrenField
562
-
563
- const ctMaps: Record<string, VxeGanttDefines.RowCacheItem> = {}
564
- const renderFn = createChartRender($xeGanttView, fullCols)
565
- const handleParseRender = (row: any) => {
566
- const rowid = $xeTable.getRowid(row)
567
- let startValue = XEUtils.get(row, startField)
568
- let endValue = XEUtils.get(row, endField)
569
- const renderTaskType = getTaskType(XEUtils.get(row, typeField))
570
- const isMilestone = hasMilestoneTask(renderTaskType)
571
- const isSubview = hasSubviewTask(renderTaskType)
572
- if (isMilestone) {
573
- if (!startValue) {
574
- startValue = endValue
575
- }
576
- endValue = startValue
577
- }
578
- if (isSubview) {
579
- ctMaps[rowid] = {
580
- row,
581
- rowid,
582
- oLeftSize: 0,
583
- oWidthSize: 0
584
- }
585
- } else if (startValue && endValue) {
586
- const { offsetLeftSize, offsetWidthSize } = renderFn(startValue, endValue)
587
- ctMaps[rowid] = {
588
- row,
589
- rowid,
590
- oLeftSize: offsetLeftSize,
591
- oWidthSize: offsetWidthSize
592
- }
593
- }
594
- }
595
-
596
- if (isRowGroupStatus) {
597
- // 行分组
598
- const mapChildrenField = aggregateOpts.mapChildrenField
599
- if (mapChildrenField) {
600
- XEUtils.eachTree(afterGroupFullData, handleParseRender, { children: mapChildrenField })
601
- }
602
- } else if (treeConfig) {
603
- // 树结构
604
- XEUtils.eachTree(afterTreeFullData, handleParseRender, { children: transform ? treeOpts.mapChildrenField : childrenField })
605
- } else {
606
- afterFullData.forEach(handleParseRender)
607
- }
608
- internalData.chartMaps = ctMaps
609
- }
610
- }
611
- internalData.visibleColumn = fullCols
612
- reactData.headerGroups = groupCols
613
- updateTodayData($xeGanttView)
614
- updateScrollXStatus($xeGanttView)
615
- handleTableColumn($xeGanttView)
616
- }
617
-
618
- function handleUpdateData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
619
- const $xeGantt = $xeGanttView.$xeGantt
620
- const reactData = $xeGanttView.reactData
621
- const internalData = $xeGanttView.internalData
622
-
623
- const ganttProps = $xeGantt
624
- const { treeConfig } = ganttProps
625
- const { scrollXStore } = internalData
626
- const $xeTable = internalData.xeTable
627
- const sdMaps: Record<string, any> = {}
628
- const edMaps: Record<string, any> = {}
629
- let minDate: Date | null = null
630
- let maxDate: Date | null = null
631
- if ($xeTable) {
632
- const startField = $xeGantt.computeStartField
633
- const endField = $xeGantt.computeEndField
634
- const typeField = $xeGantt.computeTypeField
635
- const tableReactData = $xeTable as unknown as TableReactData
636
- const { isRowGroupStatus } = tableReactData
637
- const tableInternalData = $xeTable as unknown as TableInternalData
638
- const { afterFullData, afterTreeFullData, afterGroupFullData } = tableInternalData
639
- const aggregateOpts = $xeTable.computeAggregateOpts
640
- const treeOpts = $xeTable.computeTreeOpts
641
- const { transform } = treeOpts
642
- const childrenField = treeOpts.children || treeOpts.childrenField
643
-
644
- const handleMinMaxData = (row: any) => {
645
- let startValue = XEUtils.get(row, startField)
646
- let endValue = XEUtils.get(row, endField)
647
- const typeValue = XEUtils.get(row, typeField)
648
- const isMilestone = hasMilestoneTask(typeValue)
649
- if (!startValue) {
650
- startValue = endValue
651
- }
652
- if (isMilestone || !endValue) {
653
- endValue = startValue
654
- }
655
- if (startValue) {
656
- const startDate = parseStringDate($xeGanttView, startValue)
657
- if (!minDate || minDate.getTime() > startDate.getTime()) {
658
- minDate = startDate
659
- }
660
- }
661
- if (endValue) {
662
- const endDate = parseStringDate($xeGanttView, endValue)
663
- if (!maxDate || maxDate.getTime() < endDate.getTime()) {
664
- maxDate = endDate
665
- }
666
- }
667
- }
668
-
669
- if (isRowGroupStatus) {
670
- // 行分组
671
- const mapChildrenField = aggregateOpts.mapChildrenField
672
- if (mapChildrenField) {
673
- XEUtils.eachTree(afterGroupFullData, handleMinMaxData, { children: mapChildrenField })
674
- }
675
- } else if (treeConfig) {
676
- // 树结构
677
- XEUtils.eachTree(afterTreeFullData, handleMinMaxData, { children: transform ? treeOpts.mapChildrenField : childrenField })
678
- } else {
679
- afterFullData.forEach(handleMinMaxData)
680
- }
681
- }
682
- scrollXStore.startIndex = 0
683
- scrollXStore.endIndex = Math.max(1, scrollXStore.visibleSize)
684
- reactData.minViewDate = minDate
685
- reactData.maxViewDate = maxDate
686
- internalData.startMaps = sdMaps
687
- internalData.endMaps = edMaps
688
- handleParseColumn($xeGanttView)
689
- }
690
-
691
- function calcScrollbar ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
692
- const $xeGantt = $xeGanttView.$xeGantt
693
- const reactData = $xeGanttView.reactData
694
- const internalData = $xeGanttView.internalData
695
-
696
- const { scrollXWidth, scrollYHeight } = reactData
697
- const { elemStore } = internalData
698
- const scrollbarOpts = $xeGantt.computeScrollbarOpts
699
- const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper'])
700
- const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
701
- const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
702
- let overflowY = false
703
- let overflowX = false
704
- if (bodyWrapperElem) {
705
- overflowY = scrollYHeight > bodyWrapperElem.clientHeight
706
- if (yHandleEl) {
707
- reactData.scrollbarWidth = scrollbarOpts.width || (yHandleEl.offsetWidth - yHandleEl.clientWidth) || 14
708
- }
709
- reactData.overflowY = overflowY
710
-
711
- overflowX = scrollXWidth > bodyWrapperElem.clientWidth
712
- if (xHandleEl) {
713
- reactData.scrollbarHeight = scrollbarOpts.height || (xHandleEl.offsetHeight - xHandleEl.clientHeight) || 14
714
- }
715
-
716
- reactData.overflowX = overflowX
717
- }
718
- }
719
-
720
- function handleSubTaskMinMaxSize ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, $xeTable: VxeTableConstructor, list: any[]) {
721
- const $xeGantt = $xeGanttView.$xeGantt
722
- const internalData = $xeGanttView.internalData
723
-
724
- const { chartMaps } = internalData
725
- const treeOpts = $xeTable.computeTreeOpts
726
- const childrenField = treeOpts.children || treeOpts.childrenField
727
-
728
- const typeField = $xeGantt.computeTypeField
729
- let minChildLeftSize = 0
730
- let maxChildLeftSize = 0
731
- XEUtils.eachTree(list, childRow => {
732
- const childRowid = $xeTable.getRowid(childRow)
733
- const renderTaskType = XEUtils.get(childRow, typeField)
734
- if (hasSubviewTask(renderTaskType)) {
735
- return
736
- }
737
- const childChartRest = childRowid ? chartMaps[childRowid] : null
738
- if (childChartRest) {
739
- maxChildLeftSize = Math.max(maxChildLeftSize, childChartRest.oLeftSize + childChartRest.oWidthSize)
740
- minChildLeftSize = minChildLeftSize ? Math.min(minChildLeftSize, childChartRest.oLeftSize) : childChartRest.oLeftSize
741
- }
742
- }, { children: childrenField })
743
- return {
744
- minSize: minChildLeftSize,
745
- maxSize: maxChildLeftSize
746
- }
747
- }
748
-
749
- function updateTaskChartStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
750
- const $xeGantt = $xeGanttView.$xeGantt
751
- const reactData = $xeGanttView.reactData
752
- const internalData = $xeGanttView.internalData
753
- const ganttInternalData = $xeGantt.internalData
754
- const $xeTable = internalData.xeTable
755
-
756
- const { dragBarRow } = ganttInternalData
757
- const { viewCellWidth } = reactData
758
- const { elemStore, chartMaps } = internalData
759
- const chartWrapper = getRefElem(elemStore['main-chart-task-wrapper'])
760
- if (chartWrapper && $xeTable) {
761
- const treeOpts = $xeTable.computeTreeOpts
762
- const childrenField = treeOpts.children || treeOpts.childrenField
763
- XEUtils.arrayEach(chartWrapper.children, (rowEl) => {
764
- const barEl = rowEl.children[0] as HTMLDivElement
765
- if (!barEl) {
766
- return
767
- }
768
- const rowid = rowEl.getAttribute('rowid')
769
- if (dragBarRow && $xeTable.getRowid(dragBarRow) === rowid) {
770
- return
771
- }
772
- const chartRest = rowid ? chartMaps[rowid] : null
773
- const row = chartRest ? chartRest.row : null
774
- // 子任务视图
775
- if (hasClass(barEl, 'is--subview')) {
776
- const childWrapperEl = barEl.firstElementChild as HTMLDivElement
777
- if (childWrapperEl) {
778
- // 行内展示
779
- if (hasClass(childWrapperEl, 'is--inline')) {
780
- XEUtils.arrayEach(childWrapperEl.children, (childRowEl) => {
781
- const childBarEl = childRowEl.children[0] as HTMLDivElement
782
- const childRowid = childBarEl.getAttribute('rowid') || ''
783
- const childChartRest = childRowid ? chartMaps[childRowid] : null
784
- if (childChartRest) {
785
- const childRow = childChartRest.row
786
- // 如果是子视图
787
- if (hasClass(childBarEl, 'is--subview')) {
788
- const subChildren: any[] = childRow[childrenField]
789
- const { minSize: minChildLeftSize, maxSize: maxChildLeftSize } = handleSubTaskMinMaxSize($xeGanttView, $xeTable, subChildren)
790
- childBarEl.style.left = `${viewCellWidth * minChildLeftSize}px`
791
- childBarEl.style.width = `${viewCellWidth * (maxChildLeftSize - minChildLeftSize)}px`
792
- } else {
793
- childBarEl.style.left = `${getTaskBarLeft(childChartRest, viewCellWidth)}px`
794
- if (!hasClass(childBarEl, 'is--milestone')) {
795
- // 里程碑不需要宽度
796
- childBarEl.style.width = `${getTaskBarWidth(childChartRest, viewCellWidth)}px`
797
- }
798
- }
799
- }
800
- })
801
- } else {
802
- // 如果展开子任务
803
- const childRowEl = childWrapperEl.children[0] as HTMLDivElement
804
- const childBarEl = childRowEl ? childRowEl.children[0] as HTMLDivElement : null
805
- if (childBarEl) {
806
- const rowChildren: any[] = row ? row[childrenField] : []
807
- const { minSize: minChildLeftSize, maxSize: maxChildLeftSize } = handleSubTaskMinMaxSize($xeGanttView, $xeTable, rowChildren)
808
- childBarEl.style.left = `${viewCellWidth * minChildLeftSize}px`
809
- childBarEl.style.width = `${viewCellWidth * (maxChildLeftSize - minChildLeftSize)}px`
810
- }
811
- }
812
- }
813
- } else {
814
- barEl.style.left = `${getTaskBarLeft(chartRest, viewCellWidth)}px`
815
- // 里程碑不需要宽度
816
- if (!hasClass(barEl, 'is--milestone')) {
817
- barEl.style.width = `${getTaskBarWidth(chartRest, viewCellWidth)}px`
818
- }
819
- }
820
- })
821
- }
822
- return $xeGanttView.$nextTick()
823
- }
824
-
825
- function updateStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
826
- const $xeGantt = $xeGanttView.$xeGantt as VxeGanttConstructor & VxeGanttPrivateMethods
827
- const reactData = $xeGanttView.reactData
828
- const internalData = $xeGanttView.internalData
829
-
830
- const { scrollbarWidth, scrollbarHeight, headerGroups, tableColumn } = reactData
831
- const { elemStore, visibleColumn } = internalData
832
- const $xeTable = internalData.xeTable
833
-
834
- const el = $xeGanttView.$refs.refElem as HTMLDivElement
835
- if (!el) {
836
- return
837
- }
838
- if (!$xeGantt) {
839
- return
840
- }
841
-
842
- const scrollbarOpts = $xeGantt.computeScrollbarOpts
843
- const scrollbarXToTop = $xeGantt.computeScrollbarXToTop
844
- const scrollbarYToLeft = $xeGantt.computeScrollbarYToLeft
845
-
846
- const xLeftCornerEl = $xeGanttView.$refs.refScrollXLeftCornerElem as HTMLDivElement
847
- const xRightCornerEl = $xeGanttView.$refs.refScrollXRightCornerElem as HTMLDivElement
848
- const scrollXVirtualEl = $xeGanttView.$refs.refScrollXVirtualElem as HTMLDivElement
849
-
850
- let osbWidth = scrollbarWidth
851
- const osbHeight = scrollbarHeight
852
-
853
- let tbHeight = 0
854
- let tHeaderHeight = 0
855
- let tFooterHeight = 0
856
- if ($xeTable) {
857
- const tableInternalData = $xeTable as unknown as TableInternalData
858
- tbHeight = tableInternalData.tBodyHeight
859
- tHeaderHeight = tableInternalData.tHeaderHeight
860
- tFooterHeight = tableInternalData.tFooterHeight
861
- }
862
-
863
- let yScrollbarVisible = 'visible'
864
- if (scrollbarYToLeft || (scrollbarOpts.y && scrollbarOpts.y.visible === false)) {
865
- osbWidth = 0
866
- yScrollbarVisible = 'hidden'
867
- }
868
-
869
- const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
870
- if (headerScrollElem) {
871
- headerScrollElem.style.height = `${tHeaderHeight}px`
872
- headerScrollElem.style.setProperty('--vxe-ui-gantt-view-cell-height', `${tHeaderHeight / headerGroups.length}px`)
873
- }
874
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
875
- if (bodyScrollElem) {
876
- bodyScrollElem.style.height = `${tbHeight}px`
877
- }
878
- const footerScrollElem = getRefElem(elemStore['main-footer-scroll'])
879
- if (footerScrollElem) {
880
- footerScrollElem.style.height = `${tFooterHeight}px`
881
- }
882
-
883
- if (scrollXVirtualEl) {
884
- scrollXVirtualEl.style.height = `${osbHeight}px`
885
- scrollXVirtualEl.style.visibility = 'visible'
886
- }
887
- const xWrapperEl = $xeGanttView.$refs.refScrollXWrapperElem as HTMLDivElement
888
- if (xWrapperEl) {
889
- xWrapperEl.style.left = scrollbarXToTop ? `${osbWidth}px` : ''
890
- xWrapperEl.style.width = `${el.clientWidth - osbWidth}px`
891
- }
892
- if (xLeftCornerEl) {
893
- xLeftCornerEl.style.width = scrollbarXToTop ? `${osbWidth}px` : ''
894
- xLeftCornerEl.style.display = scrollbarXToTop ? (osbHeight ? 'block' : '') : ''
895
- }
896
- if (xRightCornerEl) {
897
- xRightCornerEl.style.width = scrollbarXToTop ? '' : `${osbWidth}px`
898
- xRightCornerEl.style.display = scrollbarXToTop ? '' : (osbHeight ? 'block' : '')
899
- }
900
-
901
- const scrollYVirtualEl = $xeGanttView.$refs.refScrollYVirtualElem as HTMLDivElement
902
- if (scrollYVirtualEl) {
903
- scrollYVirtualEl.style.width = `${osbWidth}px`
904
- scrollYVirtualEl.style.height = `${tbHeight + tHeaderHeight + tFooterHeight}px`
905
- scrollYVirtualEl.style.visibility = yScrollbarVisible
906
- }
907
- const yTopCornerEl = $xeGanttView.$refs.refScrollYTopCornerElem as HTMLDivElement
908
- if (yTopCornerEl) {
909
- yTopCornerEl.style.height = `${tHeaderHeight}px`
910
- yTopCornerEl.style.display = tHeaderHeight ? 'block' : ''
911
- }
912
- const yWrapperEl = $xeGanttView.$refs.refScrollYWrapperElem as HTMLDivElement
913
- if (yWrapperEl) {
914
- yWrapperEl.style.height = `${tbHeight}px`
915
- yWrapperEl.style.top = `${tHeaderHeight}px`
916
- }
917
- const yBottomCornerEl = $xeGanttView.$refs.refScrollYBottomCornerElem as HTMLDivElement
918
- if (yBottomCornerEl) {
919
- yBottomCornerEl.style.height = `${tFooterHeight}px`
920
- yBottomCornerEl.style.top = `${tHeaderHeight + tbHeight}px`
921
- yBottomCornerEl.style.display = tFooterHeight ? 'block' : ''
922
- }
923
-
924
- const colInfoElem = $xeGanttView.$refs.refColInfoElem as HTMLDivElement
925
- let viewCellWidth = 40
926
- if (colInfoElem) {
927
- viewCellWidth = colInfoElem.clientWidth || 40
928
- }
929
- let viewTableWidth = viewCellWidth
930
- if (visibleColumn.length) {
931
- viewTableWidth = Math.max(0, viewCellWidth * visibleColumn.length)
932
- if (bodyScrollElem) {
933
- const viewWidth = bodyScrollElem.clientWidth
934
- const remainWidth = viewWidth - viewTableWidth
935
- if (remainWidth > 0) {
936
- viewCellWidth += Math.max(0, remainWidth / visibleColumn.length)
937
- viewTableWidth = viewWidth
938
- }
939
- }
940
- }
941
- reactData.viewCellWidth = viewCellWidth
942
- const headerTableElem = getRefElem(elemStore['main-header-table'])
943
- const bodyTableElem = getRefElem(elemStore['main-body-table'])
944
- const vmTableWidth = viewCellWidth * tableColumn.length
945
- if (headerTableElem) {
946
- headerTableElem.style.width = `${viewTableWidth}px`
947
- }
948
- if (bodyTableElem) {
949
- bodyTableElem.style.width = `${vmTableWidth}px`
950
- }
951
-
952
- reactData.scrollXWidth = viewTableWidth
953
-
954
- return Promise.all([
955
- updateTaskChartStyle($xeGanttView),
956
- $xeGantt.handleUpdateTaskLinkStyle ? $xeGantt.handleUpdateTaskLinkStyle($xeGanttView) : null
957
- ])
958
- }
959
-
960
- function handleRecalculateStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
961
- const internalData = $xeGanttView.internalData
962
- const $xeGantt = $xeGanttView.$xeGantt
963
-
964
- const el = $xeGanttView.$refs.refElem as HTMLDivElement
965
- internalData.rceRunTime = Date.now()
966
- if (!el || !el.clientWidth) {
967
- return $xeGanttView.$nextTick()
968
- }
969
- if (!$xeGantt) {
970
- return $xeGanttView.$nextTick()
971
- }
972
- calcScrollbar($xeGanttView)
973
- updateStyle($xeGanttView)
974
- return computeScrollLoad($xeGanttView)
975
- }
976
-
977
- function handleLazyRecalculate ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
978
- const internalData = $xeGanttView.internalData
979
-
980
- return new Promise<void>(resolve => {
981
- const { rceTimeout, rceRunTime } = internalData
982
- const $xeTable = internalData.xeTable
983
- let refreshDelay = 30
984
- if ($xeTable) {
985
- const resizeOpts = $xeTable.computeResizeOpts
986
- refreshDelay = resizeOpts.refreshDelay || refreshDelay
987
- }
988
- if (rceTimeout) {
989
- clearTimeout(rceTimeout)
990
- if (rceRunTime && rceRunTime + (refreshDelay - 5) < Date.now()) {
991
- resolve(
992
- handleRecalculateStyle($xeGanttView)
993
- )
994
- } else {
995
- $xeGanttView.$nextTick(() => {
996
- resolve()
997
- })
998
- }
999
- } else {
1000
- resolve(
1001
- handleRecalculateStyle($xeGanttView)
1002
- )
1003
- }
1004
- internalData.rceTimeout = setTimeout(() => {
1005
- internalData.rceTimeout = undefined
1006
- handleRecalculateStyle($xeGanttView)
1007
- }, refreshDelay)
1008
- })
1009
- }
1010
-
1011
- function computeScrollLoad ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1012
- const reactData = $xeGanttView.reactData
1013
- const internalData = $xeGanttView.internalData
1014
-
1015
- return $xeGanttView.$nextTick().then(() => {
1016
- const { scrollXLoad } = reactData
1017
- const { scrollXStore } = internalData
1018
- // 计算 X 逻辑
1019
- if (scrollXLoad) {
1020
- const { toVisibleIndex: toXVisibleIndex, visibleSize: visibleXSize } = handleVirtualXVisible($xeGanttView)
1021
- const offsetXSize = 2
1022
- scrollXStore.preloadSize = 1
1023
- scrollXStore.offsetSize = offsetXSize
1024
- scrollXStore.visibleSize = visibleXSize
1025
- scrollXStore.endIndex = Math.max(scrollXStore.startIndex + scrollXStore.visibleSize + offsetXSize, scrollXStore.endIndex)
1026
- scrollXStore.visibleStartIndex = Math.max(scrollXStore.startIndex, toXVisibleIndex)
1027
- scrollXStore.visibleEndIndex = Math.min(scrollXStore.endIndex, toXVisibleIndex + visibleXSize)
1028
- updateScrollXData($xeGanttView).then(() => {
1029
- loadScrollXData($xeGanttView)
1030
- })
1031
- } else {
1032
- updateScrollXSpace($xeGanttView)
1033
- }
1034
- })
1035
- }
1036
-
1037
- function handleVirtualXVisible ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1038
- const reactData = $xeGanttView.reactData
1039
- const internalData = $xeGanttView.internalData
1040
-
1041
- const { viewCellWidth } = reactData
1042
- const { elemStore } = internalData
1043
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1044
- if (bodyScrollElem) {
1045
- const clientWidth = bodyScrollElem.clientWidth
1046
- const scrollLeft = bodyScrollElem.scrollLeft
1047
- const toVisibleIndex = Math.floor(scrollLeft / viewCellWidth) - 1
1048
- const visibleSize = Math.ceil(clientWidth / viewCellWidth) + 1
1049
- return { toVisibleIndex: Math.max(0, toVisibleIndex), visibleSize: Math.max(1, visibleSize) }
1050
- }
1051
- return { toVisibleIndex: 0, visibleSize: 6 }
1052
- }
1053
-
1054
- function loadScrollXData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1055
- const reactData = $xeGanttView.reactData
1056
- const internalData = $xeGanttView.internalData
1057
-
1058
- const { isScrollXBig } = reactData
1059
- const { scrollXStore } = internalData
1060
- const { preloadSize, startIndex, endIndex, offsetSize } = scrollXStore
1061
- const { toVisibleIndex, visibleSize } = handleVirtualXVisible($xeGanttView)
1062
- const offsetItem = {
1063
- startIndex: Math.max(0, isScrollXBig ? toVisibleIndex - 1 : toVisibleIndex - 1 - offsetSize - preloadSize),
1064
- endIndex: isScrollXBig ? toVisibleIndex + visibleSize : toVisibleIndex + visibleSize + offsetSize + preloadSize
1065
- }
1066
- scrollXStore.visibleStartIndex = toVisibleIndex - 1
1067
- scrollXStore.visibleEndIndex = toVisibleIndex + visibleSize + 1
1068
- const { startIndex: offsetStartIndex, endIndex: offsetEndIndex } = offsetItem
1069
- if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
1070
- if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
1071
- scrollXStore.startIndex = offsetStartIndex
1072
- scrollXStore.endIndex = offsetEndIndex
1073
- updateScrollXData($xeGanttView)
1074
- }
1075
- }
1076
- }
1077
-
1078
- function updateScrollXData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1079
- handleTableColumn($xeGanttView)
1080
- updateScrollXSpace($xeGanttView)
1081
- return $xeGanttView.$nextTick()
1082
- }
1083
-
1084
- function updateScrollXStatus ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1085
- const reactData = $xeGanttView.reactData
1086
-
1087
- const scrollXLoad = true
1088
- reactData.scrollXLoad = scrollXLoad
1089
- return scrollXLoad
1090
- }
1091
-
1092
- function handleTableColumn ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1093
- const reactData = $xeGanttView.reactData
1094
- const internalData = $xeGanttView.internalData
1095
-
1096
- const { scrollXLoad } = reactData
1097
- const { visibleColumn, scrollXStore } = internalData
1098
- const tableColumn = scrollXLoad ? visibleColumn.slice(scrollXStore.startIndex, scrollXStore.endIndex) : visibleColumn.slice(0)
1099
- reactData.tableColumn = tableColumn
1100
- }
1101
-
1102
- function updateScrollXSpace ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1103
- const reactData = $xeGanttView.reactData
1104
- const internalData = $xeGanttView.internalData
1105
-
1106
- const { scrollXLoad, scrollXWidth, viewCellWidth } = reactData
1107
- const { elemStore, scrollXStore } = internalData
1108
- const bodyTableElem = getRefElem(elemStore['main-body-table'])
1109
- // const headerTableElem = getRefElem(elemStore['main-header-table'])
1110
- // const footerTableElem = getRefElem(elemStore['main-footer-table'])
1111
-
1112
- const { startIndex } = scrollXStore
1113
- let xSpaceLeft = 0
1114
- if (scrollXLoad) {
1115
- xSpaceLeft = Math.max(0, startIndex * viewCellWidth)
1116
- }
1117
-
1118
- // if (headerTableElem) {
1119
- // headerTableElem.style.transform = `translate(${xSpaceLeft}px, 0px)`
1120
- // }
1121
- if (bodyTableElem) {
1122
- bodyTableElem.style.transform = `translate(${xSpaceLeft}px, ${reactData.scrollYTop || 0}px)`
1123
- }
1124
- // if (footerTableElem) {
1125
- // footerTableElem.style.transform = `translate(${xSpaceLeft}px, 0px)`
1126
- // }
1127
-
1128
- const ySpaceWidth = scrollXWidth
1129
-
1130
- const layoutList = ['header', 'body', 'footer']
1131
- layoutList.forEach(layout => {
1132
- const xSpaceElem = getRefElem(elemStore[`main-${layout}-xSpace`])
1133
- if (xSpaceElem) {
1134
- xSpaceElem.style.width = scrollXLoad ? `${ySpaceWidth}px` : ''
1135
- }
1136
- })
1137
-
1138
- const scrollXSpaceEl = $xeGanttView.$refs.refScrollXSpaceElem as HTMLDivElement
1139
- if (scrollXSpaceEl) {
1140
- scrollXSpaceEl.style.width = `${ySpaceWidth}px`
1141
- }
1142
-
1143
- const beforeWrapper = getRefElem(elemStore['main-chart-before-wrapper'])
1144
- const beforeSvgElem = beforeWrapper ? beforeWrapper.firstElementChild as HTMLDivElement : null
1145
- if (beforeSvgElem) {
1146
- beforeSvgElem.style.width = `${ySpaceWidth}px`
1147
- }
1148
- const afterWrapper = getRefElem(elemStore['main-chart-after-wrapper'])
1149
- const afterSvgElem = afterWrapper ? afterWrapper.firstElementChild as HTMLDivElement : null
1150
- if (afterSvgElem) {
1151
- afterSvgElem.style.width = `${ySpaceWidth}px`
1152
- }
1153
-
1154
- reactData.scrollXLeft = xSpaceLeft
1155
- reactData.scrollXWidth = ySpaceWidth
1156
-
1157
- calcScrollbar($xeGanttView)
1158
- return $xeGanttView.$nextTick()
1159
- }
1160
-
1161
- function triggerScrollXEvent ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1162
- loadScrollXData($xeGanttView)
1163
- }
1164
-
1165
- function updateScrollYSpace ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1166
- const reactData = $xeGanttView.reactData
1167
- const internalData = $xeGanttView.internalData
1168
-
1169
- const { scrollYLoad, overflowY } = reactData
1170
- const { elemStore } = internalData
1171
- const $xeTable = internalData.xeTable
1172
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1173
- const bodyTableElem = getRefElem(elemStore['main-body-table'])
1174
-
1175
- let ySpaceTop = 0
1176
- let scrollYHeight = 0
1177
- let isScrollYBig = false
1178
- if ($xeTable) {
1179
- const tableReactData = $xeTable as unknown as TableReactData
1180
- ySpaceTop = tableReactData.scrollYTop
1181
- scrollYHeight = tableReactData.scrollYHeight
1182
- isScrollYBig = tableReactData.isScrollYBig
1183
- }
1184
-
1185
- let ySpaceHeight = scrollYHeight
1186
- let scrollYTop = ySpaceTop
1187
-
1188
- let clientHeight = 0
1189
- if (bodyScrollElem) {
1190
- clientHeight = bodyScrollElem.clientHeight
1191
- }
1192
- if (isScrollYBig) {
1193
- // 触底
1194
- if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollTop + clientHeight >= maxYHeight) {
1195
- scrollYTop = maxYHeight - bodyTableElem.clientHeight
1196
- } else {
1197
- scrollYTop = (maxYHeight - clientHeight) * (ySpaceTop / (scrollYHeight - clientHeight))
1198
- }
1199
- ySpaceHeight = maxYHeight
1200
- }
1201
- if (!(scrollYLoad && overflowY)) {
1202
- scrollYTop = 0
1203
- }
1204
-
1205
- const bodyChartWrapperElem = getRefElem(elemStore['main-chart-task-wrapper'])
1206
- if (bodyTableElem) {
1207
- bodyTableElem.style.transform = `translate(${reactData.scrollXLeft || 0}px, ${scrollYTop}px)`
1208
- }
1209
- if (bodyChartWrapperElem) {
1210
- bodyChartWrapperElem.style.transform = `translateY(${scrollYTop}px)`
1211
- }
1212
-
1213
- const bodyYSpaceElem = getRefElem(elemStore['main-body-ySpace'])
1214
- if (bodyYSpaceElem) {
1215
- bodyYSpaceElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1216
- }
1217
-
1218
- const scrollYSpaceEl = $xeGanttView.$refs.refScrollYSpaceElem as HTMLDivElement
1219
- if (scrollYSpaceEl) {
1220
- scrollYSpaceEl.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1221
- }
1222
-
1223
- const beforeWrapper = getRefElem(elemStore['main-chart-before-wrapper'])
1224
- const beforeSvgElem = beforeWrapper ? beforeWrapper.firstElementChild as HTMLDivElement : null
1225
- if (beforeSvgElem) {
1226
- beforeSvgElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1227
- }
1228
- const afterWrapper = getRefElem(elemStore['main-chart-after-wrapper'])
1229
- const afterSvgElem = afterWrapper ? afterWrapper.firstElementChild as HTMLDivElement : null
1230
- if (afterSvgElem) {
1231
- afterSvgElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1232
- }
1233
-
1234
- const nowLineElem = getRefElem(elemStore['main-chart-now-line'])
1235
- if (nowLineElem) {
1236
- nowLineElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1237
- }
1238
-
1239
- reactData.scrollYTop = scrollYTop
1240
- reactData.scrollYHeight = scrollYHeight
1241
- reactData.isScrollYBig = isScrollYBig
1242
-
1243
- calcScrollbar($xeGanttView)
1244
- return $xeGanttView.$nextTick().then(() => {
1245
- updateStyle($xeGanttView)
1246
- })
1247
- }
1248
-
1249
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1250
- function checkLastSyncScroll ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, isRollX: boolean, isRollY: boolean) {
1251
- const reactData = $xeGanttView.reactData
1252
- const internalData = $xeGanttView.internalData
1253
-
1254
- const { lcsTimeout } = internalData
1255
- reactData.lazScrollLoading = true
1256
- if (lcsTimeout) {
1257
- clearTimeout(lcsTimeout)
1258
- }
1259
- internalData.lcsTimeout = setTimeout(() => {
1260
- internalData.lcsRunTime = Date.now()
1261
- internalData.lcsTimeout = undefined
1262
- internalData.intoRunScroll = false
1263
- internalData.inVirtualScroll = false
1264
- internalData.inWheelScroll = false
1265
- internalData.inHeaderScroll = false
1266
- internalData.inBodyScroll = false
1267
- internalData.inFooterScroll = false
1268
- reactData.lazScrollLoading = false
1269
- }, 200)
1270
- }
1271
-
1272
- function handleScrollData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, isRollY: boolean, isRollX: boolean, scrollTop: number, scrollLeft: number) {
1273
- const reactData = $xeGanttView.reactData
1274
- const internalData = $xeGanttView.internalData
1275
-
1276
- if (isRollX) {
1277
- internalData.lastScrollLeft = scrollLeft
1278
- }
1279
- if (isRollY) {
1280
- internalData.lastScrollTop = scrollTop
1281
- }
1282
- reactData.lastScrollTime = Date.now()
1283
- checkLastSyncScroll($xeGanttView, isRollX, isRollY)
1284
- }
1285
-
1286
- function handleScrollEvent ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, evnt: Event, isRollY: boolean, isRollX: boolean, scrollTop: number, scrollLeft: number) {
1287
- const $xeGantt = $xeGanttView.$xeGantt
1288
- const internalData = $xeGanttView.internalData
1289
- const $xeTable = internalData.xeTable
1290
-
1291
- const { lastScrollLeft, lastScrollTop } = internalData
1292
- const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
1293
- const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
1294
- if (!xHandleEl || !yHandleEl) {
1295
- return
1296
- }
1297
- if (!$xeTable) {
1298
- return
1299
- }
1300
- const bodyHeight = yHandleEl.clientHeight
1301
- const bodyWidth = xHandleEl.clientWidth
1302
- const scrollHeight = yHandleEl.scrollHeight
1303
- const scrollWidth = xHandleEl.scrollWidth
1304
- let isTop = false
1305
- let isBottom = false
1306
- let isLeft = false
1307
- let isRight = false
1308
- let direction = ''
1309
- let isTopBoundary = false
1310
- let isBottomBoundary = false
1311
- let isLeftBoundary = false
1312
- let isRightBoundary = false
1313
- if (isRollX) {
1314
- const xThreshold = $xeTable.computeScrollXThreshold
1315
- isLeft = scrollLeft <= 0
1316
- if (!isLeft) {
1317
- isRight = scrollLeft + bodyWidth >= scrollWidth - 1
1318
- }
1319
- if (scrollLeft > lastScrollLeft) {
1320
- direction = 'right'
1321
- if (scrollLeft + bodyWidth >= scrollWidth - xThreshold) {
1322
- isRightBoundary = true
1323
- }
1324
- } else {
1325
- direction = 'left'
1326
- if (scrollLeft <= xThreshold) {
1327
- isLeftBoundary = true
1328
- }
1329
- }
1330
- }
1331
- if (isRollY) {
1332
- const yThreshold = $xeTable.computeScrollYThreshold
1333
- isTop = scrollTop <= 0
1334
- if (!isTop) {
1335
- isBottom = scrollTop + bodyHeight >= scrollHeight - 1
1336
- }
1337
- if (scrollTop > lastScrollTop) {
1338
- direction = 'bottom'
1339
- if (scrollTop + bodyHeight >= scrollHeight - yThreshold) {
1340
- isBottomBoundary = true
1341
- }
1342
- } else {
1343
- direction = 'top'
1344
- if (scrollTop <= yThreshold) {
1345
- isTopBoundary = true
1346
- }
1347
- }
1348
- }
1349
- handleScrollData($xeGanttView, isRollY, isRollX, scrollTop, scrollLeft)
1350
- const evntParams = {
1351
- source: sourceType,
1352
- scrollTop,
1353
- scrollLeft,
1354
- bodyHeight,
1355
- bodyWidth,
1356
- scrollHeight,
1357
- scrollWidth,
1358
- isX: isRollX,
1359
- isY: isRollY,
1360
- isTop,
1361
- isBottom,
1362
- isLeft,
1363
- isRight,
1364
- direction
1365
- }
1366
- if (isBottomBoundary || isTopBoundary || isRightBoundary || isLeftBoundary) {
1367
- $xeGantt.dispatchEvent('scroll-boundary', evntParams, evnt)
1368
- }
1369
- $xeGantt.dispatchEvent('scroll', evntParams, evnt)
1370
- }
1371
-
1372
- /**
1373
- * 同步表格滚动
1374
- */
1375
- function syncTableScrollTop ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, scrollTop: number) {
1376
- const internalData = $xeGanttView.internalData
1377
-
1378
- const $xeTable = internalData.xeTable
1379
- if ($xeTable) {
1380
- const tableInternalData = $xeTable as unknown as TableInternalData
1381
- const { elemStore: tableElemStore } = tableInternalData
1382
- const tableBodyScrollElem = getRefElem(tableElemStore['main-body-scroll'])
1383
- if (tableBodyScrollElem) {
1384
- tableBodyScrollElem.scrollTop = scrollTop
1385
- }
1386
- }
1387
- }
1388
-
1389
- export default defineVxeComponent({
1390
- name: 'VxeGanttView',
1391
- inject: {
1392
- $xeGantt: {
1393
- default: null
1394
- }
1395
- },
1396
- provide () {
1397
- const $xeGanttView = this
1398
-
1399
- return {
1400
- $xeGanttView
1401
- }
1402
- },
1403
- props: {},
1404
- data () {
1405
- const xID = XEUtils.uniqueId()
1406
-
1407
- const reactData = createReactData()
1408
-
1409
- const internalData = createInternalData()
1410
-
1411
- return {
1412
- xID,
1413
- reactData,
1414
- internalData
1415
- }
1416
- },
1417
- computed: {
1418
- ...({} as {
1419
- $xeGantt(): (VxeGanttConstructor & VxeGanttPrivateMethods)
1420
- }),
1421
- computeScaleDateList () {
1422
- const $xeGanttView = this
1423
- const $xeGantt = $xeGanttView.$xeGantt
1424
- const reactData = $xeGanttView.reactData
1425
- const ganttReactData = $xeGantt.reactData
1426
-
1427
- const { minViewDate, maxViewDate } = reactData
1428
- const taskViewOpts = $xeGantt.computeTaskViewOpts
1429
- const minScale = $xeGantt.computeMinScale
1430
- const { gridding } = taskViewOpts
1431
- const dateList: Date[] = []
1432
- if (!minScale || !minViewDate || !maxViewDate) {
1433
- return dateList
1434
- }
1435
- const { type, startDay } = minScale
1436
-
1437
- const leftSize = -(ganttReactData.currLeftSpacing + XEUtils.toNumber(gridding ? gridding.leftSpacing || 0 : 0))
1438
- const rightSize = ganttReactData.currRightSpacing + XEUtils.toNumber(gridding ? gridding.rightSpacing || 0 : 0)
1439
- const currStep = 1// XEUtils.toNumber(step || 1) || 1
1440
- switch (type) {
1441
- case 'year': {
1442
- let currDate = XEUtils.getWhatYear(minViewDate, leftSize, 'first')
1443
- const endDate = XEUtils.getWhatYear(maxViewDate, rightSize, 'first')
1444
- while (currDate <= endDate) {
1445
- const itemDate = currDate
1446
- dateList.push(itemDate)
1447
- currDate = XEUtils.getWhatYear(currDate, currStep)
1448
- }
1449
- break
1450
- }
1451
- case 'quarter': {
1452
- let currDate = XEUtils.getWhatQuarter(minViewDate, leftSize, 'first')
1453
- const endDate = XEUtils.getWhatQuarter(maxViewDate, rightSize, 'first')
1454
- while (currDate <= endDate) {
1455
- const itemDate = currDate
1456
- dateList.push(itemDate)
1457
- currDate = XEUtils.getWhatQuarter(currDate, currStep)
1458
- }
1459
- break
1460
- }
1461
- case 'month': {
1462
- let currDate = XEUtils.getWhatMonth(minViewDate, leftSize, 'first')
1463
- const endDate = XEUtils.getWhatMonth(maxViewDate, rightSize, 'first')
1464
- while (currDate <= endDate) {
1465
- const itemDate = currDate
1466
- dateList.push(itemDate)
1467
- currDate = XEUtils.getWhatMonth(currDate, currStep)
1468
- }
1469
- break
1470
- }
1471
- case 'week': {
1472
- let currDate = XEUtils.getWhatWeek(minViewDate, leftSize, startDay, startDay)
1473
- const endDate = XEUtils.getWhatWeek(maxViewDate, rightSize, startDay, startDay)
1474
- while (currDate <= endDate) {
1475
- const itemDate = currDate
1476
- dateList.push(itemDate)
1477
- currDate = XEUtils.getWhatWeek(currDate, currStep)
1478
- }
1479
- break
1480
- }
1481
- case 'day':
1482
- case 'date': {
1483
- let currDate = XEUtils.getWhatDay(minViewDate, leftSize, 'first')
1484
- const endDate = XEUtils.getWhatDay(maxViewDate, rightSize, 'first')
1485
- while (currDate <= endDate) {
1486
- const itemDate = currDate
1487
- dateList.push(itemDate)
1488
- currDate = XEUtils.getWhatDay(currDate, currStep)
1489
- }
1490
- break
1491
- }
1492
- case 'hour':
1493
- case 'minute':
1494
- case 'second': {
1495
- const gapTime = getStandardGapTime(minScale.type) * currStep
1496
- let currTime = minViewDate.getTime() + (leftSize * gapTime)
1497
- const endTime = maxViewDate.getTime() + (rightSize * gapTime)
1498
- while (currTime <= endTime) {
1499
- const itemDate = new Date(currTime)
1500
- dateList.push(itemDate)
1501
- currTime += gapTime
1502
- }
1503
- break
1504
- }
1505
- }
1506
- return dateList
1507
- },
1508
- computeNowLineLeft () {
1509
- const $xeGanttView = this
1510
- const $xeGantt = $xeGanttView.$xeGantt
1511
- const reactData = $xeGanttView.reactData
1512
- const internalData = $xeGanttView.internalData
1513
- const ganttReactData = $xeGantt.reactData
1514
-
1515
- const { minViewDate, maxViewDate, viewCellWidth } = reactData
1516
- const { visibleColumn, todayDateMaps } = internalData
1517
- const minScale = $xeGantt.computeMinScale
1518
- const taskViewOpts = $xeGantt.computeTaskViewOpts
1519
- const taskNowLineOpts = $xeGantt.computeTaskNowLineOpts
1520
- const { showNowLine } = taskViewOpts
1521
- const { mode } = taskNowLineOpts
1522
- const { nowTime } = ganttReactData
1523
-
1524
- // 此刻线
1525
- let nlLeft = 0
1526
- if (showNowLine && minScale && minViewDate && maxViewDate && nowTime >= minViewDate.getTime() && nowTime <= maxViewDate.getTime()) {
1527
- const todayValue = todayDateMaps[minScale.type]
1528
- let currCol: VxeGanttDefines.ViewColumn | null = null
1529
- let nextCol: VxeGanttDefines.ViewColumn | null = null
1530
- for (let i = 0; i < visibleColumn.length; i++) {
1531
- const column = visibleColumn[i]
1532
- if (column.field === todayValue) {
1533
- currCol = column
1534
- nlLeft = i * viewCellWidth
1535
- nextCol = visibleColumn[i + 1]
1536
- break
1537
- }
1538
- }
1539
- if (mode === 'progress') {
1540
- if (currCol && nextCol) {
1541
- const currTime = currCol.dateObj.date.getTime()
1542
- const offsetTime = nowTime - currTime
1543
- const nowProgress = Math.max(0, Math.min(1, offsetTime / (nextCol.dateObj.date.getTime() - currTime)))
1544
- nlLeft += nowProgress * viewCellWidth
1545
- }
1546
- } else if (mode === 'center') {
1547
- nlLeft += viewCellWidth / 2
1548
- } else if (mode === 'end') {
1549
- nlLeft += viewCellWidth - 1
1550
- }
1551
- }
1552
- return nlLeft
1553
- }
1554
- },
1555
- methods: {
1556
- //
1557
- // Method
1558
- //
1559
- refreshData (): Promise<void> {
1560
- const $xeGanttView = this
1561
- const internalData = $xeGanttView.internalData
1562
-
1563
- handleUpdateData($xeGanttView)
1564
- handleRecalculateStyle($xeGanttView)
1565
- return $xeGanttView.$nextTick().then(() => {
1566
- const $xeTable = internalData.xeTable
1567
- handleRecalculateStyle($xeGanttView)
1568
- if ($xeTable) {
1569
- return $xeTable.recalculate()
1570
- }
1571
- })
1572
- },
1573
- updateViewData (force?: boolean): Promise<void> {
1574
- const $xeGanttView = this
1575
- const $xeGantt = $xeGanttView.$xeGantt
1576
- const reactData = $xeGanttView.reactData
1577
- const internalData = $xeGanttView.internalData
1578
- const ganttReactData = $xeGantt.reactData
1579
-
1580
- const $xeTable = internalData.xeTable
1581
- if ($xeTable) {
1582
- const tableReactData = $xeTable as unknown as TableReactData
1583
- const { tableData } = tableReactData
1584
- reactData.tableData = tableData
1585
- if (force) {
1586
- ganttReactData.currLeftSpacing = 0
1587
- ganttReactData.currRightSpacing = 0
1588
- handleUpdateData($xeGanttView)
1589
- }
1590
- handleRecalculateStyle($xeGanttView)
1591
- }
1592
- return $xeGanttView.$nextTick()
1593
- },
1594
- connectUpdate ({ $table }: {
1595
- $table: VxeTableConstructor & VxeTableMethods & VxeTablePrivateMethods
1596
- }) {
1597
- const $xeGanttView = this
1598
- const internalData = $xeGanttView.internalData
1599
-
1600
- if ($table) {
1601
- internalData.xeTable = $table
1602
- }
1603
- return $xeGanttView.$nextTick()
1604
- },
1605
- handleUpdateStyle () {
1606
- const $xeGanttView = this
1607
-
1608
- return updateStyle($xeGanttView)
1609
- },
1610
- handleLazyRecalculate () {
1611
- const $xeGanttView = this
1612
-
1613
- return handleLazyRecalculate($xeGanttView)
1614
- },
1615
- handleUpdateCurrentRow (row: any) {
1616
- const $xeGanttView = this
1617
- const internalData = $xeGanttView.internalData
1618
-
1619
- const $xeTable = internalData.xeTable
1620
- const el = $xeGanttView.$refs.refElem as HTMLDivElement
1621
- if ($xeTable && el) {
1622
- if (row) {
1623
- const tableProps = $xeTable
1624
- const rowOpts = $xeTable.computeRowOpts
1625
- if (rowOpts.isCurrent || tableProps.highlightCurrentRow) {
1626
- XEUtils.arrayEach(el.querySelectorAll(`[rowid="${$xeTable.getRowid(row)}"]`), elem => addClass(elem, 'row--current'))
1627
- }
1628
- } else {
1629
- XEUtils.arrayEach(el.querySelectorAll('.row--current'), elem => removeClass(elem, 'row--current'))
1630
- }
1631
- }
1632
- },
1633
- handleUpdateHoverRow (row: any) {
1634
- const $xeGanttView = this
1635
- const internalData = $xeGanttView.internalData
1636
-
1637
- const $xeTable = internalData.xeTable
1638
- const el = $xeGanttView.$refs.refElem as HTMLDivElement
1639
- if ($xeTable && el) {
1640
- if (row) {
1641
- XEUtils.arrayEach(el.querySelectorAll(`.vxe-body--row[rowid="${$xeTable.getRowid(row)}"]`), elem => addClass(elem, 'row--hover'))
1642
- } else {
1643
- XEUtils.arrayEach(el.querySelectorAll('.vxe-body--row.row--hover'), elem => removeClass(elem, 'row--hover'))
1644
- }
1645
- }
1646
- },
1647
- triggerHeaderScrollEvent (evnt: Event) {
1648
- const $xeGanttView = this
1649
- const internalData = $xeGanttView.internalData
1650
-
1651
- const { elemStore, inVirtualScroll, inBodyScroll, inFooterScroll } = internalData
1652
- if (inVirtualScroll) {
1653
- return
1654
- }
1655
- if (inBodyScroll || inFooterScroll) {
1656
- return
1657
- }
1658
- const wrapperEl = evnt.currentTarget as HTMLDivElement
1659
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1660
- const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
1661
- if (bodyScrollElem && wrapperEl) {
1662
- const isRollX = true
1663
- const isRollY = false
1664
- const currLeftNum = wrapperEl.scrollLeft
1665
- internalData.inHeaderScroll = true
1666
- setScrollLeft(xHandleEl, currLeftNum)
1667
- setScrollLeft(bodyScrollElem, currLeftNum)
1668
- handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
1669
- }
1670
- },
1671
- triggerBodyScrollEvent (evnt: Event) {
1672
- const $xeGanttView = this
1673
- const reactData = $xeGanttView.reactData
1674
- const internalData = $xeGanttView.internalData
1675
-
1676
- const { scrollXLoad } = reactData
1677
- const { elemStore, inVirtualScroll, inHeaderScroll, inFooterScroll, lastScrollLeft, lastScrollTop } = internalData
1678
- if (inVirtualScroll) {
1679
- return
1680
- }
1681
- if (inHeaderScroll || inFooterScroll) {
1682
- return
1683
- }
1684
- const wrapperEl = evnt.currentTarget as HTMLDivElement
1685
- const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
1686
- const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
1687
- const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
1688
- const scrollLeft = wrapperEl.scrollLeft
1689
- const scrollTop = wrapperEl.scrollTop
1690
- const isRollX = scrollLeft !== lastScrollLeft
1691
- const isRollY = scrollTop !== lastScrollTop
1692
- internalData.inBodyScroll = true
1693
- internalData.scrollRenderType = ''
1694
- if (isRollY) {
1695
- setScrollTop(yHandleEl, scrollTop)
1696
- syncTableScrollTop($xeGanttView, scrollTop)
1697
- }
1698
- if (isRollX) {
1699
- internalData.inBodyScroll = true
1700
- setScrollLeft(xHandleEl, scrollLeft)
1701
- setScrollLeft(headerScrollElem, scrollLeft)
1702
- if (scrollXLoad) {
1703
- triggerScrollXEvent($xeGanttView)
1704
- }
1705
- }
1706
- handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, scrollLeft)
1707
- },
1708
- // triggerFooterScrollEvent (evnt: Event) {
1709
- // const $xeGanttView = this
1710
- // const internalData = $xeGanttView.internalData
1711
-
1712
- // const { inVirtualScroll, inHeaderScroll, inBodyScroll } = internalData
1713
- // if (inVirtualScroll) {
1714
- // return
1715
- // }
1716
- // if (inHeaderScroll || inBodyScroll) {
1717
- // return
1718
- // }
1719
- // const wrapperEl = evnt.currentTarget as HTMLDivElement
1720
- // if (wrapperEl) {
1721
- // const isRollX = true
1722
- // const isRollY = false
1723
- // const currLeftNum = wrapperEl.scrollLeft
1724
- // handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
1725
- // }
1726
- // },
1727
- triggerVirtualScrollXEvent (evnt: Event) {
1728
- const $xeGanttView = this
1729
- const reactData = $xeGanttView.reactData
1730
- const internalData = $xeGanttView.internalData
1731
-
1732
- const { scrollXLoad } = reactData
1733
- const { elemStore, inHeaderScroll, inBodyScroll } = internalData
1734
- if (inHeaderScroll || inBodyScroll) {
1735
- return
1736
- }
1737
- const wrapperEl = evnt.currentTarget as HTMLDivElement
1738
- const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
1739
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1740
- if (wrapperEl) {
1741
- const isRollY = false
1742
- const isRollX = true
1743
- const currLeftNum = wrapperEl.scrollLeft
1744
- internalData.inVirtualScroll = true
1745
- setScrollLeft(headerScrollElem, currLeftNum)
1746
- setScrollLeft(bodyScrollElem, currLeftNum)
1747
- if (scrollXLoad) {
1748
- triggerScrollXEvent($xeGanttView)
1749
- }
1750
- handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
1751
- }
1752
- },
1753
- triggerVirtualScrollYEvent (evnt: Event) {
1754
- const $xeGanttView = this
1755
- const internalData = $xeGanttView.internalData
1756
-
1757
- const { elemStore, inHeaderScroll, inBodyScroll } = internalData
1758
- if (inHeaderScroll || inBodyScroll) {
1759
- return
1760
- }
1761
- const wrapperEl = evnt.currentTarget as HTMLDivElement
1762
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1763
- if (wrapperEl) {
1764
- const isRollY = true
1765
- const isRollX = false
1766
- const currTopNum = wrapperEl.scrollTop
1767
- internalData.inVirtualScroll = true
1768
- setScrollTop(bodyScrollElem, currTopNum)
1769
- syncTableScrollTop($xeGanttView, currTopNum)
1770
- handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, currTopNum, wrapperEl.scrollLeft)
1771
- }
1772
- },
1773
- handleUpdateSXSpace () {
1774
- const $xeGanttView = this
1775
-
1776
- return updateScrollXSpace($xeGanttView)
1777
- },
1778
- handleUpdateSYSpace () {
1779
- const $xeGanttView = this
1780
-
1781
- return updateScrollYSpace($xeGanttView)
1782
- },
1783
- handleUpdateSYStatus (sYLoad: boolean) {
1784
- const $xeGanttView = this
1785
- const reactData = $xeGanttView.reactData
1786
-
1787
- reactData.scrollYLoad = sYLoad
1788
- },
1789
- handleGlobalResizeEvent () {
1790
- const $xeGanttView = this
1791
-
1792
- handleLazyRecalculate($xeGanttView)
1793
- },
1794
-
1795
- //
1796
- // Render
1797
- //
1798
- renderScrollX (h: CreateElement) {
1799
- const $xeGanttView = this
1800
-
1801
- return h('div', {
1802
- key: 'vsx',
1803
- ref: 'refScrollXVirtualElem',
1804
- class: 'vxe-gantt-view--scroll-x-virtual'
1805
- }, [
1806
- h('div', {
1807
- ref: 'refScrollXLeftCornerElem',
1808
- class: 'vxe-gantt-view--scroll-x-left-corner'
1809
- }),
1810
- h('div', {
1811
- ref: 'refScrollXWrapperElem',
1812
- class: 'vxe-gantt-view--scroll-x-wrapper'
1813
- }, [
1814
- h('div', {
1815
- ref: 'refScrollXHandleElem',
1816
- class: 'vxe-gantt-view--scroll-x-handle',
1817
- on: {
1818
- scroll: $xeGanttView.triggerVirtualScrollXEvent
1819
- }
1820
- }, [
1821
- h('div', {
1822
- ref: 'refScrollXSpaceElem',
1823
- class: 'vxe-gantt-view--scroll-x-space'
1824
- })
1825
- ]),
1826
- h('div', {
1827
- class: 'vxe-gantt-view--scroll-x-handle-appearance'
1828
- })
1829
- ]),
1830
- h('div', {
1831
- ref: 'refScrollXRightCornerElem',
1832
- class: 'vxe-gantt-view--scroll-x-right-corner'
1833
- })
1834
- ])
1835
- },
1836
- renderScrollY (h: CreateElement) {
1837
- const $xeGanttView = this
1838
-
1839
- return h('div', {
1840
- ref: 'refScrollYVirtualElem',
1841
- class: 'vxe-gantt-view--scroll-y-virtual'
1842
- }, [
1843
- h('div', {
1844
- ref: 'refScrollYTopCornerElem',
1845
- class: 'vxe-gantt-view--scroll-y-top-corner'
1846
- }),
1847
- h('div', {
1848
- ref: 'refScrollYWrapperElem',
1849
- class: 'vxe-gantt-view--scroll-y-wrapper'
1850
- }, [
1851
- h('div', {
1852
- ref: 'refScrollYHandleElem',
1853
- class: 'vxe-gantt-view--scroll-y-handle',
1854
- on: {
1855
- scroll: $xeGanttView.triggerVirtualScrollYEvent
1856
- }
1857
- }, [
1858
- h('div', {
1859
- ref: 'refScrollYSpaceElem',
1860
- class: 'vxe-gantt-view--scroll-y-space'
1861
- })
1862
- ]),
1863
- h('div', {
1864
- class: 'vxe-gantt-view--scroll-y-handle-appearance'
1865
- })
1866
- ]),
1867
- h('div', {
1868
- ref: 'refScrollYBottomCornerElem',
1869
- class: 'vxe-gantt-view--scroll-y-bottom-corner'
1870
- })
1871
- ])
1872
- },
1873
- renderViewport (h: CreateElement) {
1874
- return h('div', {
1875
- class: 'vxe-gantt-view--viewport-wrapper'
1876
- }, [
1877
- h(GanttViewHeaderComponent),
1878
- h(GanttViewBodyComponent),
1879
- h(GanttViewFooterComponent)
1880
- ])
1881
- },
1882
- renderBody (h: CreateElement) {
1883
- const $xeGanttView = this
1884
- const $xeGantt = $xeGanttView.$xeGantt
1885
-
1886
- const scrollbarYToLeft = $xeGantt.computeScrollbarYToLeft
1887
- return h('div', {
1888
- class: 'vxe-gantt-view--layout-wrapper'
1889
- }, scrollbarYToLeft
1890
- ? [
1891
- $xeGanttView.renderScrollY(h),
1892
- $xeGanttView.renderViewport(h)
1893
- ]
1894
- : [
1895
- $xeGanttView.renderViewport(h),
1896
- $xeGanttView.renderScrollY(h)
1897
- ])
1898
- },
1899
- renderVN (h: CreateElement): VNode {
1900
- const $xeGanttView = this
1901
- const $xeGantt = $xeGanttView.$xeGantt
1902
- const reactData = $xeGanttView.reactData
1903
-
1904
- const { overflowX, overflowY, scrollXLoad, scrollYLoad } = reactData
1905
- const scrollbarXToTop = $xeGantt.computeScrollbarXToTop
1906
- return h('div', {
1907
- ref: 'refElem',
1908
- class: ['vxe-gantt-view', {
1909
- 'is--scroll-y': overflowY,
1910
- 'is--scroll-x': overflowX,
1911
- 'is--virtual-x': scrollXLoad,
1912
- 'is--virtual-y': scrollYLoad
1913
- }]
1914
- }, [
1915
- h('div', {
1916
- class: 'vxe-gantt-view--render-wrapper'
1917
- }, scrollbarXToTop
1918
- ? [
1919
- $xeGanttView.renderScrollX(h),
1920
- $xeGanttView.renderBody(h)
1921
- ]
1922
- : [
1923
- $xeGanttView.renderBody(h),
1924
- $xeGanttView.renderScrollX(h)
1925
- ]),
1926
- h('div', {
1927
- class: 'vxe-gantt-view--render-vars'
1928
- }, [
1929
- h('div', {
1930
- ref: 'refColInfoElem',
1931
- class: 'vxe-gantt-view--column-info'
1932
- })
1933
- ])
1934
- ])
1935
- }
1936
- },
1937
- mounted () {
1938
- const $xeGanttView = this
1939
-
1940
- globalEvents.on($xeGanttView, 'resize', $xeGanttView.handleGlobalResizeEvent)
1941
- },
1942
- beforeDestroy () {
1943
- const $xeGanttView = this
1944
- const reactData = $xeGanttView.reactData
1945
- const internalData = $xeGanttView.internalData
1946
-
1947
- globalEvents.off($xeGanttView, 'keydown')
1948
- XEUtils.assign(reactData, createReactData())
1949
- XEUtils.assign(internalData, createInternalData())
1950
- },
1951
- render (this: any, h) {
1952
- return this.renderVN(h)
1953
- }
1954
- })
1
+ import { VNode, CreateElement } from 'vue'
2
+ import { defineVxeComponent } from '../../ui/src/comp'
3
+ import { VxeUI } from '@vxe-ui/core'
4
+ import { setScrollTop, setScrollLeft, removeClass, addClass, hasClass } from '../../ui/src/dom'
5
+ import { getRefElem, getStandardGapTime, getTaskBarLeft, getTaskBarWidth, hasMilestoneTask, getTaskType, hasSubviewTask } from './util'
6
+ import XEUtils from 'xe-utils'
7
+ import GanttViewHeaderComponent from './gantt-header'
8
+ import GanttViewBodyComponent from './gantt-body'
9
+ import GanttViewFooterComponent from './gantt-footer'
10
+
11
+ import type { TableReactData, TableInternalData, VxeTableConstructor, VxeTableMethods, VxeTablePrivateMethods } from 'vxe-table'
12
+ import type { VxeGanttViewConstructor, GanttViewReactData, VxeGanttDefines, VxeGanttViewPrivateMethods, GanttViewInternalData, VxeGanttConstructor, VxeGanttPrivateMethods } from '../../../types'
13
+
14
+ const { globalEvents } = VxeUI
15
+
16
+ const sourceType = 'gantt'
17
+ const minuteMs = 1000 * 60
18
+ const dayMs = minuteMs * 60 * 24
19
+
20
+ function createInternalData (): GanttViewInternalData {
21
+ return {
22
+ xeTable: null,
23
+ visibleColumn: [],
24
+ startMaps: {},
25
+ endMaps: {},
26
+ chartMaps: {},
27
+ todayDateMaps: {},
28
+ elemStore: {},
29
+ // 存放横向 X 虚拟滚动相关的信息
30
+ scrollXStore: {
31
+ preloadSize: 0,
32
+ offsetSize: 0,
33
+ visibleSize: 0,
34
+ visibleStartIndex: 0,
35
+ visibleEndIndex: 0,
36
+ startIndex: 0,
37
+ endIndex: 0
38
+ },
39
+ // 最后滚动位置
40
+ lastScrollTop: 0,
41
+ lastScrollLeft: 0
42
+ }
43
+ }
44
+
45
+ function createReactData (): GanttViewReactData {
46
+ return {
47
+ // 是否启用了横向 X 可视渲染方式加载
48
+ scrollXLoad: false,
49
+ // 是否启用了纵向 Y 可视渲染方式加载
50
+ scrollYLoad: false,
51
+ // 是否存在纵向滚动条
52
+ overflowY: true,
53
+ // 是否存在横向滚动条
54
+ overflowX: true,
55
+ // 纵向滚动条的宽度
56
+ scrollbarWidth: 0,
57
+ // 横向滚动条的高度
58
+ scrollbarHeight: 0,
59
+
60
+ // 最后滚动时间戳
61
+ lastScrollTime: 0,
62
+ lazScrollLoading: false,
63
+
64
+ scrollVMLoading: false,
65
+ scrollYHeight: 0,
66
+ scrollYTop: 0,
67
+ isScrollYBig: false,
68
+ scrollXLeft: 0,
69
+ scrollXWidth: 0,
70
+ isScrollXBig: false,
71
+
72
+ minViewDate: null,
73
+ maxViewDate: null,
74
+ tableData: [],
75
+ tableColumn: [],
76
+ headerGroups: [],
77
+
78
+ viewCellWidth: 40
79
+ }
80
+ }
81
+
82
+ const maxYHeight = 5e6
83
+ // const maxXWidth = 5e6
84
+
85
+ function parseStringDate ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, dateValue: any) {
86
+ const $xeGantt = $xeGanttView.$xeGantt
87
+
88
+ const taskOpts = $xeGantt.computeTaskOpts
89
+ const { dateFormat } = taskOpts
90
+ return XEUtils.toStringDate(dateValue, dateFormat || null)
91
+ }
92
+
93
+ function updateTodayData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
94
+ const $xeGantt = $xeGanttView.$xeGantt
95
+ const internalData = $xeGanttView.internalData
96
+
97
+ const ganttReactData = $xeGantt.reactData
98
+ const { taskScaleList } = ganttReactData
99
+ const minScale = $xeGantt.computeMinScale
100
+ if (minScale) {
101
+ const weekScale = taskScaleList.find(item => item.type === 'week')
102
+ const isMinWeek = minScale.type === 'week'
103
+ const itemDate = new Date()
104
+ let [yyyy, M, MM, dd, HH, mm, ss] = XEUtils.toDateString(itemDate, 'yyyy-M-MM-dd-HH-mm-ss').split('-')
105
+ const e = itemDate.getDay()
106
+ const E = e + 1
107
+ const q = Math.ceil((itemDate.getMonth() + 1) / 3)
108
+ const W = `${XEUtils.getYearWeek(itemDate, weekScale ? weekScale.startDay : undefined)}`
109
+ if (isMinWeek && checkWeekOfsetYear(W, M)) {
110
+ yyyy = `${Number(yyyy) + 1}`
111
+ M = '1'
112
+ MM = '0' + M
113
+ }
114
+ ganttReactData.nowTime = itemDate.getTime()
115
+ internalData.todayDateMaps = {
116
+ year: yyyy,
117
+ quarter: `${yyyy}_q${q}`,
118
+ month: `${yyyy}_${MM}`,
119
+ week: `${yyyy}_W${W}`,
120
+ day: `${yyyy}_${MM}_${dd}_E${E}`,
121
+ date: `${yyyy}_${MM}_${dd}`,
122
+ hour: `${yyyy}_${MM}_${dd}_${HH}`,
123
+ minute: `${yyyy}_${MM}_${dd}_${HH}_${mm}`,
124
+ second: `${yyyy}_${MM}_${dd}_${HH}_${mm}_${ss}`
125
+ }
126
+ }
127
+ }
128
+
129
+ function handleColumnHeader ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
130
+ const $xeGantt = $xeGanttView.$xeGantt
131
+
132
+ const ganttReactData = $xeGantt.reactData
133
+ const { taskScaleList } = ganttReactData
134
+ const scaleUnit = $xeGantt.computeScaleUnit
135
+ const minScale = $xeGantt.computeMinScale
136
+ const weekScale = $xeGantt.computeWeekScale
137
+ const scaleDateList = $xeGanttView.computeScaleDateList
138
+ const fullCols: VxeGanttDefines.ViewColumn[] = []
139
+ const groupCols: VxeGanttDefines.GroupColumn[] = []
140
+
141
+ if (minScale && scaleUnit && scaleDateList.length) {
142
+ const renderListMaps: Record<VxeGanttDefines.ColumnScaleType, VxeGanttDefines.ViewColumn[]> = {
143
+ year: [],
144
+ quarter: [],
145
+ month: [],
146
+ week: [],
147
+ day: [],
148
+ date: [],
149
+ hour: [],
150
+ minute: [],
151
+ second: []
152
+ }
153
+ const tempTypeMaps: Record<VxeGanttDefines.ColumnScaleType, Record<string, VxeGanttDefines.ViewColumn>> = {
154
+ year: {},
155
+ quarter: {},
156
+ month: {},
157
+ week: {},
158
+ day: {},
159
+ date: {},
160
+ hour: {},
161
+ minute: {},
162
+ second: {}
163
+ }
164
+ const isMinWeek = minScale.type === 'week'
165
+
166
+ const handleData = (type: VxeGanttDefines.ColumnScaleType, colMaps: Record<VxeGanttDefines.ColumnScaleType, VxeGanttDefines.ViewColumn>, minCol: VxeGanttDefines.ViewColumn) => {
167
+ if (minScale.type === type) {
168
+ return
169
+ }
170
+ const currCol = colMaps[type]
171
+ const currKey = `${currCol.field}`
172
+ let currGpCol = tempTypeMaps[type][currKey]
173
+ if (!currGpCol) {
174
+ currGpCol = currCol
175
+ tempTypeMaps[type][currKey] = currGpCol
176
+ renderListMaps[type].push(currGpCol)
177
+ }
178
+ if (currGpCol) {
179
+ if (!currGpCol.children) {
180
+ currGpCol.children = []
181
+ }
182
+ currGpCol.children.push(minCol)
183
+ }
184
+ }
185
+
186
+ for (let i = 0; i < scaleDateList.length; i++) {
187
+ const itemDate = scaleDateList[i]
188
+ let [yy, yyyy, M, MM, d, dd, H, HH, m, mm, s, ss] = XEUtils.toDateString(itemDate, 'yy-yyyy-M-MM-d-dd-H-HH-m-mm-s-ss').split('-')
189
+ const e = itemDate.getDay()
190
+ const E = e + 1
191
+ const q = Math.ceil((itemDate.getMonth() + 1) / 3)
192
+ const W = `${XEUtils.getYearWeek(itemDate, weekScale ? weekScale.startDay : undefined)}`
193
+ const WW = XEUtils.padStart(W, 2, '0')
194
+ if (isMinWeek && checkWeekOfsetYear(W, M)) {
195
+ yyyy = `${Number(yyyy) + 1}`
196
+ M = '1'
197
+ MM = '0' + M
198
+ }
199
+ const dateObj: VxeGanttDefines.ScaleDateObj = { date: itemDate, yy, yyyy, M, MM, d, dd, H, HH, m, mm, s, ss, q, W, WW, E, e }
200
+ const colMaps: Record<VxeGanttDefines.ColumnScaleType, VxeGanttDefines.ViewColumn> = {
201
+ year: {
202
+ field: yyyy,
203
+ title: yyyy,
204
+ dateObj
205
+ },
206
+ quarter: {
207
+ field: `${yyyy}_q${q}`,
208
+ title: `${q}`,
209
+ dateObj
210
+ },
211
+ month: {
212
+ field: `${yyyy}_${MM}`,
213
+ title: MM,
214
+ dateObj
215
+ },
216
+ week: {
217
+ field: `${yyyy}_W${W}`,
218
+ title: `${W}`,
219
+ dateObj
220
+ },
221
+ day: {
222
+ field: `${yyyy}_${MM}_${dd}_E${E}`,
223
+ title: `${E}`,
224
+ dateObj
225
+ },
226
+ date: {
227
+ field: `${yyyy}_${MM}_${dd}`,
228
+ title: dd,
229
+ dateObj
230
+ },
231
+ hour: {
232
+ field: `${yyyy}_${MM}_${dd}_${HH}`,
233
+ title: HH,
234
+ dateObj
235
+ },
236
+ minute: {
237
+ field: `${yyyy}_${MM}_${dd}_${HH}_${mm}`,
238
+ title: mm,
239
+ dateObj
240
+ },
241
+ second: {
242
+ field: `${yyyy}_${MM}_${dd}_${HH}_${mm}_${ss}`,
243
+ title: ss,
244
+ dateObj
245
+ }
246
+ }
247
+ const minCol = colMaps[minScale.type]
248
+ if (minScale.level < 19) {
249
+ handleData('year', colMaps, minCol)
250
+ }
251
+ if (minScale.level < 17) {
252
+ handleData('quarter', colMaps, minCol)
253
+ }
254
+ if (minScale.level < 15) {
255
+ handleData('month', colMaps, minCol)
256
+ }
257
+ if (minScale.level < 13) {
258
+ handleData('week', colMaps, minCol)
259
+ }
260
+ if (minScale.level < 11) {
261
+ handleData('day', colMaps, minCol)
262
+ }
263
+ if (minScale.level < 9) {
264
+ handleData('date', colMaps, minCol)
265
+ }
266
+ if (minScale.level < 7) {
267
+ handleData('hour', colMaps, minCol)
268
+ }
269
+ if (minScale.level < 5) {
270
+ handleData('minute', colMaps, minCol)
271
+ }
272
+ if (minScale.level < 3) {
273
+ handleData('second', colMaps, minCol)
274
+ }
275
+
276
+ fullCols.push(minCol)
277
+ }
278
+
279
+ taskScaleList.forEach(scaleItem => {
280
+ if (scaleItem.type === minScale.type) {
281
+ groupCols.push({
282
+ scaleItem,
283
+ columns: fullCols
284
+ })
285
+ return
286
+ }
287
+ const list = renderListMaps[scaleItem.type] || []
288
+ if (list) {
289
+ list.forEach(item => {
290
+ item.childCount = item.children ? item.children.length : 0
291
+ item.children = undefined
292
+ })
293
+ }
294
+ groupCols.push({
295
+ scaleItem,
296
+ columns: list
297
+ })
298
+ })
299
+ }
300
+
301
+ return {
302
+ fullCols,
303
+ groupCols
304
+ }
305
+ }
306
+
307
+ /**
308
+ * 判断周的年份是否跨年
309
+ */
310
+ function checkWeekOfsetYear (W: number | string, M: number | string) {
311
+ return `${W}` === '1' && `${M}` === '12'
312
+ }
313
+
314
+ /**
315
+ * 周维度,由于年份和第几周是冲突的行为,所以需要特殊处理,判断是否跨年,例如
316
+ * '2024-12-31' 'yyyy-MM-dd W' >> '2024-12-31 1'
317
+ * '2025-01-01' 'yyyy-MM-dd W' >> '2025-01-01 1'
318
+ */
319
+ function parseWeekObj (date: any, firstDay?: 0 | 5 | 1 | 2 | 3 | 4 | 6) {
320
+ const currDate = XEUtils.toStringDate(date)
321
+ let yyyy = currDate.getFullYear()
322
+ const month = currDate.getMonth()
323
+ const weekNum = XEUtils.getYearWeek(currDate, firstDay)
324
+ if (checkWeekOfsetYear(weekNum, month + 1)) {
325
+ yyyy++
326
+ }
327
+ return {
328
+ yyyy,
329
+ W: weekNum
330
+ }
331
+ }
332
+
333
+ function createChartRender ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, fullCols: VxeGanttDefines.ViewColumn[]) {
334
+ const $xeGantt = $xeGanttView.$xeGantt
335
+ const reactData = $xeGanttView.reactData
336
+
337
+ const { minViewDate } = reactData
338
+ const minScale = $xeGantt.computeMinScale
339
+ const scaleUnit = $xeGantt.computeScaleUnit
340
+ const weekScale = $xeGantt.computeWeekScale
341
+ if (minScale) {
342
+ switch (scaleUnit) {
343
+ case 'year': {
344
+ const indexMaps: Record<string, number> = {}
345
+ fullCols.forEach(({ dateObj }, i) => {
346
+ const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy')
347
+ indexMaps[yyyyMM] = i
348
+ })
349
+ return (startValue: any, endValue: any) => {
350
+ const startDate = parseStringDate($xeGanttView, startValue)
351
+ const endDate = parseStringDate($xeGanttView, endValue)
352
+ const startStr = XEUtils.toDateString(startDate, 'yyyy')
353
+ const startFirstDate = XEUtils.getWhatYear(startDate, 0, 'first')
354
+ const endStr = XEUtils.toDateString(endDate, 'yyyy')
355
+ const endFirstDate = XEUtils.getWhatYear(endDate, 0, 'first')
356
+ const dateSize = Math.floor((XEUtils.getWhatYear(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / dayMs)
357
+ const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
358
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
359
+ const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
360
+ return {
361
+ offsetLeftSize,
362
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
363
+ }
364
+ }
365
+ }
366
+ case 'quarter': {
367
+ const indexMaps: Record<string, number> = {}
368
+ fullCols.forEach(({ dateObj }, i) => {
369
+ const q = XEUtils.toDateString(dateObj.date, 'yyyy-q')
370
+ indexMaps[q] = i
371
+ })
372
+ return (startValue: any, endValue: any) => {
373
+ const startDate = parseStringDate($xeGanttView, startValue)
374
+ const endDate = parseStringDate($xeGanttView, endValue)
375
+ const startStr = XEUtils.toDateString(startDate, 'yyyy-q')
376
+ const startFirstDate = XEUtils.getWhatQuarter(startDate, 0, 'first')
377
+ const endStr = XEUtils.toDateString(endDate, 'yyyy-q')
378
+ const endFirstDate = XEUtils.getWhatQuarter(endDate, 0, 'first')
379
+ const dateSize = Math.floor((XEUtils.getWhatQuarter(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / dayMs)
380
+ const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
381
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
382
+ const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
383
+ return {
384
+ offsetLeftSize,
385
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
386
+ }
387
+ }
388
+ }
389
+ case 'month': {
390
+ const indexMaps: Record<string, number> = {}
391
+ fullCols.forEach(({ dateObj }, i) => {
392
+ const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM')
393
+ indexMaps[yyyyMM] = i
394
+ })
395
+ return (startValue: any, endValue: any) => {
396
+ const startDate = parseStringDate($xeGanttView, startValue)
397
+ const endDate = parseStringDate($xeGanttView, endValue)
398
+ const startStr = XEUtils.toDateString(startDate, 'yyyy-MM')
399
+ const startFirstDate = XEUtils.getWhatMonth(startDate, 0, 'first')
400
+ const endStr = XEUtils.toDateString(endDate, 'yyyy-MM')
401
+ const endFirstDate = XEUtils.getWhatMonth(endDate, 0, 'first')
402
+ const dateSize = Math.floor((XEUtils.getWhatMonth(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / dayMs)
403
+ const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
404
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
405
+ const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
406
+ return {
407
+ offsetLeftSize,
408
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
409
+ }
410
+ }
411
+ }
412
+ case 'week': {
413
+ const indexMaps: Record<string, number> = {}
414
+ fullCols.forEach(({ dateObj }, i) => {
415
+ const yyyyW = `${dateObj.yyyy}-${dateObj.W}`
416
+ indexMaps[yyyyW] = i
417
+ })
418
+ return (startValue: any, endValue: any) => {
419
+ const startDate = parseStringDate($xeGanttView, startValue)
420
+ const endDate = parseStringDate($xeGanttView, endValue)
421
+ const startWeekObj = parseWeekObj(startDate, weekScale ? weekScale.startDay : undefined)
422
+ const startStr = `${startWeekObj.yyyy}-${startWeekObj.W}`
423
+ const startFirstDate = XEUtils.getWhatWeek(startDate, 0, weekScale ? weekScale.startDay : undefined, weekScale ? weekScale.startDay : undefined)
424
+ const endWeekObj = parseWeekObj(endDate, weekScale ? weekScale.startDay : undefined)
425
+ const endStr = `${endWeekObj.yyyy}-${endWeekObj.W}`
426
+ const endFirstDate = XEUtils.getWhatWeek(endDate, 0, weekScale ? weekScale.startDay : undefined, weekScale ? weekScale.startDay : undefined)
427
+ const dateSize = Math.floor((XEUtils.getWhatWeek(endDate, 1, weekScale ? weekScale.startDay : undefined, weekScale ? weekScale.startDay : undefined).getTime() - endFirstDate.getTime()) / dayMs)
428
+ const subtract = (startDate.getTime() - startFirstDate.getTime()) / dayMs / dateSize
429
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / dayMs + 1) / dateSize
430
+ const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
431
+ return {
432
+ offsetLeftSize,
433
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
434
+ }
435
+ }
436
+ }
437
+ case 'day':
438
+ case 'date': {
439
+ const indexMaps: Record<string, number> = {}
440
+ fullCols.forEach(({ dateObj }, i) => {
441
+ const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM-dd')
442
+ indexMaps[yyyyMM] = i
443
+ })
444
+ return (startValue: any, endValue: any) => {
445
+ const startDate = parseStringDate($xeGanttView, startValue)
446
+ const endDate = parseStringDate($xeGanttView, endValue)
447
+ const startStr = XEUtils.toDateString(startDate, 'yyyy-MM-dd')
448
+ const startFirstDate = XEUtils.getWhatDay(startDate, 0, 'first')
449
+ const endStr = XEUtils.toDateString(endDate, 'yyyy-MM-dd')
450
+ const endFirstDate = XEUtils.getWhatDay(endDate, 0, 'first')
451
+ const minuteSize = Math.floor((XEUtils.getWhatDay(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / minuteMs)
452
+ // 开始和结束时间是否存在偏移时
453
+ const startSubtract = (startDate.getTime() - startFirstDate.getTime()) / minuteMs / minuteSize
454
+ const endSubtract = (endDate.getTime() - endFirstDate.getTime()) / minuteMs / minuteSize
455
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / minuteMs + 1) / minuteSize
456
+ const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtract
457
+ // 如果最小轴为天,当存在时分秒时,在当前单元格内渲染维度;如果不存在,则填充满单元格
458
+ return {
459
+ offsetLeftSize,
460
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize + (startSubtract || endSubtract ? 0 : 1)
461
+ }
462
+ }
463
+ }
464
+ case 'hour': {
465
+ const indexMaps: Record<string, number> = {}
466
+ fullCols.forEach(({ dateObj }, i) => {
467
+ const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM-dd HH')
468
+ indexMaps[yyyyMM] = i
469
+ })
470
+ return (startValue: any, endValue: any) => {
471
+ const startDate = parseStringDate($xeGanttView, startValue)
472
+ const endDate = parseStringDate($xeGanttView, endValue)
473
+ const startStr = XEUtils.toDateString(startDate, 'yyyy-MM-dd HH')
474
+ const startFirstDate = XEUtils.getWhatHours(startDate, 0, 'first')
475
+ const endStr = XEUtils.toDateString(endDate, 'yyyy-MM-dd HH')
476
+ const endFirstDate = XEUtils.getWhatHours(endDate, 0, 'first')
477
+ const minuteSize = Math.floor((XEUtils.getWhatHours(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / minuteMs)
478
+ // 开始和结束时间是否存在偏移时
479
+ const startSubtract = (startDate.getTime() - startFirstDate.getTime()) / minuteMs / minuteSize
480
+ const endSubtract = (endDate.getTime() - endFirstDate.getTime()) / minuteMs / minuteSize
481
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / minuteMs + 1) / minuteSize
482
+ const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtract
483
+ return {
484
+ offsetLeftSize,
485
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize + (startSubtract || endSubtract ? 0 : 1)
486
+ }
487
+ }
488
+ }
489
+ case 'minute': {
490
+ const indexMaps: Record<string, number> = {}
491
+ fullCols.forEach(({ dateObj }, i) => {
492
+ const yyyyMM = XEUtils.toDateString(dateObj.date, 'yyyy-MM-dd HH:mm')
493
+ indexMaps[yyyyMM] = i
494
+ })
495
+ return (startValue: any, endValue: any) => {
496
+ const startDate = parseStringDate($xeGanttView, startValue)
497
+ const endDate = parseStringDate($xeGanttView, endValue)
498
+ const startStr = XEUtils.toDateString(startDate, 'yyyy-MM-dd HH:mm')
499
+ const startFirstDate = XEUtils.getWhatMinutes(startDate, 0, 'first')
500
+ const endStr = XEUtils.toDateString(endDate, 'yyyy-MM-dd HH:mm')
501
+ const endFirstDate = XEUtils.getWhatMinutes(endDate, 0, 'first')
502
+ const minuteSize = Math.floor((XEUtils.getWhatMinutes(endDate, 1, 'first').getTime() - endFirstDate.getTime()) / minuteMs)
503
+ const subtract = (startDate.getTime() - startFirstDate.getTime()) / minuteMs / minuteSize
504
+ const addSize = Math.max(0, (endDate.getTime() - endFirstDate.getTime()) / minuteMs + 1) / minuteSize
505
+ const offsetLeftSize = (indexMaps[startStr] || 0) + subtract
506
+ return {
507
+ offsetLeftSize,
508
+ offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + addSize
509
+ }
510
+ }
511
+ }
512
+ case 'second': {
513
+ const gapTime = getStandardGapTime(minScale.type)
514
+ return (startValue: any, endValue: any) => {
515
+ const startDate = parseStringDate($xeGanttView, startValue)
516
+ const endDate = parseStringDate($xeGanttView, endValue)
517
+ let offsetLeftSize = 0
518
+ let offsetWidthSize = 0
519
+ if (minViewDate) {
520
+ offsetLeftSize = (startDate.getTime() - minViewDate.getTime()) / gapTime
521
+ offsetWidthSize = ((endDate.getTime() - startDate.getTime()) / gapTime)
522
+ }
523
+ return {
524
+ offsetLeftSize,
525
+ offsetWidthSize
526
+ }
527
+ }
528
+ }
529
+ }
530
+ }
531
+ return () => {
532
+ return {
533
+ offsetLeftSize: 0,
534
+ offsetWidthSize: 0
535
+ }
536
+ }
537
+ }
538
+
539
+ function handleParseColumn ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
540
+ const $xeGantt = $xeGanttView.$xeGantt
541
+ const reactData = $xeGanttView.reactData
542
+ const internalData = $xeGanttView.internalData
543
+
544
+ const ganttProps = $xeGantt
545
+ const { treeConfig } = ganttProps
546
+ const { minViewDate, maxViewDate } = reactData
547
+ const { fullCols, groupCols } = handleColumnHeader($xeGanttView)
548
+ if (minViewDate && maxViewDate) {
549
+ const $xeTable = internalData.xeTable
550
+ if ($xeTable) {
551
+ const startField = $xeGantt.computeStartField
552
+ const endField = $xeGantt.computeEndField
553
+ const typeField = $xeGantt.computeTypeField
554
+ const tableReactData = $xeTable as unknown as TableReactData
555
+ const { isRowGroupStatus } = tableReactData
556
+ const tableInternalData = $xeTable as unknown as TableInternalData
557
+ const { afterFullData, afterTreeFullData, afterGroupFullData } = tableInternalData
558
+ const aggregateOpts = $xeTable.computeAggregateOpts
559
+ const treeOpts = $xeTable.computeTreeOpts
560
+ const { transform } = treeOpts
561
+ const childrenField = treeOpts.children || treeOpts.childrenField
562
+
563
+ const ctMaps: Record<string, VxeGanttDefines.RowCacheItem> = {}
564
+ const renderFn = createChartRender($xeGanttView, fullCols)
565
+ const handleParseRender = (row: any) => {
566
+ const rowid = $xeTable.getRowid(row)
567
+ let startValue = XEUtils.get(row, startField)
568
+ let endValue = XEUtils.get(row, endField)
569
+ const renderTaskType = getTaskType(XEUtils.get(row, typeField))
570
+ const isMilestone = hasMilestoneTask(renderTaskType)
571
+ const isSubview = hasSubviewTask(renderTaskType)
572
+ if (isMilestone) {
573
+ if (!startValue) {
574
+ startValue = endValue
575
+ }
576
+ endValue = startValue
577
+ }
578
+ if (isSubview) {
579
+ ctMaps[rowid] = {
580
+ row,
581
+ rowid,
582
+ oLeftSize: 0,
583
+ oWidthSize: 0
584
+ }
585
+ } else if (startValue && endValue) {
586
+ const { offsetLeftSize, offsetWidthSize } = renderFn(startValue, endValue)
587
+ ctMaps[rowid] = {
588
+ row,
589
+ rowid,
590
+ oLeftSize: offsetLeftSize,
591
+ oWidthSize: offsetWidthSize
592
+ }
593
+ }
594
+ }
595
+
596
+ if (isRowGroupStatus) {
597
+ // 行分组
598
+ const mapChildrenField = aggregateOpts.mapChildrenField
599
+ if (mapChildrenField) {
600
+ XEUtils.eachTree(afterGroupFullData, handleParseRender, { children: mapChildrenField })
601
+ }
602
+ } else if (treeConfig) {
603
+ // 树结构
604
+ XEUtils.eachTree(afterTreeFullData, handleParseRender, { children: transform ? treeOpts.mapChildrenField : childrenField })
605
+ } else {
606
+ afterFullData.forEach(handleParseRender)
607
+ }
608
+ internalData.chartMaps = ctMaps
609
+ }
610
+ }
611
+ internalData.visibleColumn = fullCols
612
+ reactData.headerGroups = groupCols
613
+ updateTodayData($xeGanttView)
614
+ updateScrollXStatus($xeGanttView)
615
+ handleTableColumn($xeGanttView)
616
+ }
617
+
618
+ function handleUpdateData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
619
+ const $xeGantt = $xeGanttView.$xeGantt
620
+ const reactData = $xeGanttView.reactData
621
+ const internalData = $xeGanttView.internalData
622
+
623
+ const ganttProps = $xeGantt
624
+ const { treeConfig } = ganttProps
625
+ const { scrollXStore } = internalData
626
+ const $xeTable = internalData.xeTable
627
+ const sdMaps: Record<string, any> = {}
628
+ const edMaps: Record<string, any> = {}
629
+ let minDate: Date | null = null
630
+ let maxDate: Date | null = null
631
+ if ($xeTable) {
632
+ const startField = $xeGantt.computeStartField
633
+ const endField = $xeGantt.computeEndField
634
+ const typeField = $xeGantt.computeTypeField
635
+ const tableReactData = $xeTable as unknown as TableReactData
636
+ const { isRowGroupStatus } = tableReactData
637
+ const tableInternalData = $xeTable as unknown as TableInternalData
638
+ const { afterFullData, afterTreeFullData, afterGroupFullData } = tableInternalData
639
+ const aggregateOpts = $xeTable.computeAggregateOpts
640
+ const treeOpts = $xeTable.computeTreeOpts
641
+ const { transform } = treeOpts
642
+ const childrenField = treeOpts.children || treeOpts.childrenField
643
+
644
+ const handleMinMaxData = (row: any) => {
645
+ let startValue = XEUtils.get(row, startField)
646
+ let endValue = XEUtils.get(row, endField)
647
+ const typeValue = XEUtils.get(row, typeField)
648
+ const isMilestone = hasMilestoneTask(typeValue)
649
+ if (!startValue) {
650
+ startValue = endValue
651
+ }
652
+ if (isMilestone || !endValue) {
653
+ endValue = startValue
654
+ }
655
+ if (startValue) {
656
+ const startDate = parseStringDate($xeGanttView, startValue)
657
+ if (!minDate || minDate.getTime() > startDate.getTime()) {
658
+ minDate = startDate
659
+ }
660
+ }
661
+ if (endValue) {
662
+ const endDate = parseStringDate($xeGanttView, endValue)
663
+ if (!maxDate || maxDate.getTime() < endDate.getTime()) {
664
+ maxDate = endDate
665
+ }
666
+ }
667
+ }
668
+
669
+ if (isRowGroupStatus) {
670
+ // 行分组
671
+ const mapChildrenField = aggregateOpts.mapChildrenField
672
+ if (mapChildrenField) {
673
+ XEUtils.eachTree(afterGroupFullData, handleMinMaxData, { children: mapChildrenField })
674
+ }
675
+ } else if (treeConfig) {
676
+ // 树结构
677
+ XEUtils.eachTree(afterTreeFullData, handleMinMaxData, { children: transform ? treeOpts.mapChildrenField : childrenField })
678
+ } else {
679
+ afterFullData.forEach(handleMinMaxData)
680
+ }
681
+ }
682
+ scrollXStore.startIndex = 0
683
+ scrollXStore.endIndex = Math.max(1, scrollXStore.visibleSize)
684
+ reactData.minViewDate = minDate
685
+ reactData.maxViewDate = maxDate
686
+ internalData.startMaps = sdMaps
687
+ internalData.endMaps = edMaps
688
+ handleParseColumn($xeGanttView)
689
+ }
690
+
691
+ function calcScrollbar ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
692
+ const $xeGantt = $xeGanttView.$xeGantt
693
+ const reactData = $xeGanttView.reactData
694
+ const internalData = $xeGanttView.internalData
695
+
696
+ const { scrollXWidth, scrollYHeight } = reactData
697
+ const { elemStore } = internalData
698
+ const scrollbarOpts = $xeGantt.computeScrollbarOpts
699
+ const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper'])
700
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
701
+ const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
702
+ let overflowY = false
703
+ let overflowX = false
704
+ if (bodyWrapperElem) {
705
+ overflowY = scrollYHeight > bodyWrapperElem.clientHeight
706
+ if (yHandleEl) {
707
+ reactData.scrollbarWidth = scrollbarOpts.width || (yHandleEl.offsetWidth - yHandleEl.clientWidth) || 14
708
+ }
709
+ reactData.overflowY = overflowY
710
+
711
+ overflowX = scrollXWidth > bodyWrapperElem.clientWidth
712
+ if (xHandleEl) {
713
+ reactData.scrollbarHeight = scrollbarOpts.height || (xHandleEl.offsetHeight - xHandleEl.clientHeight) || 14
714
+ }
715
+
716
+ reactData.overflowX = overflowX
717
+ }
718
+ }
719
+
720
+ function handleSubTaskMinMaxSize ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, $xeTable: VxeTableConstructor, list: any[]) {
721
+ const $xeGantt = $xeGanttView.$xeGantt
722
+ const internalData = $xeGanttView.internalData
723
+
724
+ const { chartMaps } = internalData
725
+ const treeOpts = $xeTable.computeTreeOpts
726
+ const childrenField = treeOpts.children || treeOpts.childrenField
727
+
728
+ const typeField = $xeGantt.computeTypeField
729
+ let minChildLeftSize = 0
730
+ let maxChildLeftSize = 0
731
+ XEUtils.eachTree(list, childRow => {
732
+ const childRowid = $xeTable.getRowid(childRow)
733
+ const renderTaskType = XEUtils.get(childRow, typeField)
734
+ if (hasSubviewTask(renderTaskType)) {
735
+ return
736
+ }
737
+ const childChartRest = childRowid ? chartMaps[childRowid] : null
738
+ if (childChartRest) {
739
+ maxChildLeftSize = Math.max(maxChildLeftSize, childChartRest.oLeftSize + childChartRest.oWidthSize)
740
+ minChildLeftSize = minChildLeftSize ? Math.min(minChildLeftSize, childChartRest.oLeftSize) : childChartRest.oLeftSize
741
+ }
742
+ }, { children: childrenField })
743
+ return {
744
+ minSize: minChildLeftSize,
745
+ maxSize: maxChildLeftSize
746
+ }
747
+ }
748
+
749
+ function updateTaskChartStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
750
+ const $xeGantt = $xeGanttView.$xeGantt
751
+ const reactData = $xeGanttView.reactData
752
+ const internalData = $xeGanttView.internalData
753
+ const ganttInternalData = $xeGantt.internalData
754
+ const $xeTable = internalData.xeTable
755
+
756
+ const { dragBarRow } = ganttInternalData
757
+ const { viewCellWidth } = reactData
758
+ const { elemStore, chartMaps } = internalData
759
+ const chartWrapper = getRefElem(elemStore['main-chart-task-wrapper'])
760
+ if (chartWrapper && $xeTable) {
761
+ const treeOpts = $xeTable.computeTreeOpts
762
+ const childrenField = treeOpts.children || treeOpts.childrenField
763
+ XEUtils.arrayEach(chartWrapper.children, (rowEl) => {
764
+ const barEl = rowEl.children[0] as HTMLDivElement
765
+ if (!barEl) {
766
+ return
767
+ }
768
+ const rowid = rowEl.getAttribute('rowid')
769
+ if (dragBarRow && $xeTable.getRowid(dragBarRow) === rowid) {
770
+ return
771
+ }
772
+ const chartRest = rowid ? chartMaps[rowid] : null
773
+ const row = chartRest ? chartRest.row : null
774
+ // 子任务视图
775
+ if (hasClass(barEl, 'is--subview')) {
776
+ const childWrapperEl = barEl.firstElementChild as HTMLDivElement
777
+ if (childWrapperEl) {
778
+ // 行内展示
779
+ if (hasClass(childWrapperEl, 'is--inline')) {
780
+ XEUtils.arrayEach(childWrapperEl.children, (childRowEl) => {
781
+ const childBarEl = childRowEl.children[0] as HTMLDivElement
782
+ const childRowid = childBarEl.getAttribute('rowid') || ''
783
+ const childChartRest = childRowid ? chartMaps[childRowid] : null
784
+ if (childChartRest) {
785
+ const childRow = childChartRest.row
786
+ // 如果是子视图
787
+ if (hasClass(childBarEl, 'is--subview')) {
788
+ const subChildren: any[] = childRow[childrenField]
789
+ const { minSize: minChildLeftSize, maxSize: maxChildLeftSize } = handleSubTaskMinMaxSize($xeGanttView, $xeTable, subChildren)
790
+ childBarEl.style.left = `${viewCellWidth * minChildLeftSize}px`
791
+ childBarEl.style.width = `${viewCellWidth * (maxChildLeftSize - minChildLeftSize)}px`
792
+ } else {
793
+ childBarEl.style.left = `${getTaskBarLeft(childChartRest, viewCellWidth)}px`
794
+ if (!hasClass(childBarEl, 'is--milestone')) {
795
+ // 里程碑不需要宽度
796
+ childBarEl.style.width = `${getTaskBarWidth(childChartRest, viewCellWidth)}px`
797
+ }
798
+ }
799
+ }
800
+ })
801
+ } else {
802
+ // 如果展开子任务
803
+ const childRowEl = childWrapperEl.children[0] as HTMLDivElement
804
+ const childBarEl = childRowEl ? childRowEl.children[0] as HTMLDivElement : null
805
+ if (childBarEl) {
806
+ const rowChildren: any[] = row ? row[childrenField] : []
807
+ const { minSize: minChildLeftSize, maxSize: maxChildLeftSize } = handleSubTaskMinMaxSize($xeGanttView, $xeTable, rowChildren)
808
+ childBarEl.style.left = `${viewCellWidth * minChildLeftSize}px`
809
+ childBarEl.style.width = `${viewCellWidth * (maxChildLeftSize - minChildLeftSize)}px`
810
+ }
811
+ }
812
+ }
813
+ } else {
814
+ barEl.style.left = `${getTaskBarLeft(chartRest, viewCellWidth)}px`
815
+ // 里程碑不需要宽度
816
+ if (!hasClass(barEl, 'is--milestone')) {
817
+ barEl.style.width = `${getTaskBarWidth(chartRest, viewCellWidth)}px`
818
+ }
819
+ }
820
+ })
821
+ }
822
+ return $xeGanttView.$nextTick()
823
+ }
824
+
825
+ function updateStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
826
+ const $xeGantt = $xeGanttView.$xeGantt as VxeGanttConstructor & VxeGanttPrivateMethods
827
+ const reactData = $xeGanttView.reactData
828
+ const internalData = $xeGanttView.internalData
829
+
830
+ const { scrollbarWidth, scrollbarHeight, headerGroups, tableColumn } = reactData
831
+ const { elemStore, visibleColumn } = internalData
832
+ const $xeTable = internalData.xeTable
833
+
834
+ const el = $xeGanttView.$refs.refElem as HTMLDivElement
835
+ if (!el) {
836
+ return
837
+ }
838
+ if (!$xeGantt) {
839
+ return
840
+ }
841
+
842
+ const scrollbarOpts = $xeGantt.computeScrollbarOpts
843
+ const scrollbarXToTop = $xeGantt.computeScrollbarXToTop
844
+ const scrollbarYToLeft = $xeGantt.computeScrollbarYToLeft
845
+
846
+ const xLeftCornerEl = $xeGanttView.$refs.refScrollXLeftCornerElem as HTMLDivElement
847
+ const xRightCornerEl = $xeGanttView.$refs.refScrollXRightCornerElem as HTMLDivElement
848
+ const scrollXVirtualEl = $xeGanttView.$refs.refScrollXVirtualElem as HTMLDivElement
849
+
850
+ let osbWidth = scrollbarWidth
851
+ const osbHeight = scrollbarHeight
852
+
853
+ let tbHeight = 0
854
+ let tHeaderHeight = 0
855
+ let tFooterHeight = 0
856
+ if ($xeTable) {
857
+ const tableInternalData = $xeTable as unknown as TableInternalData
858
+ tbHeight = tableInternalData.tBodyHeight
859
+ tHeaderHeight = tableInternalData.tHeaderHeight
860
+ tFooterHeight = tableInternalData.tFooterHeight
861
+ }
862
+
863
+ let yScrollbarVisible = 'visible'
864
+ if (scrollbarYToLeft || (scrollbarOpts.y && scrollbarOpts.y.visible === false)) {
865
+ osbWidth = 0
866
+ yScrollbarVisible = 'hidden'
867
+ }
868
+
869
+ const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
870
+ if (headerScrollElem) {
871
+ headerScrollElem.style.height = `${tHeaderHeight}px`
872
+ headerScrollElem.style.setProperty('--vxe-ui-gantt-view-cell-height', `${tHeaderHeight / headerGroups.length}px`)
873
+ }
874
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
875
+ if (bodyScrollElem) {
876
+ bodyScrollElem.style.height = `${tbHeight}px`
877
+ }
878
+ const footerScrollElem = getRefElem(elemStore['main-footer-scroll'])
879
+ if (footerScrollElem) {
880
+ footerScrollElem.style.height = `${tFooterHeight}px`
881
+ }
882
+
883
+ if (scrollXVirtualEl) {
884
+ scrollXVirtualEl.style.height = `${osbHeight}px`
885
+ scrollXVirtualEl.style.visibility = 'visible'
886
+ }
887
+ const xWrapperEl = $xeGanttView.$refs.refScrollXWrapperElem as HTMLDivElement
888
+ if (xWrapperEl) {
889
+ xWrapperEl.style.left = scrollbarXToTop ? `${osbWidth}px` : ''
890
+ xWrapperEl.style.width = `${el.clientWidth - osbWidth}px`
891
+ }
892
+ if (xLeftCornerEl) {
893
+ xLeftCornerEl.style.width = scrollbarXToTop ? `${osbWidth}px` : ''
894
+ xLeftCornerEl.style.display = scrollbarXToTop ? (osbHeight ? 'block' : '') : ''
895
+ }
896
+ if (xRightCornerEl) {
897
+ xRightCornerEl.style.width = scrollbarXToTop ? '' : `${osbWidth}px`
898
+ xRightCornerEl.style.display = scrollbarXToTop ? '' : (osbHeight ? 'block' : '')
899
+ }
900
+
901
+ const scrollYVirtualEl = $xeGanttView.$refs.refScrollYVirtualElem as HTMLDivElement
902
+ if (scrollYVirtualEl) {
903
+ scrollYVirtualEl.style.width = `${osbWidth}px`
904
+ scrollYVirtualEl.style.height = `${tbHeight + tHeaderHeight + tFooterHeight}px`
905
+ scrollYVirtualEl.style.visibility = yScrollbarVisible
906
+ }
907
+ const yTopCornerEl = $xeGanttView.$refs.refScrollYTopCornerElem as HTMLDivElement
908
+ if (yTopCornerEl) {
909
+ yTopCornerEl.style.height = `${tHeaderHeight}px`
910
+ yTopCornerEl.style.display = tHeaderHeight ? 'block' : ''
911
+ }
912
+ const yWrapperEl = $xeGanttView.$refs.refScrollYWrapperElem as HTMLDivElement
913
+ if (yWrapperEl) {
914
+ yWrapperEl.style.height = `${tbHeight}px`
915
+ yWrapperEl.style.top = `${tHeaderHeight}px`
916
+ }
917
+ const yBottomCornerEl = $xeGanttView.$refs.refScrollYBottomCornerElem as HTMLDivElement
918
+ if (yBottomCornerEl) {
919
+ yBottomCornerEl.style.height = `${tFooterHeight}px`
920
+ yBottomCornerEl.style.top = `${tHeaderHeight + tbHeight}px`
921
+ yBottomCornerEl.style.display = tFooterHeight ? 'block' : ''
922
+ }
923
+
924
+ const colInfoElem = $xeGanttView.$refs.refColInfoElem as HTMLDivElement
925
+ let viewCellWidth = 40
926
+ if (colInfoElem) {
927
+ viewCellWidth = colInfoElem.clientWidth || 40
928
+ }
929
+ let viewTableWidth = viewCellWidth
930
+ if (visibleColumn.length) {
931
+ viewTableWidth = Math.max(0, viewCellWidth * visibleColumn.length)
932
+ if (bodyScrollElem) {
933
+ const viewWidth = bodyScrollElem.clientWidth
934
+ const remainWidth = viewWidth - viewTableWidth
935
+ if (remainWidth > 0) {
936
+ viewCellWidth += Math.max(0, remainWidth / visibleColumn.length)
937
+ viewTableWidth = viewWidth
938
+ }
939
+ }
940
+ }
941
+ reactData.viewCellWidth = viewCellWidth
942
+ const headerTableElem = getRefElem(elemStore['main-header-table'])
943
+ const bodyTableElem = getRefElem(elemStore['main-body-table'])
944
+ const vmTableWidth = viewCellWidth * tableColumn.length
945
+ if (headerTableElem) {
946
+ headerTableElem.style.width = `${viewTableWidth}px`
947
+ }
948
+ if (bodyTableElem) {
949
+ bodyTableElem.style.width = `${vmTableWidth}px`
950
+ }
951
+
952
+ reactData.scrollXWidth = viewTableWidth
953
+
954
+ return Promise.all([
955
+ updateTaskChartStyle($xeGanttView),
956
+ $xeGantt.handleUpdateTaskLinkStyle ? $xeGantt.handleUpdateTaskLinkStyle($xeGanttView) : null
957
+ ])
958
+ }
959
+
960
+ function handleRecalculateStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
961
+ const internalData = $xeGanttView.internalData
962
+ const $xeGantt = $xeGanttView.$xeGantt
963
+
964
+ const el = $xeGanttView.$refs.refElem as HTMLDivElement
965
+ internalData.rceRunTime = Date.now()
966
+ if (!el || !el.clientWidth) {
967
+ return $xeGanttView.$nextTick()
968
+ }
969
+ if (!$xeGantt) {
970
+ return $xeGanttView.$nextTick()
971
+ }
972
+ calcScrollbar($xeGanttView)
973
+ updateStyle($xeGanttView)
974
+ return computeScrollLoad($xeGanttView)
975
+ }
976
+
977
+ function handleLazyRecalculate ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
978
+ const internalData = $xeGanttView.internalData
979
+
980
+ return new Promise<void>(resolve => {
981
+ const { rceTimeout, rceRunTime } = internalData
982
+ const $xeTable = internalData.xeTable
983
+ let refreshDelay = 30
984
+ if ($xeTable) {
985
+ const resizeOpts = $xeTable.computeResizeOpts
986
+ refreshDelay = resizeOpts.refreshDelay || refreshDelay
987
+ }
988
+ if (rceTimeout) {
989
+ clearTimeout(rceTimeout)
990
+ if (rceRunTime && rceRunTime + (refreshDelay - 5) < Date.now()) {
991
+ resolve(
992
+ handleRecalculateStyle($xeGanttView)
993
+ )
994
+ } else {
995
+ $xeGanttView.$nextTick(() => {
996
+ resolve()
997
+ })
998
+ }
999
+ } else {
1000
+ resolve(
1001
+ handleRecalculateStyle($xeGanttView)
1002
+ )
1003
+ }
1004
+ internalData.rceTimeout = setTimeout(() => {
1005
+ internalData.rceTimeout = undefined
1006
+ handleRecalculateStyle($xeGanttView)
1007
+ }, refreshDelay)
1008
+ })
1009
+ }
1010
+
1011
+ function computeScrollLoad ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1012
+ const reactData = $xeGanttView.reactData
1013
+ const internalData = $xeGanttView.internalData
1014
+
1015
+ return $xeGanttView.$nextTick().then(() => {
1016
+ const { scrollXLoad } = reactData
1017
+ const { scrollXStore } = internalData
1018
+ // 计算 X 逻辑
1019
+ if (scrollXLoad) {
1020
+ const { toVisibleIndex: toXVisibleIndex, visibleSize: visibleXSize } = handleVirtualXVisible($xeGanttView)
1021
+ const offsetXSize = 2
1022
+ scrollXStore.preloadSize = 1
1023
+ scrollXStore.offsetSize = offsetXSize
1024
+ scrollXStore.visibleSize = visibleXSize
1025
+ scrollXStore.endIndex = Math.max(scrollXStore.startIndex + scrollXStore.visibleSize + offsetXSize, scrollXStore.endIndex)
1026
+ scrollXStore.visibleStartIndex = Math.max(scrollXStore.startIndex, toXVisibleIndex)
1027
+ scrollXStore.visibleEndIndex = Math.min(scrollXStore.endIndex, toXVisibleIndex + visibleXSize)
1028
+ updateScrollXData($xeGanttView).then(() => {
1029
+ loadScrollXData($xeGanttView)
1030
+ })
1031
+ } else {
1032
+ updateScrollXSpace($xeGanttView)
1033
+ }
1034
+ })
1035
+ }
1036
+
1037
+ function handleVirtualXVisible ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1038
+ const reactData = $xeGanttView.reactData
1039
+ const internalData = $xeGanttView.internalData
1040
+
1041
+ const { viewCellWidth } = reactData
1042
+ const { elemStore } = internalData
1043
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1044
+ if (bodyScrollElem) {
1045
+ const clientWidth = bodyScrollElem.clientWidth
1046
+ const scrollLeft = bodyScrollElem.scrollLeft
1047
+ const toVisibleIndex = Math.floor(scrollLeft / viewCellWidth) - 1
1048
+ const visibleSize = Math.ceil(clientWidth / viewCellWidth) + 1
1049
+ return { toVisibleIndex: Math.max(0, toVisibleIndex), visibleSize: Math.max(1, visibleSize) }
1050
+ }
1051
+ return { toVisibleIndex: 0, visibleSize: 6 }
1052
+ }
1053
+
1054
+ function loadScrollXData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1055
+ const reactData = $xeGanttView.reactData
1056
+ const internalData = $xeGanttView.internalData
1057
+
1058
+ const { isScrollXBig } = reactData
1059
+ const { scrollXStore } = internalData
1060
+ const { preloadSize, startIndex, endIndex, offsetSize } = scrollXStore
1061
+ const { toVisibleIndex, visibleSize } = handleVirtualXVisible($xeGanttView)
1062
+ const offsetItem = {
1063
+ startIndex: Math.max(0, isScrollXBig ? toVisibleIndex - 1 : toVisibleIndex - 1 - offsetSize - preloadSize),
1064
+ endIndex: isScrollXBig ? toVisibleIndex + visibleSize : toVisibleIndex + visibleSize + offsetSize + preloadSize
1065
+ }
1066
+ scrollXStore.visibleStartIndex = toVisibleIndex - 1
1067
+ scrollXStore.visibleEndIndex = toVisibleIndex + visibleSize + 1
1068
+ const { startIndex: offsetStartIndex, endIndex: offsetEndIndex } = offsetItem
1069
+ if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
1070
+ if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
1071
+ scrollXStore.startIndex = offsetStartIndex
1072
+ scrollXStore.endIndex = offsetEndIndex
1073
+ updateScrollXData($xeGanttView)
1074
+ }
1075
+ }
1076
+ }
1077
+
1078
+ function updateScrollXData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1079
+ handleTableColumn($xeGanttView)
1080
+ updateScrollXSpace($xeGanttView)
1081
+ return $xeGanttView.$nextTick()
1082
+ }
1083
+
1084
+ function updateScrollXStatus ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1085
+ const reactData = $xeGanttView.reactData
1086
+
1087
+ const scrollXLoad = true
1088
+ reactData.scrollXLoad = scrollXLoad
1089
+ return scrollXLoad
1090
+ }
1091
+
1092
+ function handleTableColumn ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1093
+ const reactData = $xeGanttView.reactData
1094
+ const internalData = $xeGanttView.internalData
1095
+
1096
+ const { scrollXLoad } = reactData
1097
+ const { visibleColumn, scrollXStore } = internalData
1098
+ const tableColumn = scrollXLoad ? visibleColumn.slice(scrollXStore.startIndex, scrollXStore.endIndex) : visibleColumn.slice(0)
1099
+ reactData.tableColumn = tableColumn
1100
+ }
1101
+
1102
+ function updateScrollXSpace ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1103
+ const reactData = $xeGanttView.reactData
1104
+ const internalData = $xeGanttView.internalData
1105
+
1106
+ const { scrollXLoad, scrollXWidth, viewCellWidth } = reactData
1107
+ const { elemStore, scrollXStore } = internalData
1108
+ const bodyTableElem = getRefElem(elemStore['main-body-table'])
1109
+ // const headerTableElem = getRefElem(elemStore['main-header-table'])
1110
+ // const footerTableElem = getRefElem(elemStore['main-footer-table'])
1111
+
1112
+ const { startIndex } = scrollXStore
1113
+ let xSpaceLeft = 0
1114
+ if (scrollXLoad) {
1115
+ xSpaceLeft = Math.max(0, startIndex * viewCellWidth)
1116
+ }
1117
+
1118
+ // if (headerTableElem) {
1119
+ // headerTableElem.style.transform = `translate(${xSpaceLeft}px, 0px)`
1120
+ // }
1121
+ if (bodyTableElem) {
1122
+ bodyTableElem.style.transform = `translate(${xSpaceLeft}px, ${reactData.scrollYTop || 0}px)`
1123
+ }
1124
+ // if (footerTableElem) {
1125
+ // footerTableElem.style.transform = `translate(${xSpaceLeft}px, 0px)`
1126
+ // }
1127
+
1128
+ const ySpaceWidth = scrollXWidth
1129
+
1130
+ const layoutList = ['header', 'body', 'footer']
1131
+ layoutList.forEach(layout => {
1132
+ const xSpaceElem = getRefElem(elemStore[`main-${layout}-xSpace`])
1133
+ if (xSpaceElem) {
1134
+ xSpaceElem.style.width = scrollXLoad ? `${ySpaceWidth}px` : ''
1135
+ }
1136
+ })
1137
+
1138
+ const scrollXSpaceEl = $xeGanttView.$refs.refScrollXSpaceElem as HTMLDivElement
1139
+ if (scrollXSpaceEl) {
1140
+ scrollXSpaceEl.style.width = `${ySpaceWidth}px`
1141
+ }
1142
+
1143
+ const beforeWrapper = getRefElem(elemStore['main-chart-before-wrapper'])
1144
+ const beforeSvgElem = beforeWrapper ? beforeWrapper.firstElementChild as HTMLDivElement : null
1145
+ if (beforeSvgElem) {
1146
+ beforeSvgElem.style.width = `${ySpaceWidth}px`
1147
+ }
1148
+ const afterWrapper = getRefElem(elemStore['main-chart-after-wrapper'])
1149
+ const afterSvgElem = afterWrapper ? afterWrapper.firstElementChild as HTMLDivElement : null
1150
+ if (afterSvgElem) {
1151
+ afterSvgElem.style.width = `${ySpaceWidth}px`
1152
+ }
1153
+
1154
+ reactData.scrollXLeft = xSpaceLeft
1155
+ reactData.scrollXWidth = ySpaceWidth
1156
+
1157
+ calcScrollbar($xeGanttView)
1158
+ return $xeGanttView.$nextTick()
1159
+ }
1160
+
1161
+ function triggerScrollXEvent ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1162
+ loadScrollXData($xeGanttView)
1163
+ }
1164
+
1165
+ function updateScrollYSpace ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
1166
+ const reactData = $xeGanttView.reactData
1167
+ const internalData = $xeGanttView.internalData
1168
+
1169
+ const { scrollYLoad, overflowY } = reactData
1170
+ const { elemStore } = internalData
1171
+ const $xeTable = internalData.xeTable
1172
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1173
+ const bodyTableElem = getRefElem(elemStore['main-body-table'])
1174
+
1175
+ let ySpaceTop = 0
1176
+ let scrollYHeight = 0
1177
+ let isScrollYBig = false
1178
+ if ($xeTable) {
1179
+ const tableReactData = $xeTable as unknown as TableReactData
1180
+ ySpaceTop = tableReactData.scrollYTop
1181
+ scrollYHeight = tableReactData.scrollYHeight
1182
+ isScrollYBig = tableReactData.isScrollYBig
1183
+ }
1184
+
1185
+ let ySpaceHeight = scrollYHeight
1186
+ let scrollYTop = ySpaceTop
1187
+
1188
+ let clientHeight = 0
1189
+ if (bodyScrollElem) {
1190
+ clientHeight = bodyScrollElem.clientHeight
1191
+ }
1192
+ if (isScrollYBig) {
1193
+ // 触底
1194
+ if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollTop + clientHeight >= maxYHeight) {
1195
+ scrollYTop = maxYHeight - bodyTableElem.clientHeight
1196
+ } else {
1197
+ scrollYTop = (maxYHeight - clientHeight) * (ySpaceTop / (scrollYHeight - clientHeight))
1198
+ }
1199
+ ySpaceHeight = maxYHeight
1200
+ }
1201
+ if (!(scrollYLoad && overflowY)) {
1202
+ scrollYTop = 0
1203
+ }
1204
+
1205
+ const bodyChartWrapperElem = getRefElem(elemStore['main-chart-task-wrapper'])
1206
+ if (bodyTableElem) {
1207
+ bodyTableElem.style.transform = `translate(${reactData.scrollXLeft || 0}px, ${scrollYTop}px)`
1208
+ }
1209
+ if (bodyChartWrapperElem) {
1210
+ bodyChartWrapperElem.style.transform = `translateY(${scrollYTop}px)`
1211
+ }
1212
+
1213
+ const bodyYSpaceElem = getRefElem(elemStore['main-body-ySpace'])
1214
+ if (bodyYSpaceElem) {
1215
+ bodyYSpaceElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1216
+ }
1217
+
1218
+ const scrollYSpaceEl = $xeGanttView.$refs.refScrollYSpaceElem as HTMLDivElement
1219
+ if (scrollYSpaceEl) {
1220
+ scrollYSpaceEl.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1221
+ }
1222
+
1223
+ const beforeWrapper = getRefElem(elemStore['main-chart-before-wrapper'])
1224
+ const beforeSvgElem = beforeWrapper ? beforeWrapper.firstElementChild as HTMLDivElement : null
1225
+ if (beforeSvgElem) {
1226
+ beforeSvgElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1227
+ }
1228
+ const afterWrapper = getRefElem(elemStore['main-chart-after-wrapper'])
1229
+ const afterSvgElem = afterWrapper ? afterWrapper.firstElementChild as HTMLDivElement : null
1230
+ if (afterSvgElem) {
1231
+ afterSvgElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1232
+ }
1233
+
1234
+ const nowLineElem = getRefElem(elemStore['main-chart-now-line'])
1235
+ if (nowLineElem) {
1236
+ nowLineElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
1237
+ }
1238
+
1239
+ reactData.scrollYTop = scrollYTop
1240
+ reactData.scrollYHeight = scrollYHeight
1241
+ reactData.isScrollYBig = isScrollYBig
1242
+
1243
+ calcScrollbar($xeGanttView)
1244
+ return $xeGanttView.$nextTick().then(() => {
1245
+ updateStyle($xeGanttView)
1246
+ })
1247
+ }
1248
+
1249
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1250
+ function checkLastSyncScroll ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, isRollX: boolean, isRollY: boolean) {
1251
+ const reactData = $xeGanttView.reactData
1252
+ const internalData = $xeGanttView.internalData
1253
+
1254
+ const { lcsTimeout } = internalData
1255
+ reactData.lazScrollLoading = true
1256
+ if (lcsTimeout) {
1257
+ clearTimeout(lcsTimeout)
1258
+ }
1259
+ internalData.lcsTimeout = setTimeout(() => {
1260
+ internalData.lcsRunTime = Date.now()
1261
+ internalData.lcsTimeout = undefined
1262
+ internalData.intoRunScroll = false
1263
+ internalData.inVirtualScroll = false
1264
+ internalData.inWheelScroll = false
1265
+ internalData.inHeaderScroll = false
1266
+ internalData.inBodyScroll = false
1267
+ internalData.inFooterScroll = false
1268
+ reactData.lazScrollLoading = false
1269
+ }, 200)
1270
+ }
1271
+
1272
+ function handleScrollData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, isRollY: boolean, isRollX: boolean, scrollTop: number, scrollLeft: number) {
1273
+ const reactData = $xeGanttView.reactData
1274
+ const internalData = $xeGanttView.internalData
1275
+
1276
+ if (isRollX) {
1277
+ internalData.lastScrollLeft = scrollLeft
1278
+ }
1279
+ if (isRollY) {
1280
+ internalData.lastScrollTop = scrollTop
1281
+ }
1282
+ reactData.lastScrollTime = Date.now()
1283
+ checkLastSyncScroll($xeGanttView, isRollX, isRollY)
1284
+ }
1285
+
1286
+ function handleScrollEvent ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, evnt: Event, isRollY: boolean, isRollX: boolean, scrollTop: number, scrollLeft: number) {
1287
+ const $xeGantt = $xeGanttView.$xeGantt
1288
+ const internalData = $xeGanttView.internalData
1289
+ const $xeTable = internalData.xeTable
1290
+
1291
+ const { lastScrollLeft, lastScrollTop } = internalData
1292
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
1293
+ const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
1294
+ if (!xHandleEl || !yHandleEl) {
1295
+ return
1296
+ }
1297
+ if (!$xeTable) {
1298
+ return
1299
+ }
1300
+ const bodyHeight = yHandleEl.clientHeight
1301
+ const bodyWidth = xHandleEl.clientWidth
1302
+ const scrollHeight = yHandleEl.scrollHeight
1303
+ const scrollWidth = xHandleEl.scrollWidth
1304
+ let isTop = false
1305
+ let isBottom = false
1306
+ let isLeft = false
1307
+ let isRight = false
1308
+ let direction = ''
1309
+ let isTopBoundary = false
1310
+ let isBottomBoundary = false
1311
+ let isLeftBoundary = false
1312
+ let isRightBoundary = false
1313
+ if (isRollX) {
1314
+ const xThreshold = $xeTable.computeScrollXThreshold
1315
+ isLeft = scrollLeft <= 0
1316
+ if (!isLeft) {
1317
+ isRight = scrollLeft + bodyWidth >= scrollWidth - 1
1318
+ }
1319
+ if (scrollLeft > lastScrollLeft) {
1320
+ direction = 'right'
1321
+ if (scrollLeft + bodyWidth >= scrollWidth - xThreshold) {
1322
+ isRightBoundary = true
1323
+ }
1324
+ } else {
1325
+ direction = 'left'
1326
+ if (scrollLeft <= xThreshold) {
1327
+ isLeftBoundary = true
1328
+ }
1329
+ }
1330
+ }
1331
+ if (isRollY) {
1332
+ const yThreshold = $xeTable.computeScrollYThreshold
1333
+ isTop = scrollTop <= 0
1334
+ if (!isTop) {
1335
+ isBottom = scrollTop + bodyHeight >= scrollHeight - 1
1336
+ }
1337
+ if (scrollTop > lastScrollTop) {
1338
+ direction = 'bottom'
1339
+ if (scrollTop + bodyHeight >= scrollHeight - yThreshold) {
1340
+ isBottomBoundary = true
1341
+ }
1342
+ } else {
1343
+ direction = 'top'
1344
+ if (scrollTop <= yThreshold) {
1345
+ isTopBoundary = true
1346
+ }
1347
+ }
1348
+ }
1349
+ handleScrollData($xeGanttView, isRollY, isRollX, scrollTop, scrollLeft)
1350
+ const evntParams = {
1351
+ source: sourceType,
1352
+ scrollTop,
1353
+ scrollLeft,
1354
+ bodyHeight,
1355
+ bodyWidth,
1356
+ scrollHeight,
1357
+ scrollWidth,
1358
+ isX: isRollX,
1359
+ isY: isRollY,
1360
+ isTop,
1361
+ isBottom,
1362
+ isLeft,
1363
+ isRight,
1364
+ direction
1365
+ }
1366
+ if (isBottomBoundary || isTopBoundary || isRightBoundary || isLeftBoundary) {
1367
+ $xeGantt.dispatchEvent('scroll-boundary', evntParams, evnt)
1368
+ }
1369
+ $xeGantt.dispatchEvent('scroll', evntParams, evnt)
1370
+ }
1371
+
1372
+ /**
1373
+ * 同步表格滚动
1374
+ */
1375
+ function syncTableScrollTop ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, scrollTop: number) {
1376
+ const internalData = $xeGanttView.internalData
1377
+
1378
+ const $xeTable = internalData.xeTable
1379
+ if ($xeTable) {
1380
+ const tableInternalData = $xeTable as unknown as TableInternalData
1381
+ const { elemStore: tableElemStore } = tableInternalData
1382
+ const tableBodyScrollElem = getRefElem(tableElemStore['main-body-scroll'])
1383
+ if (tableBodyScrollElem) {
1384
+ tableBodyScrollElem.scrollTop = scrollTop
1385
+ }
1386
+ }
1387
+ }
1388
+
1389
+ export default defineVxeComponent({
1390
+ name: 'VxeGanttView',
1391
+ inject: {
1392
+ $xeGantt: {
1393
+ default: null
1394
+ }
1395
+ },
1396
+ provide () {
1397
+ const $xeGanttView = this
1398
+
1399
+ return {
1400
+ $xeGanttView
1401
+ }
1402
+ },
1403
+ props: {},
1404
+ data () {
1405
+ const xID = XEUtils.uniqueId()
1406
+
1407
+ const reactData = createReactData()
1408
+
1409
+ const internalData = createInternalData()
1410
+
1411
+ return {
1412
+ xID,
1413
+ reactData,
1414
+ internalData
1415
+ }
1416
+ },
1417
+ computed: {
1418
+ ...({} as {
1419
+ $xeGantt(): (VxeGanttConstructor & VxeGanttPrivateMethods)
1420
+ }),
1421
+ computeScaleDateList () {
1422
+ const $xeGanttView = this
1423
+ const $xeGantt = $xeGanttView.$xeGantt
1424
+ const reactData = $xeGanttView.reactData
1425
+ const ganttReactData = $xeGantt.reactData
1426
+
1427
+ const { minViewDate, maxViewDate } = reactData
1428
+ const taskViewOpts = $xeGantt.computeTaskViewOpts
1429
+ const minScale = $xeGantt.computeMinScale
1430
+ const { gridding } = taskViewOpts
1431
+ const dateList: Date[] = []
1432
+ if (!minScale || !minViewDate || !maxViewDate) {
1433
+ return dateList
1434
+ }
1435
+ const { type, startDay } = minScale
1436
+
1437
+ const leftSize = -(ganttReactData.currLeftSpacing + XEUtils.toNumber(gridding ? gridding.leftSpacing || 0 : 0))
1438
+ const rightSize = ganttReactData.currRightSpacing + XEUtils.toNumber(gridding ? gridding.rightSpacing || 0 : 0)
1439
+ const currStep = 1// XEUtils.toNumber(step || 1) || 1
1440
+ switch (type) {
1441
+ case 'year': {
1442
+ let currDate = XEUtils.getWhatYear(minViewDate, leftSize, 'first')
1443
+ const endDate = XEUtils.getWhatYear(maxViewDate, rightSize, 'first')
1444
+ while (currDate <= endDate) {
1445
+ const itemDate = currDate
1446
+ dateList.push(itemDate)
1447
+ currDate = XEUtils.getWhatYear(currDate, currStep)
1448
+ }
1449
+ break
1450
+ }
1451
+ case 'quarter': {
1452
+ let currDate = XEUtils.getWhatQuarter(minViewDate, leftSize, 'first')
1453
+ const endDate = XEUtils.getWhatQuarter(maxViewDate, rightSize, 'first')
1454
+ while (currDate <= endDate) {
1455
+ const itemDate = currDate
1456
+ dateList.push(itemDate)
1457
+ currDate = XEUtils.getWhatQuarter(currDate, currStep)
1458
+ }
1459
+ break
1460
+ }
1461
+ case 'month': {
1462
+ let currDate = XEUtils.getWhatMonth(minViewDate, leftSize, 'first')
1463
+ const endDate = XEUtils.getWhatMonth(maxViewDate, rightSize, 'first')
1464
+ while (currDate <= endDate) {
1465
+ const itemDate = currDate
1466
+ dateList.push(itemDate)
1467
+ currDate = XEUtils.getWhatMonth(currDate, currStep)
1468
+ }
1469
+ break
1470
+ }
1471
+ case 'week': {
1472
+ let currDate = XEUtils.getWhatWeek(minViewDate, leftSize, startDay, startDay)
1473
+ const endDate = XEUtils.getWhatWeek(maxViewDate, rightSize, startDay, startDay)
1474
+ while (currDate <= endDate) {
1475
+ const itemDate = currDate
1476
+ dateList.push(itemDate)
1477
+ currDate = XEUtils.getWhatWeek(currDate, currStep)
1478
+ }
1479
+ break
1480
+ }
1481
+ case 'day':
1482
+ case 'date': {
1483
+ let currDate = XEUtils.getWhatDay(minViewDate, leftSize, 'first')
1484
+ const endDate = XEUtils.getWhatDay(maxViewDate, rightSize, 'first')
1485
+ while (currDate <= endDate) {
1486
+ const itemDate = currDate
1487
+ dateList.push(itemDate)
1488
+ currDate = XEUtils.getWhatDay(currDate, currStep)
1489
+ }
1490
+ break
1491
+ }
1492
+ case 'hour':
1493
+ case 'minute':
1494
+ case 'second': {
1495
+ const gapTime = getStandardGapTime(minScale.type) * currStep
1496
+ let currTime = minViewDate.getTime() + (leftSize * gapTime)
1497
+ const endTime = maxViewDate.getTime() + (rightSize * gapTime)
1498
+ while (currTime <= endTime) {
1499
+ const itemDate = new Date(currTime)
1500
+ dateList.push(itemDate)
1501
+ currTime += gapTime
1502
+ }
1503
+ break
1504
+ }
1505
+ }
1506
+ return dateList
1507
+ },
1508
+ computeNowLineLeft () {
1509
+ const $xeGanttView = this
1510
+ const $xeGantt = $xeGanttView.$xeGantt
1511
+ const reactData = $xeGanttView.reactData
1512
+ const internalData = $xeGanttView.internalData
1513
+ const ganttReactData = $xeGantt.reactData
1514
+
1515
+ const { minViewDate, maxViewDate, viewCellWidth } = reactData
1516
+ const { visibleColumn, todayDateMaps } = internalData
1517
+ const minScale = $xeGantt.computeMinScale
1518
+ const taskViewOpts = $xeGantt.computeTaskViewOpts
1519
+ const taskNowLineOpts = $xeGantt.computeTaskNowLineOpts
1520
+ const { showNowLine } = taskViewOpts
1521
+ const { mode } = taskNowLineOpts
1522
+ const { nowTime } = ganttReactData
1523
+
1524
+ // 此刻线
1525
+ let nlLeft = 0
1526
+ if (showNowLine && minScale && minViewDate && maxViewDate && nowTime >= minViewDate.getTime() && nowTime <= maxViewDate.getTime()) {
1527
+ const todayValue = todayDateMaps[minScale.type]
1528
+ let currCol: VxeGanttDefines.ViewColumn | null = null
1529
+ let nextCol: VxeGanttDefines.ViewColumn | null = null
1530
+ for (let i = 0; i < visibleColumn.length; i++) {
1531
+ const column = visibleColumn[i]
1532
+ if (column.field === todayValue) {
1533
+ currCol = column
1534
+ nlLeft = i * viewCellWidth
1535
+ nextCol = visibleColumn[i + 1]
1536
+ break
1537
+ }
1538
+ }
1539
+ if (mode === 'progress') {
1540
+ if (currCol && nextCol) {
1541
+ const currTime = currCol.dateObj.date.getTime()
1542
+ const offsetTime = nowTime - currTime
1543
+ const nowProgress = Math.max(0, Math.min(1, offsetTime / (nextCol.dateObj.date.getTime() - currTime)))
1544
+ nlLeft += nowProgress * viewCellWidth
1545
+ }
1546
+ } else if (mode === 'center') {
1547
+ nlLeft += viewCellWidth / 2
1548
+ } else if (mode === 'end') {
1549
+ nlLeft += viewCellWidth - 1
1550
+ }
1551
+ }
1552
+ return nlLeft
1553
+ }
1554
+ },
1555
+ methods: {
1556
+ //
1557
+ // Method
1558
+ //
1559
+ refreshData (): Promise<void> {
1560
+ const $xeGanttView = this
1561
+ const internalData = $xeGanttView.internalData
1562
+
1563
+ handleUpdateData($xeGanttView)
1564
+ handleRecalculateStyle($xeGanttView)
1565
+ return $xeGanttView.$nextTick().then(() => {
1566
+ const $xeTable = internalData.xeTable
1567
+ handleRecalculateStyle($xeGanttView)
1568
+ if ($xeTable) {
1569
+ return $xeTable.recalculate()
1570
+ }
1571
+ })
1572
+ },
1573
+ updateViewData (force?: boolean): Promise<void> {
1574
+ const $xeGanttView = this
1575
+ const $xeGantt = $xeGanttView.$xeGantt
1576
+ const reactData = $xeGanttView.reactData
1577
+ const internalData = $xeGanttView.internalData
1578
+ const ganttReactData = $xeGantt.reactData
1579
+
1580
+ const $xeTable = internalData.xeTable
1581
+ if ($xeTable) {
1582
+ const tableReactData = $xeTable as unknown as TableReactData
1583
+ const { tableData } = tableReactData
1584
+ reactData.tableData = tableData
1585
+ if (force) {
1586
+ ganttReactData.currLeftSpacing = 0
1587
+ ganttReactData.currRightSpacing = 0
1588
+ handleUpdateData($xeGanttView)
1589
+ }
1590
+ handleRecalculateStyle($xeGanttView)
1591
+ }
1592
+ return $xeGanttView.$nextTick()
1593
+ },
1594
+ connectUpdate ({ $table }: {
1595
+ $table: VxeTableConstructor & VxeTableMethods & VxeTablePrivateMethods
1596
+ }) {
1597
+ const $xeGanttView = this
1598
+ const internalData = $xeGanttView.internalData
1599
+
1600
+ if ($table) {
1601
+ internalData.xeTable = $table
1602
+ }
1603
+ return $xeGanttView.$nextTick()
1604
+ },
1605
+ handleUpdateStyle () {
1606
+ const $xeGanttView = this
1607
+
1608
+ return updateStyle($xeGanttView)
1609
+ },
1610
+ handleLazyRecalculate () {
1611
+ const $xeGanttView = this
1612
+
1613
+ return handleLazyRecalculate($xeGanttView)
1614
+ },
1615
+ handleUpdateCurrentRow (row: any) {
1616
+ const $xeGanttView = this
1617
+ const internalData = $xeGanttView.internalData
1618
+
1619
+ const $xeTable = internalData.xeTable
1620
+ const el = $xeGanttView.$refs.refElem as HTMLDivElement
1621
+ if ($xeTable && el) {
1622
+ if (row) {
1623
+ const tableProps = $xeTable
1624
+ const rowOpts = $xeTable.computeRowOpts
1625
+ if (rowOpts.isCurrent || tableProps.highlightCurrentRow) {
1626
+ XEUtils.arrayEach(el.querySelectorAll(`[rowid="${$xeTable.getRowid(row)}"]`), elem => addClass(elem, 'row--current'))
1627
+ }
1628
+ } else {
1629
+ XEUtils.arrayEach(el.querySelectorAll('.row--current'), elem => removeClass(elem, 'row--current'))
1630
+ }
1631
+ }
1632
+ },
1633
+ handleUpdateHoverRow (row: any) {
1634
+ const $xeGanttView = this
1635
+ const internalData = $xeGanttView.internalData
1636
+
1637
+ const $xeTable = internalData.xeTable
1638
+ const el = $xeGanttView.$refs.refElem as HTMLDivElement
1639
+ if ($xeTable && el) {
1640
+ if (row) {
1641
+ XEUtils.arrayEach(el.querySelectorAll(`.vxe-body--row[rowid="${$xeTable.getRowid(row)}"]`), elem => addClass(elem, 'row--hover'))
1642
+ } else {
1643
+ XEUtils.arrayEach(el.querySelectorAll('.vxe-body--row.row--hover'), elem => removeClass(elem, 'row--hover'))
1644
+ }
1645
+ }
1646
+ },
1647
+ triggerHeaderScrollEvent (evnt: Event) {
1648
+ const $xeGanttView = this
1649
+ const internalData = $xeGanttView.internalData
1650
+
1651
+ const { elemStore, inVirtualScroll, inBodyScroll, inFooterScroll } = internalData
1652
+ if (inVirtualScroll) {
1653
+ return
1654
+ }
1655
+ if (inBodyScroll || inFooterScroll) {
1656
+ return
1657
+ }
1658
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
1659
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1660
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
1661
+ if (bodyScrollElem && wrapperEl) {
1662
+ const isRollX = true
1663
+ const isRollY = false
1664
+ const currLeftNum = wrapperEl.scrollLeft
1665
+ internalData.inHeaderScroll = true
1666
+ setScrollLeft(xHandleEl, currLeftNum)
1667
+ setScrollLeft(bodyScrollElem, currLeftNum)
1668
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
1669
+ }
1670
+ },
1671
+ triggerBodyScrollEvent (evnt: Event) {
1672
+ const $xeGanttView = this
1673
+ const reactData = $xeGanttView.reactData
1674
+ const internalData = $xeGanttView.internalData
1675
+
1676
+ const { scrollXLoad } = reactData
1677
+ const { elemStore, inVirtualScroll, inHeaderScroll, inFooterScroll, lastScrollLeft, lastScrollTop } = internalData
1678
+ if (inVirtualScroll) {
1679
+ return
1680
+ }
1681
+ if (inHeaderScroll || inFooterScroll) {
1682
+ return
1683
+ }
1684
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
1685
+ const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
1686
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
1687
+ const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
1688
+ const scrollLeft = wrapperEl.scrollLeft
1689
+ const scrollTop = wrapperEl.scrollTop
1690
+ const isRollX = scrollLeft !== lastScrollLeft
1691
+ const isRollY = scrollTop !== lastScrollTop
1692
+ internalData.inBodyScroll = true
1693
+ internalData.scrollRenderType = ''
1694
+ if (isRollY) {
1695
+ setScrollTop(yHandleEl, scrollTop)
1696
+ syncTableScrollTop($xeGanttView, scrollTop)
1697
+ }
1698
+ if (isRollX) {
1699
+ internalData.inBodyScroll = true
1700
+ setScrollLeft(xHandleEl, scrollLeft)
1701
+ setScrollLeft(headerScrollElem, scrollLeft)
1702
+ if (scrollXLoad) {
1703
+ triggerScrollXEvent($xeGanttView)
1704
+ }
1705
+ }
1706
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, scrollLeft)
1707
+ },
1708
+ // triggerFooterScrollEvent (evnt: Event) {
1709
+ // const $xeGanttView = this
1710
+ // const internalData = $xeGanttView.internalData
1711
+
1712
+ // const { inVirtualScroll, inHeaderScroll, inBodyScroll } = internalData
1713
+ // if (inVirtualScroll) {
1714
+ // return
1715
+ // }
1716
+ // if (inHeaderScroll || inBodyScroll) {
1717
+ // return
1718
+ // }
1719
+ // const wrapperEl = evnt.currentTarget as HTMLDivElement
1720
+ // if (wrapperEl) {
1721
+ // const isRollX = true
1722
+ // const isRollY = false
1723
+ // const currLeftNum = wrapperEl.scrollLeft
1724
+ // handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
1725
+ // }
1726
+ // },
1727
+ triggerVirtualScrollXEvent (evnt: Event) {
1728
+ const $xeGanttView = this
1729
+ const reactData = $xeGanttView.reactData
1730
+ const internalData = $xeGanttView.internalData
1731
+
1732
+ const { scrollXLoad } = reactData
1733
+ const { elemStore, inHeaderScroll, inBodyScroll } = internalData
1734
+ if (inHeaderScroll || inBodyScroll) {
1735
+ return
1736
+ }
1737
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
1738
+ const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
1739
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1740
+ if (wrapperEl) {
1741
+ const isRollY = false
1742
+ const isRollX = true
1743
+ const currLeftNum = wrapperEl.scrollLeft
1744
+ internalData.inVirtualScroll = true
1745
+ setScrollLeft(headerScrollElem, currLeftNum)
1746
+ setScrollLeft(bodyScrollElem, currLeftNum)
1747
+ if (scrollXLoad) {
1748
+ triggerScrollXEvent($xeGanttView)
1749
+ }
1750
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
1751
+ }
1752
+ },
1753
+ triggerVirtualScrollYEvent (evnt: Event) {
1754
+ const $xeGanttView = this
1755
+ const internalData = $xeGanttView.internalData
1756
+
1757
+ const { elemStore, inHeaderScroll, inBodyScroll } = internalData
1758
+ if (inHeaderScroll || inBodyScroll) {
1759
+ return
1760
+ }
1761
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
1762
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1763
+ if (wrapperEl) {
1764
+ const isRollY = true
1765
+ const isRollX = false
1766
+ const currTopNum = wrapperEl.scrollTop
1767
+ internalData.inVirtualScroll = true
1768
+ setScrollTop(bodyScrollElem, currTopNum)
1769
+ syncTableScrollTop($xeGanttView, currTopNum)
1770
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, currTopNum, wrapperEl.scrollLeft)
1771
+ }
1772
+ },
1773
+ handleUpdateSXSpace () {
1774
+ const $xeGanttView = this
1775
+
1776
+ return updateScrollXSpace($xeGanttView)
1777
+ },
1778
+ handleUpdateSYSpace () {
1779
+ const $xeGanttView = this
1780
+
1781
+ return updateScrollYSpace($xeGanttView)
1782
+ },
1783
+ handleUpdateSYStatus (sYLoad: boolean) {
1784
+ const $xeGanttView = this
1785
+ const reactData = $xeGanttView.reactData
1786
+
1787
+ reactData.scrollYLoad = sYLoad
1788
+ },
1789
+ handleGlobalResizeEvent () {
1790
+ const $xeGanttView = this
1791
+
1792
+ handleLazyRecalculate($xeGanttView)
1793
+ },
1794
+
1795
+ //
1796
+ // Render
1797
+ //
1798
+ renderScrollX (h: CreateElement) {
1799
+ const $xeGanttView = this
1800
+
1801
+ return h('div', {
1802
+ key: 'vsx',
1803
+ ref: 'refScrollXVirtualElem',
1804
+ class: 'vxe-gantt-view--scroll-x-virtual'
1805
+ }, [
1806
+ h('div', {
1807
+ ref: 'refScrollXLeftCornerElem',
1808
+ class: 'vxe-gantt-view--scroll-x-left-corner'
1809
+ }),
1810
+ h('div', {
1811
+ ref: 'refScrollXWrapperElem',
1812
+ class: 'vxe-gantt-view--scroll-x-wrapper'
1813
+ }, [
1814
+ h('div', {
1815
+ ref: 'refScrollXHandleElem',
1816
+ class: 'vxe-gantt-view--scroll-x-handle',
1817
+ on: {
1818
+ scroll: $xeGanttView.triggerVirtualScrollXEvent
1819
+ }
1820
+ }, [
1821
+ h('div', {
1822
+ ref: 'refScrollXSpaceElem',
1823
+ class: 'vxe-gantt-view--scroll-x-space'
1824
+ })
1825
+ ]),
1826
+ h('div', {
1827
+ class: 'vxe-gantt-view--scroll-x-handle-appearance'
1828
+ })
1829
+ ]),
1830
+ h('div', {
1831
+ ref: 'refScrollXRightCornerElem',
1832
+ class: 'vxe-gantt-view--scroll-x-right-corner'
1833
+ })
1834
+ ])
1835
+ },
1836
+ renderScrollY (h: CreateElement) {
1837
+ const $xeGanttView = this
1838
+
1839
+ return h('div', {
1840
+ ref: 'refScrollYVirtualElem',
1841
+ class: 'vxe-gantt-view--scroll-y-virtual'
1842
+ }, [
1843
+ h('div', {
1844
+ ref: 'refScrollYTopCornerElem',
1845
+ class: 'vxe-gantt-view--scroll-y-top-corner'
1846
+ }),
1847
+ h('div', {
1848
+ ref: 'refScrollYWrapperElem',
1849
+ class: 'vxe-gantt-view--scroll-y-wrapper'
1850
+ }, [
1851
+ h('div', {
1852
+ ref: 'refScrollYHandleElem',
1853
+ class: 'vxe-gantt-view--scroll-y-handle',
1854
+ on: {
1855
+ scroll: $xeGanttView.triggerVirtualScrollYEvent
1856
+ }
1857
+ }, [
1858
+ h('div', {
1859
+ ref: 'refScrollYSpaceElem',
1860
+ class: 'vxe-gantt-view--scroll-y-space'
1861
+ })
1862
+ ]),
1863
+ h('div', {
1864
+ class: 'vxe-gantt-view--scroll-y-handle-appearance'
1865
+ })
1866
+ ]),
1867
+ h('div', {
1868
+ ref: 'refScrollYBottomCornerElem',
1869
+ class: 'vxe-gantt-view--scroll-y-bottom-corner'
1870
+ })
1871
+ ])
1872
+ },
1873
+ renderViewport (h: CreateElement) {
1874
+ return h('div', {
1875
+ class: 'vxe-gantt-view--viewport-wrapper'
1876
+ }, [
1877
+ h(GanttViewHeaderComponent),
1878
+ h(GanttViewBodyComponent),
1879
+ h(GanttViewFooterComponent)
1880
+ ])
1881
+ },
1882
+ renderBody (h: CreateElement) {
1883
+ const $xeGanttView = this
1884
+ const $xeGantt = $xeGanttView.$xeGantt
1885
+
1886
+ const scrollbarYToLeft = $xeGantt.computeScrollbarYToLeft
1887
+ return h('div', {
1888
+ class: 'vxe-gantt-view--layout-wrapper'
1889
+ }, scrollbarYToLeft
1890
+ ? [
1891
+ $xeGanttView.renderScrollY(h),
1892
+ $xeGanttView.renderViewport(h)
1893
+ ]
1894
+ : [
1895
+ $xeGanttView.renderViewport(h),
1896
+ $xeGanttView.renderScrollY(h)
1897
+ ])
1898
+ },
1899
+ renderVN (h: CreateElement): VNode {
1900
+ const $xeGanttView = this
1901
+ const $xeGantt = $xeGanttView.$xeGantt
1902
+ const reactData = $xeGanttView.reactData
1903
+
1904
+ const { overflowX, overflowY, scrollXLoad, scrollYLoad } = reactData
1905
+ const scrollbarXToTop = $xeGantt.computeScrollbarXToTop
1906
+ return h('div', {
1907
+ ref: 'refElem',
1908
+ class: ['vxe-gantt-view', {
1909
+ 'is--scroll-y': overflowY,
1910
+ 'is--scroll-x': overflowX,
1911
+ 'is--virtual-x': scrollXLoad,
1912
+ 'is--virtual-y': scrollYLoad
1913
+ }]
1914
+ }, [
1915
+ h('div', {
1916
+ class: 'vxe-gantt-view--render-wrapper'
1917
+ }, scrollbarXToTop
1918
+ ? [
1919
+ $xeGanttView.renderScrollX(h),
1920
+ $xeGanttView.renderBody(h)
1921
+ ]
1922
+ : [
1923
+ $xeGanttView.renderBody(h),
1924
+ $xeGanttView.renderScrollX(h)
1925
+ ]),
1926
+ h('div', {
1927
+ class: 'vxe-gantt-view--render-vars'
1928
+ }, [
1929
+ h('div', {
1930
+ ref: 'refColInfoElem',
1931
+ class: 'vxe-gantt-view--column-info'
1932
+ })
1933
+ ])
1934
+ ])
1935
+ }
1936
+ },
1937
+ mounted () {
1938
+ const $xeGanttView = this
1939
+
1940
+ globalEvents.on($xeGanttView, 'resize', $xeGanttView.handleGlobalResizeEvent)
1941
+ },
1942
+ beforeDestroy () {
1943
+ const $xeGanttView = this
1944
+ const reactData = $xeGanttView.reactData
1945
+ const internalData = $xeGanttView.internalData
1946
+
1947
+ globalEvents.off($xeGanttView, 'keydown')
1948
+ XEUtils.assign(reactData, createReactData())
1949
+ XEUtils.assign(internalData, createInternalData())
1950
+ },
1951
+ render (this: any, h) {
1952
+ return this.renderVN(h)
1953
+ }
1954
+ })