bri-components 1.4.92 → 1.4.93

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 (156) hide show
  1. package/README.md +83 -83
  2. package/lib/styles/bundle.css +12 -12
  3. package/lib/styles/font/fontello.svg +31 -31
  4. package/package.json +125 -125
  5. package/src/components/Error/Error403.vue +42 -42
  6. package/src/components/Error/Error404.vue +40 -40
  7. package/src/components/Error/Error500.vue +51 -51
  8. package/src/components/Error/error.less +162 -162
  9. package/src/components/Error/errorBack.vue +40 -40
  10. package/src/components/controls/DshControlInput.vue +195 -195
  11. package/src/components/controls/base/BriUpload/BriUpload.vue +434 -434
  12. package/src/components/controls/base/BriUpload/BriUploadImage.vue +373 -373
  13. package/src/components/controls/base/BriUpload/uploadList.vue +724 -724
  14. package/src/components/controls/base/BriUpload/uploadMixin.js +446 -440
  15. package/src/components/controls/base/DshCascader/DshCascader.vue +210 -210
  16. package/src/components/controls/base/DshCascader/components/cascaderModal.vue +366 -366
  17. package/src/components/controls/base/DshCascader/components/cascaderPicker.vue +416 -416
  18. package/src/components/controls/base/DshCascader/components/cascaderSimple.vue +143 -143
  19. package/src/components/controls/base/DshCoordinates.vue +577 -577
  20. package/src/components/controls/base/DshDate/DshDate.vue +191 -191
  21. package/src/components/controls/base/DshDate/DshDaterange.vue +186 -186
  22. package/src/components/controls/base/DshDivider.vue +201 -201
  23. package/src/components/controls/base/DshEditor.vue +274 -274
  24. package/src/components/controls/base/DshInput/BriInputs.vue +166 -166
  25. package/src/components/controls/base/DshInput/DshInput.vue +255 -255
  26. package/src/components/controls/base/DshNumber/BriInputNumber/BriInputNumber.vue +435 -435
  27. package/src/components/controls/base/DshNumber/BriInputNumber/mixins/emitter.js +34 -34
  28. package/src/components/controls/base/DshNumber/BriInputNumber/mixins/form.js +14 -14
  29. package/src/components/controls/base/DshNumber/BriInputNumber/utils/assist.js +322 -322
  30. package/src/components/controls/base/DshNumber/DshNumber.vue +143 -143
  31. package/src/components/controls/base/DshNumber/DshNumberange.vue +109 -109
  32. package/src/components/controls/base/DshSelect/DshCheckbox.vue +168 -168
  33. package/src/components/controls/base/DshSelect/DshSelect.vue +180 -180
  34. package/src/components/controls/base/DshSwitch/DshSwitch.vue +115 -115
  35. package/src/components/controls/control.less +324 -324
  36. package/src/components/controls/controlMap.js +114 -114
  37. package/src/components/controls/extra/DshColor.vue +81 -81
  38. package/src/components/controls/extra/themeColor.vue +104 -104
  39. package/src/components/controls/extra/themeIcon.vue +114 -114
  40. package/src/components/controls/mixins/cascaderMixin.js +295 -295
  41. package/src/components/controls/mixins/cascaderPickerMixin.js +216 -216
  42. package/src/components/controls/mixins/cascaderTableMixin.js +130 -130
  43. package/src/components/controls/mixins/controlMixin.js +368 -368
  44. package/src/components/controls/mixins/dateMixin.js +149 -149
  45. package/src/components/controls/mixins/flatTableMixin.js +111 -111
  46. package/src/components/controls/mixins/numberMixin.js +112 -112
  47. package/src/components/controls/mixins/selectMixin.js +233 -233
  48. package/src/components/controls/mixins/switchMixin.js +87 -87
  49. package/src/components/controls/mixins/userAndDepartMixin.js +218 -218
  50. package/src/components/controls/senior/DshLabels.vue +331 -331
  51. package/src/components/controls/senior/DshPackage.vue +57 -57
  52. package/src/components/controls/senior/cascaderTable.vue +210 -210
  53. package/src/components/controls/senior/flatTable.vue +135 -135
  54. package/src/components/controls/senior/selectDepartments.vue +438 -438
  55. package/src/components/controls/senior/selectUsers/departMenu.vue +293 -293
  56. package/src/components/controls/senior/selectUsers/selectUsers.vue +752 -752
  57. package/src/components/controls/special/DshBack.vue +42 -42
  58. package/src/components/controls/special/DshUndeveloped.vue +41 -41
  59. package/src/components/form/DshAdvSearch.vue +510 -510
  60. package/src/components/form/DshDefaultSearch.vue +258 -258
  61. package/src/components/form/DshForm.vue +494 -494
  62. package/src/components/form/searchMixin.js +375 -375
  63. package/src/components/list/BriCard.vue +95 -95
  64. package/src/components/list/BriTable.vue +205 -205
  65. package/src/components/list/BriTree.vue +529 -529
  66. package/src/components/list/BriTreeItem.vue +163 -163
  67. package/src/components/list/DshBox/DshBox.vue +219 -219
  68. package/src/components/list/DshBox/DshCard.vue +446 -446
  69. package/src/components/list/DshBox/DshCrossTable.vue +827 -827
  70. package/src/components/list/DshBox/DshList.vue +404 -404
  71. package/src/components/list/DshBox/DshPanel.vue +669 -669
  72. package/src/components/list/DshBox/DshSingleData.vue +119 -119
  73. package/src/components/list/DshBox/DshTable.vue +239 -239
  74. package/src/components/list/DshCascaderTable.vue +115 -115
  75. package/src/components/list/DshFlatTable.vue +339 -339
  76. package/src/components/list/DshPage.vue +194 -194
  77. package/src/components/list/DshTreeTable.vue +113 -113
  78. package/src/components/list/common/importModal.vue +243 -243
  79. package/src/components/list/common/quoteListModal.vue +206 -206
  80. package/src/components/list/mixins/DshCascaderTableMixin.js +278 -278
  81. package/src/components/list/mixins/DshFlatTableMixin.js +493 -493
  82. package/src/components/list/mixins/DshTreeTableMixin.js +286 -286
  83. package/src/components/list/mixins/tableBaseMixin.js +1661 -1662
  84. package/src/components/list/mixins/treeTableBaseMixin.js +149 -149
  85. package/src/components/other/BriAvatar.vue +166 -166
  86. package/src/components/other/BriCode.vue +125 -125
  87. package/src/components/other/BriCollapseTree.vue +207 -207
  88. package/src/components/other/BriGantt.vue +1084 -1084
  89. package/src/components/other/BriIframe.vue +116 -116
  90. package/src/components/other/BriLoading.vue +171 -171
  91. package/src/components/other/BriSvg.vue +28 -28
  92. package/src/components/other/DshColorPanel.vue +128 -128
  93. package/src/components/other/DshMenuNav.vue +188 -188
  94. package/src/components/small/BriButton.vue +71 -71
  95. package/src/components/small/BriDrawer.vue +169 -169
  96. package/src/components/small/BriTooltip.vue +87 -87
  97. package/src/components/small/DshBtnModal.vue +68 -68
  98. package/src/components/small/DshButtons.vue +324 -324
  99. package/src/components/small/DshDropdown.vue +225 -225
  100. package/src/components/small/DshIcons.vue +59 -59
  101. package/src/components/small/DshListRender.js +21 -21
  102. package/src/components/small/DshModal.vue +160 -160
  103. package/src/components/small/DshSteps.vue +141 -141
  104. package/src/components/small/DshTabs.vue +598 -598
  105. package/src/components/small/DshTabsSet.vue +309 -309
  106. package/src/components/small/DshTags.vue +251 -251
  107. package/src/components/small/DshTitle.vue +50 -50
  108. package/src/components/small/render.js +20 -20
  109. package/src/components/unit/DshFormUnit.vue +398 -398
  110. package/src/components/unit/DshListUnit.vue +115 -115
  111. package/src/components/unit/unitMixin.js +86 -86
  112. package/src/data/index.js +9 -9
  113. package/src/index.js +271 -271
  114. package/src/styles/bundle.css +12 -12
  115. package/src/styles/components/BriButton.less +292 -292
  116. package/src/styles/components/BriTable.less +344 -344
  117. package/src/styles/components/DshModal.less +250 -250
  118. package/src/styles/components/index.less +3 -3
  119. package/src/styles/global/animate.less +11 -11
  120. package/src/styles/global/base.less +45 -45
  121. package/src/styles/global/box.less +186 -186
  122. package/src/styles/global/control.less +122 -122
  123. package/src/styles/global/flex.less +282 -282
  124. package/src/styles/global/global.less +8 -8
  125. package/src/styles/global/text.less +59 -59
  126. package/src/styles/global/variables.less +85 -85
  127. package/src/styles/iconfont/iconfont.css +254 -254
  128. package/src/styles/iconfont/iconfont.json +422 -422
  129. package/src/styles/iconfont/iconfont.svg +137 -137
  130. package/src/styles/index.less +11 -11
  131. package/src/styles/reset-easytable.less +21 -21
  132. package/src/styles/reset-iview-controls.less +145 -145
  133. package/src/styles/reset-iview-other.less +49 -49
  134. package/src/styles/reset-iview-variables.less +34 -34
  135. package/src/styles/reset.less +45 -45
  136. package/src/utils/index.js +5 -5
  137. package/src/utils/table.js +175 -175
  138. package/lib/0.bri-components.min.js +0 -1
  139. package/lib/1.bri-components.min.js +0 -1
  140. package/lib/10.bri-components.min.js +0 -1
  141. package/lib/11.bri-components.min.js +0 -1
  142. package/lib/2.bri-components.min.js +0 -1
  143. package/lib/3.bri-components.min.js +0 -1
  144. package/lib/4.bri-components.min.js +0 -1
  145. package/lib/5.bri-components.min.js +0 -1
  146. package/lib/6.bri-components.min.js +0 -1
  147. package/lib/7.bri-components.min.js +0 -1
  148. package/lib/8.bri-components.min.js +0 -1
  149. package/lib/9.bri-components.min.js +0 -1
  150. package/lib/bri-components.min.js +0 -18
  151. package/src/.DS_Store +0 -0
  152. package/src/components/.DS_Store +0 -0
  153. package/src/components/controls/.DS_Store +0 -0
  154. package/src/components/controls/senior/.DS_Store +0 -0
  155. package/src/styles/.DS_Store +0 -0
  156. package/src/styles/components/.DS_Store +0 -0
