Files
YGChatCS/pages/order/components/RefundPopup/index.vue
2025-08-07 20:03:03 +08:00

217 lines
5.0 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.

<template>
<uni-popup ref="popupRef" type="center" @maskClick="handleClose">
<view class="refund-popup">
<!-- 头部卡通形象 -->
<image
src="@/static/dh.png"
class="refund-popup__avatar"
mode="widthFix"
/>
<!-- 内容区域 -->
<view class="refund-popup__content">
<!-- 主标题 -->
<view class="refund-popup__title">{{ currentTitle }}</view>
<!-- 金额显示 -->
<view class="refund-popup__amount" v-if="showAmount">
<text class="amount-symbol">¥</text>
<text class="amount-value">{{ refundAmount }}</text>
<text class="amount-unit"></text>
</view>
<view class="refund-popup__amount-label" v-if="showAmount"
>可退金额</view
>
<!-- 描述信息 -->
<view class="refund-popup__description" v-if="currentDescription">
{{ currentDescription }}
</view>
<!-- 退款政策详情 -->
<view class="refund-popup__policy" v-if="showPolicy">
<view class="policy-title">退订政策</view>
<view class="policy-list">
<view
class="policy-item"
v-for="(rule, index) in currentRules"
:key="index"
>
{{ rule }}
</view>
</view>
</view>
</view>
<!-- 按钮区域 -->
<view class="refund-popup__actions">
<view class="action-btn secondary-btn" @click="handlePolicyClick">
{{ leftButtonText }}
</view>
<view class="action-btn primary-btn" @click="handleConfirmClick">
{{ rightButtonText }}
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import { ref, computed, watch, shallowRef } from "vue";
// Props定义
const props = defineProps({
// 弹窗显示状态
modelValue: {
type: Boolean,
default: false,
},
// 退款类型
refundType: {
type: String,
default: "no_refund",
validator: (value) =>
["no_refund", "all_refund", "anytime_refund"].includes(value),
},
// 可退金额
refundAmount: {
type: Number,
default: 0,
},
// 退款规则列表
refundRules: {
type: Array,
default: () => [],
},
// 自定义标题
title: {
type: String,
default: "",
},
// 自定义描述
description: {
type: String,
default: "",
},
});
// Events定义
const emit = defineEmits([
"update:modelValue",
"policy-click",
"confirm-click",
"close",
]);
// 弹窗引用
const popupRef = ref(null);
// 退款场景配置使用shallowRef优化性能
const refundScenarios = shallowRef({
no_refund: {
title: "您在入住日期12小时以内申请退款不可退款,如有疑问请咨询客服",
description: "",
showAmount: false,
showPolicy: false,
leftButton: "退订政策",
rightButton: "我知道了",
rules: [],
},
all_refund: {
title: "您在入住日期24小时内申请退款可退还100%金额",
description: "",
showAmount: true,
showPolicy: true,
leftButton: "退订政策",
rightButton: "点击退款",
rules: [],
},
anytime_refund: {
title: "该商品未使用随时可退",
description: "",
showAmount: true,
showPolicy: false,
leftButton: "退订政策",
rightButton: "点击退款",
rules: [],
},
});
// 计算属性
const currentScenario = computed(
() =>
refundScenarios.value[props.refundType] || refundScenarios.value.no_refund
);
const currentTitle = computed(() => props.title || currentScenario.value.title);
const currentDescription = computed(
() => props.description || currentScenario.value.description
);
const currentRules = computed(() => {
if (props.refundRules.length) {
return props.refundRules;
}
return currentScenario.value.rules;
});
const showAmount = computed(
() => currentScenario.value.showAmount && props.refundAmount > 0
);
const showPolicy = computed(
() => currentScenario.value.showPolicy && currentRules.value.length > 0
);
const leftButtonText = computed(() => currentScenario.value.leftButton);
const rightButtonText = computed(() => currentScenario.value.rightButton);
// 方法定义
const show = () => popupRef.value.open();
const hide = () => popupRef.value.close();
// 监听modelValue变化
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
show();
} else {
hide();
}
},
{ immediate: true }
);
// 监听退款金额变化,进行数据验证
watch(
() => props.refundAmount,
(newVal) => {
if (newVal < 0) {
console.warn("RefundPopup: 退款金额不能为负数");
}
},
{ immediate: true }
);
const handleClose = () => {
emit("update:modelValue", false);
emit("close");
};
const handlePolicyClick = () => {
emit("policy-click");
};
const handleConfirmClick = () => {
emit("confirm-click");
handleClose();
};
</script>
<style lang="scss" scoped>
@import "./styles/index.scss";
</style>