feat: 添加电子卡券功能及相关逻辑

- 在 pages.json 中新增卡密详情页面路径
- 在多个组件中实现电子卡券(E_COUPON)逻辑,包括库存管理、结算页面处理、订单详情展示等
- 优化商品页面和订单页面以支持电子卡券的特性,隐藏不适用的功能
- 新增 utils/goodsType.js 文件,集中管理与电子卡券相关的类型和工具函数
- 更新样式以适应电子卡券的展示需求
This commit is contained in:
田香琪
2026-07-31 13:57:14 +08:00
parent 6754a54f1b
commit a6ba2b3dbe
12 changed files with 550 additions and 96 deletions

91
utils/goodsType.js Normal file
View File

@@ -0,0 +1,91 @@
/**
* @Author Mike
* @Date 2026-07-31
*
* 卡密商品(电子卡券 E_COUPON类型与订单工具。
*
* 与 VIRTUAL_GOODS / VIRTUAL 核销商品区分E_COUPON 走 BUY_NOW、支付后 COMPLETED + cardKeys
* 不支持加购、促销与买家售后。需求见 lilishop/docs/requirements/card-key-goods-v4.md
*/
export const E_COUPON_GOODS_TYPE = 'E_COUPON'
export const E_COUPON_ORDER_TYPE = 'E_COUPON'
export const VIRTUAL_GOODS_TYPE = 'VIRTUAL_GOODS'
export const VIRTUAL_ORDER_TYPE = 'VIRTUAL'
/** 单次购买数量上限O-09 默认min(poolStock, 999) */
export const E_COUPON_MAX_BUY_NUM = 999
export function isECoupon(goodsType) {
return goodsType === E_COUPON_GOODS_TYPE
}
export function isECouponOrder(orderType) {
return orderType === E_COUPON_ORDER_TYPE
}
export function isVirtualGoods(goodsType) {
return goodsType === VIRTUAL_GOODS_TYPE
}
export function isVirtualOrder(orderType) {
return orderType === VIRTUAL_ORDER_TYPE
}
/** 非实物:含 E_COUPON 与核销型 VIRTUAL_GOODS详情页隐藏「送至」等 */
export function isNonPhysicalGoods(goodsType) {
return isECoupon(goodsType) || isVirtualGoods(goodsType)
}
export function isNonPhysicalOrder(orderType) {
return isECouponOrder(orderType) || isVirtualOrder(orderType)
}
/** 可售库存E_COUPON 以卡池 poolStock 为准quantity 仅为镜像回退 */
export function getECouponStock(sku) {
if (!sku) return 0
const pool = sku.poolStock
if (pool !== undefined && pool !== null) {
return Number(pool) || 0
}
return Number(sku.quantity) || 0
}
export function getECouponMaxBuyNum(sku) {
const stock = getECouponStock(sku)
if (stock <= 0) return 1
return Math.min(stock, E_COUPON_MAX_BUY_NUM)
}
/**
* 结算页识别当前交易是否含 E_COUPON SKU。
* 须从 goodsSku.goodsType 判断,不能依赖 cartTypeEnum=VIRTUALE_COUPON 仍是 BUY_NOW
*/
export function hasECouponInCheckout(orderMessage) {
if (!orderMessage) return false
const checked = orderMessage.checkedSkuList || []
if (checked.some((item) => isECoupon(item?.goodsSku?.goodsType))) {
return true
}
const cartList = orderMessage.cartList || []
return cartList.some((cart) =>
(cart.checkedSkuList || []).some((item) =>
isECoupon(item?.goodsSku?.goodsType)
)
)
}
/** 将 orderItems[].cardKeys 展平为列表,供卡密二级页展示 */
export function flattenOrderCardKeys(orderItems) {
const rows = []
;(orderItems || []).forEach((item) => {
;(item.cardKeys || []).forEach((ck) => {
rows.push({ ...ck })
})
})
return rows
}
/** 是否已发卡API-B-01cardKeyDelivered 或 orderItems 内标记) */
export function isCardKeyDelivered(orderItems) {
return (orderItems || []).some((item) => item.cardKeyDelivered)
}