refactor: 优化促销商品列表和电子卡券逻辑

- 更新促销商品列表组件,简化商品详情页跳转逻辑
- 移除不必要的礼品卡相关状态管理,确保电子卡券逻辑的清晰性
- 调整 utils/goodsType.js 中的卡密处理函数,专注于当前订单的卡密履约行
- 优化订单详情页的卡密展示逻辑,确保信息准确性
This commit is contained in:
田香琪
2026-08-05 13:48:21 +08:00
parent 370c63afcd
commit eb40916cf7
4 changed files with 165 additions and 193 deletions

View File

@@ -1,148 +1,145 @@
<template> <template>
<div> <div>
<div v-for="(item, index) in res" :key="index" class="goods-row" @click="navigateToDetailPage(item)"> <div v-for="(item, index) in res" :key="index" class="goods-row" @click="onItemClick(item)">
<div class="flex goods-col"> <div class="flex goods-col">
<div class="goods-img"> <div class="goods-img">
<u-image width="230rpx" mode="aspectFit" border-radius='16' height="230rpx" :src="item.goodsImage || item.thumbnail"> <u-image width="230rpx" mode="aspectFit" border-radius='16' height="230rpx" :src="item.goodsImage || item.thumbnail">
<template #loading><u-loading-icon></u-loading-icon></template> <template #loading><u-loading-icon></u-loading-icon></template>
</u-image> </u-image>
</div> </div>
<div class="goods-detail"> <div class="goods-detail">
<div class="title clamp3">{{ item.goodsName }}</div> <div class="title clamp3">{{ item.goodsName }}</div>
<div class='flex flex-a-c flex-j-sb'> <div class='flex flex-a-c flex-j-sb'>
<view class="price-box"> <view class="price-box">
<!-- 秒杀 / 拼团 --> <!-- 秒杀 / 拼团 -->
<div class="price" v-if="!type && item.price!=undefined"> <div class="price" v-if="!type && item.price!=undefined">
¥<span class="price-int">{{ goodsFormatPrice(item.price )[0] }} </span>.{{ ¥<span class="price-int">{{ goodsFormatPrice(item.price )[0] }} </span>.{{
goodsFormatPrice(item.price )[1] goodsFormatPrice(item.price )[1]
}} }}
</div> </div>
<!-- 砍价 --> <!-- 砍价 -->
<div class="price" v-if="type && item.purchasePrice!=undefined"> <div class="price" v-if="type && item.purchasePrice!=undefined">
最低 最低
¥<span class="price-int">{{ goodsFormatPrice(item.purchasePrice )[0] }} </span>.{{ ¥<span class="price-int">{{ goodsFormatPrice(item.purchasePrice )[0] }} </span>.{{
goodsFormatPrice(item.purchasePrice )[1] goodsFormatPrice(item.purchasePrice )[1]
}} }}
</div> </div>
<!-- 兜底策略如果金额是0 --> <!-- 兜底策略如果金额是0 -->
<div class="price" v-if="!item.price && !type"> <div class="price" v-if="!item.price && !type">
¥<span class="price-int">0 </span>.00 ¥<span class="price-int">0 </span>.00
</div> </div>
</view> </view>
<div> <div>
<image class="buy" src="/static/buy.png"></image> <image class="buy" src="/static/buy.png"></image>
</div> </div>
</div> </div>
<div class='count-config' v-if="!type"> <div class='count-config' v-if="!type">
<text class="count-config-text">即将恢复{{ item.originalPrice}}</text> <text class="count-config-text">即将恢复{{ item.originalPrice}}</text>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useGoodsListCommon } from './common' import { goodsFormatPrice } from '@/utils/filters.js'
import { goodsFormatPrice } from '@/utils/filters.js'
const props = withDefaults(defineProps<{
const { navigateToDetailPage } = useGoodsListCommon() res?: any[]
type?: string | null
const props = withDefaults(defineProps<{ }>(), {
res?: any[] res: () => [],
type?: string | null type: ''
}>(), { })
res: () => [],
type: '' // 促销列表跳转:拼团/秒杀 PromotionGoods 用 skuId砍价走活动详情
}) function onItemClick(item: any) {
if (props.type == 'kanJia') {
// 跳转到商品详情(覆盖公共方法,增加砍价跳转) uni.navigateTo({
const navigateToDetailPageOverride = (item: any) => { url: `/pages/promotion/bargain/detail?id=${item.id}`,
if(props.type == 'kanJia'){ })
uni.navigateTo({ return
url: `/pages/promotion/bargain/detail?id=${item.id}`, }
}) const skuId = item.skuId || item.id
return uni.navigateTo({
} url: `/pages/product/goods?id=${skuId}&goodsId=${item.goodsId}`,
navigateToDetailPage({ })
id: item.skuId, }
goodsId: item.goodsId, </script>
})
} <style lang='scss' scoped>
</script> .buy {
width: 152rpx;
<style lang='scss' scoped> height: 108rpx;
.buy { }
width: 152rpx; .flex-j-sb {
height: 108rpx; width: 100%;
} }
.flex-j-sb { .goods-row {
width: 100%; background: #fff;
} padding: 16rpx;
.goods-row { >.goods-col {
background: #fff; display: flex;
padding: 16rpx; >.goods-img {
>.goods-col { overflow: hidden;
display: flex; flex: 4;
>.goods-img { }
overflow: hidden; >.goods-detail {
flex: 4; flex: 7;
} }
>.goods-detail { }
flex: 7; }
} .goods-detail {
} margin: 0 20rpx;
} >.title {
.goods-detail { font-size: $font-base;
margin: 0 20rpx; color: $font-color-dark;
>.title { line-height: 1.5;
font-size: $font-base; height: 86rpx;
color: $font-color-dark; padding: 10rpx 0 0;
line-height: 1.5; display: -webkit-box;
height: 86rpx; -webkit-box-orient: vertical;
padding: 10rpx 0 0; -webkit-line-clamp: 2;
display: -webkit-box; overflow: hidden;
-webkit-box-orient: vertical; }
-webkit-line-clamp: 2;
overflow: hidden; .count-config {
} padding: 5rpx 0;
color: #666;
.count-config { display: flex;
padding: 5rpx 0; font-size: 24rpx;
color: #666; letter-spacing:2rpx;
display: flex; padding-left: 10rpx;
font-size: 24rpx;
letter-spacing:2rpx; .count-config-text {
padding-left: 10rpx; font-size: 24rpx;
}
.count-config-text { }
font-size: 24rpx;
}
}
}
.price-box {
} margin-top: 10rpx;
display: flex;
.price-box { align-items: center;
margin-top: 10rpx; justify-content: space-between;
display: flex; padding-right: 10rpx;
align-items: center; font-size: 24rpx;
justify-content: space-between; color: $font-color-light;
padding-right: 10rpx;
font-size: 24rpx; >.price {
color: $font-color-light; font-size: 26rpx;
line-height: 1;
>.price { color: $main-color;
font-size: 26rpx; font-weight: bold;
line-height: 1;
color: $main-color; .price-int {
font-weight: bold; font-size: 48rpx;
}
.price-int { }
font-size: 48rpx; }
} </style>
}
}
</style>

