/** * 订单状态(与 oms0414-back OrderStatusCodes、设计文档 §10.3.1 一致) * * 标签色系:按生命周期语义分色;渲染仍走 utils/statusTag。 */ import { STATUS_TAG_TONES, buildBooleanTagHtml, buildStatusTagHtml, getStatusTagStyle, type StatusTagTone, } from '@/utils/statusTag' export const ORDER_STATUS_ALL = 'all' as const /** @deprecated 历史值 received 已废弃,见 normalizeOrderStatusCode */ export const ORDER_STATUS_LEGACY_RECEIVED = 'received' as const export type OrderStatusCode = | typeof ORDER_STATUS_ALL | 'draft' | 'predeclared' | 'pendingAllocation' | 'pendingPayment' | 'pendingShip' | 'pendingOnline' | 'shipping' | 'deliverySuccess' | 'deliveryFailed' | 'problematic' | 'deleted' | 'claimed' /** @deprecated 使用 StatusTagTone;保留别名兼容 */ export type OrderStatusTagTone = StatusTagTone /** @deprecated 使用 STATUS_TAG_TONES */ export const ORDER_STATUS_TAG_TONES = STATUS_TAG_TONES /** 允许删除的订单状态:草稿、已预报 */ export const ORDER_DELETABLE_STATUSES: readonly OrderStatusCode[] = ['draft', 'predeclared'] export function isOrderDeletable(status: unknown): boolean { const code = normalizeOrderStatusCode(typeof status === 'string' ? status.trim() : '') return ORDER_DELETABLE_STATUSES.includes(code as OrderStatusCode) } export interface OrderStatusMeta { value: OrderStatusCode /** i18n key:tabs.* 与 status.* 共用同一套文案 */ labelKey: string tagColor?: string tagBgColor?: string tagBorder?: string /** 表格行背景(极淡,仅待办/异常) */ rowBg?: string /** Tab 是否展示数量 */ showTabCount?: boolean } /** 历史 received 归并为待排货(入库后不再停留已收货) */ export function normalizeOrderStatusCode(code: string): string { return code === ORDER_STATUS_LEGACY_RECEIVED ? 'pendingAllocation' : code } /** 后端返回的中文状态名 → code(OmsDocHelper.GetOrderStatusName) */ export const ORDER_STATUS_NAME_TO_CODE: Record = { 草稿: 'draft', 已预报: 'predeclared', 已收货: 'pendingAllocation', 待排货: 'pendingAllocation', 待支付: 'pendingPayment', 待发货: 'pendingShip', 待上网: 'pendingOnline', 运输中: 'shipping', 派送成功: 'deliverySuccess', 派送失败: 'deliveryFailed', 问题件: 'problematic', 已删除: 'deleted', 理赔件: 'claimed', 已理赔: 'claimed', 已认领: 'claimed', } /** * 订单状态标签色:按生命周期语义分色(软底标签),便于列表一眼区分。 * 待办暖色 / 在途品牌色 / 成功绿 / 失败红 / 问题橙 / 理赔紫。 */ export const ORDER_STATUS_LIST: OrderStatusMeta[] = [ { value: 'draft', labelKey: 'order.myOrders.status.draft', tagColor: '#6b7280', tagBgColor: '#f3f4f6', tagBorder: '#e5e7eb', }, { value: 'predeclared', labelKey: 'order.myOrders.status.predeclared', tagColor: '#3d6a8a', tagBgColor: '#eef4f8', tagBorder: '#d0dee8', }, { value: 'pendingAllocation', labelKey: 'order.myOrders.status.pendingAllocation', tagColor: '#8a6d3b', tagBgColor: '#f7f2e8', tagBorder: '#e8dcc6', rowBg: '#faf8f5', showTabCount: true, }, { value: 'pendingPayment', labelKey: 'order.myOrders.status.pendingPayment', tagColor: '#ea580c', tagBgColor: '#fff4e5', tagBorder: '#fb923c', rowBg: '#fff7ed', showTabCount: true, }, { value: 'pendingShip', labelKey: 'order.myOrders.status.pendingShip', tagColor: '#0f766e', tagBgColor: '#f0fdfa', tagBorder: '#99f6e4', showTabCount: true, }, { value: 'pendingOnline', labelKey: 'order.myOrders.status.pendingOnline', tagColor: '#1d4ed8', tagBgColor: '#eff6ff', tagBorder: '#bfdbfe', showTabCount: true, }, { value: 'shipping', labelKey: 'order.myOrders.status.shipping', tagColor: '#054f74', tagBgColor: '#eef3f6', tagBorder: '#b6cdd9', showTabCount: true, }, { value: 'deliverySuccess', labelKey: 'order.myOrders.status.deliverySuccess', tagColor: '#15803d', tagBgColor: '#f0fdf4', tagBorder: '#bbf7d0', showTabCount: true, }, { value: 'deliveryFailed', labelKey: 'order.myOrders.status.deliveryFailed', tagColor: '#b91c1c', tagBgColor: '#fef2f2', tagBorder: '#fecaca', showTabCount: true, }, { value: 'deleted', labelKey: 'order.myOrders.status.deleted', tagColor: '#9ca3af', tagBgColor: '#f9fafb', tagBorder: '#e5e7eb', }, { value: 'problematic', labelKey: 'order.myOrders.status.problematic', tagColor: '#c2410c', tagBgColor: '#fff7ed', tagBorder: '#fdba74', rowBg: '#fff7ed', showTabCount: true, }, { value: 'claimed', labelKey: 'order.myOrders.status.claimed', tagColor: '#6d28d9', tagBgColor: '#f5f3ff', tagBorder: '#ddd6fe', }, ] /** 已出库/在途及之后(不可拦截) */ export const ORDER_SHIPPED_STATUSES: readonly OrderStatusCode[] = [ 'pendingOnline', 'shipping', 'deliverySuccess', 'deliveryFailed', ] /** * 出库后可人工校正的状态集合。 * 规则:四态互改;派送成功只进不出(见 getPostShipStatusChangeTargets)。 */ export const ORDER_POST_SHIP_CHANGEABLE_STATUSES: readonly OrderStatusCode[] = [ 'pendingOnline', 'shipping', 'deliverySuccess', 'deliveryFailed', ] /** 当前状态允许改到的目标(派送成功返回空) */ export function getPostShipStatusChangeTargets(fromStatus: unknown): OrderStatusCode[] { const code = normalizeOrderStatusCode( typeof fromStatus === 'string' ? fromStatus.trim() : resolveOrderStatusCode(fromStatus as any), ) as OrderStatusCode if (!ORDER_POST_SHIP_CHANGEABLE_STATUSES.includes(code)) return [] if (code === 'deliverySuccess') return [] return ORDER_POST_SHIP_CHANGEABLE_STATUSES.filter((s) => s !== code) } const ORDER_SHIPPED_STATUS_SET = new Set(ORDER_SHIPPED_STATUSES) /** 未发货:待上网之前的状态均可尝试拦截/取消拦截 */ export function isOrderNotShipped( statusOrRow?: string | { status?: string; Status?: string; orderStatus?: string; OrderStatus?: string }, ): boolean { const code = typeof statusOrRow === 'string' ? normalizeOrderStatusCode(statusOrRow.trim()) : resolveOrderStatusCode(statusOrRow) if (!code || code === ORDER_STATUS_ALL) return false return !ORDER_SHIPPED_STATUS_SET.has(code) } const ORDER_STATUS_BY_CODE = new Map(ORDER_STATUS_LIST.map((item) => [item.value, item])) /** 我的订单 Tab:全部 + 各业务状态 */ export const ORDER_STATUS_TABS: OrderStatusMeta[] = [ { value: ORDER_STATUS_ALL, labelKey: 'order.myOrders.tabs.all', showTabCount: true }, ...ORDER_STATUS_LIST.map(({ value, tagColor, tagBgColor, tagBorder, rowBg, showTabCount }) => ({ value, labelKey: `order.myOrders.tabs.${value}`, tagColor, tagBgColor, tagBorder, rowBg, showTabCount: showTabCount ?? true, })), ] export function resolveOrderStatusCode(row?: { status?: string Status?: string orderStatus?: string OrderStatus?: string }): string { if (!row) return '' const rawCode = normalizeOrderStatusCode(String(row.status ?? row.Status ?? '').trim()) if (rawCode && ORDER_STATUS_BY_CODE.has(rawCode as OrderStatusCode)) { return rawCode } const rawName = String(row.orderStatus ?? row.OrderStatus ?? '').trim() if (rawName && ORDER_STATUS_NAME_TO_CODE[rawName]) { return ORDER_STATUS_NAME_TO_CODE[rawName] } if (rawName && ORDER_STATUS_BY_CODE.has(rawName as OrderStatusCode)) { return rawName } return rawCode || rawName } export function getOrderStatusMeta(codeOrName?: string): OrderStatusMeta | undefined { if (!codeOrName) return undefined const normalized = normalizeOrderStatusCode(String(codeOrName).trim()) if (ORDER_STATUS_BY_CODE.has(normalized as OrderStatusCode)) { return ORDER_STATUS_BY_CODE.get(normalized as OrderStatusCode) } const code = ORDER_STATUS_NAME_TO_CODE[codeOrName] return code ? ORDER_STATUS_BY_CODE.get(code) : undefined } export function getOrderStatusTagStyle( meta?: Pick | null, ): Record { return getStatusTagStyle(meta ?? undefined) } export function buildOrderStatusTagHtml( text: string, meta?: Pick | null, ): string { return buildStatusTagHtml(text, meta ?? undefined) } export function buildOrderStatusSubTagHtml( text: string, meta?: { tagColor?: string; tagBgColor?: string; tagBorder?: string } | null, ): string { return buildStatusTagHtml(text, meta ?? undefined, 'ghost') } export { buildBooleanTagHtml }