sh-view 2.8.1 → 2.8.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 (91) hide show
  1. package/.eslintrc.js +25 -20
  2. package/other.js +8 -8
  3. package/package.json +9 -6
  4. package/packages/components/index.js +91 -91
  5. package/packages/components/sh-alert/alert.ts +30 -0
  6. package/packages/components/sh-alert/index.vue +143 -168
  7. package/packages/components/sh-badge/index.vue +242 -242
  8. package/packages/components/sh-calendar/index.vue +650 -650
  9. package/packages/components/sh-card/index.vue +148 -148
  10. package/packages/components/sh-code-editor/index.vue +19 -19
  11. package/packages/components/sh-col/index.vue +92 -92
  12. package/packages/components/sh-corner/index.vue +230 -230
  13. package/packages/components/sh-count-to/index.vue +131 -131
  14. package/packages/components/sh-date/index.vue +301 -301
  15. package/packages/components/sh-drawer/index.vue +579 -579
  16. package/packages/components/sh-drawer/scrollbar.js +78 -78
  17. package/packages/components/sh-empty/index.vue +42 -42
  18. package/packages/components/sh-form/js/props.js +76 -76
  19. package/packages/components/sh-form/js/useForm.js +229 -229
  20. package/packages/components/sh-header/index.vue +261 -260
  21. package/packages/components/sh-icon/css/default/ionicons.svg +869 -869
  22. package/packages/components/sh-icon/css/font/iconfont.json +247 -247
  23. package/packages/components/sh-icon/index.vue +41 -41
  24. package/packages/components/sh-image/index.vue +133 -133
  25. package/packages/components/sh-list/index.vue +146 -146
  26. package/packages/components/sh-loading/index.vue +53 -53
  27. package/packages/components/sh-modal/index.vue +188 -188
  28. package/packages/components/sh-noticebar/index.vue +215 -215
  29. package/packages/components/sh-poptip/index.vue +597 -597
  30. package/packages/components/sh-progress/index.vue +276 -276
  31. package/packages/components/sh-pull-refresh/index.vue +289 -289
  32. package/packages/components/sh-result/index.vue +114 -114
  33. package/packages/components/sh-row/index.vue +66 -66
  34. package/packages/components/sh-split/components/trigger.vue +33 -33
  35. package/packages/components/sh-split/index.vue +342 -342
  36. package/packages/components/sh-table/components/importModal.vue +363 -363
  37. package/packages/components/sh-table/components/sh-column.vue +68 -68
  38. package/packages/components/sh-table/js/excel_to_json.js +313 -313
  39. package/packages/components/sh-table/js/props.js +305 -305
  40. package/packages/components/sh-table/js/tableMethods.js +167 -167
  41. package/packages/components/sh-table/js/useTable.js +636 -636
  42. package/packages/components/sh-table/table.vue +217 -217
  43. package/packages/components/sh-tabs/index.vue +426 -426
  44. package/packages/components/sh-tag/index.vue +168 -168
  45. package/packages/components/sh-toolbar/index.vue +182 -182
  46. package/packages/components/sh-tree/components/table-tree.vue +289 -289
  47. package/packages/components/sh-tree/mixin/treeProps.js +122 -122
  48. package/packages/components/sh-upload/index.vue +535 -535
  49. package/packages/components/sh-water-fall/index.vue +80 -80
  50. package/packages/components/sh-water-mark/index.vue +96 -96
  51. package/packages/css/index.js +4 -4
  52. package/packages/directive/index.js +19 -19
  53. package/packages/directive/module/click-out.js +14 -14
  54. package/packages/directive/module/draggable.js +42 -42
  55. package/packages/directive/module/line-clamp.js +22 -22
  56. package/packages/directive/module/prevent-click.js +18 -18
  57. package/packages/directive/module/resize.js +14 -14
  58. package/packages/directive/module/ripple.js +166 -166
  59. package/packages/index.js +39 -39
  60. package/packages/mixin/index.js +86 -86
  61. package/packages/other/sh-cron-modal/components/cron-content.vue +294 -294
  62. package/packages/other/sh-cron-modal/index.vue +81 -81
  63. package/packages/other/sh-cron-modal/mixin/cron-emits.js +1 -1
  64. package/packages/other/sh-cron-modal/mixin/cron-props.js +9 -9
  65. package/packages/other/sh-cron-modal/tabs/cron-week-box.vue +126 -126
  66. package/packages/other/sh-menu/index.vue +326 -326
  67. package/packages/other/sh-menu/menu-group-content.vue +136 -136
  68. package/packages/other/sh-menu/menu-item-content.vue +71 -71
  69. package/packages/other/sh-menu-card/index.vue +250 -250
  70. package/packages/other/sh-menu-card/menu-box.vue +87 -87
  71. package/packages/other/sh-preview/components/sh-excel.vue +163 -163
  72. package/packages/other/sh-preview/js/data-hook.js +41 -41
  73. package/packages/other/sh-preview/js/data-props.js +15 -15
  74. package/packages/other/sh-system-tip/index.vue +115 -115
  75. package/packages/utils/resize.js +69 -70
  76. package/packages/utils/transfer-queue.js +12 -12
  77. package/packages/vxeTable/index.js +193 -184
  78. package/packages/vxeTable/plugins/export.js +450 -450
  79. package/packages/vxeTable/render/cell/vxe-render-img.vue +27 -27
  80. package/packages/vxeTable/render/cell/vxe-render-table.vue +51 -51
  81. package/packages/vxeTable/render/cell/vxe-render-time.vue +44 -44
  82. package/packages/vxeTable/render/cell/vxe-render-tree.vue +70 -70
  83. package/packages/vxeTable/render/filters/vxe-filter-input.vue +26 -26
  84. package/packages/vxeTable/render/filters/vxe-filter-time.vue +26 -26
  85. package/packages/vxeTable/render/globalRenders.jsx +514 -514
  86. package/packages/vxeTable/render/mixin/cell-hooks.js +198 -198
  87. package/packages/vxeTable/render/mixin/cell-props.js +23 -23
  88. package/packages/vxeTable/render/mixin/filter-hooks.js +46 -46
  89. package/tsconfig.json +25 -0
  90. package/types/component.d.ts +1 -0
  91. package/types/index.ts +0 -0