View File

@@ -16,7 +16,7 @@
class="card-key-fulfill-block" class="card-key-fulfill-block"
> >
<view v-if="cardKeyFulfillLines.length > 1" class="card-key-fulfill-title"> <view v-if="cardKeyFulfillLines.length > 1" class="card-key-fulfill-title">
{{ line.goodsName || (line.isGift ? '满赠电子卡券' : '电子卡券') }} {{ line.goodsName || '电子卡券' }}
</view> </view>
<view <view
class="card-key-item" class="card-key-item"
@@ -51,7 +51,7 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* 电子卡券卡密二级页(原型 P-09 * 电子卡券卡密二级页(原型 P-09
* 数据来源GET /buyer/order/order/{orderSn} → orderItems[].cardKeys(明文 cardSecret * 仅展示当前 orderSn 对应订单的 orderItems[].cardKeys;满赠赠品请进赠品订单查看
*/ */
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app' import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app'
@@ -69,27 +69,23 @@ const orderSn = ref('')
const loading = ref(true) const loading = ref(true)
const errorMessage = ref('') const errorMessage = ref('')
const orderItems = ref<any[]>([]) const orderItems = ref<any[]>([])
const giftECouponOrders = ref<any[]>([])
const orderStatus = ref('') const orderStatus = ref('')
const cardKeyFulfillLines = computed(() => const cardKeyFulfillLines = computed(() =>
collectCardKeyFulfillLines(orderItems.value, giftECouponOrders.value).filter( collectCardKeyFulfillLines(orderItems.value).filter(
(line) => line.status === CARD_KEY_FULFILL_STATUS.DELIVERED && line.cardKeys.length (line) => line.status === CARD_KEY_FULFILL_STATUS.DELIVERED && line.cardKeys.length
) )
) )
const cardKeyRows = computed(() => const cardKeyRows = computed(() => flattenOrderCardKeys(orderItems.value))
flattenOrderCardKeys(orderItems.value, false, giftECouponOrders.value)
)
const emptyMessage = computed(() => { const emptyMessage = computed(() => {
if (orderStatus.value === 'CANCELLED') { if (orderStatus.value === 'CANCELLED') {
return '订单已关闭,暂无卡密信息' return '订单已关闭,暂无卡密信息'
} }
const pending = collectCardKeyFulfillLines( const pending = collectCardKeyFulfillLines(orderItems.value).find(
orderItems.value, (line) => line.status !== CARD_KEY_FULFILL_STATUS.DELIVERED
giftECouponOrders.value )
).find((line) => line.status !== CARD_KEY_FULFILL_STATUS.DELIVERED)
if (pending) { if (pending) {
return resolveCardKeyFulfillMessage(pending) return resolveCardKeyFulfillMessage(pending)
} }
@@ -126,15 +122,11 @@ function loadData(fromPullDown = false) {
return return
} }
const result = res.data.result const result = res.data.result
const isEcoupon = isECouponOrder(result?.order?.orderType) if (!isECouponOrder(result?.order?.orderType)) {
const hasGiftEcoupon =
Array.isArray(result?.giftECouponOrders) && result.giftECouponOrders.length > 0
if (!isEcoupon && !hasGiftEcoupon) {
errorMessage.value = '该订单没有电子卡券卡密' errorMessage.value = '该订单没有电子卡券卡密'
return return
} }
orderItems.value = result.orderItems || [] orderItems.value = result.orderItems || []
giftECouponOrders.value = result.giftECouponOrders || []
orderStatus.value = result.order?.orderStatus || '' orderStatus.value = result.order?.orderStatus || ''
}) })
.catch(() => { .catch(() => {

View File

@@ -312,19 +312,16 @@ const cancelList = ref<any[]>([])
const rogShow = ref(false) const rogShow = ref(false)
const reason = ref('') const reason = ref('')
const orderPackage = ref<any>('') const orderPackage = ref<any>('')
const giftECouponOrders = ref<any[]>([]) // orderType=E_COUPON无物流/核销码;卡密见 cardKeyDetail仅本单 orderItems不含满赠子单
// orderType=E_COUPON无物流/核销码,卡密见 cardKeyDetailAPI-B-01 orderItems[].cardKeys
const isECouponOrder = computed(() => checkECouponOrder(order.value?.orderType)) const isECouponOrder = computed(() => checkECouponOrder(order.value?.orderType))
const isNonPhysicalOrder = computed(() => checkNonPhysicalOrder(order.value?.orderType)) const isNonPhysicalOrder = computed(() => checkNonPhysicalOrder(order.value?.orderType))
const ecouponCardKeyDelivered = computed(() => const ecouponCardKeyDelivered = computed(() =>
orderHasCardKeyContent(orderGoodsList.value, giftECouponOrders.value) orderHasCardKeyContent(orderGoodsList.value)
) )
const ecouponPendingMessage = computed(() => { const ecouponPendingMessage = computed(() => {
const pending = collectCardKeyFulfillLines( const pending = collectCardKeyFulfillLines(orderGoodsList.value).find(
orderGoodsList.value, (line) => line.status !== CARD_KEY_FULFILL_STATUS.DELIVERED
giftECouponOrders.value )
).find((line) => line.status !== CARD_KEY_FULFILL_STATUS.DELIVERED)
return pending ? resolveCardKeyFulfillMessage(pending) : '' return pending ? resolveCardKeyFulfillMessage(pending) : ''
}) })
@@ -412,7 +409,6 @@ function loadData(orderSnParam: string) {
order.value = result.order order.value = result.order
orderGoodsList.value = result.orderItems orderGoodsList.value = result.orderItems
orderDetail.value = result orderDetail.value = result
giftECouponOrders.value = result.giftECouponOrders || []
if ( if (
result.order.deliveryMethod === 'LOGISTICS' && result.order.deliveryMethod === 'LOGISTICS' &&
!checkECouponOrder(result.order.orderType) && !checkECouponOrder(result.order.orderType) &&

View File

@@ -115,20 +115,16 @@ function normalizeCardKeyFulfillLine(source) {
status, status,
message: source.cardKeyFulfillMessage, message: source.cardKeyFulfillMessage,
cardKeys, cardKeys,
isGift: !!source.isGift,
} }
} }
/** 汇总 E_COUPON 主单行 + 满赠子单摘要的履约行 */ /** 汇总当前订单 orderItems 的卡密履约行(仅本单;满赠赠品在赠品订单单独查看) */
export function collectCardKeyFulfillLines(orderItems = [], giftSummaries = []) { export function collectCardKeyFulfillLines(orderItems = []) {
const lines = [] const lines = []
;(orderItems || []).forEach((item) => { ;(orderItems || []).forEach((item) => {
if (!isCardKeyFulfillApplicable(item)) return if (!isCardKeyFulfillApplicable(item)) return
lines.push(normalizeCardKeyFulfillLine(item)) lines.push(normalizeCardKeyFulfillLine(item))
}) })
;(giftSummaries || []).forEach((gift) => {
lines.push(normalizeCardKeyFulfillLine({ ...gift, isGift: true }))
})
return lines return lines
} }
@@ -143,19 +139,15 @@ function flattenCardKeyFulfillLines(lines, withGoodsName = false) {
return rows return rows
} }
/** 订单是否含已交付卡密(含满赠 E_COUPON 子单 */ /** 当前订单是否含已交付卡密(仅 orderItems */
export function orderHasCardKeyContent(orderItems, giftSummaries) { export function orderHasCardKeyContent(orderItems) {
const lines = collectCardKeyFulfillLines(orderItems, giftSummaries) const lines = collectCardKeyFulfillLines(orderItems)
return flattenCardKeyFulfillLines(lines).length > 0 return flattenCardKeyFulfillLines(lines).length > 0
} }
/** 将 orderItems[].cardKeys 展平为明文列表DELIVERED 且含 cardSecret */ /** 将 orderItems[].cardKeys 展平为明文列表DELIVERED 且含 cardSecret */
export function flattenOrderCardKeys( export function flattenOrderCardKeys(orderItems, withGoodsName = false) {
orderItems, const lines = collectCardKeyFulfillLines(orderItems)
withGoodsName = false,
giftSummaries
) {
const lines = collectCardKeyFulfillLines(orderItems, giftSummaries)
if (lines.some((line) => line.status)) { if (lines.some((line) => line.status)) {
return flattenCardKeyFulfillLines(lines, withGoodsName) return flattenCardKeyFulfillLines(lines, withGoodsName)
} }
@@ -168,8 +160,3 @@ export function flattenOrderCardKeys(
}) })
return rows return rows
} }
/** 是否已发卡(兼容旧调用;含满赠子单) */
export function isCardKeyDelivered(orderItems, giftSummaries) {
return orderHasCardKeyContent(orderItems, giftSummaries)
}