Files
EmailBill/Web/src/components/PopupContainer.vue
孙诚 c5c3b56200
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 24s
Docker Build & Deploy / Deploy to Production (push) Successful in 10s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
色彩调整
2026-01-13 17:00:44 +08:00

167 lines
3.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- eslint-disable vue/no-v-html -->
<template>
<van-popup
v-model:show="visible"
position="bottom"
:style="{ height: height }"
round
:closeable="closeable"
teleport="body"
>
<div class="popup-container">
<!-- 头部区域 -->
<div class="popup-header-fixed">
<!-- 标题行 (无子标题且有操作时使用 Grid 布局) -->
<div class="header-title-row" :class="{ 'has-actions': !subtitle && hasActions }">
<h3 class="popup-title">{{ title }}</h3>
<!-- 无子标题时操作按钮与标题同行 -->
<div v-if="!subtitle && hasActions" class="header-actions-inline">
<slot name="header-actions"></slot>
</div>
</div>
<!-- 子标题/统计信息 -->
<div v-if="subtitle" class="header-stats">
<span class="stats-text" v-html="subtitle" />
<!-- 额外操作插槽 -->
<slot v-if="hasActions" name="header-actions"></slot>
</div>
</div>
<!-- 内容区域可滚动 -->
<div class="popup-scroll-content">
<slot></slot>
</div>
<!-- 底部页脚固定不可滚动 -->
<div v-if="slots.footer" class="popup-footer-fixed">
<slot name="footer"></slot>
</div>
</div>
</van-popup>
</template>
<script setup>
import { computed, useSlots } from 'vue'
const props = defineProps({
modelValue: {
type: Boolean,
required: true,
},
title: {
type: String,
default: '',
},
subtitle: {
type: String,
default: '',
},
height: {
type: String,
default: '80%',
},
closeable: {
type: Boolean,
default: true,
},
})
const emit = defineEmits(['update:modelValue'])
const slots = useSlots()
// 双向绑定
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value),
})
// 判断是否有操作按钮
const hasActions = computed(() => !!slots['header-actions'])
</script>
<style scoped>
.popup-container {
height: 100%;
display: flex;
flex-direction: column;
}
.popup-header-fixed {
flex-shrink: 0;
padding: 16px;
background-color: var(--van-background-2);
border-bottom: 1px solid var(--van-border-color);
position: sticky;
top: 0;
z-index: 10;
}
.header-title-row.has-actions {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
}
.header-title-row.has-actions .popup-title {
grid-column: 2;
min-width: 0;
}
.header-actions-inline {
grid-column: 3;
justify-self: end;
display: flex;
align-items: center;
}
.popup-title {
font-size: 16px;
font-weight: 500;
margin: 0;
text-align: center;
color: var(--van-text-color);
/*超出长度*/
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.header-stats {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
gap: 12px;
margin-top: 12px;
}
.stats-text {
margin: 0;
font-size: 14px;
color: var(--van-text-color-2);
grid-column: 2;
text-align: center;
}
/* 按钮区域放在右侧 */
.header-stats :deep(> :last-child:not(.stats-text)) {
grid-column: 3;
justify-self: end;
}
.popup-scroll-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
.popup-footer-fixed {
flex-shrink: 0;
border-top: 1px solid var(--van-border-color);
background-color: var(--van-background-2);
padding: 12px 16px;
}
</style>