mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-12 03:01:12 +00:00
perf: 优化抽屉窗口
This commit is contained in:
parent
710609e98b
commit
d5a75f887d
@ -3,24 +3,28 @@
|
||||
ref="modal"
|
||||
v-model="show"
|
||||
:closable="escClosable"
|
||||
:mask="!isFullscreen"
|
||||
:mask="finalMask"
|
||||
:mask-closable="maskClosable"
|
||||
:footer-hide="true"
|
||||
:transition-names="transitionNames"
|
||||
:beforeClose="beforeClose"
|
||||
:class-name="className"
|
||||
fullscreen>
|
||||
<div v-if="isFullscreen" class="overlay-body">
|
||||
<slot/>
|
||||
</div>
|
||||
:fullscreen="true"
|
||||
:class-name="finalClassName"
|
||||
:transition-names="finalTransitionNames"
|
||||
:before-close="beforeClose">
|
||||
<DrawerOverlayView
|
||||
v-else
|
||||
:placement="placementName"
|
||||
:size="size"
|
||||
:minSize="minSize"
|
||||
:resize="resize"
|
||||
:placement="finalPlacement"
|
||||
:size="finalSize"
|
||||
:minSize="finalMinSize"
|
||||
:resize="finalResize"
|
||||
@on-close="close">
|
||||
<slot/>
|
||||
<template v-if="$slots.title" #title>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
<template v-if="$slots.more" #more>
|
||||
<slot name="more"></slot>
|
||||
</template>
|
||||
<template #default>
|
||||
<slot></slot>
|
||||
</template>
|
||||
</DrawerOverlayView>
|
||||
</Modal>
|
||||
</template>
|
||||
@ -36,46 +40,55 @@ export default {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示遮罩,留空自动判断
|
||||
mask: {
|
||||
default: null
|
||||
},
|
||||
// 允许点击遮罩关闭
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 允许按下 ESC 键关闭
|
||||
escClosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否全屏,留空自动判断屏幕宽度小于 768px 时自动变为全屏模式
|
||||
fullscreen: {
|
||||
default: null
|
||||
},
|
||||
// 抽屉放置位置,可选 'right' 或 'bottom'
|
||||
// 在全屏模式下无效,强制为 'bottom'
|
||||
placement: {
|
||||
validator(value) {
|
||||
return ['right', 'bottom'].includes(value)
|
||||
},
|
||||
default: 'bottom'
|
||||
},
|
||||
forceFullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
transitions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 抽屉的大小,可以是百分比或像素值,默认 100%
|
||||
// 在全屏模式下无效
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: "100%"
|
||||
},
|
||||
// 抽屉的最小大小,单位为像素,默认 300px
|
||||
// 在全屏模式下无效
|
||||
minSize: {
|
||||
type: Number,
|
||||
default: 300
|
||||
},
|
||||
// 允许调整大小,默认为 true
|
||||
// 在全屏模式下无效
|
||||
resize: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
drawerClass: {
|
||||
type: String
|
||||
},
|
||||
modalClass: {
|
||||
// 自定义类名
|
||||
className: {
|
||||
type: String
|
||||
},
|
||||
// 拦截关闭事件的函数
|
||||
beforeClose: Function
|
||||
},
|
||||
data() {
|
||||
@ -92,34 +105,55 @@ export default {
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isFullscreen() {
|
||||
return this.forceFullscreen || (this.windowWidth < 500 && this.placement != 'bottom')
|
||||
},
|
||||
placementName() {
|
||||
return this.isFullscreen ? 'bottom' : this.placement
|
||||
},
|
||||
transitionNames() {
|
||||
if (this.transitions.length > 0) {
|
||||
return this.transitions
|
||||
finalFullscreen() {
|
||||
if (typeof this.fullscreen === 'boolean') {
|
||||
return this.fullscreen
|
||||
}
|
||||
return [`drawer-slide-${this.placementName}`, '']
|
||||
return this.windowWidth < 768
|
||||
},
|
||||
className() {
|
||||
const array = []
|
||||
if (this.isFullscreen) {
|
||||
array.push("common-drawer-modal")
|
||||
if (this.modalClass) {
|
||||
array.push(this.modalClass)
|
||||
}
|
||||
} else {
|
||||
array.push("common-drawer-overlay")
|
||||
if (this.drawerClass) {
|
||||
array.push(this.drawerClass)
|
||||
}
|
||||
array.push(this.placementName)
|
||||
finalMask() {
|
||||
if (typeof this.mask === 'boolean') {
|
||||
return this.mask
|
||||
}
|
||||
return !this.finalFullscreen
|
||||
},
|
||||
finalClassName() {
|
||||
const array = [
|
||||
"common-drawer",
|
||||
`drawer-${this.finalPlacement}`
|
||||
];
|
||||
if (this.finalFullscreen) {
|
||||
array.push("drawer-fullscreen")
|
||||
}
|
||||
if (this.className) {
|
||||
array.push(this.className)
|
||||
}
|
||||
return array.join(" ");
|
||||
},
|
||||
finalTransitionNames() {
|
||||
return [`drawer-animation-${this.finalPlacement}`, 'drawer-animation-fade']
|
||||
},
|
||||
finalPlacement() {
|
||||
return this.finalFullscreen ? 'bottom' : this.placement
|
||||
},
|
||||
finalSize() {
|
||||
if (this.finalFullscreen) {
|
||||
return "100%"
|
||||
}
|
||||
return this.size
|
||||
},
|
||||
finalMinSize() {
|
||||
if (this.finalFullscreen) {
|
||||
return 0
|
||||
}
|
||||
return this.minSize
|
||||
},
|
||||
finalResize() {
|
||||
if (this.finalFullscreen) {
|
||||
return false
|
||||
}
|
||||
return this.resize
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<div ref="body" class="overlay-body" :style="bodyStyle">
|
||||
<div class="overlay-close">
|
||||
<a href="javascript:void(0)" @click.stop="onClose">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" fill="none" role="img" class="icon fill-current">
|
||||
<path d="M8.28596 6.51819C7.7978 6.03003 7.00634 6.03003 6.51819 6.51819C6.03003 7.00634 6.03003 7.7978 6.51819 8.28596L11.2322 13L6.51819 17.714C6.03003 18.2022 6.03003 18.9937 6.51819 19.4818C7.00634 19.97 7.7978 19.97 8.28596 19.4818L13 14.7678L17.714 19.4818C18.2022 19.97 18.9937 19.97 19.4818 19.4818C19.97 18.9937 19.97 18.2022 19.4818 17.714L14.7678 13L19.4818 8.28596C19.97 7.7978 19.97 7.00634 19.4818 6.51819C18.9937 6.03003 18.2022 6.03003 17.714 6.51819L13 11.2322L8.28596 6.51819Z" fill="currentColor"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="overlay-close" @click.stop="onClose">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26">
|
||||
<path d="M8.28596 6.51819C7.7978 6.03003 7.00634 6.03003 6.51819 6.51819C6.03003 7.00634 6.03003 7.7978 6.51819 8.28596L11.2322 13L6.51819 17.714C6.03003 18.2022 6.03003 18.9937 6.51819 19.4818C7.00634 19.97 7.7978 19.97 8.28596 19.4818L13 14.7678L17.714 19.4818C18.2022 19.97 18.9937 19.97 19.4818 19.4818C19.97 18.9937 19.97 18.2022 19.4818 17.714L14.7678 13L19.4818 8.28596C19.97 7.7978 19.97 7.00634 19.4818 6.51819C18.9937 6.03003 18.2022 6.03003 17.714 6.51819L13 11.2322L8.28596 6.51819Z" fill="currentColor"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<ResizeLine
|
||||
v-if="resize"
|
||||
@ -19,6 +17,14 @@
|
||||
@on-change="onChangeResize"/>
|
||||
<div class="overlay-content">
|
||||
<div class="overlay-content-status"></div>
|
||||
<div v-if="$slots.title || $slots.more" class="overlay-content-header">
|
||||
<div class="overlay-content-header-title">
|
||||
<slot name="title"/>
|
||||
</div>
|
||||
<div class="overlay-content-header-more">
|
||||
<slot name="more"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overlay-content-body"><slot/></div>
|
||||
<div class="overlay-content-navigation"></div>
|
||||
</div>
|
||||
|
||||
312
resources/assets/sass/components/drawer-overlay.scss
vendored
312
resources/assets/sass/components/drawer-overlay.scss
vendored
@ -1,36 +1,30 @@
|
||||
body {
|
||||
.ivu-modal-wrap {
|
||||
&.common-drawer-overlay {
|
||||
.ivu-modal {
|
||||
.ivu-modal-content {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.common-drawer {
|
||||
--margin-top: 8px;
|
||||
--margin-left: 8px;
|
||||
--margin-right: 8px;
|
||||
--margin-bottom: 8px;
|
||||
--close-top: 16px;
|
||||
--close-right: 16px;
|
||||
--close-size: 40px;
|
||||
--close-color: #606266;
|
||||
--title-color: #303133;
|
||||
--content-bg-color: #ffffff;
|
||||
--border-radius: 16px;
|
||||
|
||||
&.file-drawer {
|
||||
--margin-top: 40px;
|
||||
--margin-left: 0px;
|
||||
--margin-right: 0px;
|
||||
--margin-bottom: 0px;
|
||||
--close-top: 0px;
|
||||
--close-right: 0px;
|
||||
--close-color: #ffffff;
|
||||
--border-radius: 16px 16px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.common-drawer-overlay {
|
||||
.ivu-modal {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.ivu-modal-content {
|
||||
background: transparent;
|
||||
|
||||
.ivu-modal-close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ivu-modal-body {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-content: flex-end;
|
||||
}
|
||||
}
|
||||
&.approve-drawer {
|
||||
--close-top: 28px;
|
||||
--close-right: 20px;
|
||||
}
|
||||
|
||||
.overlay-body {
|
||||
@ -41,154 +35,204 @@ body {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.overlay-close {
|
||||
flex-shrink: 0;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: var(--close-top);
|
||||
right: var(--close-right);
|
||||
margin-top: var(--status-bar-height);
|
||||
width: var(--close-size);
|
||||
height: var(--close-size);
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
padding-top: var(--status-bar-height);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
color: #fff;
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px
|
||||
}
|
||||
> svg {
|
||||
color: var(--close-color);
|
||||
opacity: 0.8;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> svg {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
|
||||
> svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
opacity: 1;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-resize {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
margin-bottom: -5px;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: var(--margin-left);
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
width: 5px;
|
||||
z-index: 2;
|
||||
|
||||
&.bottom {
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: var(--margin-top);
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border-radius: 18px 18px 0 0;
|
||||
z-index: 1;
|
||||
background-color: var(--content-bg-color);
|
||||
margin: var(--margin-top) var(--margin-right) var(--margin-bottom) var(--margin-left);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.overlay-content-status {
|
||||
&-status {
|
||||
flex-shrink: 0;
|
||||
height: var(--status-bar-height);
|
||||
}
|
||||
|
||||
.overlay-content-body {
|
||||
&-header {
|
||||
flex-shrink: 0;
|
||||
padding: calc(var(--close-top) - var(--margin-top)) calc(var(--close-size) + var(--close-right)) calc(var(--close-top) - var(--margin-top)) 30px;
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 40px;
|
||||
gap: 12px;
|
||||
|
||||
&-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
color: var(--title-color);
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&-more {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-body {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.overlay-content-navigation {
|
||||
&-navigation {
|
||||
flex-shrink: 0;
|
||||
height: var(--navigation-bar-height);
|
||||
}
|
||||
|
||||
.ivu-modal-wrap-apply {
|
||||
.ivu-modal-wrap-apply-title {
|
||||
border-top-left-radius: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-fullscreen {
|
||||
--margin-top: 0px;
|
||||
--margin-left: 0px;
|
||||
--margin-right: 0px;
|
||||
--margin-bottom: 0px;
|
||||
--close-top: 8px;
|
||||
--close-right: 8px;
|
||||
--border-radius: 0;
|
||||
|
||||
&.approve-drawer {
|
||||
--close-top: 20px;
|
||||
--close-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
.ivu-modal-wrap {
|
||||
&.common-drawer {
|
||||
overflow: hidden;
|
||||
|
||||
.ivu-modal {
|
||||
.ivu-modal-content {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.ivu-modal-close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.right {
|
||||
.ivu-modal {
|
||||
.ivu-modal-content {
|
||||
.ivu-modal-body {
|
||||
flex-direction: row;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-body {
|
||||
flex-direction: row;
|
||||
|
||||
.overlay-close {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.overlay-resize {
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
margin-right: -5px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
border-radius: 18px 0 0 18px;
|
||||
}
|
||||
body.dark-mode-reverse {
|
||||
.common-drawer {
|
||||
&.file-drawer {
|
||||
--close-color: #000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-animation {
|
||||
&-fade {
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
transition: opacity .5s cubic-bezier(0.32, 0.72, 0, 1);
|
||||
}
|
||||
|
||||
.common-drawer-modal {
|
||||
.ivu-modal-fullscreen {
|
||||
background-color: #ffffff;
|
||||
&-enter,
|
||||
&-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
&-right {
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
touch-action: none;
|
||||
will-change: transform, opacity;
|
||||
transition: transform .2s cubic-bezier(0.32, 0.72, 0, 1), opacity .2s cubic-bezier(0.32, 0.72, 0, 1);
|
||||
}
|
||||
|
||||
&-enter,
|
||||
&-leave-to {
|
||||
transform: translate(15%, 0) scale(0.98);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
touch-action: none;
|
||||
will-change: transform, opacity;
|
||||
transition: transform .2s cubic-bezier(0.32, 0.72, 0, 1), opacity .2s cubic-bezier(0.32, 0.72, 0, 1);
|
||||
}
|
||||
|
||||
&-enter,
|
||||
&-leave-to {
|
||||
transform: translate(0, 15%) scale(0.98);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-slide-bottom-enter-active {
|
||||
transition: all .2s ease;
|
||||
}
|
||||
|
||||
.drawer-slide-bottom-leave-active {
|
||||
transition: all .2s ease;
|
||||
}
|
||||
|
||||
.drawer-slide-bottom-enter,
|
||||
.drawer-slide-bottom-leave-to {
|
||||
transform: translate(0, 15%) scale(0.98);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.drawer-slide-right-enter-active {
|
||||
transition: all .2s ease;
|
||||
}
|
||||
|
||||
.drawer-slide-right-leave-active {
|
||||
transition: all .2s ease;
|
||||
}
|
||||
|
||||
.drawer-slide-right-enter,
|
||||
.drawer-slide-right-leave-to {
|
||||
transform: translate(15%, 0) scale(0.98);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
25
resources/assets/sass/pages/common.scss
vendored
25
resources/assets/sass/pages/common.scss
vendored
@ -824,31 +824,6 @@ body {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/*全局 ivu-modal-wrap*/
|
||||
body {
|
||||
.ivu-modal-wrap {
|
||||
&.common-drawer-overlay {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&.common-drawer-modal {
|
||||
.ivu-modal-body {
|
||||
padding: 0 !important;
|
||||
|
||||
.dialog-wrapper {
|
||||
&.inde-list {
|
||||
border-radius: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ivu-modal-close {
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*全局返回按钮*/
|
||||
.common-nav-back{
|
||||
cursor: pointer;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user