Files
EmailBill/Web/src/components/PopupContainer.vue
孙诚 319f8f7d7b
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Failing after 1m10s
Docker Build & Deploy / Deploy to Production (push) Has been skipped
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
大量的代码格式化
2026-01-16 11:15:44 +08:00

169 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" />
</div>
</div>
<!-- 子标题/统计信息 -->
<div v-if="subtitle" class="header-stats">
<span class="stats-text" v-html="subtitle" />
<!-- 额外操作插槽 -->
<slot v-if="hasActions" name="header-actions" />
</div>
</div>
<!-- 内容区域可滚动 -->
<div class="popup-scroll-content">
<slot />
</div>
<!-- 底部页脚固定不可滚动 -->
<div v-if="slots.footer" class="popup-footer-fixed">
<slot name="footer" />
</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>