feat:权益卡片的调整

This commit is contained in:
zoujing
2026-09-20 11:44:02 +08:00
parent f499bf00dd
commit 681ba3d8f1
3 changed files with 27 additions and 14 deletions

View File

@@ -3,13 +3,12 @@
* 权益卡(全站唯一组件 · 4 处复用)
* 使用位置:权益中心 / 我的权益 / 详情页「到店权益」
* 四行固定顺序:类型 / 价格 / 规格·适用 / 有效期·名额
* 价格两形态互斥:金额型 = 优惠价大字 + 划线原价 + 右端折扣标;
* 折扣型price.rate= 「门市价」小字 + 折扣大字,不再出划线原价与折扣标
* 「进入商家」入口在权益中心与我的权益都出现(详情页本就在该商家内,不加)。
* 价格两形态互斥:金额型 = 优惠价大字 + 划线原价 + 右端折扣标;折扣型price.rate= 折扣大字。
* ①行类型短名2 字,`BENEFIT_TYPE_SHORT` 右端商家名胶囊(`merchant_name`,超 8 字截断),详情页不加胶囊
*/
import { computed } from "vue";
import { BENEFIT_STATUS, BENEFIT_TYPE_ICON, BENEFIT_TYPE_LABEL } from "@/constant";
import { basisText, discountLabel, dotDate, rateText, yuanText } from "@/utils";
import { BENEFIT_STATUS, BENEFIT_TYPE_ICON, BENEFIT_TYPE_SHORT } from "@/constant";
import { discountLabel, dotDate, rateText, yuanText } from "@/utils";
import { goDetail } from "@/utils/nav";
const props = defineProps({
@@ -30,14 +29,13 @@ const isClaimed = computed(() => status.value === BENEFIT_STATUS.CLAIMED);
/** 权益类型键:详情页走接口的 section_key权益中心仍是本地 type两者取其一 */
const typeKey = computed(() => b.value.section_key || b.value.type || "");
const typeLabel = computed(() => BENEFIT_TYPE_LABEL[typeKey.value] || "权益");
const typeLabel = computed(() => BENEFIT_TYPE_SHORT[typeKey.value] || "权益");
const typeIcon = computed(() => BENEFIT_TYPE_ICON[typeKey.value] || "gift");
const deal = computed(() => yuanText(b.value.price?.deal));
const original = computed(() => yuanText(b.value.price?.original));
const pct = computed(() => discountLabel(b.value.price?.deal, b.value.price?.original));
const rate = computed(() => rateText(b.value.price));
const basis = computed(() => basisText(b.value.price));
const isRate = computed(() => !!rate.value);
const spec = computed(() => b.value.price?.spec || "");
const hasPrice = computed(() => isRate.value || !!deal.value);
@@ -109,6 +107,13 @@ const goStateCls = computed(() =>
);
const goIconTone = computed(() => (isOff.value ? "ink3" : "accentDeep"));
/** 「进入商家」胶囊文案:取商家上架名称,超 8 字截断加省略号 */
const goLabel = computed(() => {
const name = String(b.value.merchant_name || "").trim();
if (!name) return "进入商家";
return name.length > 8 ? `${name.slice(0, 8)}` : name;
});
/** 跳该权益所属商家详情 */
const onGoMerchant = () => {
if (b.value.merchant_id) goDetail(b.value.merchant_id);
@@ -126,15 +131,15 @@ const onTap = () => {
<!-- 信息区四行固定顺序 -->
<view class="flex-1 min-w-0 rounded-l-card px-[14px] pt-[13px] pb-3 flex flex-col" :class="sideStateCls">
<!-- 类型权益中心 / 我的权益在行右端带进入商家入口 -->
<view class="flex items-center gap-[6px] text-[13px] font-semibold whitespace-nowrap" :class="kindStateCls">
<view class="flex items-center gap-2 text-[13px] font-semibold whitespace-nowrap" :class="kindStateCls">
<view class="w-[21px] h-[21px] rounded-full shrink-0 flex items-center justify-center" :class="kindIconCls">
<AppIcon :name="typeIcon" tone="white" :size="12.5" />
</view>
<text>{{ typeLabel }}</text>
<view class="min-w-0 flex-1 line-clamp-1">{{ typeLabel }}</view>
<view v-if="mode !== 'detail'"
class="ml-auto shrink-0 h-5 px-2 rounded-full flex items-center gap-[2px] text-hint font-semibold border-[0.5px]"
class="ml-auto shrink-0 -mr-0.5 h-5 pl-2 pr-1.5 rounded-full flex items-center gap-[2px] text-hint font-semibold border-[0.5px]"
:class="goStateCls" @click.stop="onGoMerchant">
<text>进入商家</text>
<view class="min-w-0 line-clamp-1">{{ goLabel }}</view>
<AppIcon name="chev" :tone="goIconTone" :size="11" />
</view>
</view>
@@ -142,7 +147,6 @@ const onTap = () => {
<!-- 价格金额型 = 优惠价 + 划线原价 + 折扣标折扣型 = 门市价 + 折扣大字 -->
<view v-if="hasPrice" class="flex items-baseline gap-[6px] mt-2 leading-none whitespace-nowrap">
<template v-if="isRate">
<text v-if="basis" class="text-[11.5px] font-medium" :class="wasCls">{{ basis }}</text>
<text class="text-display font-extrabold tracking-[-1px]" :class="priceNumCls">{{ rate }}</text>
</template>
<template v-else>

View File

@@ -6,7 +6,7 @@
*/
import { computed } from "vue";
import { BENEFIT_TYPE_LABEL } from "@/constant";
import { basisText, dateRangeText, dotDateTime, rateText, yuanText } from "@/utils";
import { dateRangeText, dotDateTime, rateText, yuanText } from "@/utils";
const props = defineProps({
visible: { type: Boolean, default: false },
@@ -30,7 +30,7 @@ const typeLabel = computed(() => BENEFIT_TYPE_LABEL[typeKey.value] || "权益");
const priceLine = computed(() => {
const rate = rateText(b.value.price);
if (rate) return `${basisText(b.value.price)}${rate}`;
if (rate) return rate;
const deal = yuanText(b.value.price?.deal);
const original = yuanText(b.value.price?.original);
if (!deal) return b.value.scope_desc || "";

View File

@@ -47,6 +47,15 @@ export const BENEFIT_TYPE_LABEL = {
general: "通用权益",
};
/** 权益类型 → 卡片类型行短名权益卡①行空间有限2 字上限;图标已承担类型辨识) */
export const BENEFIT_TYPE_SHORT = {
scenic: "景区",
stay: "住宿",
food: "餐饮",
specialty: "特产",
general: "通用",
};
/** 权益类型 → 卡片类型行图标 */
export const BENEFIT_TYPE_ICON = {
scenic: "peak",