@@ -1,579 +1,579 @@
1
- <template>
2
- <teleport to="body" :disabled="!transfer">
3
- <div class="sh-drawer-box">
4
- <transition name="fade">
5
- <div v-show="visible" v-if="mask" class="sh-drawer-mask" :class="{ 'sh-drawer-mask-inner': inner }" :style="maskStyle" @click="handleMask"></div>
6
- </transition>
7
- <div class="sh-drawer-wrap" :class="wrapClasses" @click="handleWrapClick">
8
- <transition :name="transitionName">
9
- <div v-show="visible" ref="drawerRef" class="sh-drawer" :class="classes" :style="mainStyles">
10
- <div ref="drawerContent" class="sh-drawer-content" :class="{ 'sh-drawer-content-no-mask': !mask }">
11
- <a v-if="closable" class="sh-drawer-close" @click="close">
12
- <slot name="close">
13
- <sh-icon type="ios-close"></sh-icon>
14
- </slot>
15
- </a>
16
- <div v-if="showHead" class="sh-drawer-header">
17
- <slot name="header">
18
- <div class="sh-drawer-header-inner">{{ title }}</div>
19
- </slot>
20
- </div>
21
- <div class="sh-drawer-body" :style="styles">
22
- <slot v-if="modelValue || !destroyOnClose"></slot>
23
- </div>
24
- <div v-if="slots.footer" class="sh-drawer-footer">
25
- <slot name="footer"></slot>
26
- </div>
27
- </div>
28
- <div v-if="draggable" class="sh-drawer-drag" :class="'sh-drawer-drag-' + placement" @mousedown="handleTriggerMousedown">
29
- <slot name="trigger">
30
- <div class="sh-drawer-drag-move-trigger">
31
- <div class="sh-drawer-drag-move-trigger-point"><i></i><i></i><i></i><i></i><i></i></div>
32
- </div>
33
- </slot>
34
- </div>
35
- </div>
36
- </transition>
37
- </div>
38
- </div>
39
- </teleport>
40
- </template>
41
-
42
- <script>
43
- import { defineComponent, ref, watch, onMounted, onBeforeUnmount, getCurrentInstance, computed } from 'vue'
44
- import useScrollbar from './scrollbar'
45
- export default defineComponent({
46
- name: 'ShDrawer',
47
- props: {
48
- modelValue: {
49
- type: Boolean,
50
- default: false
51
- },
52
- title: {
53
- type: String
54
- },
55
- width: {
56
- type: [Number, String],
57
- default: 256
58
- },
59
- height: {
60
- type: [Number, String],
61
- default: 256
62
- },
63
- closable: {
64
- type: Boolean,
65
- default: true
66
- },
67
- maskClosable: {
68
- type: Boolean,
69
- default: true
70
- },
71
- mask: {
72
- type: Boolean,
73
- default: true
74
- },
75
- maskStyle: {
76
- type: Object
77
- },
78
- styles: {
79
- type: Object
80
- },
81
- scrollable: {
82
- type: Boolean,
83
- default: false
84
- },
85
- placement: {
86
- type: String,
87
- default: 'right' // 'left', 'right', 'top', 'bottom'
88
- },
89
- zIndex: {
90
- type: Number,
91
- default: 1000
92
- },
93
- transfer: {
94
- type: Boolean
95
- },
96
- className: {
97
- type: String
98
- },
99
- inner: {
100
- type: Boolean,
101
- default: false
102
- },
103
- draggable: {
104
- type: Boolean,
105
- default: false
106
- },
107
- destroyOnClose: {
108
- type: Boolean,
109
- default: false
110
- },
111
- beforeClose: Function
112
- },
113
- emits: ['update:modelValue', 'close', 'resize-width', 'visible-change', 'drag'],
114
- setup(props, context) {
115
- const vm = getCurrentInstance()
116
- const { $vUtils } = vm.proxy
117
- const { emit, slots } = context
118
- const drawerRef = ref()
119
- const drawerContent = ref()
120
-
121
- const visible = ref(props.modelValue)
122
- const wrapShow = ref(false)
123
- const showHead = ref(true)
124
- const canMove = ref(false)
125
- const dragWidth = ref(props.width)
126
- const dragHeight = ref(props.height)
127
- const wrapperWidth = ref(props.width)
128
- const wrapperHeight = ref(props.height)
129
- const wrapperLeft = ref(0)
130
- const wrapperTop = ref(0)
131
- const minWidth = ref(256)
132
- const minHeight = ref(256)
133
- const id = ref($vUtils.randomStr(6))
134
- const tableList = ref([])
135
- const sliderList = ref([])
136
- let timer = null
137
-
138
- const isHorizontal = computed(() => ['left', 'right'].includes(props.placement))
139
- const wrapClasses = computed(() => {
140
- return {
141
- 'sh-drawer-hidden': !wrapShow.value,
142
- 'sh-drawer-no-mask': !props.mask,
143
- 'sh-drawer-wrap-inner': props.inner,
144
- 'sh-drawer-wrap-dragging': canMove.value,
145
- [`${props.className}`]: !!props.className
146
- }
147
- })
148
- const mainStyles = computed(() => {
149
- let style = {}
150
- if (isHorizontal.value) {
151
- const width = parseInt(dragWidth.value)
152
- const styleWidth = {
153
- width: width <= 100 ? `${width}%` : `${width}px`
154
- }
155
- Object.assign(style, styleWidth)
156
- } else {
157
- const height = parseInt(dragHeight.value)
158
- const styleHeight = {
159
- height: height <= 100 ? `${height}%` : `${height}px`
160
- }
161
- Object.assign(style, styleHeight)
162
- }
163
- return style
164
- })
165
- const classes = computed(() => {
166
- return {
167
- [`sh-drawer-${props.placement}`]: true,
168
- 'sh-drawer-no-header': !showHead.value,
169
- 'sh-drawer-inner': props.inner
170
- }
171
- })
172
- const transitionName = computed(() => {
173
- if (isHorizontal.value) return `move-${props.placement}`
174
- else if (props.placement === 'top') return 'move-up'
175
- else return 'move-down'
176
- })
177
-
178
- const { addScrollEffect, removeScrollEffect } = useScrollbar(props)
179
-
180
- const close = () => {
181
- if (!props.beforeClose) {
182
- return handleClose()
183
- }
184
- const before = props.beforeClose()
185
- if (before && before.then) {
186
- before.then(() => {
187
- handleClose()
188
- })
189
- } else {
190
- handleClose()
191
- }
192
- }
193
- const handleClose = () => {
194
- visible.value = false
195
- emit('update:modelValue', false)
196
- emit('close')
197
- }
198
- const handleMask = () => {
199
- if (canMove.value) return
200
- if (props.maskClosable && props.mask) {
201
- close()
202
- }
203
- }
204
- const handleWrapClick = event => {
205
- const className = event.target.getAttribute('class')
206
- if (className && className.indexOf('sh-drawer-wrap') > -1) handleMask()
207
- }
208
- const handleMousemove = event => {
209
- if (!canMove.value || !props.draggable || !visible.value) return
210
- // 更新容器距离
211
- handleSetWrapper()
212
- if (isHorizontal.value) {
213
- const left = event.pageX - wrapperLeft.value
214
- // 如果抽屉方向为右边,宽度计算需用容器宽度减去left
215
- let width = props.placement === 'right' ? wrapperWidth.value - left : left
216
- // 限定最小宽度
217
- width = Math.max(width, parseFloat(minWidth.value))
218
- event.atMin = width === parseFloat(minWidth.value)
219
- // 如果当前width不大于100,视为百分比
220
- if (width <= 100) width = (width / wrapperWidth.value) * 100
221
- if (width >= window.innerWidth) width = window.innerWidth
222
- dragWidth.value = width
223
- emit('resize-width', parseInt(dragWidth.value))
224
- emit('drag', 'dragging', parseInt(dragWidth.value))
225
- } else {
226
- const top = event.pageY - wrapperTop.value
227
- // 如果抽屉方向为下面,宽度计算需用容器宽度减去left
228
- let heigth = props.placement === 'bottom' ? wrapperHeight.value - top : top
229
- // 限定最小高度
230
- heigth = Math.max(heigth, parseFloat(minHeight.value))
231
- event.atMin = heigth === parseFloat(minHeight.value)
232
- // 如果当前heigth不大于100,视为百分比
233
- if (heigth <= 100) heigth = (heigth / wrapperHeight.value) * 100
234
- if (heigth >= window.innerHeight) heigth = window.innerHeight
235
- dragHeight.value = heigth
236
- emit('resize-width', parseInt(dragHeight.value))
237
- emit('drag', 'dragging', parseInt(dragHeight.value))
238
- }
239
- }
240
- const handleSetWrapper = () => {
241
- const { width, height, left, top } = drawerRef.value.getBoundingClientRect()
242
- if (isHorizontal.value) {
243
- wrapperWidth.value = width
244
- wrapperLeft.value = left
245
- } else {
246
- wrapperHeight.value = height
247
- wrapperTop.value = top
248
- }
249
- }
250
- const handleMouseup = () => {
251
- if (!props.draggable || !visible.value) return
252
- setTimeout(() => {
253
- canMove.value = false
254
- })
255
- emit('drag', 'end')
256
- }
257
- const handleTriggerMousedown = () => {
258
- canMove.value = true
259
- // 防止鼠标选中抽屉中文字,造成拖动trigger触发浏览器原生拖动行为
260
- window.getSelection().removeAllRanges()
261
- emit('drag', 'start')
262
- }
263
- const addDrawer = () => {
264
- const root = vm.root
265
- if (!root.drawerList) root.drawerList = []
266
- root.drawerList.push({
267
- id: id.value,
268
- drawer: vm
269
- })
270
- }
271
- const removeDrawer = () => {
272
- const root = vm.root
273
- if (!root.drawerList) return
274
- const index = root.drawerList.findIndex(item => item.id === id.value)
275
- root.drawerList.splice(index, 1)
276
- }
277
-
278
- watch(
279
- () => props.modelValue,
280
- value => {
281
- visible.value = value
282
- }
283
- )
284
- watch(
285
- () => visible.value,
286
- val => {
287
- if (val === false) {
288
- timer = setTimeout(() => {
289
- wrapShow.value = false
290
- const drawers = vm.root.drawerList.map(item => item.drawer)
291
- const otherDrawers = drawers.filter(item => item.id !== id.value)
292
- const isScrollDrawer = otherDrawers.some(item => item.visible && !item.scrollable)
293
- if (!isScrollDrawer) {
294
- removeScrollEffect()
295
- }
296
- }, 300)
297
- } else {
298
- if (timer) clearTimeout(timer)
299
- wrapShow.value = true
300
- if (!props.scrollable) {
301
- addScrollEffect()
302
- }
303
- }
304
- tableList.value.forEach(item => {
305
- item.table.handleOnVisibleChange(val)
306
- })
307
- sliderList.value.forEach(item => {
308
- item.slider.handleOnVisibleChange(val)
309
- })
310
- emit('visible-change', val)
311
- }
312
- )
313
- watch(
314
- () => props.scrollable,
315
- val => {
316
- if (!val) {
317
- addScrollEffect()
318
- } else {
319
- removeScrollEffect()
320
- }
321
- }
322
- )
323
- watch(
324
- () => props.title,
325
- val => {
326
- if (slots.header === undefined) {
327
- showHead.value = !!val
328
- }
329
- }
330
- )
331
- watch(
332
- () => props.width,
333
- val => {
334
- dragWidth.value = val
335
- }
336
- )
337
- watch(
338
- () => props.height,
339
- val => {
340
- dragHeight.value = val
341
- }
342
- )
343
- onMounted(() => {
344
- if (visible.value) {
345
- wrapShow.value = true
346
- }
347
- let isShowHead = true
348
- if (slots.header === undefined && !props.title) {
349
- isShowHead = false
350
- }
351
- showHead.value = isShowHead
352
- addDrawer()
353
- $vUtils.onListener(document, 'mousemove', handleMousemove)
354
- $vUtils.onListener(document, 'mouseup', handleMouseup)
355
- handleSetWrapper()
356
- })
357
- onBeforeUnmount(() => {
358
- removeDrawer()
359
- $vUtils.offListener(document, 'mousemove', handleMousemove)
360
- $vUtils.offListener(document, 'mouseup', handleMouseup)
361
- removeScrollEffect()
362
- })
363
-
364
- return {
365
- slots,
366
- visible,
367
- wrapClasses,
368
- transitionName,
369
- classes,
370
- mainStyles,
371
- showHead,
372
- drawerRef,
373
- drawerContent,
374
- close,
375
- handleMask,
376
- handleWrapClick,
377
- handleTriggerMousedown
378
- }
379
- }
380
- })
381
- </script>
382
-
383
- <style scoped lang="scss">
384
- .sh-drawer {
385
- width: auto;
386
- height: 100%;
387
- position: fixed;
388
- top: 0;
389
- &-inner {
390
- position: absolute;
391
- }
392
- &-left {
393
- left: 0;
394
- }
395
- &-right {
396
- right: 0;
397
- }
398
- &-top,
399
- &-bottom {
400
- width: 100%;
401
- height: auto;
402
- top: auto;
403
- }
404
- &-bottom {
405
- bottom: 0;
406
- }
407
- &-hidden {
408
- display: none !important;
409
- }
410
- &-wrap {
411
- position: fixed;
412
- overflow: auto;
413
- top: 0;
414
- right: 0;
415
- bottom: 0;
416
- left: 0;
417
- z-index: 1000;
418
- -webkit-overflow-scrolling: touch;
419
- outline: 0;
420
- &-inner {
421
- position: absolute;
422
- overflow: hidden;
423
- }
424
- &-dragging {
425
- user-select: none;
426
- }
427
- }
428
- &-wrap * {
429
- box-sizing: border-box;
430
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
431
- }
432
- &-mask {
433
- position: fixed;
434
- top: 0;
435
- bottom: 0;
436
- left: 0;
437
- right: 0;
438
- background-color: rgba(55, 55, 55, 0.6);
439
- height: 100%;
440
- z-index: 1000;
441
- &-hidden {
442
- display: none;
443
- }
444
- &-inner {
445
- position: absolute;
446
- }
447
- }
448
- &-content {
449
- width: 100%;
450
- height: 100%;
451
- display: flex;
452
- flex-direction: column;
453
- background-color: var(--vxe-table-body-background-color);
454
- border: 0;
455
- background-clip: padding-box;
456
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
457
- &-no-mask {
458
- pointer-events: auto;
459
- }
460
- }
461
- &-header {
462
- border-bottom: 1px solid var(--vxe-table-border-color);
463
- padding: 14px 16px;
464
- line-height: 1;
465
- &-inner {
466
- display: inline-block;
467
- width: 100%;
468
- height: 20px;
469
- line-height: 20px;
470
- font-size: var(--vxe-font-size-medium);
471
- font-weight: 500;
472
- overflow: hidden;
473
- text-overflow: ellipsis;
474
- white-space: nowrap;
475
- }
476
- }
477
- &-close {
478
- z-index: 1;
479
- position: absolute;
480
- right: 8px;
481
- top: 10px;
482
- overflow: hidden;
483
- cursor: pointer;
484
- font-size: 26px;
485
- display: inline-block;
486
- vertical-align: top;
487
- line-height: 1;
488
- }
489
- &-body {
490
- width: 100%;
491
- flex: 1;
492
- padding: 16px;
493
- font-size: var(--vxe-font-size);
494
- line-height: 1.5;
495
- word-wrap: break-word;
496
- position: relative;
497
- overflow: auto;
498
- }
499
- &-footer {
500
- position: relative;
501
- border-top: 1px solid var(--vxe-table-border-color);
502
- padding: 14px 16px;
503
- line-height: 1;
504
- }
505
- &-no-mask {
506
- pointer-events: none;
507
- .sh-drawer-drag {
508
- pointer-events: auto;
509
- }
510
- }
511
- &-drag {
512
- top: 0;
513
- height: 100%;
514
- width: 0;
515
- position: absolute;
516
- &-left {
517
- right: 0;
518
- }
519
- &-top,
520
- &-bottom {
521
- top: auto;
522
- width: 100%;
523
- height: 0;
524
- }
525
- &-top {
526
- bottom: 0;
527
- }
528
- &-bottom {
529
- top: 0;
530
- }
531
- &-move-trigger {
532
- width: 8px;
533
- height: 100px;
534
- line-height: 100px;
535
- position: absolute;
536
- top: 50%;
537
- background: rgb(243, 243, 243);
538
- transform: translate(-50%, -50%);
539
- border-radius: 4px;
540
- box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.2);
541
- cursor: col-resize;
542
- &-point {
543
- display: inline-block;
544
- width: 50%;
545
- transform: translateX(50%);
546
- i {
547
- display: block;
548
- border-bottom: 1px solid rgb(192, 192, 192);
549
- padding-bottom: 2px;
550
- }
551
- }
552
- }
553
- &-top &-move-trigger,
554
- &-bottom &-move-trigger {
555
- width: 100px;
556
- height: 8px;
557
- line-height: 8px;
558
- top: auto;
559
- left: 50%;
560
- cursor: row-resize;
561
- &-point {
562
- width: 100%;
563
- height: 50%;
564
- transform: translateY(-75%);
565
- text-align: center;
566
- i {
567
- display: inline-block;
568
- border-bottom: inherit;
569
- width: 1px;
570
- height: 100%;
571
- border-left: 1px solid rgb(192, 192, 192);
572
- padding-bottom: inherit;
573
- margin-left: 2px;
574
- }
575
- }
576
- }
577
- }
578
- }
579
- </style>
1
+ <template>
2
+ <teleport to="body" :disabled="!transfer">
3
+ <div class="sh-drawer-box">
4
+ <transition name="fade">
5
+ <div v-show="visible" v-if="mask" class="sh-drawer-mask" :class="{ 'sh-drawer-mask-inner': inner }" :style="maskStyle" @click="handleMask"></div>
6
+ </transition>
7
+ <div class="sh-drawer-wrap" :class="wrapClasses" @click="handleWrapClick">
8
+ <transition :name="transitionName">
9
+ <div v-show="visible" ref="drawerRef" class="sh-drawer" :class="classes" :style="mainStyles">
10
+ <div ref="drawerContent" class="sh-drawer-content" :class="{ 'sh-drawer-content-no-mask': !mask }">
11
+ <a v-if="closable" class="sh-drawer-close" @click="close">
12
+ <slot name="close">
13
+ <sh-icon type="ios-close"></sh-icon>
14
+ </slot>
15
+ </a>
16
+ <div v-if="showHead" class="sh-drawer-header">
17
+ <slot name="header">
18
+ <div class="sh-drawer-header-inner">{{ title }}</div>
19
+ </slot>
20
+ </div>
21
+ <div class="sh-drawer-body" :style="styles">
22
+ <slot v-if="modelValue || !destroyOnClose"></slot>
23
+ </div>
24
+ <div v-if="slots.footer" class="sh-drawer-footer">
25
+ <slot name="footer"></slot>
26
+ </div>
27
+ </div>
28
+ <div v-if="draggable" class="sh-drawer-drag" :class="'sh-drawer-drag-' + placement" @mousedown="handleTriggerMousedown">
29
+ <slot name="trigger">
30
+ <div class="sh-drawer-drag-move-trigger">
31
+ <div class="sh-drawer-drag-move-trigger-point"><i></i><i></i><i></i><i></i><i></i></div>
32
+ </div>
33
+ </slot>
34
+ </div>
35
+ </div>
36
+ </transition>
37
+ </div>
38
+ </div>
39
+ </teleport>
40
+ </template>
41
+
42
+ <script>
43
+ import { defineComponent, ref, watch, onMounted, onBeforeUnmount, getCurrentInstance, computed } from 'vue'
44
+ import useScrollbar from './scrollbar'
45
+ export default defineComponent({
46
+ name: 'ShDrawer',
47
+ props: {
48
+ modelValue: {
49
+ type: Boolean,
50
+ default: false
51
+ },
52
+ title: {
53
+ type: String
54
+ },
55
+ width: {
56
+ type: [Number, String],
57
+ default: 256
58
+ },
59
+ height: {
60
+ type: [Number, String],
61
+ default: 256
62
+ },
63
+ closable: {
64
+ type: Boolean,
65
+ default: true
66
+ },
67
+ maskClosable: {
68
+ type: Boolean,
69
+ default: true
70
+ },
71
+ mask: {
72
+ type: Boolean,
73
+ default: true
74
+ },
75
+ maskStyle: {
76
+ type: Object
77
+ },
78
+ styles: {
79
+ type: Object
80
+ },
81
+ scrollable: {
82
+ type: Boolean,
83
+ default: false
84
+ },
85
+ placement: {
86
+ type: String,
87
+ default: 'right' // 'left', 'right', 'top', 'bottom'
88
+ },
89
+ zIndex: {
90
+ type: Number,
91
+ default: 1000
92
+ },
93
+ transfer: {
94
+ type: Boolean
95
+ },
96
+ className: {
97
+ type: String
98
+ },
99
+ inner: {
100
+ type: Boolean,
101
+ default: false
102
+ },
103
+ draggable: {
104
+ type: Boolean,
105
+ default: false
106
+ },
107
+ destroyOnClose: {
108
+ type: Boolean,
109
+ default: false
110
+ },
111
+ beforeClose: Function
112
+ },
113
+ emits: ['update:modelValue', 'close', 'resize-width', 'visible-change', 'drag'],
114
+ setup(props, context) {
115
+ const vm = getCurrentInstance()
116
+ const { $vUtils } = vm.proxy
117
+ const { emit, slots } = context
118
+ const drawerRef = ref()
119
+ const drawerContent = ref()
120
+
121
+ const visible = ref(props.modelValue)
122
+ const wrapShow = ref(false)
123
+ const showHead = ref(true)
124
+ const canMove = ref(false)
125
+ const dragWidth = ref(props.width)
126
+ const dragHeight = ref(props.height)
127
+ const wrapperWidth = ref(props.width)
128
+ const wrapperHeight = ref(props.height)
129
+ const wrapperLeft = ref(0)
130
+ const wrapperTop = ref(0)
131
+ const minWidth = ref(256)
132
+ const minHeight = ref(256)
133
+ const id = ref($vUtils.randomStr(6))
134
+ const tableList = ref([])
135
+ const sliderList = ref([])
136
+ let timer = null
137
+
138
+ const isHorizontal = computed(() => ['left', 'right'].includes(props.placement))
139
+ const wrapClasses = computed(() => {
140
+ return {
141
+ 'sh-drawer-hidden': !wrapShow.value,
142
+ 'sh-drawer-no-mask': !props.mask,
143
+ 'sh-drawer-wrap-inner': props.inner,
144
+ 'sh-drawer-wrap-dragging': canMove.value,
145
+ [`${props.className}`]: !!props.className
146
+ }
147
+ })
148
+ const mainStyles = computed(() => {
149
+ let style = {}
150
+ if (isHorizontal.value) {
151
+ const width = parseInt(dragWidth.value)
152
+ const styleWidth = {
153
+ width: width <= 100 ? `${width}%` : `${width}px`
154
+ }
155
+ Object.assign(style, styleWidth)
156
+ } else {
157
+ const height = parseInt(dragHeight.value)
158
+ const styleHeight = {
159
+ height: height <= 100 ? `${height}%` : `${height}px`
160
+ }
161
+ Object.assign(style, styleHeight)
162
+ }
163
+ return style
164
+ })
165
+ const classes = computed(() => {
166
+ return {
167
+ [`sh-drawer-${props.placement}`]: true,
168
+ 'sh-drawer-no-header': !showHead.value,
169
+ 'sh-drawer-inner': props.inner
170
+ }
171
+ })
172
+ const transitionName = computed(() => {
173
+ if (isHorizontal.value) return `move-${props.placement}`
174
+ else if (props.placement === 'top') return 'move-up'
175
+ else return 'move-down'
176
+ })
177
+
178
+ const { addScrollEffect, removeScrollEffect } = useScrollbar(props)
179
+
180
+ const close = () => {
181
+ if (!props.beforeClose) {
182
+ return handleClose()
183
+ }
184
+ const before = props.beforeClose()
185
+ if (before && before.then) {
186
+ before.then(() => {
187
+ handleClose()
188
+ })
189
+ } else {
190
+ handleClose()
191
+ }
192
+ }
193
+ const handleClose = () => {
194
+ visible.value = false
195
+ emit('update:modelValue', false)
196
+ emit('close')
197
+ }
198
+ const handleMask = () => {
199
+ if (canMove.value) return
200
+ if (props.maskClosable && props.mask) {
201
+ close()
202
+ }
203
+ }
204
+ const handleWrapClick = event => {
205
+ const className = event.target.getAttribute('class')
206
+ if (className && className.indexOf('sh-drawer-wrap') > -1) handleMask()
207
+ }
208
+ const handleMousemove = event => {
209
+ if (!canMove.value || !props.draggable || !visible.value) return
210
+ // 更新容器距离
211
+ handleSetWrapper()
212
+ if (isHorizontal.value) {
213
+ const left = event.pageX - wrapperLeft.value
214
+ // 如果抽屉方向为右边,宽度计算需用容器宽度减去left
215
+ let width = props.placement === 'right' ? wrapperWidth.value - left : left
216
+ // 限定最小宽度
217
+ width = Math.max(width, parseFloat(minWidth.value))
218
+ event.atMin = width === parseFloat(minWidth.value)
219
+ // 如果当前width不大于100,视为百分比
220
+ if (width <= 100) width = (width / wrapperWidth.value) * 100
221
+ if (width >= window.innerWidth) width = window.innerWidth
222
+ dragWidth.value = width
223
+ emit('resize-width', parseInt(dragWidth.value))
224
+ emit('drag', 'dragging', parseInt(dragWidth.value))
225
+ } else {
226
+ const top = event.pageY - wrapperTop.value
227
+ // 如果抽屉方向为下面,宽度计算需用容器宽度减去left
228
+ let heigth = props.placement === 'bottom' ? wrapperHeight.value - top : top
229
+ // 限定最小高度
230
+ heigth = Math.max(heigth, parseFloat(minHeight.value))
231
+ event.atMin = heigth === parseFloat(minHeight.value)
232
+ // 如果当前heigth不大于100,视为百分比
233
+ if (heigth <= 100) heigth = (heigth / wrapperHeight.value) * 100
234
+ if (heigth >= window.innerHeight) heigth = window.innerHeight
235
+ dragHeight.value = heigth
236
+ emit('resize-width', parseInt(dragHeight.value))
237
+ emit('drag', 'dragging', parseInt(dragHeight.value))
238
+ }
239
+ }
240
+ const handleSetWrapper = () => {
241
+ const { width, height, left, top } = drawerRef.value.getBoundingClientRect()
242
+ if (isHorizontal.value) {
243
+ wrapperWidth.value = width
244
+ wrapperLeft.value = left
245
+ } else {
246
+ wrapperHeight.value = height
247
+ wrapperTop.value = top
248
+ }
249
+ }
250
+ const handleMouseup = () => {
251
+ if (!props.draggable || !visible.value) return
252
+ setTimeout(() => {
253
+ canMove.value = false
254
+ })
255
+ emit('drag', 'end')
256
+ }
257
+ const handleTriggerMousedown = () => {
258
+ canMove.value = true
259
+ // 防止鼠标选中抽屉中文字,造成拖动trigger触发浏览器原生拖动行为
260
+ window.getSelection().removeAllRanges()
261
+ emit('drag', 'start')
262
+ }
263
+ const addDrawer = () => {
264
+ const root = vm.root
265
+ if (!root.drawerList) root.drawerList = []
266
+ root.drawerList.push({
267
+ id: id.value,
268
+ drawer: vm
269
+ })
270
+ }
271
+ const removeDrawer = () => {
272
+ const root = vm.root
273
+ if (!root.drawerList) return
274
+ const index = root.drawerList.findIndex(item => item.id === id.value)
275
+ root.drawerList.splice(index, 1)
276
+ }
277
+
278
+ watch(
279
+ () => props.modelValue,
280
+ value => {
281
+ visible.value = value
282
+ }
283
+ )
284
+ watch(
285
+ () => visible.value,
286
+ val => {
287
+ if (val === false) {
288
+ timer = setTimeout(() => {
289
+ wrapShow.value = false
290
+ const drawers = vm.root.drawerList.map(item => item.drawer)
291
+ const otherDrawers = drawers.filter(item => item.id !== id.value)
292
+ const isScrollDrawer = otherDrawers.some(item => item.visible && !item.scrollable)
293
+ if (!isScrollDrawer) {
294
+ removeScrollEffect()
295
+ }
296
+ }, 300)
297
+ } else {
298
+ if (timer) clearTimeout(timer)
299
+ wrapShow.value = true
300
+ if (!props.scrollable) {
301
+ addScrollEffect()
302
+ }
303
+ }
304
+ tableList.value.forEach(item => {
305
+ item.table.handleOnVisibleChange(val)
306
+ })
307
+ sliderList.value.forEach(item => {
308
+ item.slider.handleOnVisibleChange(val)
309
+ })
310
+ emit('visible-change', val)
311
+ }
312
+ )
313
+ watch(
314
+ () => props.scrollable,
315
+ val => {
316
+ if (!val) {
317
+ addScrollEffect()
318
+ } else {
319
+ removeScrollEffect()
320
+ }
321
+ }
322
+ )
323
+ watch(
324
+ () => props.title,
325
+ val => {
326
+ if (slots.header === undefined) {
327
+ showHead.value = !!val
328
+ }
329
+ }
330
+ )
331
+ watch(
332
+ () => props.width,
333
+ val => {
334
+ dragWidth.value = val
335
+ }
336
+ )
337
+ watch(
338
+ () => props.height,
339
+ val => {
340
+ dragHeight.value = val
341
+ }
342
+ )
343
+ onMounted(() => {
344
+ if (visible.value) {
345
+ wrapShow.value = true
346
+ }
347
+ let isShowHead = true
348
+ if (slots.header === undefined && !props.title) {
349
+ isShowHead = false
350
+ }
351
+ showHead.value = isShowHead
352
+ addDrawer()
353
+ $vUtils.onListener(document, 'mousemove', handleMousemove)
354
+ $vUtils.onListener(document, 'mouseup', handleMouseup)
355
+ handleSetWrapper()
356
+ })
357
+ onBeforeUnmount(() => {
358
+ removeDrawer()
359
+ $vUtils.offListener(document, 'mousemove', handleMousemove)
360
+ $vUtils.offListener(document, 'mouseup', handleMouseup)
361
+ removeScrollEffect()
362
+ })
363
+
364
+ return {
365
+ slots,
366
+ visible,
367
+ wrapClasses,
368
+ transitionName,
369
+ classes,
370
+ mainStyles,
371
+ showHead,
372
+ drawerRef,
373
+ drawerContent,
374
+ close,
375
+ handleMask,
376
+ handleWrapClick,
377
+ handleTriggerMousedown
378
+ }
379
+ }
380
+ })
381
+ </script>
382
+
383
+ <style scoped lang="scss">
384
+ .sh-drawer {
385
+ width: auto;
386
+ height: 100%;
387
+ position: fixed;
388
+ top: 0;
389
+ &-inner {
390
+ position: absolute;
391
+ }
392
+ &-left {
393
+ left: 0;
394
+ }
395
+ &-right {
396
+ right: 0;
397
+ }
398
+ &-top,
399
+ &-bottom {
400
+ width: 100%;
401
+ height: auto;
402
+ top: auto;
403
+ }
404
+ &-bottom {
405
+ bottom: 0;
406
+ }
407
+ &-hidden {
408
+ display: none !important;
409
+ }
410
+ &-wrap {
411
+ position: fixed;
412
+ overflow: auto;
413
+ top: 0;
414
+ right: 0;
415
+ bottom: 0;
416
+ left: 0;
417
+ z-index: 1000;
418
+ -webkit-overflow-scrolling: touch;
419
+ outline: 0;
420
+ &-inner {
421
+ position: absolute;
422
+ overflow: hidden;
423
+ }
424
+ &-dragging {
425
+ user-select: none;
426
+ }
427
+ }
428
+ &-wrap * {
429
+ box-sizing: border-box;
430
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
431
+ }
432
+ &-mask {
433
+ position: fixed;
434
+ top: 0;
435
+ bottom: 0;
436
+ left: 0;
437
+ right: 0;
438
+ background-color: rgba(55, 55, 55, 0.6);
439
+ height: 100%;
440
+ z-index: 1000;
441
+ &-hidden {
442
+ display: none;
443
+ }
444
+ &-inner {
445
+ position: absolute;
446
+ }
447
+ }
448
+ &-content {
449
+ width: 100%;
450
+ height: 100%;
451
+ display: flex;
452
+ flex-direction: column;
453
+ background-color: var(--vxe-table-body-background-color);
454
+ border: 0;
455
+ background-clip: padding-box;
456
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
457
+ &-no-mask {
458
+ pointer-events: auto;
459
+ }
460
+ }
461
+ &-header {
462
+ border-bottom: 1px solid var(--vxe-table-border-color);
463
+ padding: 14px 16px;
464
+ line-height: 1;
465
+ &-inner {
466
+ display: inline-block;
467
+ width: 100%;
468
+ height: 20px;
469
+ line-height: 20px;
470
+ font-size: var(--vxe-font-size-medium);
471
+ font-weight: 500;
472
+ overflow: hidden;
473
+ text-overflow: ellipsis;
474
+ white-space: nowrap;
475
+ }
476
+ }
477
+ &-close {
478
+ z-index: 1;
479
+ position: absolute;
480
+ right: 8px;
481
+ top: 10px;
482
+ overflow: hidden;
483
+ cursor: pointer;
484
+ font-size: 26px;
485
+ display: inline-block;
486
+ vertical-align: top;
487
+ line-height: 1;
488
+ }
489
+ &-body {
490
+ width: 100%;
491
+ flex: 1;
492
+ padding: 16px;
493
+ font-size: var(--vxe-font-size);
494
+ line-height: 1.5;
495
+ word-wrap: break-word;
496
+ position: relative;
497
+ overflow: auto;
498
+ }
499
+ &-footer {
500
+ position: relative;
501
+ border-top: 1px solid var(--vxe-table-border-color);
502
+ padding: 14px 16px;
503
+ line-height: 1;
504
+ }
505
+ &-no-mask {
506
+ pointer-events: none;
507
+ .sh-drawer-drag {
508
+ pointer-events: auto;
509
+ }
510
+ }
511
+ &-drag {
512
+ top: 0;
513
+ height: 100%;
514
+ width: 0;
515
+ position: absolute;
516
+ &-left {
517
+ right: 0;
518
+ }
519
+ &-top,
520
+ &-bottom {
521
+ top: auto;
522
+ width: 100%;
523
+ height: 0;
524
+ }
525
+ &-top {
526
+ bottom: 0;
527
+ }
528
+ &-bottom {
529
+ top: 0;
530
+ }
531
+ &-move-trigger {
532
+ width: 8px;
533
+ height: 100px;
534
+ line-height: 100px;
535
+ position: absolute;
536
+ top: 50%;
537
+ background: rgb(243, 243, 243);
538
+ transform: translate(-50%, -50%);
539
+ border-radius: 4px;
540
+ box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.2);
541
+ cursor: col-resize;
542
+ &-point {
543
+ display: inline-block;
544
+ width: 50%;
545
+ transform: translateX(50%);
546
+ i {
547
+ display: block;
548
+ border-bottom: 1px solid rgb(192, 192, 192);
549
+ padding-bottom: 2px;
550
+ }
551
+ }
552
+ }
553
+ &-top &-move-trigger,
554
+ &-bottom &-move-trigger {
555
+ width: 100px;
556
+ height: 8px;
557
+ line-height: 8px;
558
+ top: auto;
559
+ left: 50%;
560
+ cursor: row-resize;
561
+ &-point {
562
+ width: 100%;
563
+ height: 50%;
564
+ transform: translateY(-75%);
565
+ text-align: center;
566
+ i {
567
+ display: inline-block;
568
+ border-bottom: inherit;
569
+ width: 1px;
570
+ height: 100%;
571
+ border-left: 1px solid rgb(192, 192, 192);
572
+ padding-bottom: inherit;
573
+ margin-left: 2px;
574
+ }
575
+ }
576
+ }
577
+ }
578
+ }
579
+ </style>