vxe-gantt 0.0.2 → 3.0.0-beta.0

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 (94) hide show
  1. package/README.md +18 -24
  2. package/es/components.js +3 -2
  3. package/es/gantt/src/gantt-body.js +137 -0
  4. package/es/gantt/src/gantt-chart.js +125 -0
  5. package/es/gantt/src/gantt-header.js +97 -0
  6. package/es/gantt/src/gantt-view.js +820 -0
  7. package/es/gantt/src/gantt.js +1897 -43
  8. package/es/gantt/src/util.js +9 -0
  9. package/es/gantt/style.css +624 -0
  10. package/es/gantt/style.min.css +1 -0
  11. package/es/index.esm.js +5 -2
  12. package/es/style.css +1 -0
  13. package/es/style.min.css +1 -0
  14. package/es/ui/index.js +55 -5
  15. package/es/ui/src/comp.js +1 -2
  16. package/es/ui/src/dom.js +44 -105
  17. package/es/ui/src/log.js +3 -2
  18. package/es/ui/src/utils.js +4 -3
  19. package/es/ui/src/vn.js +1 -32
  20. package/es/vxe-gantt/style.css +624 -0
  21. package/es/vxe-gantt/style.min.css +1 -0
  22. package/helper/vetur/attributes.json +1 -1
  23. package/helper/vetur/tags.json +1 -1
  24. package/lib/components.js +20 -19
  25. package/lib/components.min.js +1 -1
  26. package/lib/gantt/index.js +3 -3
  27. package/lib/gantt/index.min.js +1 -1
  28. package/lib/gantt/src/gantt-body.js +140 -0
  29. package/lib/gantt/src/gantt-body.min.js +1 -0
  30. package/lib/gantt/src/gantt-chart.js +134 -0
  31. package/lib/gantt/src/gantt-chart.min.js +1 -0
  32. package/lib/gantt/src/gantt-header.js +97 -0
  33. package/lib/gantt/src/gantt-header.min.js +1 -0
  34. package/lib/gantt/src/gantt-view.js +808 -0
  35. package/lib/gantt/src/gantt-view.min.js +1 -0
  36. package/lib/gantt/src/gantt.js +2045 -48
  37. package/lib/gantt/src/gantt.min.js +1 -1
  38. package/lib/gantt/src/util.js +16 -0
  39. package/lib/gantt/src/util.min.js +1 -0
  40. package/lib/gantt/style/style.css +624 -0
  41. package/lib/gantt/style/style.min.css +1 -0
  42. package/lib/index.common.js +12 -7
  43. package/lib/index.umd.js +11484 -235
  44. package/lib/index.umd.min.js +1 -1
  45. package/lib/style.css +1 -0
  46. package/lib/style.min.css +1 -0
  47. package/lib/ui/index.js +54 -14
  48. package/lib/ui/index.min.js +1 -1
  49. package/lib/ui/src/comp.js +3 -2
  50. package/lib/ui/src/comp.min.js +1 -1
  51. package/lib/ui/src/dom.js +78 -138
  52. package/lib/ui/src/dom.min.js +1 -1
  53. package/lib/ui/src/log.js +4 -3
  54. package/lib/ui/src/log.min.js +1 -1
  55. package/lib/ui/src/utils.js +5 -4
  56. package/lib/ui/src/utils.min.js +1 -1
  57. package/lib/ui/src/vn.js +1 -43
  58. package/lib/ui/src/vn.min.js +0 -1
  59. package/lib/vxe-gantt/index.js +4 -2
  60. package/lib/vxe-gantt/index.min.js +1 -1
  61. package/lib/vxe-gantt/style/style.css +624 -0
  62. package/lib/vxe-gantt/style/style.min.css +1 -0
  63. package/lib/vxe-ui/index.js +4 -2
  64. package/lib/vxe-ui/index.min.js +1 -1
  65. package/package.json +13 -13
  66. package/packages/components.ts +8 -5
  67. package/packages/gantt/index.ts +2 -2
  68. package/packages/gantt/src/gantt-body.ts +155 -0
  69. package/packages/gantt/src/gantt-chart.ts +143 -0
  70. package/packages/gantt/src/gantt-header.ts +109 -0
  71. package/packages/gantt/src/gantt-view.ts +908 -0
  72. package/packages/gantt/src/gantt.ts +2048 -46
  73. package/packages/gantt/src/util.ts +12 -0
  74. package/packages/index.ts +6 -2
  75. package/packages/ui/index.ts +56 -4
  76. package/packages/ui/src/comp.ts +2 -2
  77. package/packages/ui/src/dom.ts +53 -110
  78. package/packages/ui/src/log.ts +4 -2
  79. package/packages/ui/src/utils.ts +5 -3
  80. package/packages/ui/src/vn.ts +0 -37
  81. package/styles/components/gantt-module/all.scss +1 -0
  82. package/styles/components/gantt-module/gantt-chart.scss +65 -0
  83. package/styles/components/gantt.scss +591 -0
  84. package/styles/helpers/baseMixin.scss +96 -0
  85. package/styles/helpers/baseVar.scss +4 -0
  86. package/styles/helpers/placement.scss +39 -0
  87. package/styles/theme/base.scss +11 -0
  88. package/styles/theme/dark.scss +5 -0
  89. package/styles/theme/light.scss +5 -0
  90. package/types/all.d.ts +3 -3
  91. package/types/index.d.ts +2 -2
  92. package/README.en.md +0 -72
  93. package/README.ja-JP.md +0 -72
  94. package/README.zh-TW.md +0 -73
