refactor: 整理组件目录结构
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Failing after 4m47s
Docker Build & Deploy / Deploy to Production (push) Has been skipped
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Failing after 4m47s
Docker Build & Deploy / Deploy to Production (push) Has been skipped
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s
- TransactionDetail, CategoryBillPopup 移入 Transaction/ - BudgetTypeTabs 移入 Budget/ - GlassBottomNav, ModernEmpty 移入 Global/ - Icon, IconSelector, ClassifySelector 等 8 个通用组件移入 Common/ - 更新所有相关引用路径
This commit is contained in:
180
Web/src/components/Common/PopupContainerV2.vue
Normal file
180
Web/src/components/Common/PopupContainerV2.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<!--
|
||||
PopupContainer V2 - 通用底部弹窗组件(采用 TransactionDetailSheet 样式风格)
|
||||
|
||||
## 与 V1 的区别
|
||||
- V1 (PopupContainer.vue): 使用 Vant 主题变量,标准化布局,默认高度 80%
|
||||
- V2 (PopupContainerV2.vue): 使用 Inter 字体,16px 圆角,纯白背景,更现代化的视觉风格
|
||||
|
||||
## 基础用法
|
||||
<PopupContainerV2 v-model:show="show" title="标题">
|
||||
<div class="content">内容区域</div>
|
||||
<template #footer>
|
||||
<van-button type="primary">确定</van-button>
|
||||
</template>
|
||||
</PopupContainerV2>
|
||||
|
||||
## Props
|
||||
- show (Boolean, required): 控制弹窗显示/隐藏
|
||||
- title (String, required): 标题文本
|
||||
- height (String, default: 'auto'): 弹窗高度,支持 'auto', '80%', '500px' 等
|
||||
- maxHeight (String, default: '85%'): 最大高度
|
||||
|
||||
## Slots
|
||||
- default: 可滚动的内容区域(不提供默认 padding,由使用方控制)
|
||||
- footer: 固定底部区域(操作按钮等)
|
||||
|
||||
## Events
|
||||
- update:show: 弹窗显示/隐藏状态变更
|
||||
-->
|
||||
<template>
|
||||
<van-popup
|
||||
v-model:show="visible"
|
||||
position="bottom"
|
||||
:style="{
|
||||
height: height === 'auto' ? maxHeight : height,
|
||||
borderTopLeftRadius: '16px',
|
||||
borderTopRightRadius: '16px'
|
||||
}"
|
||||
teleport="body"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="popup-container-v2">
|
||||
<!-- 固定头部 -->
|
||||
<div class="popup-header">
|
||||
<h3 class="popup-title">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<van-icon
|
||||
name="cross"
|
||||
class="popup-close"
|
||||
@click="handleClose"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 可滚动内容区域 -->
|
||||
<div class="popup-content">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<!-- 固定底部 -->
|
||||
<div
|
||||
v-if="hasFooter"
|
||||
class="popup-footer"
|
||||
>
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, useSlots } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: '85%'
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:show'])
|
||||
|
||||
const slots = useSlots()
|
||||
|
||||
// 双向绑定
|
||||
const visible = computed({
|
||||
get: () => props.show,
|
||||
set: (value) => emit('update:show', value)
|
||||
})
|
||||
|
||||
// 判断是否有 footer 插槽
|
||||
const hasFooter = computed(() => !!slots.footer)
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.popup-container-v2 {
|
||||
background: #ffffff;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// 固定头部
|
||||
.popup-header {
|
||||
flex-shrink: 0;
|
||||
padding: 24px;
|
||||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.popup-title {
|
||||
font-family: Inter, sans-serif;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #09090b;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 24px;
|
||||
color: #71717a;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 可滚动内容区域
|
||||
.popup-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
// 不提供默认 padding,由使用方控制
|
||||
}
|
||||
|
||||
// 固定底部
|
||||
.popup-footer {
|
||||
flex-shrink: 0;
|
||||
padding: 24px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
// 暗色模式
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.popup-container-v2 {
|
||||
background: #18181b;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
.popup-title {
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
color: #a1a1aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user