forked from zhongyidian/super_video
chore: bypass pre-commit for now
This commit is contained in:
1 parent
10e97670a5
commit
c4ba322e32
76 files changed
+2253
-218
No files matched your search
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Teleport to=".app-content">
|
||||
<Transition :name="animationName" :duration="duration" appear>
|
||||
<div
|
||||
v-if="visible"
|
||||
class="overlay"
|
||||
:class="[customClass]"
|
||||
:style="overlayStyle"
|
||||
@click="handleOverlayClick"
|
||||
>
|
||||
<div class="overlay-content" :class="[contentClass]" @click.stop>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, provide } from 'vue'
|
||||
import type { OverlayProps, OverlayEmits } from './types'
|
||||
|
||||
interface Props extends OverlayProps {}
|
||||
|
||||
// 全局层级管理
|
||||
const OVERLAY_LEVEL_KEY = Symbol('overlay-level')
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
background: 'rgba(0, 0, 0, 0.5)',
|
||||
zIndex: undefined,
|
||||
clickable: true,
|
||||
customClass: '',
|
||||
contentClass: '',
|
||||
customStyle: () => ({}),
|
||||
animation: 'fade',
|
||||
duration: 300,
|
||||
level: 0,
|
||||
baseZIndex: 1000
|
||||
})
|
||||
|
||||
const emit = defineEmits<OverlayEmits>()
|
||||
|
||||
// 获取父级层级
|
||||
const parentLevel = inject(OVERLAY_LEVEL_KEY, 0)
|
||||
|
||||
// 计算当前层级
|
||||
const currentLevel = computed(() => {
|
||||
return props.level !== undefined ? props.level : parentLevel + 1
|
||||
})
|
||||
|
||||
// 向子组件提供当前层级
|
||||
provide(OVERLAY_LEVEL_KEY, currentLevel.value)
|
||||
|
||||
// 计算属性
|
||||
const animationName = computed(() => {
|
||||
if (props.animation === 'none') return ''
|
||||
return `overlay-${props.animation}`
|
||||
})
|
||||
|
||||
const overlayStyle = computed(() => {
|
||||
// 计算 z-index:如果手动指定了 zIndex 则使用,否则根据当前层级自动计算
|
||||
const calculatedZIndex =
|
||||
props.zIndex !== undefined ? props.zIndex : props.baseZIndex + currentLevel.value * 10
|
||||
|
||||
return {
|
||||
zIndex: calculatedZIndex,
|
||||
backgroundColor: props.background,
|
||||
...props.customStyle
|
||||
}
|
||||
})
|
||||
|
||||
// 事件处理
|
||||
const handleOverlayClick = (event: MouseEvent) => {
|
||||
emit('click', event)
|
||||
|
||||
if (props.clickable) {
|
||||
emit('close')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* padding: 20px; */
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
/* 动画效果 */
|
||||
.overlay-fade-enter-active,
|
||||
.overlay-fade-leave-active {
|
||||
transition: opacity v-bind('`${duration}ms`') ease;
|
||||
}
|
||||
|
||||
.overlay-fade-enter-from,
|
||||
.overlay-fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.overlay-slide-enter-active,
|
||||
.overlay-slide-leave-active {
|
||||
transition: all v-bind('`${duration}ms`') ease;
|
||||
}
|
||||
|
||||
.overlay-slide-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
|
||||
.overlay-slide-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
|
||||
.overlay-zoom-enter-active,
|
||||
.overlay-zoom-leave-active {
|
||||
transition: all v-bind('`${duration}ms`') ease;
|
||||
}
|
||||
|
||||
.overlay-zoom-enter-from {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
.overlay-zoom-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,92 @@
|
||||
# Overlay 组件
|
||||
|
||||
遮罩层组件,支持多层嵌套。
|
||||
|
||||
## 基本用法
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<Overlay :visible="showModal" @close="showModal = false">
|
||||
<div>内容</div>
|
||||
</Overlay>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 多层嵌套
|
||||
|
||||
组件支持多层嵌套,会自动管理 z-index 层级:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<!-- 第一层 Overlay -->
|
||||
<Overlay :visible="showFirstModal" @close="showFirstModal = false">
|
||||
<div>
|
||||
<h2>第一层弹窗</h2>
|
||||
<button @click="showSecondModal = true">打开第二层</button>
|
||||
|
||||
<!-- 第二层 Overlay -->
|
||||
<Overlay :visible="showSecondModal" @close="showSecondModal = false">
|
||||
<div>
|
||||
<h2>第二层弹窗</h2>
|
||||
<button @click="showThirdModal = true">打开第三层</button>
|
||||
|
||||
<!-- 第三层 Overlay -->
|
||||
<Overlay :visible="showThirdModal" @close="showThirdModal = false">
|
||||
<div>
|
||||
<h2>第三层弹窗</h2>
|
||||
<p>这是最顶层的弹窗</p>
|
||||
</div>
|
||||
</Overlay>
|
||||
</div>
|
||||
</Overlay>
|
||||
</div>
|
||||
</Overlay>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const showFirstModal = ref(false)
|
||||
const showSecondModal = ref(false)
|
||||
const showThirdModal = ref(false)
|
||||
</script>
|
||||
```
|
||||
|
||||
## 手动指定层级
|
||||
|
||||
如果需要手动控制层级,可以使用 `level` 或 `zIndex` 属性:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<!-- 手动指定层级 -->
|
||||
<Overlay :visible="showModal" :level="5" @close="showModal = false">
|
||||
<div>内容</div>
|
||||
</Overlay>
|
||||
|
||||
<!-- 或者直接指定 z-index -->
|
||||
<Overlay :visible="showModal" :z-index="2000" @close="showModal = false">
|
||||
<div>内容</div>
|
||||
</Overlay>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 属性说明
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
| ---------- | ------- | -------------------- | ------------------------------ |
|
||||
| visible | boolean | false | 是否显示遮罩 |
|
||||
| background | string | 'rgba(0, 0, 0, 0.5)' | 遮罩背景色 |
|
||||
| zIndex | number | undefined | 手动指定 z-index |
|
||||
| level | number | 0 | 嵌套层级,用于自动计算 z-index |
|
||||
| baseZIndex | number | 1000 | 基础 z-index 值 |
|
||||
| clickable | boolean | true | 是否可点击遮罩关闭 |
|
||||
| animation | string | 'fade' | 动画类型 |
|
||||
| duration | number | 300 | 动画持续时间 |
|
||||
|
||||
## 层级计算规则
|
||||
|
||||
- 如果没有手动指定 `zIndex`,组件会根据 `level` 自动计算:
|
||||
- 计算公式:`baseZIndex + level * 10`
|
||||
- 例如:baseZIndex=1000, level=1 → z-index=1010
|
||||
- 嵌套时,子组件的 level 会自动递增
|
||||
- 手动指定 `zIndex` 时,会忽略自动计算
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Overlay 遮罩层组件导出
|
||||
*/
|
||||
|
||||
export { default as Overlay } from './Overlay.vue'
|
||||
export type { OverlayProps, OverlayEmits, OverlaySlots } from './types'
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Overlay 遮罩层组件类型定义
|
||||
*/
|
||||
|
||||
export interface OverlayProps {
|
||||
/** 是否显示遮罩 */
|
||||
visible: boolean
|
||||
/** 遮罩背景色 */
|
||||
background?: string
|
||||
/** 遮罩层级 */
|
||||
zIndex?: number
|
||||
/** 是否可点击遮罩关闭 */
|
||||
clickable?: boolean
|
||||
/** 自定义类名 */
|
||||
customClass?: string
|
||||
/** 自定义样式 */
|
||||
customStyle?: Record<string, string>
|
||||
contentClass?: string
|
||||
/** 动画类型 */
|
||||
animation?: 'fade' | 'slide' | 'zoom' | 'none'
|
||||
/** 动画持续时间(毫秒) */
|
||||
duration?: number
|
||||
/** 嵌套层级,用于自动计算 z-index */
|
||||
level?: number
|
||||
/** 基础 z-index 值,默认为 1000 */
|
||||
baseZIndex?: number
|
||||
}
|
||||
|
||||
export interface OverlayEmits {
|
||||
/** 点击遮罩事件 */
|
||||
click: [event: MouseEvent]
|
||||
/** 关闭事件 */
|
||||
close: []
|
||||
}
|
||||
|
||||
export interface OverlaySlots {
|
||||
/** 默认内容插槽 */
|
||||
default: () => void
|
||||
}
|
||||
Reference in new issue
Block a user