| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- import { resolveFileUrl } from '@/utils/image'
- import { formatPrice } from '@/utils/format'
- import { parseCartSpecText } from '@/utils/cartSpec'
- import { listAftersales } from '@/api/orderAftersale'
- import {
- ORDER_ACTION,
- ORDER_ACTION_LABEL,
- REVIEW_ITEM_STATUS,
- AFTERSALE_APPLY_TYPE_OPTIONS,
- AFTERSALE_TAB,
- ORDER_STATUS,
- ORDER_AFTERSALE_CARD_LABEL,
- ORDER_AFTERSALE_CARD_STATUS
- } from '@/constants/order'
- /** 订单级不再展示的评价按钮(改在商品行) */
- const ORDER_LEVEL_REVIEW_CODES = [ORDER_ACTION.REVIEW, ORDER_ACTION.VIEW_REVIEW]
- const GOODS_PLACEHOLDER = '/static/logo.png'
- const SHOP_PLACEHOLDER = '/static/logo.png'
- /** 后端凭证图可能是逗号拼接字符串,统一转成数组 */
- function normalizePicList(raw) {
- if (!raw) return []
- if (Array.isArray(raw)) return raw.filter(Boolean)
- if (typeof raw === 'string') {
- return raw.split(',').map((s) => s.trim()).filter(Boolean)
- }
- return []
- }
- function mapAftersaleApplyTypeText(applyType) {
- const hit = AFTERSALE_APPLY_TYPE_OPTIONS.find((opt) => opt.value === applyType)
- return hit ? hit.label : applyType || ''
- }
- function mapAftersaleStatusText(status) {
- if (status === '2') return '售后完结'
- if (status === '1') return '商家处理中'
- return status || ''
- }
- function mapAftersaleProgressText(stage) {
- if (stage === 'FINISHED') return '商家处理 → 售后完结(当前:售后完结)'
- return '商家处理 → 售后完结(当前:商家处理)'
- }
- function mapFirstItem(item) {
- if (!item) return null
- const specText = (item.goodsSpec || item.specText || '').trim() || '默认'
- return {
- orderItemId: item.itemId || item.orderItemId,
- goodsId: item.goodsId,
- goodsName: item.goodsName || '',
- goodsImage: item.goodsImage || item.mainPic || '',
- mainPic: item.mainPic || '',
- displayPic: resolveFileUrl(item.goodsImage || item.mainPic) || GOODS_PLACEHOLDER,
- specText,
- specList: parseCartSpecText(specText),
- quantity: Number(item.quantity) || 1,
- unitPrice: item.unitPrice,
- priceText: formatPrice(item.unitPrice),
- reviewStatus: item.reviewStatus,
- reviewId: item.reviewId
- }
- }
- function mapOrderItemRow(row) {
- if (!row) return null
- const specText = (row.goodsSpec || row.specText || '').trim() || '默认'
- return {
- orderItemId: row.orderItemId || row.itemId,
- goodsId: row.goodsId,
- goodsName: row.goodsName || '',
- goodsImage: row.goodsImage || row.mainPic || '',
- mainPic: row.mainPic || '',
- displayPic: resolveFileUrl(row.goodsImage || row.mainPic) || GOODS_PLACEHOLDER,
- specText,
- specList: parseCartSpecText(specText),
- serviceDesc: row.serviceDesc || '',
- quantity: Number(row.quantity) || 1,
- unitPrice: row.unitPrice || row.salePrice,
- priceText: formatPrice(row.unitPrice || row.salePrice),
- lineAmount: row.lineAmount || row.subtotal,
- lineAmountText: formatPrice(row.lineAmount || row.subtotal),
- buyerRemark: row.buyerRemark || '',
- reviewStatus: row.reviewStatus,
- reviewId: row.reviewId
- }
- }
- /** 订单已有进行中/已完结售后时,不再展示「申请售后」 */
- export function hasOrderAftersale(aftersaleStatus) {
- const status = aftersaleStatus != null ? String(aftersaleStatus) : ''
- return (
- status === ORDER_AFTERSALE_CARD_STATUS.IN_PROGRESS ||
- status === ORDER_AFTERSALE_CARD_STATUS.FINISHED
- )
- }
- function mapActions(actions, aftersaleStatus) {
- const hideAftersale = hasOrderAftersale(aftersaleStatus)
- return (actions || [])
- .filter((code) => !ORDER_LEVEL_REVIEW_CODES.includes(code))
- .filter((code) => !(hideAftersale && code === ORDER_ACTION.AFTERSALE))
- .map((code) => ({
- code,
- label: ORDER_ACTION_LABEL[code] || code
- }))
- .filter((item) => item.label)
- }
- /** 详情页补查订单售后态(列表接口有 aftersaleStatus,详情接口暂无) */
- export async function resolveOrderAftersaleStatus(orderId) {
- if (!orderId) return null
- try {
- const inProgressRes = await listAftersales({
- tab: AFTERSALE_TAB.IN_PROGRESS,
- pageNum: 1,
- pageSize: 100
- })
- const inProgressRows = inProgressRes.rows || []
- if (inProgressRows.some((row) => String(row.orderId) === String(orderId))) {
- return ORDER_AFTERSALE_CARD_STATUS.IN_PROGRESS
- }
- const finishedRes = await listAftersales({
- tab: AFTERSALE_TAB.FINISHED,
- pageNum: 1,
- pageSize: 100
- })
- const finishedRows = finishedRes.rows || []
- if (finishedRows.some((row) => String(row.orderId) === String(orderId))) {
- return ORDER_AFTERSALE_CARD_STATUS.FINISHED
- }
- } catch (e) {
- // 查询失败时不阻断详情展示
- }
- return null
- }
- /** 交易成功商品行:待评价→评价,已评价→查看评价 */
- export function getItemReviewAction(item) {
- if (!item || !item.reviewStatus) return null
- if (item.reviewStatus === REVIEW_ITEM_STATUS.PENDING) {
- return {
- code: ORDER_ACTION.REVIEW,
- label: ORDER_ACTION_LABEL[ORDER_ACTION.REVIEW]
- }
- }
- if (item.reviewStatus === REVIEW_ITEM_STATUS.DONE) {
- return {
- code: ORDER_ACTION.VIEW_REVIEW,
- label: ORDER_ACTION_LABEL[ORDER_ACTION.VIEW_REVIEW]
- }
- }
- return null
- }
- /** 评价列表「待评价」:订单行展平为待评价商品行 */
- export function flattenPendingReviewItems(rows) {
- const result = []
- for (const row of rows || []) {
- const card = mapOrderListRow(row)
- if (!card) continue
- for (const item of card.items || []) {
- if (item.reviewStatus !== REVIEW_ITEM_STATUS.PENDING) continue
- result.push({
- key: `pending-${card.orderId}-${item.orderItemId}`,
- orderId: card.orderId,
- item
- })
- }
- }
- return result
- }
- /** 评价列表「已评价」行 → 紧凑卡片模型 */
- export function mapReviewDoneRow(row) {
- if (!row) return null
- const item = mapFirstItem(row.firstItem)
- const content = (row.content || '').trim()
- return {
- key: `done-${row.reviewId || row.orderId}-${item?.orderItemId || 0}`,
- reviewId: row.reviewId,
- orderId: row.orderId,
- orderItemId: item?.orderItemId,
- score: Number(row.score) || 0,
- content,
- contentBrief: trimText(content, 48, '此用户未填写评价内容'),
- reviewTime: row.reviewTime || row.createTime || '',
- item
- }
- }
- function trimText(text, maxLen, emptyFallback = '') {
- const s = (text || '').trim()
- if (!s) return emptyFallback
- if (s.length <= maxLen) return s
- return `${s.slice(0, maxLen)}…`
- }
- /**
- * 列表卡片状态文案(MO-L4 调整)
- * 仅「售后处理中」覆盖主状态;售后已完结后订单应变已关闭,列表不再展示「售后已完成」
- */
- export function mapOrderCardStatusText(orderStatusText, aftersaleStatus, orderStatus) {
- if (aftersaleStatus === ORDER_AFTERSALE_CARD_STATUS.IN_PROGRESS) {
- return ORDER_AFTERSALE_CARD_LABEL[aftersaleStatus]
- }
- if (aftersaleStatus === ORDER_AFTERSALE_CARD_STATUS.FINISHED) {
- if (orderStatus === ORDER_STATUS.CLOSED) {
- return orderStatusText || '已关闭'
- }
- // 售后已完结但订单主状态未同步(异常数据)时,仍按已关闭展示
- return '已关闭'
- }
- return orderStatusText || ''
- }
- /** 列表行 VO → 卡片模型 */
- export function mapOrderListRow(row) {
- if (!row) return null
- const rawItems = Array.isArray(row.items) && row.items.length
- ? row.items
- : row.firstItem
- ? [row.firstItem]
- : []
- const items = rawItems.map(mapFirstItem).filter(Boolean)
- const firstItem = items[0] || mapFirstItem(row.firstItem)
- const orderStatusText = row.orderStatusText || ''
- const aftersaleStatus = row.aftersaleStatus || null
- return {
- orderId: row.orderId,
- orderNo: row.orderNo || '',
- orderStatus: row.orderStatus,
- orderStatusText,
- aftersaleStatus,
- statusText: mapOrderCardStatusText(orderStatusText, aftersaleStatus, row.orderStatus),
- statusIsAftersale: aftersaleStatus === ORDER_AFTERSALE_CARD_STATUS.IN_PROGRESS,
- amountLabel: row.orderStatus === ORDER_STATUS.PENDING_PAY ? '应付' : '实付',
- shopId: row.shopId,
- shopName: row.shopName || '',
- shopAvatar: resolveFileUrl(row.shopAvatar) || SHOP_PLACEHOLDER,
- payAmount: row.payAmount,
- payAmountText: formatPrice(row.payAmount),
- goodsAmount: row.goodsAmount,
- freightAmount: row.freightAmount,
- createTime: row.createTime || '',
- itemCount: Number(row.itemCount) || items.length,
- items,
- firstItem,
- payRemainSeconds: row.payRemainSeconds,
- reviewStatus: row.reviewStatus,
- actions: mapActions(row.actions, aftersaleStatus)
- }
- }
- /** 详情 VO → 页面模型;options.aftersaleStatus 用于补全售后态并过滤操作按钮 */
- export function mapOrderDetail(data, options = {}) {
- if (!data) return null
- const items = (data.items || []).map(mapOrderItemRow).filter(Boolean)
- const latestTrace = data.latestTrace || null
- const aftersaleStatus = data.aftersaleStatus || options.aftersaleStatus || null
- return {
- orderId: data.orderId,
- orderNo: data.orderNo || '',
- orderStatus: data.orderStatus,
- statusText: data.orderStatusText || '',
- payStatus: data.payStatus,
- payType: data.payType,
- payTypeText: data.payTypeText || '',
- shopId: data.shopId,
- shopName: data.shopName || '',
- shopAvatar: resolveFileUrl(data.shopAvatar) || SHOP_PLACEHOLDER,
- consigneeName: data.consigneeName || '',
- consigneeMobile: data.consigneeMobile || '',
- consigneeAddress: data.consigneeAddress || '',
- goodsAmount: data.goodsAmount,
- goodsAmountText: formatPrice(data.goodsAmount),
- freightAmount: data.freightAmount,
- freightAmountText: formatPrice(data.freightAmount),
- freightDesc: data.freightDesc || '',
- payAmount: data.payAmount,
- payAmountText: formatPrice(data.payAmount),
- createTime: data.createTime || '',
- payTime: data.payTime || '',
- payExpireTime: data.payExpireTime || '',
- payRemainSeconds: data.payRemainSeconds,
- finishTime: data.finishTime || '',
- shipTime: data.shipTime || '',
- closeType: data.closeType,
- closeTypeText: data.closeTypeText || '',
- closeReason: data.closeReason || '',
- deliveryType: data.deliveryType,
- logisticsCompany: data.logisticsCompany || '',
- trackingNo: data.trackingNo || '',
- vehicleNo: data.vehicleNo || '',
- courierName: data.courierName || '',
- courierMobile: data.courierMobile || '',
- latestTrace: latestTrace
- ? {
- traceType: latestTrace.traceType,
- traceTime: latestTrace.traceTime || '',
- content: latestTrace.content || ''
- }
- : null,
- items,
- reviewStatus: data.reviewStatus,
- reviewId: data.reviewId,
- aftersaleStatus,
- actions: mapActions(data.actions, aftersaleStatus)
- }
- }
- /** 评价详情 */
- export function mapOrderReview(data) {
- if (!data) return null
- const pics = (data.pics || []).map((p) => resolveFileUrl(p) || p).filter(Boolean)
- return {
- score: Number(data.score) || 0,
- content: data.content || '',
- pics,
- createTime: data.createTime || '',
- replyContent: data.replyContent || '',
- replyTime: data.replyTime || ''
- }
- }
- /** 售后列表行 */
- export function mapAftersaleListRow(row) {
- if (!row) return null
- const specText = (row.goodsSpec || row.specText || '').trim() || '默认'
- return {
- aftersaleId: row.aftersaleId,
- aftersaleNo: row.aftersaleNo || '',
- aftersaleStatus: row.aftersaleStatus,
- statusText:
- row.aftersaleStatusText ||
- row.statusText ||
- mapAftersaleStatusText(row.aftersaleStatus),
- applyType: row.applyType,
- applyTypeText: row.applyTypeText || mapAftersaleApplyTypeText(row.applyType),
- applyReason: row.applyReason || '',
- applyAmount: row.applyAmount,
- applyAmountText: formatPrice(row.applyAmount),
- createTime: row.createTime || '',
- goodsName: row.goodsName || '',
- goodsImage: row.goodsImage || row.mainPic || '',
- mainPic: row.mainPic || '',
- displayPic: resolveFileUrl(row.goodsImage || row.mainPic) || GOODS_PLACEHOLDER,
- specList: parseCartSpecText(specText),
- orderId: row.orderId,
- orderNo: row.orderNo || ''
- }
- }
- /** 售后详情 */
- export function mapAftersaleDetail(data) {
- if (!data) return null
- const info = data.info || data
- const specText = (info.goodsSpec || info.specText || '').trim() || '默认'
- const progressStage = data.progressStage || info.progressStage || ''
- const aftersaleStatus = info.aftersaleStatus || data.aftersaleStatus
- return {
- aftersaleId: info.aftersaleId || data.aftersaleId,
- aftersaleNo: info.aftersaleNo || data.aftersaleNo || '',
- aftersaleStatus,
- statusText:
- info.aftersaleStatusText ||
- info.statusText ||
- mapAftersaleStatusText(aftersaleStatus),
- progress: data.progress || info.progress || progressStage,
- progressText:
- data.progressText ||
- info.progressText ||
- mapAftersaleProgressText(progressStage),
- applyType: info.applyType,
- applyTypeText: info.applyTypeText || mapAftersaleApplyTypeText(info.applyType),
- applyReason: info.applyReason || '',
- returnQuantity: info.returnQuantity,
- applyAmount: info.applyAmount,
- applyAmountText: formatPrice(info.applyAmount),
- description: info.description || '',
- evidencePics: normalizePicList(info.evidencePics).map((p) => resolveFileUrl(p) || p),
- createTime: info.createTime || '',
- finishTime: info.finishTime || '',
- processResult: data.processResult || info.processResult || '',
- orderId: info.orderId,
- orderNo: info.orderNo || data.orderNo || '',
- orderItemId: info.orderItemId,
- goodsName: info.goodsName || '',
- goodsImage: info.goodsImage || info.mainPic || '',
- displayPic: resolveFileUrl(info.goodsImage || info.mainPic) || GOODS_PLACEHOLDER,
- specList: parseCartSpecText(specText),
- quantity: Number(info.quantity) || 1
- }
- }
- /** 待支付倒计时文案 */
- export function formatPayCountdown(seconds) {
- if (seconds == null || seconds <= 0) return '已超时'
- const h = Math.floor(seconds / 3600)
- const m = Math.floor((seconds % 3600) / 60)
- const s = seconds % 60
- if (h > 0) {
- return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`
- }
- return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`
- }
|