diff --git a/scripts/build-icons.mjs b/scripts/build-icons.mjs index 3a53209..91cbad0 100644 --- a/scripts/build-icons.mjs +++ b/scripts/build-icons.mjs @@ -55,6 +55,14 @@ const STROKE_ICONS = { food: '', bed: '', peak: '', + table: + '', + hotspring: + '', + fuel: + '', + cart: + '', people: '', }; @@ -90,6 +98,10 @@ const MATRIX = { food: ["brandDeep", "accent", "white", "brand"], bed: ["accent", "brand", "white", "brandDeep"], peak: ["accent", "brand", "white"], + table: ["white", "accent", "brandDeep"], + hotspring: ["white", "accent", "brandDeep"], + fuel: ["white", "accent", "brandDeep"], + cart: ["white", "accent", "brandDeep"], people: ["ink3", "brand", "white", "brandDeep"], wx: ["white"], }; diff --git a/src/components/BenefitCard/index.vue b/src/components/BenefitCard/index.vue index ab507c7..35b3d02 100644 --- a/src/components/BenefitCard/index.vue +++ b/src/components/BenefitCard/index.vue @@ -4,10 +4,11 @@ * 使用位置:权益中心 / 我的权益 / 详情页「到店权益」 * 四行固定顺序:类型 / 价格 / 规格·适用 / 有效期·名额 * 价格两形态互斥:金额型 = 优惠价大字 + 划线原价 + 右端折扣标;折扣型(price.rate)= 折扣大字。 - * ①行=类型短名(2 字,`BENEFIT_TYPE_SHORT`)+ 右端商家名胶囊(`merchant_name`,超 8 字截断),详情页不加胶囊。 + * ①行=类型名(权益 `type_label` → 商家 `type_label` → 板块 2 字短名)+ 类型图标(`type_icon` → `type_label` 反查 → 板块图标) + * + 右端商家名胶囊(`merchant_name`,超 8 字截断),详情页不加胶囊。 */ import { computed } from "vue"; -import { BENEFIT_STATUS, BENEFIT_TYPE_ICON, BENEFIT_TYPE_SHORT } from "@/constant"; +import { BENEFIT_ICON_ALIAS, BENEFIT_LABEL_ICON, BENEFIT_STATUS, BENEFIT_TYPE_ICON, BENEFIT_TYPE_SHORT } from "@/constant"; import { discountLabel, dotDate, rateText, yuanText } from "@/utils"; import { goDetail } from "@/utils/nav"; @@ -15,6 +16,8 @@ const props = defineProps({ benefit: { type: Object, required: true }, /** center 权益中心 | mine 我的权益 | detail 详情页到店权益 */ mode: { type: String, default: "center" }, + /** 所属商家的 type_label(详情页由 merchant 传入,优先于板块短名) */ + typeLabel: { type: String, default: "" }, }); const emit = defineEmits(["action", "tap"]); @@ -29,14 +32,39 @@ 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_SHORT[typeKey.value] || "权益"); -const typeIcon = computed(() => BENEFIT_TYPE_ICON[typeKey.value] || "gift"); +/** + * ①行类型名:权益自带 type_label 最优先 —— 同一商家下权益类型可能不同 + * (如云从朵花既有「住宿」又有「温泉」),不能只跟商家的分类走; + * 其次回落商家 type_label(详情页传入)、板块 2 字短名。 + */ +const typeLabel = computed(() => { + const own = String(b.value.type_label || "").trim(); + if (own) return own; + const fromMerchant = String(props.typeLabel || "").trim(); + return fromMerchant || BENEFIT_TYPE_SHORT[typeKey.value] || "权益"; +}); +/** ①行图标:type_icon → 权益 type_label → 商家 type_label → 板块兜底 */ +const typeIcon = computed(() => { + const byIcon = BENEFIT_ICON_ALIAS[String(b.value.type_icon || "").trim().toLowerCase()]; + if (byIcon) return byIcon; + for (const label of [b.value.type_label, props.typeLabel]) { + const hit = BENEFIT_LABEL_ICON[String(label || "").trim()]; + if (hit) return hit; + } + return 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 isRate = computed(() => !!rate.value); +/** 折扣型文案偏长(如「每升优惠0.20元」)时降字号,避免溢出信息区 */ +const rateCls = computed(() => + rate.value.length > 5 + ? "text-[17px] font-bold tracking-[-0.3px]" + : "text-display font-extrabold tracking-[-1px]" +); const spec = computed(() => b.value.price?.spec || ""); const hasPrice = computed(() => isRate.value || !!deal.value); @@ -147,7 +175,7 @@ const onTap = () => {