@@ -0,0 +1,908 @@
1
+ import { VNode, CreateElement } from 'vue'
2
+ import { defineVxeComponent } from '../../ui/src/comp'
3
+ import { VxeUI } from '@vxe-ui/core'
4
+ import { setScrollTop, setScrollLeft } from '../../ui/src/dom'
5
+ import { getRefElem } from './util'
6
+ import XEUtils from 'xe-utils'
7
+ import GanttViewHeaderComponent from './gantt-header'
8
+ import GanttViewBodyComponent from './gantt-body'
9
+
10
+ import type { TableReactData, TableInternalData, VxeTableConstructor, VxeTableMethods, VxeTablePrivateMethods } from 'vxe-table'
11
+ import type { VxeGanttViewConstructor, GanttViewReactData, VxeGanttPropTypes, VxeGanttDefines, VxeGanttViewPrivateMethods, GanttViewInternalData, VxeGanttConstructor, VxeGanttPrivateMethods } from '../../../types'
12
+
13
+ const { globalEvents } = VxeUI
14
+
15
+ function createInternalData (): GanttViewInternalData {
16
+ return {
17
+ xeTable: null,
18
+ startMaps: {},
19
+ endMaps: {},
20
+ chartMaps: {},
21
+ elemStore: {},
22
+ // 存放横向 X 虚拟滚动相关的信息
23
+ scrollXStore: {
24
+ preloadSize: 0,
25
+ offsetSize: 0,
26
+ visibleSize: 0,
27
+ visibleStartIndex: 0,
28
+ visibleEndIndex: 0,
29
+ startIndex: 0,
30
+ endIndex: 0
31
+ },
32
+ // 存放纵向 Y 虚拟滚动相关信息
33
+ scrollYStore: {
34
+ preloadSize: 0,
35
+ offsetSize: 0,
36
+ visibleSize: 0,
37
+ visibleStartIndex: 0,
38
+ visibleEndIndex: 0,
39
+ startIndex: 0,
40
+ endIndex: 0
41
+ }
42
+ }
43
+ }
44
+ const maxYHeight = 5e6
45
+ const maxXWidth = 5e6
46
+
47
+ function handleParseColumn ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
48
+ const $xeGantt = $xeGanttView.$xeGantt
49
+ const reactData = $xeGanttView.reactData
50
+ const internalData = $xeGanttView.internalData
51
+
52
+ const { minViewDate, maxViewDate } = reactData
53
+ const taskViewOpts = $xeGantt.computeTaskViewOpts
54
+ const fullCols: VxeGanttPropTypes.Column[] = []
55
+ const groupCols: VxeGanttPropTypes.Column[][] = []
56
+ switch (taskViewOpts.mode) {
57
+ case 'year':
58
+ break
59
+ case 'quarter':
60
+ break
61
+ case 'month':
62
+ break
63
+ case 'week':
64
+ break
65
+ default: {
66
+ if (minViewDate && maxViewDate) {
67
+ const currTime = minViewDate.getTime()
68
+ const diffDayNum = maxViewDate.getTime() - minViewDate.getTime()
69
+ const countDayNum = Math.max(6, Math.floor(diffDayNum / 86400000) + 1)
70
+ const groupList: VxeGanttDefines.GroupHeaderColumn[] = []
71
+ const colList: VxeGanttPropTypes.Column[] = []
72
+ const groupMaps: Record<string, VxeGanttDefines.GroupHeaderColumn> = {}
73
+ for (let i = 0; i < countDayNum; i++) {
74
+ const itemDate = new Date(currTime + (i * 86400000))
75
+ const yyyyy = `${itemDate.getFullYear()}-${itemDate.getMonth() + 1}`
76
+ const mmDd = `${itemDate.getDate()}`
77
+ let groupCol = groupMaps[yyyyy]
78
+ const column = {
79
+ field: `${yyyyy}-${mmDd}`,
80
+ title: mmDd
81
+ }
82
+ if (groupCol) {
83
+ groupCol.children.push(column)
84
+ fullCols.push(groupCol)
85
+ } else {
86
+ groupCol = {
87
+ field: yyyyy,
88
+ title: yyyyy,
89
+ children: [column]
90
+ }
91
+ groupList.push(groupCol)
92
+ fullCols.push(groupCol)
93
+ groupMaps[yyyyy] = groupCol
94
+ }
95
+ colList.push(column)
96
+ }
97
+ groupCols.push(groupList, colList)
98
+
99
+ const $xeTable = internalData.xeTable
100
+ if ($xeTable) {
101
+ const startField = $xeGantt.computeStartField
102
+ const endField = $xeGantt.computeEndField
103
+ const tableInternalData = $xeTable as unknown as TableInternalData
104
+ const { afterFullData } = tableInternalData
105
+ const ctMaps: Record<string, VxeGanttDefines.RowCacheItem> = {}
106
+ afterFullData.forEach(row => {
107
+ const rowid = $xeTable.getRowid(row)
108
+ const startValue = XEUtils.get(row, startField)
109
+ const endValue = XEUtils.get(row, endField)
110
+ if (startValue && endValue) {
111
+ const startDate = XEUtils.toStringDate(startValue)
112
+ const endDate = XEUtils.toStringDate(endValue)
113
+ const oLeftSize = Math.floor((startDate.getTime() - minViewDate.getTime()) / 86400000)
114
+ const oWidthSize = Math.floor((endDate.getTime() - startDate.getTime()) / 86400000) + 1
115
+ ctMaps[rowid] = {
116
+ row,
117
+ rowid,
118
+ oLeftSize,
119
+ oWidthSize
120
+ }
121
+ }
122
+ })
123
+ internalData.chartMaps = ctMaps
124
+ }
125
+ }
126
+ break
127
+ }
128
+ }
129
+ reactData.tableColumn = fullCols
130
+ reactData.headerGroups = groupCols
131
+ }
132
+
133
+ function handleUpdateData ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
134
+ const $xeGantt = $xeGanttView.$xeGantt
135
+ const reactData = $xeGanttView.reactData
136
+ const internalData = $xeGanttView.internalData
137
+
138
+ const $xeTable = internalData.xeTable
139
+ const sdMaps: Record<string, any> = {}
140
+ const edMaps: Record<string, any> = {}
141
+ let minDate: Date | null = null
142
+ let maxDate: Date | null = null
143
+ if ($xeTable) {
144
+ const startField = $xeGantt.computeStartField
145
+ const endField = $xeGantt.computeEndField
146
+ const tableInternalData = $xeTable as unknown as TableInternalData
147
+ const { afterFullData } = tableInternalData
148
+ afterFullData.forEach(row => {
149
+ const startValue = XEUtils.get(row, startField)
150
+ const endValue = XEUtils.get(row, endField)
151
+ if (startValue && endValue) {
152
+ const startDate = XEUtils.toStringDate(startValue)
153
+ if (!minDate || minDate.getTime() > startDate.getTime()) {
154
+ minDate = startDate
155
+ }
156
+ const endDate = XEUtils.toStringDate(endValue)
157
+ if (!maxDate || maxDate.getTime() < endDate.getTime()) {
158
+ maxDate = endDate
159
+ }
160
+ }
161
+ })
162
+ }
163
+ reactData.minViewDate = minDate
164
+ reactData.maxViewDate = maxDate
165
+ internalData.startMaps = sdMaps
166
+ internalData.endMaps = edMaps
167
+ handleParseColumn($xeGanttView)
168
+ }
169
+
170
+ function calcScrollbar ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
171
+ const $xeGantt = $xeGanttView.$xeGantt
172
+ const reactData = $xeGanttView.reactData
173
+ const internalData = $xeGanttView.internalData
174
+
175
+ const { scrollXWidth, scrollYHeight } = reactData
176
+ const { elemStore } = internalData
177
+ const scrollbarOpts = $xeGantt.computeScrollbarOpts
178
+ const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper'])
179
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
180
+ const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
181
+ let overflowY = false
182
+ let overflowX = false
183
+ if (bodyWrapperElem) {
184
+ overflowY = scrollYHeight > bodyWrapperElem.clientHeight
185
+ if (yHandleEl) {
186
+ reactData.scrollbarWidth = scrollbarOpts.width || (yHandleEl.offsetWidth - yHandleEl.clientWidth) || 14
187
+ }
188
+ reactData.overflowY = overflowY
189
+
190
+ overflowX = scrollXWidth > bodyWrapperElem.clientWidth
191
+ if (xHandleEl) {
192
+ reactData.scrollbarHeight = scrollbarOpts.height || (xHandleEl.offsetHeight - xHandleEl.clientHeight) || 14
193
+ }
194
+
195
+ reactData.overflowX = overflowX
196
+ }
197
+ }
198
+
199
+ function updateChart ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
200
+ const reactData = $xeGanttView.reactData
201
+ const internalData = $xeGanttView.internalData
202
+
203
+ const { viewCellWidth } = reactData
204
+ const { elemStore, chartMaps } = internalData
205
+ const chartWrapper = getRefElem(elemStore['main-chart-wrapper'])
206
+ if (chartWrapper) {
207
+ XEUtils.arrayEach(chartWrapper.children, (rowEl) => {
208
+ const barEl = rowEl.children[0] as HTMLDivElement
209
+ if (!barEl) {
210
+ return
211
+ }
212
+ const rowid = rowEl.getAttribute('rowid')
213
+ const rowRest = rowid ? chartMaps[rowid] : null
214
+ if (rowRest) {
215
+ barEl.style.left = `${viewCellWidth * rowRest.oLeftSize}px`
216
+ barEl.style.width = `${viewCellWidth * rowRest.oWidthSize}px`
217
+ }
218
+ })
219
+ }
220
+ return $xeGanttView.$nextTick()
221
+ }
222
+
223
+ function updateStyle ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
224
+ const $xeGantt = $xeGanttView.$xeGantt
225
+ const reactData = $xeGanttView.reactData
226
+ const internalData = $xeGanttView.internalData
227
+
228
+ const { scrollbarWidth, scrollbarHeight, tableColumn } = reactData
229
+ const { elemStore } = internalData
230
+ const $xeTable = internalData.xeTable
231
+
232
+ const el = $xeGanttView.$refs.refElem as HTMLDivElement
233
+ if (!el || !el.clientHeight) {
234
+ return
235
+ }
236
+
237
+ const scrollbarXToTop = $xeGantt.computeScrollbarXToTop
238
+
239
+ const xLeftCornerEl = $xeGanttView.$refs.refScrollXLeftCornerElem as HTMLDivElement
240
+ const xRightCornerEl = $xeGanttView.$refs.refScrollXRightCornerElem as HTMLDivElement
241
+ const scrollXVirtualEl = $xeGanttView.$refs.refScrollXVirtualElem as HTMLDivElement
242
+
243
+ const osbWidth = scrollbarWidth
244
+ const osbHeight = scrollbarHeight
245
+
246
+ let tbHeight = 0
247
+ let tHeaderHeight = 0
248
+ let tFooterHeight = 0
249
+ if ($xeTable) {
250
+ const tableInternalData = $xeTable as unknown as TableInternalData
251
+ tbHeight = tableInternalData.tBodyHeight
252
+ tHeaderHeight = tableInternalData.tHeaderHeight
253
+ tFooterHeight = tableInternalData.tFooterHeight
254
+ }
255
+
256
+ const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
257
+ if (headerScrollElem) {
258
+ headerScrollElem.style.height = `${tHeaderHeight}px`
259
+ }
260
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
261
+ if (bodyScrollElem) {
262
+ bodyScrollElem.style.height = `${tbHeight}px`
263
+ }
264
+
265
+ if (scrollXVirtualEl) {
266
+ scrollXVirtualEl.style.height = `${osbHeight}px`
267
+ scrollXVirtualEl.style.visibility = 'visible'
268
+ }
269
+ const xWrapperEl = $xeGanttView.$refs.refScrollXWrapperElem as HTMLDivElement
270
+ if (xWrapperEl) {
271
+ xWrapperEl.style.left = scrollbarXToTop ? `${osbWidth}px` : ''
272
+ xWrapperEl.style.width = `${el.clientWidth - osbWidth}px`
273
+ }
274
+ if (xLeftCornerEl) {
275
+ xLeftCornerEl.style.width = scrollbarXToTop ? `${osbWidth}px` : ''
276
+ xLeftCornerEl.style.display = scrollbarXToTop ? (osbHeight ? 'block' : '') : ''
277
+ }
278
+ if (xRightCornerEl) {
279
+ xRightCornerEl.style.width = scrollbarXToTop ? '' : `${osbWidth}px`
280
+ xRightCornerEl.style.display = scrollbarXToTop ? '' : (osbHeight ? 'block' : '')
281
+ }
282
+
283
+ const scrollYVirtualEl = $xeGanttView.$refs.refScrollYVirtualElem as HTMLDivElement
284
+ if (scrollYVirtualEl) {
285
+ scrollYVirtualEl.style.width = `${osbWidth}px`
286
+ scrollYVirtualEl.style.height = `${tbHeight + tHeaderHeight + tFooterHeight}px`
287
+ scrollYVirtualEl.style.visibility = 'visible'
288
+ }
289
+ const yTopCornerEl = $xeGanttView.$refs.refScrollYTopCornerElem as HTMLDivElement
290
+ if (yTopCornerEl) {
291
+ yTopCornerEl.style.height = `${tHeaderHeight}px`
292
+ yTopCornerEl.style.display = tHeaderHeight ? 'block' : ''
293
+ }
294
+ const yWrapperEl = $xeGanttView.$refs.refScrollYWrapperElem as HTMLDivElement
295
+ if (yWrapperEl) {
296
+ yWrapperEl.style.height = `${tbHeight}px`
297
+ yWrapperEl.style.top = `${tHeaderHeight}px`
298
+ }
299
+ const yBottomCornerEl = $xeGanttView.$refs.refScrollYBottomCornerElem as HTMLDivElement
300
+ if (yBottomCornerEl) {
301
+ yBottomCornerEl.style.height = `${tFooterHeight}px`
302
+ yBottomCornerEl.style.top = `${tHeaderHeight + tbHeight}px`
303
+ yBottomCornerEl.style.display = tFooterHeight ? 'block' : ''
304
+ }
305
+
306
+ const colInfoElem = $xeGanttView.$refs.refColInfoElem as HTMLDivElement
307
+ if (colInfoElem) {
308
+ reactData.viewCellWidth = colInfoElem.clientWidth || 40
309
+ }
310
+ let viewTableWidth = reactData.viewCellWidth * tableColumn.length
311
+ if (bodyScrollElem) {
312
+ const viewWidth = bodyScrollElem.clientWidth
313
+ const remainWidth = viewWidth - viewTableWidth
314
+ if (remainWidth > 0) {
315
+ reactData.viewCellWidth += Math.floor(remainWidth / tableColumn.length)
316
+ viewTableWidth = viewWidth
317
+ }
318
+ }
319
+ const headerTableElem = getRefElem(elemStore['main-header-table'])
320
+ const bodyTableElem = getRefElem(elemStore['main-body-table'])
321
+ if (headerTableElem) {
322
+ headerTableElem.style.width = `${viewTableWidth}px`
323
+ }
324
+ if (bodyTableElem) {
325
+ bodyTableElem.style.width = `${viewTableWidth}px`
326
+ }
327
+
328
+ reactData.scrollXWidth = viewTableWidth
329
+
330
+ return updateChart($xeGanttView)
331
+ }
332
+
333
+ function handleLazyRecalculate ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
334
+ calcScrollbar($xeGanttView)
335
+ updateStyle($xeGanttView)
336
+ return $xeGanttView.$nextTick()
337
+ }
338
+
339
+ function updateScrollXSpace ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
340
+ const reactData = $xeGanttView.reactData
341
+ const internalData = $xeGanttView.internalData
342
+
343
+ const { scrollXLoad, scrollXWidth } = reactData
344
+ const { elemStore } = internalData
345
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
346
+ const bodyTableElem = getRefElem(elemStore['main-body-table'])
347
+
348
+ let xSpaceLeft = 0
349
+
350
+ let clientWidth = 0
351
+ if (bodyScrollElem) {
352
+ clientWidth = bodyScrollElem.clientWidth
353
+ }
354
+ // 虚拟渲染
355
+ let isScrollXBig = false
356
+ let ySpaceWidth = scrollXWidth
357
+ if (scrollXWidth > maxXWidth) {
358
+ // 触右
359
+ if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollLeft + clientWidth >= maxXWidth) {
360
+ xSpaceLeft = maxXWidth - bodyTableElem.clientWidth
361
+ } else {
362
+ xSpaceLeft = (maxXWidth - clientWidth) * (xSpaceLeft / (scrollXWidth - clientWidth))
363
+ }
364
+ ySpaceWidth = maxXWidth
365
+ isScrollXBig = true
366
+ }
367
+
368
+ if (bodyTableElem) {
369
+ bodyTableElem.style.transform = `translate(${xSpaceLeft}px, ${reactData.scrollYTop || 0}px)`
370
+ }
371
+
372
+ const layoutList = ['header', 'body', 'footer']
373
+ layoutList.forEach(layout => {
374
+ const xSpaceElem = getRefElem(elemStore[`main-${layout}-xSpace`])
375
+ if (xSpaceElem) {
376
+ xSpaceElem.style.width = scrollXLoad ? `${ySpaceWidth}px` : ''
377
+ }
378
+ })
379
+
380
+ reactData.scrollXLeft = xSpaceLeft
381
+ reactData.scrollXWidth = ySpaceWidth
382
+ reactData.isScrollXBig = isScrollXBig
383
+
384
+ const scrollXSpaceEl = $xeGanttView.$refs.refScrollXSpaceElem as HTMLDivElement
385
+ if (scrollXSpaceEl) {
386
+ scrollXSpaceEl.style.width = `${ySpaceWidth}px`
387
+ }
388
+
389
+ calcScrollbar($xeGanttView)
390
+ return $xeGanttView.$nextTick().then(() => {
391
+ updateStyle($xeGanttView)
392
+ })
393
+ }
394
+
395
+ function updateScrollYSpace ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods) {
396
+ const reactData = $xeGanttView.reactData
397
+ const internalData = $xeGanttView.internalData
398
+
399
+ const { scrollYLoad, overflowY } = reactData
400
+ const { elemStore } = internalData
401
+ const $xeTable = internalData.xeTable
402
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
403
+ const bodyTableElem = getRefElem(elemStore['main-body-table'])
404
+
405
+ let ySpaceTop = 0
406
+ let scrollYHeight = 0
407
+ let isScrollYBig = false
408
+ if ($xeTable) {
409
+ const tableReactData = $xeTable as unknown as TableReactData
410
+ ySpaceTop = tableReactData.scrollYTop
411
+ scrollYHeight = tableReactData.scrollYHeight
412
+ isScrollYBig = tableReactData.isScrollYBig
413
+ }
414
+
415
+ let ySpaceHeight = scrollYHeight
416
+ let scrollYTop = ySpaceTop
417
+
418
+ let clientHeight = 0
419
+ if (bodyScrollElem) {
420
+ clientHeight = bodyScrollElem.clientHeight
421
+ }
422
+ if (isScrollYBig) {
423
+ // 触底
424
+ if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollTop + clientHeight >= maxYHeight) {
425
+ scrollYTop = maxYHeight - bodyTableElem.clientHeight
426
+ } else {
427
+ scrollYTop = (maxYHeight - clientHeight) * (ySpaceTop / (scrollYHeight - clientHeight))
428
+ }
429
+ ySpaceHeight = maxYHeight
430
+ }
431
+ if (!(scrollYLoad && overflowY)) {
432
+ scrollYTop = 0
433
+ }
434
+
435
+ if (bodyTableElem) {
436
+ bodyTableElem.style.transform = `translate(${reactData.scrollXLeft || 0}px, ${scrollYTop}px)`
437
+ }
438
+
439
+ const layoutList = ['header', 'body', 'footer']
440
+ layoutList.forEach(layout => {
441
+ const ySpaceElem = getRefElem(elemStore[`main-${layout}-ySpace`])
442
+ if (ySpaceElem) {
443
+ ySpaceElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
444
+ }
445
+ })
446
+
447
+ const scrollYSpaceEl = $xeGanttView.$refs.refScrollYSpaceElem as HTMLDivElement
448
+ if (scrollYSpaceEl) {
449
+ scrollYSpaceEl.style.height = ySpaceHeight ? `${ySpaceHeight}px` : ''
450
+ }
451
+ reactData.scrollYTop = scrollYTop
452
+ reactData.scrollYHeight = scrollYHeight
453
+ reactData.isScrollYBig = isScrollYBig
454
+
455
+ calcScrollbar($xeGanttView)
456
+ return $xeGanttView.$nextTick().then(() => {
457
+ updateStyle($xeGanttView)
458
+ })
459
+ }
460
+
461
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
462
+ function checkLastSyncScroll ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, isRollX: boolean, isRollY: boolean) {
463
+ const reactData = $xeGanttView.reactData
464
+ const internalData = $xeGanttView.internalData
465
+
466
+ const { lcsTimeout } = internalData
467
+ reactData.lazScrollLoading = true
468
+ if (lcsTimeout) {
469
+ clearTimeout(lcsTimeout)
470
+ }
471
+ internalData.lcsTimeout = setTimeout(() => {
472
+ internalData.lcsRunTime = Date.now()
473
+ internalData.lcsTimeout = undefined
474
+ internalData.intoRunScroll = false
475
+ internalData.inVirtualScroll = false
476
+ internalData.inWheelScroll = false
477
+ internalData.inHeaderScroll = false
478
+ internalData.inBodyScroll = false
479
+ internalData.inFooterScroll = false
480
+ reactData.lazScrollLoading = false
481
+ }, 200)
482
+ }
483
+
484
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
485
+ function handleScrollEvent ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, evnt: Event, isRollY: boolean, isRollX: boolean, scrollTop: number, scrollLeft: number) {
486
+ checkLastSyncScroll($xeGanttView, isRollX, isRollY)
487
+ }
488
+
489
+ /**
490
+ * 同步表格滚动
491
+ */
492
+ function syncTableScrollTop ($xeGanttView: VxeGanttViewConstructor & VxeGanttViewPrivateMethods, scrollTop: number) {
493
+ const internalData = $xeGanttView.internalData
494
+
495
+ const $xeTable = internalData.xeTable
496
+ if ($xeTable) {
497
+ const tableInternalData = $xeTable as unknown as TableInternalData
498
+ const { elemStore: tableElemStore } = tableInternalData
499
+ const tableBodyScrollElem = getRefElem(tableElemStore['main-body-scroll'])
500
+ if (tableBodyScrollElem) {
501
+ tableBodyScrollElem.scrollTop = scrollTop
502
+ }
503
+ }
504
+ }
505
+
506
+ export default defineVxeComponent({
507
+ name: 'VxeGanttView',
508
+ inject: {
509
+ $xeGantt: {
510
+ default: null
511
+ }
512
+ },
513
+ provide () {
514
+ const $xeGanttView = this
515
+
516
+ return {
517
+ $xeGanttView
518
+ }
519
+ },
520
+ props: {},
521
+ data () {
522
+ const xID = XEUtils.uniqueId()
523
+
524
+ const reactData: GanttViewReactData = {
525
+ // 是否启用了横向 X 可视渲染方式加载
526
+ scrollXLoad: false,
527
+ // 是否启用了纵向 Y 可视渲染方式加载
528
+ scrollYLoad: false,
529
+ // 是否存在纵向滚动条
530
+ overflowY: false,
531
+ // 是否存在横向滚动条
532
+ overflowX: false,
533
+ // 纵向滚动条的宽度
534
+ scrollbarWidth: 0,
535
+ // 横向滚动条的高度
536
+ scrollbarHeight: 0,
537
+
538
+ lazScrollLoading: false,
539
+
540
+ scrollVMLoading: false,
541
+ scrollYHeight: 0,
542
+ scrollYTop: 0,
543
+ isScrollYBig: false,
544
+ scrollXLeft: 0,
545
+ scrollXWidth: 0,
546
+ isScrollXBig: false,
547
+
548
+ minViewDate: null,
549
+ maxViewDate: null,
550
+ tableData: [],
551
+ tableColumn: [],
552
+ headerGroups: [],
553
+
554
+ viewCellWidth: 40,
555
+
556
+ rowHeightStore: {
557
+ large: 52,
558
+ default: 48,
559
+ medium: 44,
560
+ small: 40,
561
+ mini: 36
562
+ }
563
+ }
564
+
565
+ const internalData = createInternalData()
566
+
567
+ return {
568
+ xID,
569
+ reactData,
570
+ internalData
571
+ }
572
+ },
573
+ computed: {
574
+ ...({} as {
575
+ $xeGantt(): (VxeGanttConstructor & VxeGanttPrivateMethods)
576
+ })
577
+ },
578
+ methods: {
579
+ //
580
+ // Method
581
+ //
582
+ refreshData (): Promise<void> {
583
+ const $xeGanttView = this
584
+
585
+ handleUpdateData($xeGanttView)
586
+ return handleLazyRecalculate($xeGanttView)
587
+ },
588
+ updateViewData (): Promise<void> {
589
+ const $xeGanttView = this
590
+ const reactData = $xeGanttView.reactData
591
+ const internalData = $xeGanttView.internalData
592
+
593
+ const $xeTable = internalData.xeTable
594
+ if ($xeTable) {
595
+ const tableReactData = $xeTable as unknown as TableReactData
596
+ const { tableData } = tableReactData
597
+ reactData.tableData = tableData
598
+ }
599
+ return $xeGanttView.$nextTick()
600
+ },
601
+ connectUpdate ({ $table }: {
602
+ $table: VxeTableConstructor & VxeTableMethods & VxeTablePrivateMethods
603
+ }) {
604
+ const $xeGanttView = this
605
+ const internalData = $xeGanttView.internalData
606
+
607
+ if ($table) {
608
+ internalData.xeTable = $table
609
+ }
610
+ return $xeGanttView.$nextTick()
611
+ },
612
+ handleUpdateStyle () {
613
+ const $xeGanttView = this
614
+
615
+ return updateStyle($xeGanttView)
616
+ },
617
+ handleLazyRecalculate () {
618
+ const $xeGanttView = this
619
+
620
+ return handleLazyRecalculate($xeGanttView)
621
+ },
622
+ triggerHeaderScrollEvent (evnt: Event) {
623
+ const $xeGanttView = this
624
+ const internalData = $xeGanttView.internalData
625
+
626
+ const { elemStore, inVirtualScroll, inBodyScroll, inFooterScroll } = internalData
627
+ if (inVirtualScroll) {
628
+ return
629
+ }
630
+ if (inBodyScroll || inFooterScroll) {
631
+ return
632
+ }
633
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
634
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
635
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
636
+ if (bodyScrollElem && wrapperEl) {
637
+ const isRollX = true
638
+ const isRollY = false
639
+ const currLeftNum = wrapperEl.scrollLeft
640
+ internalData.inHeaderScroll = true
641
+ setScrollLeft(xHandleEl, currLeftNum)
642
+ setScrollLeft(bodyScrollElem, currLeftNum)
643
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
644
+ }
645
+ },
646
+ triggerBodyScrollEvent (evnt: Event) {
647
+ const $xeGanttView = this
648
+ const internalData = $xeGanttView.internalData
649
+
650
+ const { elemStore, inVirtualScroll, inHeaderScroll, inFooterScroll } = internalData
651
+ if (inVirtualScroll) {
652
+ return
653
+ }
654
+ if (inHeaderScroll || inFooterScroll) {
655
+ return
656
+ }
657
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
658
+ const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
659
+ const xHandleEl = $xeGanttView.$refs.refScrollXHandleElem as HTMLDivElement
660
+ const yHandleEl = $xeGanttView.$refs.refScrollYHandleElem as HTMLDivElement
661
+ if (headerScrollElem && wrapperEl) {
662
+ const isRollX = true
663
+ const isRollY = true
664
+ const currLeftNum = wrapperEl.scrollLeft
665
+ const currTopNum = wrapperEl.scrollTop
666
+ internalData.inBodyScroll = true
667
+ setScrollLeft(xHandleEl, currLeftNum)
668
+ setScrollLeft(headerScrollElem, currLeftNum)
669
+ setScrollTop(yHandleEl, currTopNum)
670
+ syncTableScrollTop($xeGanttView, currTopNum)
671
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
672
+ }
673
+ },
674
+ triggerFooterScrollEvent (evnt: Event) {
675
+ const $xeGanttView = this
676
+ const internalData = $xeGanttView.internalData
677
+
678
+ const { inVirtualScroll, inHeaderScroll, inBodyScroll } = internalData
679
+ if (inVirtualScroll) {
680
+ return
681
+ }
682
+ if (inHeaderScroll || inBodyScroll) {
683
+ return
684
+ }
685
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
686
+ if (wrapperEl) {
687
+ const isRollX = true
688
+ const isRollY = false
689
+ const currLeftNum = wrapperEl.scrollLeft
690
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
691
+ }
692
+ },
693
+ triggerVirtualScrollXEvent (evnt: Event) {
694
+ const $xeGanttView = this
695
+ const internalData = $xeGanttView.internalData
696
+
697
+ const { elemStore, inHeaderScroll, inBodyScroll } = internalData
698
+ if (inHeaderScroll || inBodyScroll) {
699
+ return
700
+ }
701
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
702
+ const headerScrollElem = getRefElem(elemStore['main-header-scroll'])
703
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
704
+ if (wrapperEl) {
705
+ const isRollY = false
706
+ const isRollX = true
707
+ const currLeftNum = wrapperEl.scrollLeft
708
+ internalData.inVirtualScroll = true
709
+ setScrollLeft(headerScrollElem, currLeftNum)
710
+ setScrollLeft(bodyScrollElem, currLeftNum)
711
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
712
+ }
713
+ },
714
+ triggerVirtualScrollYEvent (evnt: Event) {
715
+ const $xeGanttView = this
716
+ const internalData = $xeGanttView.internalData
717
+
718
+ const { elemStore, inHeaderScroll, inBodyScroll } = internalData
719
+ if (inHeaderScroll || inBodyScroll) {
720
+ return
721
+ }
722
+ const wrapperEl = evnt.currentTarget as HTMLDivElement
723
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
724
+ if (wrapperEl) {
725
+ const isRollY = true
726
+ const isRollX = false
727
+ const currTopNum = wrapperEl.scrollTop
728
+ internalData.inVirtualScroll = true
729
+ setScrollTop(bodyScrollElem, currTopNum)
730
+ syncTableScrollTop($xeGanttView, currTopNum)
731
+ handleScrollEvent($xeGanttView, evnt, isRollY, isRollX, currTopNum, wrapperEl.scrollLeft)
732
+ }
733
+ },
734
+ updateScrollXSpace () {
735
+ const $xeGanttView = this
736
+
737
+ return updateScrollXSpace($xeGanttView)
738
+ },
739
+ updateScrollYSpace () {
740
+ const $xeGanttView = this
741
+
742
+ return updateScrollYSpace($xeGanttView)
743
+ },
744
+ handleGlobalResizeEvent () {
745
+ const $xeGanttView = this
746
+
747
+ handleLazyRecalculate($xeGanttView)
748
+ },
749
+
750
+ //
751
+ // Render
752
+ //
753
+ renderScrollX (h: CreateElement) {
754
+ const $xeGanttView = this
755
+
756
+ return h('div', {
757
+ key: 'vsx',
758
+ ref: 'refScrollXVirtualElem',
759
+ class: 'vxe-gantt-view--scroll-x-virtual'
760
+ }, [
761
+ h('div', {
762
+ ref: 'refScrollXLeftCornerElem',
763
+ class: 'vxe-gantt-view--scroll-x-left-corner'
764
+ }),
765
+ h('div', {
766
+ ref: 'refScrollXWrapperElem',
767
+ class: 'vxe-gantt-view--scroll-x-wrapper'
768
+ }, [
769
+ h('div', {
770
+ ref: 'refScrollXHandleElem',
771
+ class: 'vxe-gantt-view--scroll-x-handle',
772
+ on: {
773
+ scroll: $xeGanttView.triggerVirtualScrollXEvent
774
+ }
775
+ }, [
776
+ h('div', {
777
+ ref: 'refScrollXSpaceElem',
778
+ class: 'vxe-gantt-view--scroll-x-space'
779
+ })
780
+ ])
781
+ ]),
782
+ h('div', {
783
+ ref: 'refScrollXRightCornerElem',
784
+ class: 'vxe-gantt-view--scroll-x-right-corner'
785
+ })
786
+ ])
787
+ },
788
+ renderScrollY (h: CreateElement) {
789
+ const $xeGanttView = this
790
+
791
+ return h('div', {
792
+ ref: 'refScrollYVirtualElem',
793
+ class: 'vxe-gantt-view--scroll-y-virtual'
794
+ }, [
795
+ h('div', {
796
+ ref: 'refScrollYTopCornerElem',
797
+ class: 'vxe-gantt-view--scroll-y-top-corner'
798
+ }),
799
+ h('div', {
800
+ ref: 'refScrollYWrapperElem',
801
+ class: 'vxe-gantt-view--scroll-y-wrapper'
802
+ }, [
803
+ h('div', {
804
+ ref: 'refScrollYHandleElem',
805
+ class: 'vxe-gantt-view--scroll-y-handle',
806
+ on: {
807
+ scroll: $xeGanttView.triggerVirtualScrollYEvent
808
+ }
809
+ }, [
810
+ h('div', {
811
+ ref: 'refScrollYSpaceElem',
812
+ class: 'vxe-gantt-view--scroll-y-space'
813
+ })
814
+ ])
815
+ ]),
816
+ h('div', {
817
+ ref: 'refScrollYBottomCornerElem',
818
+ class: 'vxe-gantt-view--scroll-y-bottom-corner'
819
+ })
820
+ ])
821
+ },
822
+ renderViewport (h: CreateElement) {
823
+ return h('div', {
824
+ class: 'vxe-gantt-view--viewport-wrapper'
825
+ }, [
826
+ h(GanttViewHeaderComponent),
827
+ h(GanttViewBodyComponent)
828
+ ])
829
+ },
830
+ renderBody (h: CreateElement) {
831
+ const $xeGanttView = this
832
+ const $xeGantt = $xeGanttView.$xeGantt
833
+
834
+ const scrollbarYToLeft = $xeGantt.computeScrollbarYToLeft
835
+ return h('div', {
836
+ class: 'vxe-gantt-view--layout-wrapper'
837
+ }, scrollbarYToLeft
838
+ ? [
839
+ $xeGanttView.renderScrollY(h),
840
+ $xeGanttView.renderViewport(h)
841
+ ]
842
+ : [
843
+ $xeGanttView.renderViewport(h),
844
+ $xeGanttView.renderScrollY(h)
845
+ ])
846
+ },
847
+ renderVN (h: CreateElement): VNode {
848
+ const $xeGanttView = this
849
+ const $xeGantt = $xeGanttView.$xeGantt
850
+ const reactData = $xeGanttView.reactData
851
+
852
+ const { overflowX, overflowY, scrollXLoad, scrollYLoad } = reactData
853
+ const taskViewOpts = $xeGantt.computeTaskViewOpts
854
+ const scrollbarXToTop = $xeGantt.computeScrollbarXToTop
855
+ return h('div', {
856
+ ref: 'refElem',
857
+ class: ['vxe-gantt-view', `mode--${taskViewOpts.mode || 'day'}`, {
858
+ 'is--scroll-y': overflowY,
859
+ 'is--scroll-x': overflowX,
860
+ 'is--virtual-x': scrollXLoad,
861
+ 'is--virtual-y': scrollYLoad
862
+ }]
863
+ }, [
864
+ h('div', {
865
+ class: 'vxe-gantt-view--render-wrapper'
866
+ }, scrollbarXToTop
867
+ ? [
868
+ $xeGanttView.renderScrollX(h),
869
+ $xeGanttView.renderBody(h)
870
+ ]
871
+ : [
872
+ $xeGanttView.renderBody(h),
873
+ $xeGanttView.renderScrollX(h)
874
+ ]),
875
+ h('div', {
876
+ class: 'vxe-gantt-view--render-vars'
877
+ }, [
878
+ h('div', {
879
+ ref: 'refColInfoElem',
880
+ class: 'vxe-gantt-view--column-info'
881
+ })
882
+ ])
883
+ ])
884
+ }
885
+ },
886
+ watch: {
887
+ 'reactData.tableData' () {
888
+ const $xeGanttView = this
889
+
890
+ handleUpdateData($xeGanttView)
891
+ }
892
+ },
893
+ mounted () {
894
+ const $xeGanttView = this
895
+
896
+ globalEvents.on($xeGanttView, 'resize', $xeGanttView.handleGlobalResizeEvent)
897
+ },
898
+ beforeDestroy () {
899
+ const $xeGanttView = this
900
+ const internalData = $xeGanttView.internalData
901
+
902
+ globalEvents.off($xeGanttView, 'keydown')
903
+ XEUtils.assign(internalData, createInternalData())
904
+ },
905
+ render (this: any, h) {
906
+ return this.renderVN(h)
907
+ }
908
+ })