feat(project): 优惠券列表门店标签显示具体门店名称
All checks were successful
Build and Deploy TenantUI / build-and-deploy (push) Successful in 50s

This commit is contained in:
2026-02-28 13:27:59 +08:00
parent c868268bbb
commit 50274f2361
5 changed files with 64 additions and 6 deletions

View File

@@ -17,6 +17,7 @@ import {
resolveCouponFaceConditionText,
resolveCouponFaceValueText,
resolveCouponRuleText,
resolveCouponStoreTagText,
resolveCouponTypeClass,
resolveCouponTypeLabel,
resolveCouponValidityText,
@@ -25,6 +26,7 @@ import {
defineProps<{
item: CouponCardViewModel;
storeNameMap: Record<string, string>;
}>();
const emit = defineEmits<{
@@ -83,12 +85,17 @@ function resolveClaimedText(item: CouponCardViewModel) {
</div>
<div class="mcp-bottom">
<span
class="mcp-status-tag"
:class="COUPON_STATUS_TAG_CLASS_MAP[item.displayStatus]"
>
{{ COUPON_STATUS_TEXT_MAP[item.displayStatus] }}
</span>
<div class="mcp-meta-tags">
<span
class="mcp-status-tag"
:class="COUPON_STATUS_TAG_CLASS_MAP[item.displayStatus]"
>
{{ COUPON_STATUS_TEXT_MAP[item.displayStatus] }}
</span>
<span class="mcp-store-tag">
{{ resolveCouponStoreTagText(item, storeNameMap) }}
</span>
</div>
<div class="mcp-actions">
<template v-if="item.displayStatus === 'ended'">

View File

@@ -113,6 +113,30 @@ export function resolveCouponRuleText(item: CouponCardViewModel) {
return `${limitText} | ${channelText}`;
}
/** 门店范围标签文本。 */
export function resolveCouponStoreTagText(
item: CouponCardViewModel,
storeNameMap: Record<string, string>,
) {
if (item.storeScopeMode === 'all') {
return '全部门店';
}
const storeNames = item.storeIds
.map((storeId) => storeNameMap[storeId])
.filter((name) => typeof name === 'string' && name.length > 0);
if (storeNames.length <= 0) {
return '指定门店';
}
if (storeNames.length === 1) {
return storeNames[0];
}
return `${storeNames[0]}${storeNames.length}`;
}
/** 渠道文本。 */
export function resolveChannelsText(channels: MarketingCouponChannel[]) {
const normalized = channels.toSorted();

View File

@@ -47,6 +47,9 @@ export function useMarketingCouponPage() {
value: item.id,
})),
);
const storeNameMap = computed<Record<string, string>>(() =>
Object.fromEntries(stores.value.map((item) => [item.id, item.name])),
);
const hasStore = computed(() => !!selectedStoreId.value);
@@ -192,6 +195,7 @@ export function useMarketingCouponPage() {
setStatusFilter,
setTypeFilter,
stats,
storeNameMap,
storeOptions,
stores,
submitDrawer,

View File

@@ -62,6 +62,7 @@ const {
setStatusFilter,
setTypeFilter,
stats,
storeNameMap,
storeOptions,
submitDrawer,
total,
@@ -139,6 +140,7 @@ function onTypeFilterChange(value: unknown) {
v-for="item in rows"
:key="item.id"
:item="item"
:store-name-map="storeNameMap"
@edit="(row) => openEditDrawer(row.id)"
@view="(row) => openEditDrawer(row.id)"
@enable="enableCoupon"

View File

@@ -173,6 +173,12 @@
margin-top: 10px;
}
.mcp-meta-tags {
display: inline-flex;
gap: 6px;
align-items: center;
}
.mcp-status-tag {
display: inline-flex;
align-items: center;
@@ -201,4 +207,19 @@
color: #92400e;
background: #fef3c7;
}
.mcp-store-tag {
display: inline-flex;
align-items: center;
max-width: 180px;
height: 22px;
padding: 0 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
color: #475569;
background: #f1f5f9;
border-radius: 999px;
}
}