feat: 补齐权益使用成功的弹窗

This commit is contained in:
zoujing committed 2026-09-18 15:00:00 +08:00
1 parent a3698add2a
commit 2f240246bc
6 files changed
+160 -37

No files matched your search

+103 -27
View File
@@ -1,15 +1,24 @@
<script setup>
/**
* 使用确认弹窗(需求 §7.4)
* 使用弹窗(需求 §7.4)· 三态共用一个遮罩与卡片
* confirm 确认使用 → success 使用成功(回带权益信息 + 本次使用时间)→ fail 使用失败(仅一行说明)
* 点已领取的权益 → 弹窗确认 → 仅记录一次使用,权益保持可用(可多次使用,不失效)
*/
import { computed } from "vue";
import { BENEFIT_TYPE_LABEL } from "@/constant";
import { dateRangeText, priceText, rateText } from "@/utils";
import { dateRangeText, dotDateTime, priceText, rateText } from "@/utils";
const props = defineProps({
visible: { type: Boolean, default: false },
benefit: { type: Object, default: null },
/** confirm 确认使用 | success 使用成功 | fail 使用失败 */
state: { type: String, default: "confirm" },
/** 本次使用时间(接口 used_at,RFC3339) */
usedAt: { type: String, default: "" },
/** 失败原因(接口 message;缺省走统一兜底文案) */
failText: { type: String, default: "" },
/** 提交中:确认按钮防重复点击 */
submitting: { type: Boolean, default: false },
});
const emit = defineEmits(["close", "confirm"]);
@@ -42,13 +51,21 @@ const ruleText = computed(
"该权益不绑定具体商品,可多次使用。本次操作仅记录一次使用,不会使权益失效。"
);
/** 弹窗内四行对照:label + 值 */
/** 确认弹窗四行对照:label + 值 */
const rows = computed(() => [
{ label: "优惠价格", value: priceLine.value, accent: true },
{ label: "适用规格", value: b.value.price?.spec || "—" },
{ label: "适用门店", value: b.value.merchant_name || b.value.scope_desc || "—" },
{ label: "有效期", value: validLine.value || "—" },
]);
/** 成功弹窗信息块:权益名 + 四行 */
const successRows = computed(() => [
{ label: "优惠价格", value: priceLine.value || "—" },
{ label: "适用规格", value: b.value.price?.spec || "—" },
{ label: "适用门店", value: b.value.merchant_name || b.value.scope_desc || "—" },
{ label: "本次使用", value: dotDateTime(props.usedAt) || "—" },
]);
</script>
<template>
@@ -57,37 +74,96 @@ const rows = computed(() => [
class="fixed inset-0 z-[200] flex items-center justify-center px-[34px] bg-[rgba(3,20,15,0.52)] backdrop-blur-[7px]"
@click="emit('close')"
>
<view class="w-full bg-white rounded-dialog pt-6 px-[22px] pb-[18px] text-center shadow-dialog" @click.stop>
<view class="w-[52px] h-[52px] rounded-full mx-auto flex items-center justify-center grad-brand shadow-glowbrand">
<AppIcon name="check" tone="white" :size="22" />
</view>
<view class="mt-[14px] text-title font-semibold text-ink">确认使用该权益?</view>
<view class="mt-[14px] p-3 text-left rounded-[10px] border-[0.5px] border-line2 grad-brand-soft">
<view class="text-[13.5px] font-semibold text-ink">{{ typeLabel }}</view>
<view v-for="row in rows" :key="row.label" class="flex justify-between gap-3 mt-[5px] text-[11.5px] text-ink2">
<text>{{ row.label }}</text>
<text class="text-right" :class="row.accent ? 'font-semibold text-accent' : ''">{{ row.value }}</text>
<view
class="w-full bg-white rounded-dialog shadow-dialog text-center"
:class="state === 'fail' ? 'pt-6 px-5 pb-[18px]' : 'pt-6 px-[22px] pb-[18px]'"
@click.stop
>
<!-- 一 · 确认使用 -->
<template v-if="state === 'confirm'">
<view class="w-[52px] h-[52px] rounded-full mx-auto flex items-center justify-center grad-brand shadow-glowbrand">
<AppIcon name="check" tone="white" :size="22" />
</view>
</view>
<view class="mt-3 text-[11px] leading-[1.7] text-ink3 text-left">{{ ruleText }}</view>
<view class="mt-[14px] text-title font-semibold text-ink">确认使用该权益?</view>
<view class="flex gap-[10px] mt-[18px]">
<view class="mt-[14px] p-3 text-left rounded-[10px] border-[0.5px] border-line2 grad-brand-soft">
<view class="text-[13.5px] font-semibold text-ink">{{ typeLabel }}</view>
<view v-for="row in rows" :key="row.label" class="flex justify-between gap-3 mt-[5px] text-[11.5px] text-ink2">
<text>{{ row.label }}</text>
<text class="text-right" :class="row.accent ? 'font-semibold text-accent' : ''">{{ row.value }}</text>
</view>
</view>
<view class="mt-3 text-[11px] leading-[1.7] text-ink3 text-left">{{ ruleText }}</view>
<view class="flex gap-[10px] mt-[18px]">
<view
class="flex-1 h-11 rounded-[16px] flex items-center justify-center text-body bg-alt text-ink2 font-normal"
@click="emit('close')"
>
再想想
</view>
<view
class="flex-1 h-11 rounded-[16px] flex items-center justify-center text-body font-semibold grad-brand text-white shadow-glowbrand"
@click="emit('confirm')"
>
{{ submitting ? "使用中…" : "确认使用" }}
</view>
</view>
</template>
<!-- 二 · 使用成功 -->
<template v-else-if="state === 'success'">
<view
class="flex-1 h-11 rounded-[16px] flex items-center justify-center text-body bg-alt text-ink2 font-normal"
@click="emit('close')"
class="w-[60px] h-[60px] rounded-full mx-auto flex items-center justify-center grad-brand shadow-[0_0_0_9px_rgba(0,181,120,0.075),0_12px_28px_rgba(0,181,120,0.3)]"
>
再想想
<AppIcon name="check" tone="white" :size="27" />
</view>
<view
class="flex-1 h-11 rounded-[16px] flex items-center justify-center text-body font-semibold grad-brand shadow-glowbrand"
@click="emit('confirm')"
>
确认使用
<view class="mt-4 text-[19px] font-semibold text-ink">使用成功</view>
<view class="mt-[7px] text-[12px] leading-[1.65] text-ink2">该权益仍可继续使用</view>
<view class="mt-4 p-[13px] pb-3 text-left rounded-[10px] border-[0.5px] border-line2 grad-brand-soft">
<view class="text-[13.5px] font-semibold text-ink">{{ typeLabel }}</view>
<view
v-for="row in successRows"
:key="row.label"
class="flex justify-between gap-3 mt-[7px] text-[11.5px] text-ink2"
>
<text>{{ row.label }}</text>
<text class="text-right font-semibold text-ink">{{ row.value }}</text>
</view>
</view>
</view>
<view class="flex mt-4">
<view
class="flex-1 h-[46px] rounded-[16px] flex items-center justify-center text-body font-semibold grad-brand text-white shadow-glowbrand"
@click="emit('close')"
>
知道了
</view>
</view>
</template>
<!-- 三 · 使用失败 -->
<template v-else>
<view class="w-11 h-11 rounded-full mx-auto flex items-center justify-center bg-[rgba(229,72,77,0.09)]">
<AppIcon name="close" tone="danger" :size="20" />
</view>
<view class="mt-3 text-[15.5px] font-semibold text-ink">使用失败</view>
<view class="mt-[7px] text-[11.5px] leading-[1.7] text-ink3">{{ failText || "网络异常,请稍后重试" }}</view>
<view class="flex mt-4">
<view
class="flex-1 h-[42px] rounded-[16px] flex items-center justify-center text-[14px] font-medium bg-alt text-ink2"
@click="emit('close')"
>
知道了
</view>
</view>
</template>
</view>
</view>
</template>