@@ -1,1084 +1,1084 @@
1
- <template>
2
- <div class="briGantt">
3
- <div class="briGantt-top">
4
- <div class="bri-scrollbar0">
5
- <slot></slot>
6
- </div>
7
- <!-- 时间渲染 -->
8
- <div
9
- class="briGantt-timer"
10
- :style="{width: clientWidth + 'px'}"
11
- >
12
- <a
13
- class="briGantt-timer-icon briGantt-timer-icon-left"
14
- @click="preTime"
15
- >
16
- <Icon type="ios-arrow-back" />
17
- </a>
18
- <div class="briGantt-timer-bg"></div>
19
- <div
20
- class="bri-scrollbar0 briGantt-timer-main"
21
- ref="briGanttTimer"
22
- v-on:scroll="handleScroll($event, [{ ref: 'briGanttArea', direction: 'scrollLeft' }])"
23
- >
24
- <table
25
- :style="{tableLayout:'fixed', width: tableWidth}"
26
- class="briGantt-tableBox"
27
- >
28
- <thead class="briGantt-table-thead">
29
- <tr>
30
- <th
31
- class="briGantt-table-th"
32
- v-for="timeItem in simpleData"
33
- :key="timeItem.key"
34
- :colspan="timeItem.colspan"
35
- :style="{...timeItem.style}"
36
- >
37
- <Tooltip
38
- :content="timeItem.fullName"
39
- placement="top"
40
- :transfer="true"
41
- :transfer-class-name="`briGantt-transfer-tooltip-${themeName}`"
42
- >
43
- {{ timeItem.name }}
44
- </Tooltip>
45
- <div
46
- v-if="timeItem.now"
47
- class="briGantt-line-now"
48
- ></div>
49
- </th>
50
- </tr>
51
- </thead>
52
- </table>
53
- </div>
54
- <a
55
- class="briGantt-timer-icon briGantt-timer-icon-right"
56
- @click="nextTime"
57
- >
58
- <Icon type="ios-arrow-forward" />
59
- </a>
60
- </div>
61
- </div>
62
- <div class="briGantt-bottom">
63
- <div
64
- class="briGantt-bottom-title"
65
- v-if="title"
66
- >{{ title }}</div>
67
- <div class="briGantt-bottom-content">
68
- <!-- 数据映射 -->
69
- <div
70
- v-if="table"
71
- class="bri-scrollbar0 briGantt-tabledata"
72
- ref="briGanttColumn"
73
- v-on:scroll="handleScroll($event, [{ ref: 'briGanttArea', direction: 'scrollTop' }])"
74
- >
75
- <table class="briGantt-tableBox briGantt-table">
76
- <tbody>
77
- <tr
78
- class="briGantt-table-tr"
79
- v-for="(row, rowIndex) in table"
80
- :key="rowIndex"
81
- >
82
- <td
83
- class="briGantt-table-td"
84
- v-for="(col, colIndex) in row"
85
- :key="colIndex"
86
- :colspan="col.colspan"
87
- :rowspan="col.rowspan"
88
- :style="col.rowspan > 1 ? {background: '#fff',padding: '0 10px',fontWeight:500} : {padding: '0 10px'}"
89
- v-html="col.label"
90
- ></td>
91
- </tr>
92
- </tbody>
93
- </table>
94
- </div>
95
- <!-- 区域映射 -->
96
- <div
97
- class="briGantt-data bri-scrollbar"
98
- :class="`briGantt-data-${type}`"
99
- ref="briGanttArea"
100
- v-on:scroll="handleScroll($event, [{ ref: 'briGanttTimer', direction: 'scrollLeft' }, { ref:'briGanttColumn', direction:'scrollTop' }, { ref:'briGanttScrollbar', direction:'scrollLeft' }])"
101
- >
102
- <table
103
- :style="{tableLayout:'fixed', width: tableWidth}"
104
- class="briGantt-tableBox briGantt-table"
105
- border="0"
106
- cellspacing="0"
107
- cellpadding="0"
108
- >
109
- <tr v-if="computedData.length === 0">
110
- <td
111
- :colspan="timeData.length"
112
- class="briGantt-table-td"
113
- >暂无内容</td>
114
- </tr>
115
- <tbody v-if="type==='table'">
116
- <tr v-if="computedData.length === 0">
117
- <td
118
- :colspan="timeData.length"
119
- class="briGantt-table-td"
120
- >暂无内容</td>
121
- </tr>
122
- <tr
123
- class="briGantt-table-tr"
124
- v-for="(taskItem, taskIndex) in computedData"
125
- :key="taskIndex"
126
- style="border-left: none"
127
- >
128
- <td
129
- class="briGantt-table-td"
130
- v-for="(timeItem, timeIndex) in taskItem"
131
- :key="timeIndex"
132
- :colspan="timeItem.colspan"
133
- >
134
- <slot
135
- v-if="timeItem.isApply"
136
- name="table"
137
- v-bind:task="timeItem.task"
138
- v-bind:time="timeItem"
139
- >
140
- <div
141
- class="briGantt-table-td-main"
142
- :style="timeItem.style"
143
- ></div>
144
- </slot>
145
- <slot
146
- v-else
147
- name="tabletd"
148
- v-bind:preTime="taskItem[timeIndex-1]"
149
- v-bind:nextTime="taskItem[timeIndex+1]"
150
- v-bind:task="timeItem.task"
151
- v-bind:time="timeItem"
152
- ></slot>
153
- </td>
154
- </tr>
155
- </tbody>
156
- <tbody v-else-if="type==='chart'">
157
- <tr
158
- class="briGantt-chart-tr"
159
- v-for="(taskItem, taskIndex) in computedData"
160
- :key="taskIndex"
161
- >
162
- <td
163
- class="briGantt-chart-td"
164
- v-for="(timeItem, timeIndex) in taskItem"
165
- :key="timeIndex"
166
- :colspan="timeItem.colspan"
167
- >
168
- <div
169
- v-if="timeItem.isApply"
170
- class="briGantt-chart-td-main"
171
- >
172
- <slot
173
- name="chart"
174
- v-bind:task="timeItem.task"
175
- v-bind:chartItem="timeItem"
176
- >
177
- <Tooltip
178
- placement="right"
179
- transfer
180
- :transfer-class-name="`briGantt-transfer-tooltip-${themeName}`"
181
- style="width:100%"
182
- >
183
- <div
184
- class="briGantt-chart-td-main-center"
185
- :style="{
186
- background:$getColor(timeItem.style.background),
187
- minWidth: minTdWidth,
188
- border: `1px solid ${timeItem.style.background}`,
189
- padding: timeItem.task.progressField == 100 ? '' : '1px',
190
- cursor: canClick ? 'pointer' : ''
191
- }"
192
- @click="clickRow(timeItem)"
193
- >
194
- <slot
195
- name="chartCenter"
196
- v-bind:task="timeItem.task"
197
- v-bind:chartItem="timeItem"
198
- >
199
- <div
200
- class="ms-ellipsis"
201
- :style="{
202
- background:timeItem.style.background,
203
- width: `${timeItem.task.progressField}%`
204
- }"
205
- >
206
- {{ timeItem.task.label }}
207
- </div>
208
- </slot>
209
- </div>
210
- <div
211
- slot="content"
212
- class="briGantt-chart-td-main-center-tooltip"
213
- >
214
- <span
215
- class="briGantt-chart-td-main-center-tooltip-select"
216
- :style="{...timeItem.style}"
217
- >
218
- </span>
219
- {{timeItem.task.select}}
220
- <div>完成度:{{timeItem.task.progressField}}%</div>
221
- <div>{{ timeItem.task.label }}</div>
222
- </div>
223
- </Tooltip>
224
- </slot>
225
- </div>
226
- <slot
227
- v-else
228
- name="charttd"
229
- v-bind:task="timeItem.task"
230
- v-bind:time="timeItem"
231
- v-bind:preTime="taskItem[timeIndex-1]"
232
- v-bind:nextTime="taskItem[timeIndex+1]"
233
- >
234
- <div class="briGantt-chart-td-greyLine"></div>
235
- </slot>
236
- </td>
237
- </tr>
238
- </tbody>
239
- </table>
240
- </div>
241
- </div>
242
-
243
- <!-- 底部滚动条 -->
244
- <!-- <div class="briGantt-scroll">
245
- <div class="briGantt-scroll-main"
246
- ref="briGanttScrollbar"
247
- :style="{ width: clientWidth + 'px' }"
248
- v-on:scroll="handleScroll($event, [{ ref: 'briGanttTimer', direction: 'scrollLeft' }, { ref:'briGanttArea', direction:'scrollLeft' }, { ref:'briGanttBlue', direction:'scrollLeft' }])">
249
- <div :style="{width: tableWidth}"></div>
250
- </div>
251
- </div> -->
252
- </div>
253
- </div>
254
- </template>
255
- <script>
256
- function getDate (hours) {
257
- const currentDate = new Date();
258
- const currentYear = currentDate.getFullYear();
259
- const currentMonth = currentDate.getMonth();
260
- const currentDay = currentDate.getDate();
261
- const timeStamp = new Date(
262
- currentYear,
263
- currentMonth,
264
- currentDay,
265
- 0,
266
- 0,
267
- 0
268
- ).getTime();
269
- return new Date(timeStamp + hours * 60 * 60 * 1000).getTime();
270
- }
271
- function getMonth (N) {
272
- const currentDate = new Date();
273
- const currentYear = currentDate.getFullYear();
274
- const currentMonth = currentDate.getMonth();
275
- return new Date(currentYear, currentMonth + N, 1).getTime();
276
- }
277
- // 示例数据
278
- let tasks = [
279
- {
280
- id: 1,
281
- label: "Make some noise",
282
- user:
283
- '<a href="https://www.google.com/search?q=John+Doe" target="_blank" style="color:#0077c0;">John Doe</a>',
284
- start: getDate(-24 * 5),
285
- end: getDate(0),
286
- select: "紧急",
287
- duration: 15 * 24 * 60 * 60 * 1000,
288
- percent: 85,
289
- type: "project",
290
- style: {
291
- background: "orange",
292
- main: "rgba(109,174,242,1)"
293
- }
294
- // collapsed: true,
295
- },
296
- {
297
- id: 2,
298
- label: "With great power comes great responsibility",
299
- user:
300
- '<a href="https://www.google.com/search?q=Peter+Parker" target="_blank" style="color:#0077c0;">Peter Parker</a>',
301
- parentId: 1,
302
- start: getDate(-24 * 20),
303
- duration: 20 * 24 * 60 * 60 * 1000,
304
- percent: 50,
305
- select: "重要",
306
- type: "milestone",
307
- collapsed: true,
308
- style: {
309
- background: "red",
310
- main: "rgba(240,143,145,1)"
311
- }
312
- },
313
- {
314
- id: 3,
315
- label: "Courage is being scared to death, but saddling up anyway.",
316
- user:
317
- '<a href="https://www.google.com/search?q=John+Wayne" target="_blank" style="color:#0077c0;">John Wayne</a>',
318
- parentId: 2,
319
- select: "普通",
320
- start: getDate(-24 * 3),
321
- duration: 2 * 24 * 60 * 60 * 1000,
322
- percent: 100,
323
- type: "task",
324
- style: {
325
- background: "rgba(255,248,242,1)",
326
- main: "rgba(255,190,114,1)"
327
- }
328
- },
329
- {
330
- id: 4,
331
- label: "Put that toy AWAY!",
332
- user:
333
- '<a href="https://www.google.com/search?q=Clark+Kent" target="_blank" style="color:#0077c0;">Clark Kent</a>',
334
- start: getDate(-24 * 2),
335
- duration: 2 * 24 * 60 * 60 * 1000,
336
- select: "紧急",
337
- percent: 50,
338
- type: "task",
339
- dependentOn: [3],
340
- style: {
341
- background: "rgba(235,248,240,1)",
342
- main: "rgba(137,213,166,1)"
343
- }
344
- },
345
- {
346
- id: 5,
347
- label: "Put that toy AWAY!",
348
- select: "紧急",
349
- user:
350
- '<a href="https://www.google.com/search?q=Clark+Kent" target="_blank" style="color:#0077c0;">Clark Kent</a>',
351
- start: getDate(1 * 24),
352
- end: getDate(1 * 24),
353
- // duration: 1 * 24 * 60 * 60 * 1000,
354
- percent: 50,
355
- type: "task",
356
- dependentOn: [3],
357
- style: {
358
- background: "rgba(235,248,240,1)",
359
- main: "rgba(137,213,166,1)"
360
- }
361
- }
362
- ];
363
-
364
- export default {
365
- name: "briGantt",
366
- components: {},
367
- props: {
368
- simpleDataColor: String,
369
-
370
- tasks: Array,
371
- options: {
372
- type: Object,
373
- default () {
374
- return {};
375
- }
376
- },
377
- value: {
378
- type: Object,
379
- default () {
380
- return {};
381
- }
382
- },
383
- propsObj: {
384
- type: Object,
385
- default () {
386
- return {};
387
- }
388
- },
389
- // 是否展示示例数据
390
- showEs: {
391
- type: Boolean,
392
- default: false
393
- },
394
- title: String,
395
- // 展示类型, 分图标和表格,默认表格
396
- type: {
397
- type: String,
398
- default: "table"
399
- },
400
- dimension: {
401
- type: String,
402
- default: "quarter"
403
- },
404
- showCloumns: {
405
- type: Boolean,
406
- default: true
407
- },
408
- table: Array,
409
- // 距离今天个数
410
- count: {
411
- type: Number,
412
- default: 5
413
- },
414
- // 展示日期间隔
415
- step: {
416
- type: Number,
417
- default: 1
418
- },
419
- canClick: {
420
- type: Boolean,
421
- default: false
422
- }
423
- },
424
- computed: {
425
- // 默认列表
426
- defaultTasks () {
427
- if (this.showEs) {
428
- return tasks;
429
- } else {
430
- return this.tasks || [];
431
- }
432
- },
433
- // 表格宽度
434
- tableWidth () {
435
- let timeDataWidth = this.simpleData.length * 50;
436
- let clientWidth = this.clientWidth;
437
- if (this.computedCountStep.stepKind === "month") {
438
- timeDataWidth = this.timeData.length * 3;
439
- }
440
- if (timeDataWidth < clientWidth) {
441
- return "100%";
442
- } else {
443
- return timeDataWidth + "px";
444
- }
445
- },
446
- minTdWidth () {
447
- let minWidth = 2;
448
- if (this.tableWidth.includes("px")) {
449
- minWidth = parseInt(this.tableWidth) / this.timeData.length;
450
- } else {
451
- minWidth = parseInt(this.clientWidth) / this.timeData.length;
452
- }
453
- minWidth > 20 && (minWidth = 2);
454
- return minWidth + "px";
455
- },
456
- // 间隔及时间,当前选择时间维度
457
- computedCountStep () {
458
- this.refreshStepCount();
459
- return this.dimensionObject[this.dimension] || { count: this.count, step: this.step };
460
- },
461
- // 任务数据
462
- taskData () {
463
- /**
464
- * task 默认数据
465
- */
466
- let tasks = this.defaultTasks;
467
- for (let task of tasks) {
468
- if (typeof task.x === "undefined") {
469
- task.x = 0;
470
- }
471
- if (typeof task.y === "undefined") {
472
- task.y = 0;
473
- }
474
- if (typeof task.width === "undefined") {
475
- task.width = 0;
476
- }
477
- if (typeof task.height === "undefined") {
478
- task.height = 0;
479
- }
480
- if (typeof task.mouseOver === "undefined") {
481
- task.mouseOver = false;
482
- }
483
- if (typeof task.collapsed === "undefined") {
484
- task.collapsed = false;
485
- }
486
- if (typeof task.dependentOn === "undefined") {
487
- task.dependentOn = [];
488
- }
489
- if (typeof task.parentId === "undefined") {
490
- task.parentId = null;
491
- }
492
- if (typeof task.style === "undefined") {
493
- task.style = {};
494
- }
495
- if (typeof task.children === "undefined") {
496
- task.children = [];
497
- }
498
- if (typeof task.allChildren === "undefined") {
499
- task.allChildren = [];
500
- }
501
- if (typeof task.parents === "undefined") {
502
- task.parents = [];
503
- }
504
- if (typeof task.parent === "undefined") {
505
- task.parent = null;
506
- }
507
- if (typeof task.startTime === "undefined") {
508
- task.startTime = new Date(task.start).valueOf();
509
- }
510
- if (typeof task.endTime === "undefined" && task.hasOwnProperty("end")) {
511
- task.endTime = new Date(task.end).valueOf();
512
- } else if (typeof task.endTime === "undefined" && task.hasOwnProperty("duration")) {
513
- task.endTime = task.startTime + task.duration - (1 * 24 * 60 * 60 * 1000);
514
- }
515
- if (typeof task.duration === "undefined" && task.hasOwnProperty("endTime")) {
516
- task.duration = task.endTime - task.startTime;
517
- }
518
- }
519
- return tasks;
520
- },
521
- // 时间数据
522
- simpleData () {
523
- // 小于今天
524
- let { count, step, stepKind } = this.computedCountStep;
525
- let data = [
526
- { key: getDate(0),
527
- endKey: getDate((step - 1) * 24 + 23.9999),
528
- name: "今天",
529
- colspan: 1,
530
- fullName: this.$dateFormat(getDate(0), "yyyy-MM-dd"),
531
- style: { color: this.simpleDataColor, fontWeight: 500 },
532
- now: true
533
- }
534
- ];
535
- let preCount = this.preCount * count + count;
536
- let nextCount = this.nextCount * count + count;
537
- for (let i = -step; i >= -(preCount * step); i -= step) {
538
- let key = stepKind === "month" ? getMonth(i) : getDate(i * 24);
539
- data.unshift({
540
- colspan: 1,
541
- key: key,
542
- endKey: getDate((i + step - 1) * 24 + 23.9999),
543
- name: this.getDayName(key, stepKind),
544
- fullName: this.$dateFormat(key, "yyyy-MM-dd"),
545
- style: this.$dateFormat(key, "d") == "1" && { fontWeight: 500 }
546
- });
547
- }
548
- // 大于今天
549
- for (let i = step; i <= nextCount * step; i += step) {
550
- let key = stepKind === "month" ? getMonth(i) : getDate(i * 24);
551
- data.push({
552
- colspan: 1,
553
- key: key,
554
- endKey: getDate((i + step - 1) * 24 + 23.9999),
555
- name: this.getDayName(key, stepKind),
556
- fullName: this.$dateFormat(key, "yyyy-MM-dd"),
557
- style: this.$dateFormat(key, "d") == "1" && { fontWeight: 500 }
558
- });
559
- }
560
- return data;
561
- },
562
- timeData () {
563
- let { count, step, stepKind } = this.computedCountStep;
564
- let data = [];
565
- let preCount = this.preCount * count + count;
566
- let nextCount = this.nextCount * count + count;
567
- let startTime = -(preCount * step); // 个数
568
- let endTime = nextCount * step;
569
- // 年度以月为分隔符
570
- if (stepKind === "month") {
571
- startTime = (getMonth(-preCount) - getMonth(0)) / 24 / 60 / 60 / 1000;
572
- endTime = (getMonth(nextCount) - getMonth(0)) / 24 / 60 / 60 / 1000;
573
- }
574
- for (let i = startTime; i <= endTime; i++) {
575
- let key = getDate(i * 24);
576
- data.push({
577
- now: this.$dateFormat(key, "yyyy-MM-dd") === this.$dateFormat(new Date(), "yyyy-MM-dd"),
578
- key: key,
579
- endKey: getDate(i * 24 + 23.9999),
580
- name: this.getDayName(key, stepKind),
581
- fullName: this.$dateFormat(key, "yyyy-MM-dd")
582
- });
583
- }
584
- return data;
585
- },
586
- // 任务时间结合数据
587
- computedData () {
588
- return this.taskData.map(taskItem => {
589
- let tr = [];
590
- this.timeData.forEach(timeItem => {
591
- let flag = this.filterTaskDate(taskItem, timeItem);
592
- if (flag) {
593
- let isEndStep = new Date(timeItem.endKey) > new Date(taskItem.endTime);
594
- if (tr[tr.length - 1] && tr[tr.length - 1].isApply) {
595
- tr[tr.length - 1].colspan++;
596
- // 判断是不是结束日期,当前节点日期startEnd endTime, endKey
597
- if (isEndStep) {
598
- tr[tr.length - 1].isEndStep = isEndStep;
599
- }
600
- } else {
601
- let defaultStyle = {
602
- background: "rgba(232,243,253,1)",
603
- border: "1px solid rgba(109,174,242,1)",
604
- main: "rgba(109,174,242,1)"
605
- };
606
- let obj = {
607
- colspan: 1,
608
- ...timeItem,
609
- style: taskItem.style || defaultStyle,
610
- task: taskItem,
611
- isApply: true
612
- };
613
- if (isEndStep) {
614
- obj.isEndStep = isEndStep;
615
- }
616
- tr.push(obj);
617
- }
618
-
619
- } else {
620
- let obj = {
621
- colspan: 1,
622
- ...timeItem,
623
- task: taskItem,
624
- isApply: false
625
- };
626
- tr.push(obj);
627
- }
628
- });
629
- return tr;
630
- });
631
- },
632
-
633
- theme () {
634
- return this.propsObj.theme || {};
635
- },
636
- themeName () {
637
- return this.theme.name;
638
- }
639
- },
640
- data () {
641
- return {
642
- // 当前客户端宽度
643
- clientWidth: 0,
644
- // 向下点了几次
645
- nextCount: 0,
646
- // 向上点了几次
647
- preCount: 0,
648
- // 时间维度
649
- dimensionObject: {
650
- doubleWeek: { name: "按周", count: 3, step: 1, stepKind: "day" },
651
- week: { name: "双周", count: 7, step: 1, stepKind: "day" },
652
- month: { name: "按月", count: 7, step: 2, stepKind: "day" },
653
- quarter: { name: "季度", count: 9, step: 5, stepKind: "day" },
654
- year: { name: "按年", count: 6, step: 1, stepKind: "month" }
655
- },
656
- nowOffsetLeft: 0
657
- };
658
- },
659
- created () {
660
- this.init();
661
- },
662
- mounted () {
663
- // 宽度调整
664
- window.onresize = this.refreshWidth;
665
- },
666
- destroyed () {
667
- window.onresize = null;
668
- },
669
- methods: {
670
- init () {
671
- // 赋初值
672
- setTimeout(() => {
673
- this.refreshWidth();
674
- });
675
- },
676
- // 比较时间
677
- filterTaskDate (taskItem, timeItem) {
678
- let flag = (new Date(taskItem.startTime) <= new Date(timeItem.endKey)) && (taskItem.endTime ? ((new Date(timeItem.key) <= new Date(taskItem.endTime))) : taskItem.endInfinite);
679
- return flag;
680
- },
681
- // 获得日期显示格式
682
- getDayName (key, stepKind) {
683
- let name = this.$dateFormat(key, "M月d日");
684
- if (name === "1日") {
685
- name = this.$dateFormat(key, "M月d日");
686
- }
687
- if (stepKind === "month") {
688
- name = this.$dateFormat(key, "M月");
689
- if (name === "1月") {
690
- name = `${this.$dateFormat(key, "yyyy年M月")}`;
691
- }
692
- }
693
- return name;
694
- },
695
- // 左右按钮重置
696
- refreshStepCount () {
697
- this.preCount = 0;
698
- this.nextCount = 0;
699
- },
700
- // 重新计算宽度
701
- refreshWidth () {
702
- this.clientWidth = this.$refs.briGanttArea ? this.$refs.briGanttArea.clientWidth : 0;
703
- },
704
- // 重新渲染
705
- refresh () {
706
-
707
- },
708
- // 绑定同步滚动
709
- handleScroll (el, scrollList) {
710
- scrollList.forEach(({ref, direction} = item) => {
711
- this.$refs[ref] && (this.$refs[ref][direction] = el.target[direction]);
712
- });
713
- },
714
- // 点击上一节点
715
- preTime () {
716
- let briGanttTimer = this.$refs.briGanttTimer;
717
- let timerWidth = briGanttTimer.clientWidth; // 盒子宽度
718
- let scrollLeft = briGanttTimer.scrollLeft; // 滚动距离
719
- if (scrollLeft === 0) {
720
- // 已经滑到尽头,加载时间数据
721
- this.preCount++;
722
- this.$nextTick(() => {
723
- this.slideTo(briGanttTimer, scrollLeft - timerWidth);
724
- });
725
- } else {
726
- this.slideTo(briGanttTimer, scrollLeft - timerWidth);
727
- }
728
- },
729
- // 点击下一节点
730
- nextTime () {
731
- let briGanttTimer = this.$refs.briGanttTimer;
732
- let timerWidth = briGanttTimer.clientWidth; // 盒子宽度
733
- let tableWidth = parseInt(this.tableWidth); // table 总宽度
734
- let scrollLeft = briGanttTimer.scrollLeft; // 滚动距离
735
- let distance = tableWidth - timerWidth; // 当前滚动条距离顶部的距离
736
- if (scrollLeft < distance) {
737
- // 未滑到尽头
738
- this.slideTo(briGanttTimer, scrollLeft + timerWidth);
739
- } else {
740
- // 已经滑到尽头,加载时间数据
741
- this.nextCount++;
742
- this.$nextTick(() => {
743
- this.slideTo(briGanttTimer, scrollLeft + timerWidth);
744
- });
745
- }
746
- },
747
- // 滚动到指定位置 增加滚动效果
748
- slideTo (ref, target) {
749
- let currScrollLeft = ref.scrollLeft; // 当前的距离
750
- let distance = target - currScrollLeft;
751
- let speed = distance / 10; // 每时刻速度
752
- let speedTarget = currScrollLeft + speed;
753
- let timer = setInterval(function () {
754
- if (distance > 0 ? (speedTarget > target) : (speedTarget < target)) {
755
- clearInterval(timer);
756
- } else {
757
- ref.scrollTo(speedTarget, 0);
758
- speedTarget += speed;
759
- }
760
- }, 10);
761
- },
762
- // 行点击
763
- clickRow (col) {
764
- this.canClick && this.$emit("clickRow", col.task, col);
765
- }
766
- }
767
- };
768
- </script>
769
-
770
- <style lang="less">
771
- .briGantt {
772
- width: 100%;
773
- height: 100%;
774
- color: #656565;
775
- font-size: @smallSize;
776
- line-height: 28px;
777
- position: relative;
778
- display: flex;
779
- overflow: auto;
780
- flex-direction: column;
781
-
782
- &-top {
783
- display: flex;
784
- height: 100%;
785
- width: 100%;
786
- justify-content: space-between;
787
- position: absolute;
788
- }
789
-
790
- &-bottom {
791
- width: 100%;
792
- overflow: auto;
793
- display: flex;
794
- flex-direction: column;
795
- margin-top: 38px;
796
- background: @white;
797
-
798
- &-title {
799
- text-align: center;
800
- border: 1px solid #EDEDED;
801
- border-bottom: none;
802
- line-height: 27px;
803
- // margin: 10px 14px 0 14px;
804
- }
805
-
806
- &-content {
807
- flex: 1;
808
- display: flex;
809
- overflow: auto;
810
- }
811
- }
812
-
813
- // 表格渲染
814
- &-tableBox {
815
- width: 100%;
816
- text-align: center;
817
- border-collapse: collapse;
818
- border-spacing: 0;
819
-
820
- td,
821
- th {
822
- word-break: break-all;
823
- word-wrap: break-word;
824
- min-width: 50px;
825
- height: 29px;
826
- text-align: center;
827
- // overflow: hidden;
828
- white-space: nowrap;
829
- text-overflow: ellipsis;
830
- max-width: 200px;
831
- }
832
-
833
- .briGantt-chart-td {
834
- height: 40px;
835
- }
836
-
837
- .briGantt-table-th-now {
838
- color: @themeColor;
839
- }
840
- }
841
-
842
- &-table {
843
- &-tr {
844
- border: 1px solid #EDEDED;
845
- }
846
-
847
- &-tr:nth-child(2n) {
848
- background: rgba(244, 246, 249, 0.5119);
849
- }
850
-
851
- &-th {
852
- background: #F4F8FF;
853
- font-weight: 400;
854
- color: rgba(101, 101, 101, 1);
855
- }
856
-
857
- &-td {
858
- border-right: 1px solid #EDEDED;
859
- font-weight: 400;
860
- color: rgba(111, 111, 111, 1);
861
-
862
- &-main {
863
- height: 28px;
864
- background: rgba(238, 238, 238, 0.5);
865
- border: 1px solid #f6f6f6;
866
- }
867
- }
868
-
869
- &-td:last-of-type {
870
- border: none;
871
- }
872
- }
873
-
874
- &-chart {
875
- &-td {
876
- overflow: visible;
877
-
878
- &-greyLine {
879
- border-top: 1px dashed #D5D5D5;
880
- }
881
-
882
- &-main {
883
- display: flex;
884
- width: 100%;
885
- height: 100%;
886
- align-items: center;
887
- justify-content: center;
888
-
889
- &-left,
890
- &-right {
891
- height: 100%;
892
- overflow: hidden;
893
- }
894
-
895
- &-right-auto {
896
- height: 100%;
897
- overflow: hidden;
898
- flex: 1;
899
- }
900
-
901
- &-center {
902
- height: 30px;
903
- border-radius: 4px;
904
- background: #f6f6f6;
905
- z-index: 1;
906
- min-width: 2px;
907
-
908
- .ms-ellipsis {
909
- border-radius: 4px;
910
- height: 100%;
911
- color: @white;
912
- text-align: left;
913
- padding-left: 10px;
914
- white-space: nowrap;
915
- text-overflow: ellipsis;
916
- overflow: hidden;
917
- }
918
-
919
- &-tooltip {
920
- white-space: normal;
921
-
922
- &-select {
923
- height: 5px;
924
- display: inline-block;
925
- vertical-align: middle;
926
- width: 5px;
927
- border-radius: 50%;
928
- }
929
- }
930
- }
931
-
932
- &-line {
933
- width: 100%;
934
- border-bottom: 1px solid #D5D5D5;
935
- font-weight: 400;
936
- color: rgba(74, 74, 74, 1);
937
- padding: 0 10px;
938
- transform: translateY(15px);
939
- text-align: left;
940
- height: 29px;
941
- font-size: @smallSize;
942
- white-space: nowrap;
943
- text-overflow: ellipsis;
944
- overflow: hidden;
945
-
946
- &-circle {
947
- display: block;
948
- width: 10px;
949
- height: 100%;
950
- min-width: 10px;
951
-
952
- .circle {
953
- display: block;
954
- width: 10px;
955
- height: 10px;
956
- border-radius: 50%;
957
- min-width: 10px;
958
- margin-top: 38px;
959
- background: #D5D5D5;
960
- }
961
- }
962
- }
963
-
964
- ;
965
- }
966
- }
967
- }
968
-
969
- // 蓝色虚线
970
- &-line-now {
971
- z-index: 9;
972
- text-align: center;
973
- background: transparent;
974
-
975
- &::before {
976
- content: "";
977
- border-left: 1px dashed @themeColor;
978
- position: absolute;
979
- top: 25px;
980
- bottom: 0px;
981
- z-index: 9;
982
- }
983
-
984
- &::after {
985
- content: "";
986
- width: 6px;
987
- height: 6px;
988
- border-radius: 6px;
989
- background: @themeColor;
990
- position: absolute;
991
- top: 25px;
992
- margin-left: -3px;
993
- }
994
- }
995
-
996
- // 时间轴
997
- &-timer {
998
- align-items: center;
999
- position: relative;
1000
- float: right;
1001
- overflow: hidden;
1002
-
1003
- &-main {
1004
- overflow: auto;
1005
- flex: 1;
1006
- height: 100%;
1007
- position: relative;
1008
- }
1009
-
1010
- &-bg {
1011
- position: absolute;
1012
- background: #F4F8FF;
1013
- left: 0px;
1014
- right: 0px;
1015
- height: 28px;
1016
- border-radius: 28px;
1017
- }
1018
-
1019
- &-icon {
1020
- background: #F4F8FF;
1021
- color: #fff;
1022
- width: 28px;
1023
- height: 28px;
1024
- min-width: 28px;
1025
- display: flex;
1026
- align-items: center;
1027
- justify-content: center;
1028
- position: absolute;
1029
- z-index: 2;
1030
- top: 0px;
1031
- background: #F2F8FF;
1032
-
1033
- &:hover {
1034
- color: #fff;
1035
- }
1036
-
1037
- i {
1038
- display: block;
1039
- width: 16px;
1040
- height: 16px;
1041
- border-radius: 16px;
1042
- font-size: 13px;
1043
- background: @themeColor;
1044
- display: flex;
1045
- align-items: center;
1046
- justify-content: center;
1047
- }
1048
-
1049
- &-left {
1050
- left: -1px;
1051
- border-top-left-radius: 28px;
1052
- border-bottom-left-radius: 28px;
1053
- }
1054
-
1055
- &-right {
1056
- right: -1px;
1057
- border-top-right-radius: 28px;
1058
- border-bottom-right-radius: 28px;
1059
- }
1060
- }
1061
- }
1062
-
1063
- // 区域映射
1064
- &-data {
1065
- flex: 1;
1066
- overflow: auto;
1067
- position: relative;
1068
-
1069
- &-table {}
1070
-
1071
- &-chart {}
1072
-
1073
- &::-webkit-scrollbar {
1074
- height: 0px;
1075
- }
1076
- }
1077
-
1078
- // table 列表映射
1079
- &-tabledata {
1080
- overflow-y: auto;
1081
- border-right: none;
1082
- }
1083
- }
1084
- </style>
1
+ <template>
2
+ <div class="briGantt">
3
+ <div class="briGantt-top">
4
+ <div class="bri-scrollbar0">
5
+ <slot></slot>
6
+ </div>
7
+ <!-- 时间渲染 -->
8
+ <div
9
+ class="briGantt-timer"
10
+ :style="{width: clientWidth + 'px'}"
11
+ >
12
+ <a
13
+ class="briGantt-timer-icon briGantt-timer-icon-left"
14
+ @click="preTime"
15
+ >
16
+ <Icon type="ios-arrow-back" />
17
+ </a>
18
+ <div class="briGantt-timer-bg"></div>
19
+ <div
20
+ class="bri-scrollbar0 briGantt-timer-main"
21
+ ref="briGanttTimer"
22
+ v-on:scroll="handleScroll($event, [{ ref: 'briGanttArea', direction: 'scrollLeft' }])"
23
+ >
24
+ <table
25
+ :style="{tableLayout:'fixed', width: tableWidth}"
26
+ class="briGantt-tableBox"
27
+ >
28
+ <thead class="briGantt-table-thead">
29
+ <tr>
30
+ <th
31
+ class="briGantt-table-th"
32
+ v-for="timeItem in simpleData"
33
+ :key="timeItem.key"
34
+ :colspan="timeItem.colspan"
35
+ :style="{...timeItem.style}"
36
+ >
37
+ <Tooltip
38
+ :content="timeItem.fullName"
39
+ placement="top"
40
+ :transfer="true"
41
+ :transfer-class-name="`briGantt-transfer-tooltip-${themeName}`"
42
+ >
43
+ {{ timeItem.name }}
44
+ </Tooltip>
45
+ <div
46
+ v-if="timeItem.now"
47
+ class="briGantt-line-now"
48
+ ></div>
49
+ </th>
50
+ </tr>
51
+ </thead>
52
+ </table>
53
+ </div>
54
+ <a
55
+ class="briGantt-timer-icon briGantt-timer-icon-right"
56
+ @click="nextTime"
57
+ >
58
+ <Icon type="ios-arrow-forward" />
59
+ </a>
60
+ </div>
61
+ </div>
62
+ <div class="briGantt-bottom">
63
+ <div
64
+ class="briGantt-bottom-title"
65
+ v-if="title"
66
+ >{{ title }}</div>
67
+ <div class="briGantt-bottom-content">
68
+ <!-- 数据映射 -->
69
+ <div
70
+ v-if="table"
71
+ class="bri-scrollbar0 briGantt-tabledata"
72
+ ref="briGanttColumn"
73
+ v-on:scroll="handleScroll($event, [{ ref: 'briGanttArea', direction: 'scrollTop' }])"
74
+ >
75
+ <table class="briGantt-tableBox briGantt-table">
76
+ <tbody>
77
+ <tr
78
+ class="briGantt-table-tr"
79
+ v-for="(row, rowIndex) in table"
80
+ :key="rowIndex"
81
+ >
82
+ <td
83
+ class="briGantt-table-td"
84
+ v-for="(col, colIndex) in row"
85
+ :key="colIndex"
86
+ :colspan="col.colspan"
87
+ :rowspan="col.rowspan"
88
+ :style="col.rowspan > 1 ? {background: '#fff',padding: '0 10px',fontWeight:500} : {padding: '0 10px'}"
89
+ v-html="col.label"
90
+ ></td>
91
+ </tr>
92
+ </tbody>
93
+ </table>
94
+ </div>
95
+ <!-- 区域映射 -->
96
+ <div
97
+ class="briGantt-data bri-scrollbar"
98
+ :class="`briGantt-data-${type}`"
99
+ ref="briGanttArea"
100
+ v-on:scroll="handleScroll($event, [{ ref: 'briGanttTimer', direction: 'scrollLeft' }, { ref:'briGanttColumn', direction:'scrollTop' }, { ref:'briGanttScrollbar', direction:'scrollLeft' }])"
101
+ >
102
+ <table
103
+ :style="{tableLayout:'fixed', width: tableWidth}"
104
+ class="briGantt-tableBox briGantt-table"
105
+ border="0"
106
+ cellspacing="0"
107
+ cellpadding="0"
108
+ >
109
+ <tr v-if="computedData.length === 0">
110
+ <td
111
+ :colspan="timeData.length"
112
+ class="briGantt-table-td"
113
+ >暂无内容</td>
114
+ </tr>
115
+ <tbody v-if="type==='table'">
116
+ <tr v-if="computedData.length === 0">
117
+ <td
118
+ :colspan="timeData.length"
119
+ class="briGantt-table-td"
120
+ >暂无内容</td>
121
+ </tr>
122
+ <tr
123
+ class="briGantt-table-tr"
124
+ v-for="(taskItem, taskIndex) in computedData"
125
+ :key="taskIndex"
126
+ style="border-left: none"
127
+ >
128
+ <td
129
+ class="briGantt-table-td"
130
+ v-for="(timeItem, timeIndex) in taskItem"
131
+ :key="timeIndex"
132
+ :colspan="timeItem.colspan"
133
+ >
134
+ <slot
135
+ v-if="timeItem.isApply"
136
+ name="table"
137
+ v-bind:task="timeItem.task"
138
+ v-bind:time="timeItem"
139
+ >
140
+ <div
141
+ class="briGantt-table-td-main"
142
+ :style="timeItem.style"
143
+ ></div>
144
+ </slot>
145
+ <slot
146
+ v-else
147
+ name="tabletd"
148
+ v-bind:preTime="taskItem[timeIndex-1]"
149
+ v-bind:nextTime="taskItem[timeIndex+1]"
150
+ v-bind:task="timeItem.task"
151
+ v-bind:time="timeItem"
152
+ ></slot>
153
+ </td>
154
+ </tr>
155
+ </tbody>
156
+ <tbody v-else-if="type==='chart'">
157
+ <tr
158
+ class="briGantt-chart-tr"
159
+ v-for="(taskItem, taskIndex) in computedData"
160
+ :key="taskIndex"
161
+ >
162
+ <td
163
+ class="briGantt-chart-td"
164
+ v-for="(timeItem, timeIndex) in taskItem"
165
+ :key="timeIndex"
166
+ :colspan="timeItem.colspan"
167
+ >
168
+ <div
169
+ v-if="timeItem.isApply"
170
+ class="briGantt-chart-td-main"
171
+ >
172
+ <slot
173
+ name="chart"
174
+ v-bind:task="timeItem.task"
175
+ v-bind:chartItem="timeItem"
176
+ >
177
+ <Tooltip
178
+ placement="right"
179
+ transfer
180
+ :transfer-class-name="`briGantt-transfer-tooltip-${themeName}`"
181
+ style="width:100%"
182
+ >
183
+ <div
184
+ class="briGantt-chart-td-main-center"
185
+ :style="{
186
+ background:$getColor(timeItem.style.background),
187
+ minWidth: minTdWidth,
188
+ border: `1px solid ${timeItem.style.background}`,
189
+ padding: timeItem.task.progressField == 100 ? '' : '1px',
190
+ cursor: canClick ? 'pointer' : ''
191
+ }"
192
+ @click="clickRow(timeItem)"
193
+ >
194
+ <slot
195
+ name="chartCenter"
196
+ v-bind:task="timeItem.task"
197
+ v-bind:chartItem="timeItem"
198
+ >
199
+ <div
200
+ class="ms-ellipsis"
201
+ :style="{
202
+ background:timeItem.style.background,
203
+ width: `${timeItem.task.progressField}%`
204
+ }"
205
+ >
206
+ {{ timeItem.task.label }}
207
+ </div>
208
+ </slot>
209
+ </div>
210
+ <div
211
+ slot="content"
212
+ class="briGantt-chart-td-main-center-tooltip"
213
+ >
214
+ <span
215
+ class="briGantt-chart-td-main-center-tooltip-select"
216
+ :style="{...timeItem.style}"
217
+ >
218
+ </span>
219
+ {{timeItem.task.select}}
220
+ <div>完成度:{{timeItem.task.progressField}}%</div>
221
+ <div>{{ timeItem.task.label }}</div>
222
+ </div>
223
+ </Tooltip>
224
+ </slot>
225
+ </div>
226
+ <slot
227
+ v-else
228
+ name="charttd"
229
+ v-bind:task="timeItem.task"
230
+ v-bind:time="timeItem"
231
+ v-bind:preTime="taskItem[timeIndex-1]"
232
+ v-bind:nextTime="taskItem[timeIndex+1]"
233
+ >
234
+ <div class="briGantt-chart-td-greyLine"></div>
235
+ </slot>
236
+ </td>
237
+ </tr>
238
+ </tbody>
239
+ </table>
240
+ </div>
241
+ </div>
242
+
243
+ <!-- 底部滚动条 -->
244
+ <!-- <div class="briGantt-scroll">
245
+ <div class="briGantt-scroll-main"
246
+ ref="briGanttScrollbar"
247
+ :style="{ width: clientWidth + 'px' }"
248
+ v-on:scroll="handleScroll($event, [{ ref: 'briGanttTimer', direction: 'scrollLeft' }, { ref:'briGanttArea', direction:'scrollLeft' }, { ref:'briGanttBlue', direction:'scrollLeft' }])">
249
+ <div :style="{width: tableWidth}"></div>
250
+ </div>
251
+ </div> -->
252
+ </div>
253
+ </div>
254
+ </template>
255
+ <script>
256
+ function getDate (hours) {
257
+ const currentDate = new Date();
258
+ const currentYear = currentDate.getFullYear();
259
+ const currentMonth = currentDate.getMonth();
260
+ const currentDay = currentDate.getDate();
261
+ const timeStamp = new Date(
262
+ currentYear,
263
+ currentMonth,
264
+ currentDay,
265
+ 0,
266
+ 0,
267
+ 0
268
+ ).getTime();
269
+ return new Date(timeStamp + hours * 60 * 60 * 1000).getTime();
270
+ }
271
+ function getMonth (N) {
272
+ const currentDate = new Date();
273
+ const currentYear = currentDate.getFullYear();
274
+ const currentMonth = currentDate.getMonth();
275
+ return new Date(currentYear, currentMonth + N, 1).getTime();
276
+ }
277
+ // 示例数据
278
+ let tasks = [
279
+ {
280
+ id: 1,
281
+ label: "Make some noise",
282
+ user:
283
+ '<a href="https://www.google.com/search?q=John+Doe" target="_blank" style="color:#0077c0;">John Doe</a>',
284
+ start: getDate(-24 * 5),
285
+ end: getDate(0),
286
+ select: "紧急",
287
+ duration: 15 * 24 * 60 * 60 * 1000,
288
+ percent: 85,
289
+ type: "project",
290
+ style: {
291
+ background: "orange",
292
+ main: "rgba(109,174,242,1)"
293
+ }
294
+ // collapsed: true,
295
+ },
296
+ {
297
+ id: 2,
298
+ label: "With great power comes great responsibility",
299
+ user:
300
+ '<a href="https://www.google.com/search?q=Peter+Parker" target="_blank" style="color:#0077c0;">Peter Parker</a>',
301
+ parentId: 1,
302
+ start: getDate(-24 * 20),
303
+ duration: 20 * 24 * 60 * 60 * 1000,
304
+ percent: 50,
305
+ select: "重要",
306
+ type: "milestone",
307
+ collapsed: true,
308
+ style: {
309
+ background: "red",
310
+ main: "rgba(240,143,145,1)"
311
+ }
312
+ },
313
+ {
314
+ id: 3,
315
+ label: "Courage is being scared to death, but saddling up anyway.",
316
+ user:
317
+ '<a href="https://www.google.com/search?q=John+Wayne" target="_blank" style="color:#0077c0;">John Wayne</a>',
318
+ parentId: 2,
319
+ select: "普通",
320
+ start: getDate(-24 * 3),
321
+ duration: 2 * 24 * 60 * 60 * 1000,
322
+ percent: 100,
323
+ type: "task",
324
+ style: {
325
+ background: "rgba(255,248,242,1)",
326
+ main: "rgba(255,190,114,1)"
327
+ }
328
+ },
329
+ {
330
+ id: 4,
331
+ label: "Put that toy AWAY!",
332
+ user:
333
+ '<a href="https://www.google.com/search?q=Clark+Kent" target="_blank" style="color:#0077c0;">Clark Kent</a>',
334
+ start: getDate(-24 * 2),
335
+ duration: 2 * 24 * 60 * 60 * 1000,
336
+ select: "紧急",
337
+ percent: 50,
338
+ type: "task",
339
+ dependentOn: [3],
340
+ style: {
341
+ background: "rgba(235,248,240,1)",
342
+ main: "rgba(137,213,166,1)"
343
+ }
344
+ },
345
+ {
346
+ id: 5,
347
+ label: "Put that toy AWAY!",
348
+ select: "紧急",
349
+ user:
350
+ '<a href="https://www.google.com/search?q=Clark+Kent" target="_blank" style="color:#0077c0;">Clark Kent</a>',
351
+ start: getDate(1 * 24),
352
+ end: getDate(1 * 24),
353
+ // duration: 1 * 24 * 60 * 60 * 1000,
354
+ percent: 50,
355
+ type: "task",
356
+ dependentOn: [3],
357
+ style: {
358
+ background: "rgba(235,248,240,1)",
359
+ main: "rgba(137,213,166,1)"
360
+ }
361
+ }
362
+ ];
363
+
364
+ export default {
365
+ name: "briGantt",
366
+ components: {},
367
+ props: {
368
+ simpleDataColor: String,
369
+
370
+ tasks: Array,
371
+ options: {
372
+ type: Object,
373
+ default () {
374
+ return {};
375
+ }
376
+ },
377
+ value: {
378
+ type: Object,
379
+ default () {
380
+ return {};
381
+ }
382
+ },
383
+ propsObj: {
384
+ type: Object,
385
+ default () {
386
+ return {};
387
+ }
388
+ },
389
+ // 是否展示示例数据
390
+ showEs: {
391
+ type: Boolean,
392
+ default: false
393
+ },
394
+ title: String,
395
+ // 展示类型, 分图标和表格,默认表格
396
+ type: {
397
+ type: String,
398
+ default: "table"
399
+ },
400
+ dimension: {
401
+ type: String,
402
+ default: "quarter"
403
+ },
404
+ showCloumns: {
405
+ type: Boolean,
406
+ default: true
407
+ },
408
+ table: Array,
409
+ // 距离今天个数
410
+ count: {
411
+ type: Number,
412
+ default: 5
413
+ },
414
+ // 展示日期间隔
415
+ step: {
416
+ type: Number,
417
+ default: 1
418
+ },
419
+ canClick: {
420
+ type: Boolean,
421
+ default: false
422
+ }
423
+ },
424
+ computed: {
425
+ // 默认列表
426
+ defaultTasks () {
427
+ if (this.showEs) {
428
+ return tasks;
429
+ } else {
430
+ return this.tasks || [];
431
+ }
432
+ },
433
+ // 表格宽度
434
+ tableWidth () {
435
+ let timeDataWidth = this.simpleData.length * 50;
436
+ let clientWidth = this.clientWidth;
437
+ if (this.computedCountStep.stepKind === "month") {
438
+ timeDataWidth = this.timeData.length * 3;
439
+ }
440
+ if (timeDataWidth < clientWidth) {
441
+ return "100%";
442
+ } else {
443
+ return timeDataWidth + "px";
444
+ }
445
+ },
446
+ minTdWidth () {
447
+ let minWidth = 2;
448
+ if (this.tableWidth.includes("px")) {
449
+ minWidth = parseInt(this.tableWidth) / this.timeData.length;
450
+ } else {
451
+ minWidth = parseInt(this.clientWidth) / this.timeData.length;
452
+ }
453
+ minWidth > 20 && (minWidth = 2);
454
+ return minWidth + "px";
455
+ },
456
+ // 间隔及时间,当前选择时间维度
457
+ computedCountStep () {
458
+ this.refreshStepCount();
459
+ return this.dimensionObject[this.dimension] || { count: this.count, step: this.step };
460
+ },
461
+ // 任务数据
462
+ taskData () {
463
+ /**
464
+ * task 默认数据
465
+ */
466
+ let tasks = this.defaultTasks;
467
+ for (let task of tasks) {
468
+ if (typeof task.x === "undefined") {
469
+ task.x = 0;
470
+ }
471
+ if (typeof task.y === "undefined") {
472
+ task.y = 0;
473
+ }
474
+ if (typeof task.width === "undefined") {
475
+ task.width = 0;
476
+ }
477
+ if (typeof task.height === "undefined") {
478
+ task.height = 0;
479
+ }
480
+ if (typeof task.mouseOver === "undefined") {
481
+ task.mouseOver = false;
482
+ }
483
+ if (typeof task.collapsed === "undefined") {
484
+ task.collapsed = false;
485
+ }
486
+ if (typeof task.dependentOn === "undefined") {
487
+ task.dependentOn = [];
488
+ }
489
+ if (typeof task.parentId === "undefined") {
490
+ task.parentId = null;
491
+ }
492
+ if (typeof task.style === "undefined") {
493
+ task.style = {};
494
+ }
495
+ if (typeof task.children === "undefined") {
496
+ task.children = [];
497
+ }
498
+ if (typeof task.allChildren === "undefined") {
499
+ task.allChildren = [];
500
+ }
501
+ if (typeof task.parents === "undefined") {
502
+ task.parents = [];
503
+ }
504
+ if (typeof task.parent === "undefined") {
505
+ task.parent = null;
506
+ }
507
+ if (typeof task.startTime === "undefined") {
508
+ task.startTime = new Date(task.start).valueOf();
509
+ }
510
+ if (typeof task.endTime === "undefined" && task.hasOwnProperty("end")) {
511
+ task.endTime = new Date(task.end).valueOf();
512
+ } else if (typeof task.endTime === "undefined" && task.hasOwnProperty("duration")) {
513
+ task.endTime = task.startTime + task.duration - (1 * 24 * 60 * 60 * 1000);
514
+ }
515
+ if (typeof task.duration === "undefined" && task.hasOwnProperty("endTime")) {
516
+ task.duration = task.endTime - task.startTime;
517
+ }
518
+ }
519
+ return tasks;
520
+ },
521
+ // 时间数据
522
+ simpleData () {
523
+ // 小于今天
524
+ let { count, step, stepKind } = this.computedCountStep;
525
+ let data = [
526
+ { key: getDate(0),
527
+ endKey: getDate((step - 1) * 24 + 23.9999),
528
+ name: "今天",
529
+ colspan: 1,
530
+ fullName: this.$dateFormat(getDate(0), "yyyy-MM-dd"),
531
+ style: { color: this.simpleDataColor, fontWeight: 500 },
532
+ now: true
533
+ }
534
+ ];
535
+ let preCount = this.preCount * count + count;
536
+ let nextCount = this.nextCount * count + count;
537
+ for (let i = -step; i >= -(preCount * step); i -= step) {
538
+ let key = stepKind === "month" ? getMonth(i) : getDate(i * 24);
539
+ data.unshift({
540
+ colspan: 1,
541
+ key: key,
542
+ endKey: getDate((i + step - 1) * 24 + 23.9999),
543
+ name: this.getDayName(key, stepKind),
544
+ fullName: this.$dateFormat(key, "yyyy-MM-dd"),
545
+ style: this.$dateFormat(key, "d") == "1" && { fontWeight: 500 }
546
+ });
547
+ }
548
+ // 大于今天
549
+ for (let i = step; i <= nextCount * step; i += step) {
550
+ let key = stepKind === "month" ? getMonth(i) : getDate(i * 24);
551
+ data.push({
552
+ colspan: 1,
553
+ key: key,
554
+ endKey: getDate((i + step - 1) * 24 + 23.9999),
555
+ name: this.getDayName(key, stepKind),
556
+ fullName: this.$dateFormat(key, "yyyy-MM-dd"),
557
+ style: this.$dateFormat(key, "d") == "1" && { fontWeight: 500 }
558
+ });
559
+ }
560
+ return data;
561
+ },
562
+ timeData () {
563
+ let { count, step, stepKind } = this.computedCountStep;
564
+ let data = [];
565
+ let preCount = this.preCount * count + count;
566
+ let nextCount = this.nextCount * count + count;
567
+ let startTime = -(preCount * step); // 个数
568
+ let endTime = nextCount * step;
569
+ // 年度以月为分隔符
570
+ if (stepKind === "month") {
571
+ startTime = (getMonth(-preCount) - getMonth(0)) / 24 / 60 / 60 / 1000;
572
+ endTime = (getMonth(nextCount) - getMonth(0)) / 24 / 60 / 60 / 1000;
573
+ }
574
+ for (let i = startTime; i <= endTime; i++) {
575
+ let key = getDate(i * 24);
576
+ data.push({
577
+ now: this.$dateFormat(key, "yyyy-MM-dd") === this.$dateFormat(new Date(), "yyyy-MM-dd"),
578
+ key: key,
579
+ endKey: getDate(i * 24 + 23.9999),
580
+ name: this.getDayName(key, stepKind),
581
+ fullName: this.$dateFormat(key, "yyyy-MM-dd")
582
+ });
583
+ }
584
+ return data;
585
+ },
586
+ // 任务时间结合数据
587
+ computedData () {
588
+ return this.taskData.map(taskItem => {
589
+ let tr = [];
590
+ this.timeData.forEach(timeItem => {
591
+ let flag = this.filterTaskDate(taskItem, timeItem);
592
+ if (flag) {
593
+ let isEndStep = new Date(timeItem.endKey) > new Date(taskItem.endTime);
594
+ if (tr[tr.length - 1] && tr[tr.length - 1].isApply) {
595
+ tr[tr.length - 1].colspan++;
596
+ // 判断是不是结束日期,当前节点日期startEnd endTime, endKey
597
+ if (isEndStep) {
598
+ tr[tr.length - 1].isEndStep = isEndStep;
599
+ }
600
+ } else {
601
+ let defaultStyle = {
602
+ background: "rgba(232,243,253,1)",
603
+ border: "1px solid rgba(109,174,242,1)",
604
+ main: "rgba(109,174,242,1)"
605
+ };
606
+ let obj = {
607
+ colspan: 1,
608
+ ...timeItem,
609
+ style: taskItem.style || defaultStyle,
610
+ task: taskItem,
611
+ isApply: true
612
+ };
613
+ if (isEndStep) {
614
+ obj.isEndStep = isEndStep;
615
+ }
616
+ tr.push(obj);
617
+ }
618
+
619
+ } else {
620
+ let obj = {
621
+ colspan: 1,
622
+ ...timeItem,
623
+ task: taskItem,
624
+ isApply: false
625
+ };
626
+ tr.push(obj);
627
+ }
628
+ });
629
+ return tr;
630
+ });
631
+ },
632
+
633
+ theme () {
634
+ return this.propsObj.theme || {};
635
+ },
636
+ themeName () {
637
+ return this.theme.name;
638
+ }
639
+ },
640
+ data () {
641
+ return {
642
+ // 当前客户端宽度
643
+ clientWidth: 0,
644
+ // 向下点了几次
645
+ nextCount: 0,
646
+ // 向上点了几次
647
+ preCount: 0,
648
+ // 时间维度
649
+ dimensionObject: {
650
+ doubleWeek: { name: "按周", count: 3, step: 1, stepKind: "day" },
651
+ week: { name: "双周", count: 7, step: 1, stepKind: "day" },
652
+ month: { name: "按月", count: 7, step: 2, stepKind: "day" },
653
+ quarter: { name: "季度", count: 9, step: 5, stepKind: "day" },
654
+ year: { name: "按年", count: 6, step: 1, stepKind: "month" }
655
+ },
656
+ nowOffsetLeft: 0
657
+ };
658
+ },
659
+ created () {
660
+ this.init();
661
+ },
662
+ mounted () {
663
+ // 宽度调整
664
+ window.onresize = this.refreshWidth;
665
+ },
666
+ destroyed () {
667
+ window.onresize = null;
668
+ },
669
+ methods: {
670
+ init () {
671
+ // 赋初值
672
+ setTimeout(() => {
673
+ this.refreshWidth();
674
+ });
675
+ },
676
+ // 比较时间
677
+ filterTaskDate (taskItem, timeItem) {
678
+ let flag = (new Date(taskItem.startTime) <= new Date(timeItem.endKey)) && (taskItem.endTime ? ((new Date(timeItem.key) <= new Date(taskItem.endTime))) : taskItem.endInfinite);
679
+ return flag;
680
+ },
681
+ // 获得日期显示格式
682
+ getDayName (key, stepKind) {
683
+ let name = this.$dateFormat(key, "M月d日");
684
+ if (name === "1日") {
685
+ name = this.$dateFormat(key, "M月d日");
686
+ }
687
+ if (stepKind === "month") {
688
+ name = this.$dateFormat(key, "M月");
689
+ if (name === "1月") {
690
+ name = `${this.$dateFormat(key, "yyyy年M月")}`;
691
+ }
692
+ }
693
+ return name;
694
+ },
695
+ // 左右按钮重置
696
+ refreshStepCount () {
697
+ this.preCount = 0;
698
+ this.nextCount = 0;
699
+ },
700
+ // 重新计算宽度
701
+ refreshWidth () {
702
+ this.clientWidth = this.$refs.briGanttArea ? this.$refs.briGanttArea.clientWidth : 0;
703
+ },
704
+ // 重新渲染
705
+ refresh () {
706
+
707
+ },
708
+ // 绑定同步滚动
709
+ handleScroll (el, scrollList) {
710
+ scrollList.forEach(({ref, direction} = item) => {
711
+ this.$refs[ref] && (this.$refs[ref][direction] = el.target[direction]);
712
+ });
713
+ },
714
+ // 点击上一节点
715
+ preTime () {
716
+ let briGanttTimer = this.$refs.briGanttTimer;
717
+ let timerWidth = briGanttTimer.clientWidth; // 盒子宽度
718
+ let scrollLeft = briGanttTimer.scrollLeft; // 滚动距离
719
+ if (scrollLeft === 0) {
720
+ // 已经滑到尽头,加载时间数据
721
+ this.preCount++;
722
+ this.$nextTick(() => {
723
+ this.slideTo(briGanttTimer, scrollLeft - timerWidth);
724
+ });
725
+ } else {
726
+ this.slideTo(briGanttTimer, scrollLeft - timerWidth);
727
+ }
728
+ },
729
+ // 点击下一节点
730
+ nextTime () {
731
+ let briGanttTimer = this.$refs.briGanttTimer;
732
+ let timerWidth = briGanttTimer.clientWidth; // 盒子宽度
733
+ let tableWidth = parseInt(this.tableWidth); // table 总宽度
734
+ let scrollLeft = briGanttTimer.scrollLeft; // 滚动距离
735
+ let distance = tableWidth - timerWidth; // 当前滚动条距离顶部的距离
736
+ if (scrollLeft < distance) {
737
+ // 未滑到尽头
738
+ this.slideTo(briGanttTimer, scrollLeft + timerWidth);
739
+ } else {
740
+ // 已经滑到尽头,加载时间数据
741
+ this.nextCount++;
742
+ this.$nextTick(() => {
743
+ this.slideTo(briGanttTimer, scrollLeft + timerWidth);
744
+ });
745
+ }
746
+ },
747
+ // 滚动到指定位置 增加滚动效果
748
+ slideTo (ref, target) {
749
+ let currScrollLeft = ref.scrollLeft; // 当前的距离
750
+ let distance = target - currScrollLeft;
751
+ let speed = distance / 10; // 每时刻速度
752
+ let speedTarget = currScrollLeft + speed;
753
+ let timer = setInterval(function () {
754
+ if (distance > 0 ? (speedTarget > target) : (speedTarget < target)) {
755
+ clearInterval(timer);
756
+ } else {
757
+ ref.scrollTo(speedTarget, 0);
758
+ speedTarget += speed;
759
+ }
760
+ }, 10);
761
+ },
762
+ // 行点击
763
+ clickRow (col) {
764
+ this.canClick && this.$emit("clickRow", col.task, col);
765
+ }
766
+ }
767
+ };
768
+ </script>
769
+
770
+ <style lang="less">
771
+ .briGantt {
772
+ width: 100%;
773
+ height: 100%;
774
+ color: #656565;
775
+ font-size: @smallSize;
776
+ line-height: 28px;
777
+ position: relative;
778
+ display: flex;
779
+ overflow: auto;
780
+ flex-direction: column;
781
+
782
+ &-top {
783
+ display: flex;
784
+ height: 100%;
785
+ width: 100%;
786
+ justify-content: space-between;
787
+ position: absolute;
788
+ }
789
+
790
+ &-bottom {
791
+ width: 100%;
792
+ overflow: auto;
793
+ display: flex;
794
+ flex-direction: column;
795
+ margin-top: 38px;
796
+ background: @white;
797
+
798
+ &-title {
799
+ text-align: center;
800
+ border: 1px solid #EDEDED;
801
+ border-bottom: none;
802
+ line-height: 27px;
803
+ // margin: 10px 14px 0 14px;
804
+ }
805
+
806
+ &-content {
807
+ flex: 1;
808
+ display: flex;
809
+ overflow: auto;
810
+ }
811
+ }
812
+
813
+ // 表格渲染
814
+ &-tableBox {
815
+ width: 100%;
816
+ text-align: center;
817
+ border-collapse: collapse;
818
+ border-spacing: 0;
819
+
820
+ td,
821
+ th {
822
+ word-break: break-all;
823
+ word-wrap: break-word;
824
+ min-width: 50px;
825
+ height: 29px;
826
+ text-align: center;
827
+ // overflow: hidden;
828
+ white-space: nowrap;
829
+ text-overflow: ellipsis;
830
+ max-width: 200px;
831
+ }
832
+
833
+ .briGantt-chart-td {
834
+ height: 40px;
835
+ }
836
+
837
+ .briGantt-table-th-now {
838
+ color: @themeColor;
839
+ }
840
+ }
841
+
842
+ &-table {
843
+ &-tr {
844
+ border: 1px solid #EDEDED;
845
+ }
846
+
847
+ &-tr:nth-child(2n) {
848
+ background: rgba(244, 246, 249, 0.5119);
849
+ }
850
+
851
+ &-th {
852
+ background: #F4F8FF;
853
+ font-weight: 400;
854
+ color: rgba(101, 101, 101, 1);
855
+ }
856
+
857
+ &-td {
858
+ border-right: 1px solid #EDEDED;
859
+ font-weight: 400;
860
+ color: rgba(111, 111, 111, 1);
861
+
862
+ &-main {
863
+ height: 28px;
864
+ background: rgba(238, 238, 238, 0.5);
865
+ border: 1px solid #f6f6f6;
866
+ }
867
+ }
868
+
869
+ &-td:last-of-type {
870
+ border: none;
871
+ }
872
+ }
873
+
874
+ &-chart {
875
+ &-td {
876
+ overflow: visible;
877
+
878
+ &-greyLine {
879
+ border-top: 1px dashed #D5D5D5;
880
+ }
881
+
882
+ &-main {
883
+ display: flex;
884
+ width: 100%;
885
+ height: 100%;
886
+ align-items: center;
887
+ justify-content: center;
888
+
889
+ &-left,
890
+ &-right {
891
+ height: 100%;
892
+ overflow: hidden;
893
+ }
894
+
895
+ &-right-auto {
896
+ height: 100%;
897
+ overflow: hidden;
898
+ flex: 1;
899
+ }
900
+
901
+ &-center {
902
+ height: 30px;
903
+ border-radius: 4px;
904
+ background: #f6f6f6;
905
+ z-index: 1;
906
+ min-width: 2px;
907
+
908
+ .ms-ellipsis {
909
+ border-radius: 4px;
910
+ height: 100%;
911
+ color: @white;
912
+ text-align: left;
913
+ padding-left: 10px;
914
+ white-space: nowrap;
915
+ text-overflow: ellipsis;
916
+ overflow: hidden;
917
+ }
918
+
919
+ &-tooltip {
920
+ white-space: normal;
921
+
922
+ &-select {
923
+ height: 5px;
924
+ display: inline-block;
925
+ vertical-align: middle;
926
+ width: 5px;
927
+ border-radius: 50%;
928
+ }
929
+ }
930
+ }
931
+
932
+ &-line {
933
+ width: 100%;
934
+ border-bottom: 1px solid #D5D5D5;
935
+ font-weight: 400;
936
+ color: rgba(74, 74, 74, 1);
937
+ padding: 0 10px;
938
+ transform: translateY(15px);
939
+ text-align: left;
940
+ height: 29px;
941
+ font-size: @smallSize;
942
+ white-space: nowrap;
943
+ text-overflow: ellipsis;
944
+ overflow: hidden;
945
+
946
+ &-circle {
947
+ display: block;
948
+ width: 10px;
949
+ height: 100%;
950
+ min-width: 10px;
951
+
952
+ .circle {
953
+ display: block;
954
+ width: 10px;
955
+ height: 10px;
956
+ border-radius: 50%;
957
+ min-width: 10px;
958
+ margin-top: 38px;
959
+ background: #D5D5D5;
960
+ }
961
+ }
962
+ }
963
+
964
+ ;
965
+ }
966
+ }
967
+ }
968
+
969
+ // 蓝色虚线
970
+ &-line-now {
971
+ z-index: 9;
972
+ text-align: center;
973
+ background: transparent;
974
+
975
+ &::before {
976
+ content: "";
977
+ border-left: 1px dashed @themeColor;
978
+ position: absolute;
979
+ top: 25px;
980
+ bottom: 0px;
981
+ z-index: 9;
982
+ }
983
+
984
+ &::after {
985
+ content: "";
986
+ width: 6px;
987
+ height: 6px;
988
+ border-radius: 6px;
989
+ background: @themeColor;
990
+ position: absolute;
991
+ top: 25px;
992
+ margin-left: -3px;
993
+ }
994
+ }
995
+
996
+ // 时间轴
997
+ &-timer {
998
+ align-items: center;
999
+ position: relative;
1000
+ float: right;
1001
+ overflow: hidden;
1002
+
1003
+ &-main {
1004
+ overflow: auto;
1005
+ flex: 1;
1006
+ height: 100%;
1007
+ position: relative;
1008
+ }
1009
+
1010
+ &-bg {
1011
+ position: absolute;
1012
+ background: #F4F8FF;
1013
+ left: 0px;
1014
+ right: 0px;
1015
+ height: 28px;
1016
+ border-radius: 28px;
1017
+ }
1018
+
1019
+ &-icon {
1020
+ background: #F4F8FF;
1021
+ color: #fff;
1022
+ width: 28px;
1023
+ height: 28px;
1024
+ min-width: 28px;
1025
+ display: flex;
1026
+ align-items: center;
1027
+ justify-content: center;
1028
+ position: absolute;
1029
+ z-index: 2;
1030
+ top: 0px;
1031
+ background: #F2F8FF;
1032
+
1033
+ &:hover {
1034
+ color: #fff;
1035
+ }
1036
+
1037
+ i {
1038
+ display: block;
1039
+ width: 16px;
1040
+ height: 16px;
1041
+ border-radius: 16px;
1042
+ font-size: 13px;
1043
+ background: @themeColor;
1044
+ display: flex;
1045
+ align-items: center;
1046
+ justify-content: center;
1047
+ }
1048
+
1049
+ &-left {
1050
+ left: -1px;
1051
+ border-top-left-radius: 28px;
1052
+ border-bottom-left-radius: 28px;
1053
+ }
1054
+
1055
+ &-right {
1056
+ right: -1px;
1057
+ border-top-right-radius: 28px;
1058
+ border-bottom-right-radius: 28px;
1059
+ }
1060
+ }
1061
+ }
1062
+
1063
+ // 区域映射
1064
+ &-data {
1065
+ flex: 1;
1066
+ overflow: auto;
1067
+ position: relative;
1068
+
1069
+ &-table {}
1070
+
1071
+ &-chart {}
1072
+
1073
+ &::-webkit-scrollbar {
1074
+ height: 0px;
1075
+ }
1076
+ }
1077
+
1078
+ // table 列表映射
1079
+ &-tabledata {
1080
+ overflow-y: auto;
1081
+ border-right: none;
1082
+ }
1083
+ }
1084
+ </style>