vxe-gantt 0.0.1 → 0.0.3

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