From bcfe1688b1a3773d947c741baa6526c60a752408 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 28 Jul 2026 12:16:55 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8D=E8=AE=A2=E5=8D=95=E5=8F=AF?= =?UTF-8?q?=E6=A0=B8=E9=94=80=E6=98=8E=E7=BB=86=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/mock.ts | 7 +- src/api/orders.ts | 2 +- src/types/order.ts | 11 +- src/utils/__tests__/writeOffCode.test.ts | 22 ++ src/utils/__tests__/writeOffItem.test.ts | 53 +++++ src/utils/__tests__/writeOffRequestNo.test.ts | 29 +++ src/utils/constants.ts | 3 +- src/utils/writeOffCode.ts | 26 +++ src/utils/writeOffItem.ts | 94 ++++++++ src/utils/writeOffRequestNo.ts | 21 ++ src/views/orders/OrderDetailView.vue | 46 +++- src/views/verify/VerifyConfirmView.vue | 204 +++++++++++------- src/views/verify/VerifyView.vue | 1 + 13 files changed, 428 insertions(+), 91 deletions(-) create mode 100644 src/utils/__tests__/writeOffCode.test.ts create mode 100644 src/utils/__tests__/writeOffItem.test.ts create mode 100644 src/utils/__tests__/writeOffRequestNo.test.ts create mode 100644 src/utils/writeOffItem.ts create mode 100644 src/utils/writeOffRequestNo.ts diff --git a/src/api/mock.ts b/src/api/mock.ts index d4e662e..b3f8645 100644 --- a/src/api/mock.ts +++ b/src/api/mock.ts @@ -242,11 +242,16 @@ export const mockApi = { commodityDescription: '面向到店客人的酒店权益商品,需由员工确认后核销。', commodityPackageConfig: [ { + orderWriteOffItemId: `WOI${order.id}-1`, packageName: order.commodityName, packageContent: `${order.commodityName} x ${order.commodityAmount}`, name: order.commodityName, count: totalCount, unit: '份', + writeOffStatus: writeOffCount >= totalCount ? 'WRITTEN_OFF' : 'NOT_WRITE_OFF', + legacySnapshot: false, + writeOffSupported: true, + snapshotOperationSupported: true, packageStatus: writeOffCount >= totalCount ? 1 : 0, writeOffCount } @@ -278,7 +283,7 @@ export const mockApi = { return { success: true, orderId: payload.orderId, - packageName: payload.packageName, + orderWriteOffItemId: payload.orderWriteOffItemId, message: '核销成功', operatedAt: formatDateTime(new Date()) } diff --git a/src/api/orders.ts b/src/api/orders.ts index 57e4c03..aae415e 100644 --- a/src/api/orders.ts +++ b/src/api/orders.ts @@ -36,7 +36,7 @@ export const writeOffOrder = async (payload: WriteOffPayload): Promise { + assert.deepEqual( + parseWriteOffCode('{"v":2,"orderId":"2067459232180035585","orderWriteOffItemId":"item-2","packageName":"全价门票"}'), + { + orderId: '2067459232180035585', + orderWriteOffItemId: 'item-2', + packageName: '全价门票', + version: 2 + } + ) +}) + +test('parses legacy orderId and packageName write off code', () => { + assert.deepEqual(parseWriteOffCode('order-1&%E5%A5%97%E9%A4%90A'), { + orderId: 'order-1', + packageName: '套餐A' + }) +}) diff --git a/src/utils/__tests__/writeOffItem.test.ts b/src/utils/__tests__/writeOffItem.test.ts new file mode 100644 index 0000000..14756a6 --- /dev/null +++ b/src/utils/__tests__/writeOffItem.test.ts @@ -0,0 +1,53 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import { + findWriteOffItem, + getWriteOffItemAvailability, + getWriteOffItemQuantity +} from '../writeOffItem.ts' + +const items = [ + { + orderWriteOffItemId: 'item-1', + name: '双人套餐', + count: 2, + writeOffCount: 0, + writeOffSupported: true, + snapshotOperationSupported: true + }, + { + orderWriteOffItemId: 'item-2', + name: '双人套餐', + count: 2, + writeOffCount: 1, + writeOffSupported: true, + snapshotOperationSupported: true + } +] + +test('finds write off item by id before matching duplicated package name', () => { + assert.equal( + findWriteOffItem(items, { orderWriteOffItemId: 'item-2', packageName: '双人套餐' })?.orderWriteOffItemId, + 'item-2' + ) +}) + +test('matches legacy package name when item id is absent', () => { + assert.equal(findWriteOffItem(items, { packageName: '双人套餐' })?.orderWriteOffItemId, 'item-1') +}) + +test('calculates total, written off and remaining quantity from item fields', () => { + assert.deepEqual(getWriteOffItemQuantity(items[1]), { + total: 2, + writtenOff: 1, + writable: 1, + unit: '' + }) +}) + +test('marks legacy or unsupported or completed item unavailable', () => { + assert.equal(getWriteOffItemAvailability({ ...items[0], legacySnapshot: true }).available, false) + assert.equal(getWriteOffItemAvailability({ ...items[0], writeOffSupported: false }).available, false) + assert.equal(getWriteOffItemAvailability({ ...items[0], snapshotOperationSupported: false }).available, false) + assert.equal(getWriteOffItemAvailability({ ...items[0], writeOffCount: 2 }).available, false) +}) diff --git a/src/utils/__tests__/writeOffRequestNo.test.ts b/src/utils/__tests__/writeOffRequestNo.test.ts new file mode 100644 index 0000000..bb0d050 --- /dev/null +++ b/src/utils/__tests__/writeOffRequestNo.test.ts @@ -0,0 +1,29 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import { getReusableWriteOffRequestNo, type WriteOffRequestNoState } from '../writeOffRequestNo.ts' + +test('reuses request number for the same write off target', () => { + const state: WriteOffRequestNoState = { targetKey: '', requestNo: '' } + let sequence = 0 + const createRequestNo = () => `request-${++sequence}` + + const first = getReusableWriteOffRequestNo(state, 'order-1:item-1', createRequestNo) + const retry = getReusableWriteOffRequestNo(state, 'order-1:item-1', createRequestNo) + + assert.equal(first, 'request-1') + assert.equal(retry, 'request-1') + assert.equal(sequence, 1) +}) + +test('creates a new request number when the write off target changes', () => { + const state: WriteOffRequestNoState = { targetKey: '', requestNo: '' } + let sequence = 0 + const createRequestNo = () => `request-${++sequence}` + + const first = getReusableWriteOffRequestNo(state, 'order-1:item-1', createRequestNo) + const second = getReusableWriteOffRequestNo(state, 'order-1:item-2', createRequestNo) + + assert.equal(first, 'request-1') + assert.equal(second, 'request-2') + assert.equal(sequence, 2) +}) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index b7d8154..dbdb22a 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -29,7 +29,8 @@ export const payStatusText: Record = { export const commodityTypeText: Record = { '0': '酒店', '1': '门票', - '2': '餐饮' + '2': '餐饮', + '3': '套餐' } export const eventStatusText: Record = { diff --git a/src/utils/writeOffCode.ts b/src/utils/writeOffCode.ts index 5c3b914..e438c1b 100644 --- a/src/utils/writeOffCode.ts +++ b/src/utils/writeOffCode.ts @@ -1,6 +1,8 @@ export interface WriteOffCodePayload { orderId: string + orderWriteOffItemId?: string packageName?: string + version?: number } const safeDecode = (value: string) => { @@ -17,6 +19,30 @@ export const parseWriteOffCode = (rawValue: string): WriteOffCodePayload => { throw new Error('未识别到核销码') } + if (raw.startsWith('{')) { + try { + const payload = JSON.parse(raw) as { + v?: number + orderId?: string + orderWriteOffItemId?: string + packageName?: string + } + const orderId = String(payload.orderId || '').trim() + if (!orderId) { + throw new Error('核销码缺少订单号') + } + return { + orderId, + orderWriteOffItemId: payload.orderWriteOffItemId ? String(payload.orderWriteOffItemId).trim() : undefined, + packageName: payload.packageName ? String(payload.packageName).trim() : undefined, + version: payload.v + } + } catch (error) { + if (error instanceof Error && error.message === '核销码缺少订单号') throw error + throw new Error('核销码格式不正确') + } + } + const splitIndex = raw.indexOf('&') const orderId = safeDecode(splitIndex >= 0 ? raw.slice(0, splitIndex) : raw).trim() const packageName = splitIndex >= 0 ? safeDecode(raw.slice(splitIndex + 1)).trim() : '' diff --git a/src/utils/writeOffItem.ts b/src/utils/writeOffItem.ts new file mode 100644 index 0000000..919ce71 --- /dev/null +++ b/src/utils/writeOffItem.ts @@ -0,0 +1,94 @@ +import type { CommodityPackageConfig } from '@/types/order' + +export interface WriteOffItemMatch { + orderWriteOffItemId?: string + packageName?: string +} + +export interface WriteOffItemQuantity { + total: number + writtenOff: number + writable: number + unit: string +} + +export interface WriteOffItemAvailability { + available: boolean + reason: string +} + +const statusTextMap: Record = { + '0': '待核销', + '1': '已核销', + '2': '部分核销', + NOT_WRITE_OFF: '待核销', + WAIT_WRITE_OFF: '待核销', + PART_WRITE_OFF: '部分核销', + PARTIAL_WRITE_OFF: '部分核销', + WRITE_OFF: '已核销', + WRITTEN_OFF: '已核销', + FINISHED: '已核销' +} + +export const toNumber = (value: unknown) => { + const number = Number(value) + return Number.isFinite(number) ? number : undefined +} + +export const getWriteOffItemId = (item?: CommodityPackageConfig) => { + return String(item?.orderWriteOffItemId || '').trim() +} + +export const getWriteOffItemName = (item?: CommodityPackageConfig, fallbackName = '') => { + return (item?.name || item?.packageName || fallbackName || '').trim() +} + +export const getWriteOffItemContent = (item?: CommodityPackageConfig) => { + return item?.packageContent || item?.packageDesc || item?.content || '' +} + +export const getWriteOffItemQuantity = (item?: CommodityPackageConfig): WriteOffItemQuantity => { + const total = toNumber(item?.count) ?? 0 + const writtenOff = Math.min(toNumber(item?.writeOffCount) ?? 0, total) + return { + total, + writtenOff, + writable: Math.max(total - writtenOff, 0), + unit: item?.unit || '' + } +} + +export const getWriteOffItemAvailability = (item?: CommodityPackageConfig): WriteOffItemAvailability => { + if (!item) return { available: false, reason: '缺少可核销明细' } + if (!getWriteOffItemId(item)) return { available: false, reason: '缺少核销明细ID' } + if (item.legacySnapshot) return { available: false, reason: '历史未迁移明细不可核销' } + if (item.writeOffSupported === false) return { available: false, reason: '当前明细不支持核销' } + if (item.snapshotOperationSupported === false) return { available: false, reason: '当前明细不支持快照核销' } + if (getWriteOffItemQuantity(item).writable <= 0) return { available: false, reason: '当前明细已核销完' } + return { available: true, reason: '' } +} + +export const findWriteOffItem = (items: CommodityPackageConfig[], match: WriteOffItemMatch) => { + const itemId = String(match.orderWriteOffItemId || '').trim() + if (itemId) { + return items.find((item) => getWriteOffItemId(item) === itemId) + } + + const packageName = String(match.packageName || '').trim() + if (packageName) { + return items.find((item) => getWriteOffItemName(item) === packageName || item.packageName === packageName) + } + + return undefined +} + +export const getFirstAvailableWriteOffItem = (items: CommodityPackageConfig[]) => { + return items.find((item) => getWriteOffItemAvailability(item).available) +} + +export const getWriteOffStatusText = (item?: CommodityPackageConfig) => { + const status = item?.writeOffStatus ?? item?.packageStatus + if (status === undefined || status === null || status === '') return '' + const key = String(status) + return statusTextMap[key] || key +} diff --git a/src/utils/writeOffRequestNo.ts b/src/utils/writeOffRequestNo.ts new file mode 100644 index 0000000..cfbf1e5 --- /dev/null +++ b/src/utils/writeOffRequestNo.ts @@ -0,0 +1,21 @@ +export interface WriteOffRequestNoState { + targetKey: string + requestNo: string +} + +export const createWriteOffRequestNo = () => { + if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID() + return `h5-${Date.now()}-${Math.random().toString(16).slice(2)}` +} + +export const getReusableWriteOffRequestNo = ( + state: WriteOffRequestNoState, + targetKey: string, + createRequestNo = createWriteOffRequestNo +) => { + if (!state.requestNo || state.targetKey !== targetKey) { + state.targetKey = targetKey + state.requestNo = createRequestNo() + } + return state.requestNo +} diff --git a/src/views/orders/OrderDetailView.vue b/src/views/orders/OrderDetailView.vue index 4fc03f7..df59e92 100644 --- a/src/views/orders/OrderDetailView.vue +++ b/src/views/orders/OrderDetailView.vue @@ -7,6 +7,15 @@ import PageNav from '@/components/PageNav.vue' import StatusTag from '@/components/StatusTag.vue' import type { UserOrderDetail } from '@/types/order' import { canWriteOff, commodityTypeText, payStatusText } from '@/utils/constants' +import { + getFirstAvailableWriteOffItem, + getWriteOffItemAvailability, + getWriteOffItemContent, + getWriteOffItemId, + getWriteOffItemName, + getWriteOffItemQuantity, + getWriteOffStatusText +} from '@/utils/writeOffItem' const route = useRoute() const router = useRouter() @@ -14,10 +23,8 @@ const detail = ref(null) const loading = ref(false) const orderId = computed(() => String(route.params.id || '')) -const packageName = computed(() => { - const first = detail.value?.commodityPackageConfig?.[0] - return first?.packageName || first?.name || detail.value?.commodityName || '' -}) +const firstWritableItem = computed(() => getFirstAvailableWriteOffItem(detail.value?.commodityPackageConfig || [])) +const canGoWriteOff = computed(() => Boolean(detail.value && canWriteOff(detail.value.orderStatus) && firstWritableItem.value)) const loadDetail = async () => { loading.value = true @@ -29,11 +36,13 @@ const loadDetail = async () => { } const goWriteOff = () => { + if (!firstWritableItem.value) return router.push({ path: '/verify/confirm', query: { orderId: orderId.value, - packageName: packageName.value + orderWriteOffItemId: getWriteOffItemId(firstWritableItem.value), + packageName: getWriteOffItemName(firstWritableItem.value, detail.value?.commodityName) } }) } @@ -103,11 +112,24 @@ onMounted(loadDetail)

套餐内容

-
+
- {{ item.packageName || item.name || detail.commodityName }} -

{{ item.packageContent || item.packageDesc || item.content }}

+ {{ getWriteOffItemName(item, detail.commodityName) }} +

{{ getWriteOffItemContent(item) }}

+

+ {{ getWriteOffStatusText(item) }} · + 已核销 {{ getWriteOffItemQuantity(item).writtenOff }}{{ getWriteOffItemQuantity(item).unit }} / + 剩余 {{ getWriteOffItemQuantity(item).writable }}{{ getWriteOffItemQuantity(item).unit }} / + 总数 {{ getWriteOffItemQuantity(item).total }}{{ getWriteOffItemQuantity(item).unit }} +

+

+ {{ getWriteOffItemAvailability(item).reason }} +

{{ detail.commodityTip }}

@@ -133,9 +155,9 @@ onMounted(loadDetail)
- + - 立即核销 + {{ canGoWriteOff ? '立即核销' : '暂无可核销明细' }}
@@ -242,6 +264,10 @@ onMounted(loadDetail) line-height: 1.5; } +.package-row__warning { + color: var(--rose) !important; +} + .empty-line { padding: 12px; border-radius: var(--radius); diff --git a/src/views/verify/VerifyConfirmView.vue b/src/views/verify/VerifyConfirmView.vue index 0036301..0f95c24 100644 --- a/src/views/verify/VerifyConfirmView.vue +++ b/src/views/verify/VerifyConfirmView.vue @@ -8,25 +8,36 @@ import PageNav from '@/components/PageNav.vue' import StatusTag from '@/components/StatusTag.vue' import type { CommodityPackageConfig, UserOrderDetail } from '@/types/order' import { canWriteOff } from '@/utils/constants' +import { + findWriteOffItem, + getFirstAvailableWriteOffItem, + getWriteOffItemAvailability, + getWriteOffItemContent, + getWriteOffItemId, + getWriteOffItemName, + getWriteOffItemQuantity, + getWriteOffStatusText, + toNumber +} from '@/utils/writeOffItem' +import { + getReusableWriteOffRequestNo, + type WriteOffRequestNoState +} from '@/utils/writeOffRequestNo' const route = useRoute() const router = useRouter() const detail = ref(null) -const packageName = ref('') +const selectedItemId = ref('') +const writeOffRequestNoState = ref({ targetKey: '', requestNo: '' }) const loading = ref(false) const submitting = ref(false) const orderId = computed(() => String(route.query.orderId || '')) const routePackageName = computed(() => String(route.query.packageName || '').trim()) -const isScanPackageLocked = computed(() => String(route.query.source || '') === 'scan' && Boolean(routePackageName.value)) - -const toNumber = (value: unknown) => { - const number = Number(value) - return Number.isFinite(number) ? number : undefined -} - -const getPackageName = (item?: CommodityPackageConfig) => - (item?.packageName || item?.name || detail.value?.commodityName || '').trim() +const routeWriteOffItemId = computed(() => String(route.query.orderWriteOffItemId || '').trim()) +const isScanSource = computed(() => String(route.query.source || '') === 'scan') +const isScanItemLocked = computed(() => isScanSource.value && Boolean(routeWriteOffItemId.value)) +const hasScanMatchCriteria = computed(() => isScanSource.value && Boolean(routeWriteOffItemId.value || routePackageName.value)) const packageConfigs = computed(() => { if (!detail.value) return [] @@ -41,55 +52,62 @@ const packageConfigs = computed(() => { }) const packageOptions = computed(() => { - if (!isScanPackageLocked.value) return packageConfigs.value - return packageConfigs.value.filter((item) => getPackageName(item) === routePackageName.value) + if (isScanSource.value && routeWriteOffItemId.value) { + return packageConfigs.value.filter((item) => getWriteOffItemId(item) === routeWriteOffItemId.value) + } + if (isScanSource.value && routePackageName.value) { + return packageConfigs.value.filter( + (item) => + getWriteOffItemName(item, detail.value?.commodityName) === routePackageName.value || + item.packageName === routePackageName.value + ) + } + return packageConfigs.value }) -const packageMismatch = computed(() => isScanPackageLocked.value && packageOptions.value.length === 0) +const packageMismatch = computed(() => hasScanMatchCriteria.value && packageOptions.value.length === 0) const selectedPackage = computed(() => { - return packageOptions.value.find((item) => getPackageName(item) === packageName.value) || packageOptions.value[0] + return packageOptions.value.find((item) => getWriteOffItemId(item) === selectedItemId.value) || packageOptions.value[0] }) -const writtenOffByRecord = computed(() => { - if (!detail.value) return 0 - const selectedName = getPackageName(selectedPackage.value) - return (detail.value.writeOffRecordList || []).filter((record) => { - if (!selectedName) return true - return !record.packageName || record.packageName === selectedName - }).length -}) +const quantityInfo = computed(() => getWriteOffItemQuantity(selectedPackage.value)) -const quantityInfo = computed(() => { - const total = toNumber(selectedPackage.value?.count) ?? toNumber(detail.value?.commodityAmount) ?? 0 - const packageWriteOffCount = toNumber(selectedPackage.value?.writeOffCount) - const writtenOff = - packageWriteOffCount ?? - (selectedPackage.value?.packageStatus === 1 && total > 0 ? total : writtenOffByRecord.value) - - return { - total, - writtenOff, - writable: Math.max(total - writtenOff, 0), - unit: selectedPackage.value?.unit || '' - } -}) +const selectedItemAvailability = computed(() => getWriteOffItemAvailability(selectedPackage.value)) +const selectedPackageName = computed(() => getWriteOffItemName(selectedPackage.value, detail.value?.commodityName)) const canSubmit = computed(() => { return Boolean( detail.value && canWriteOff(detail.value.orderStatus) && - packageName.value && + selectedItemId.value && !packageMismatch.value && - quantityInfo.value.writable > 0 + selectedItemAvailability.value.available ) }) const formatCount = (value: number) => `${value}${quantityInfo.value.unit || ''}` +const getErrorMessage = (error: unknown) => (error instanceof Error ? error.message : '核销失败') + +const hasShownToast = (error: unknown) => { + return Boolean(error && typeof error === 'object' && (error as { toastShown?: boolean }).toastShown) +} + +const getItemLabel = (item: CommodityPackageConfig) => { + const quantity = getWriteOffItemQuantity(item) + const statusText = getWriteOffStatusText(item) + const parts = [`已核销 ${quantity.writtenOff}${quantity.unit}`, `剩余 ${quantity.writable}${quantity.unit}`] + if (statusText) parts.unshift(statusText) + return parts.join(' · ') +} + +const canSelectItem = (item: CommodityPackageConfig) => { + return !isScanItemLocked.value && getWriteOffItemAvailability(item).available +} const selectPackage = (item: CommodityPackageConfig) => { - if (isScanPackageLocked.value) return - packageName.value = getPackageName(item) + if (!canSelectItem(item)) return + selectedItemId.value = getWriteOffItemId(item) } const loadDetail = async () => { @@ -101,13 +119,13 @@ const loadDetail = async () => { loading.value = true try { detail.value = await fetchOrderDetail(orderId.value) - const matchedPackage = routePackageName.value - ? packageConfigs.value.find((item) => getPackageName(item) === routePackageName.value) - : undefined - packageName.value = - routePackageName.value && (matchedPackage || isScanPackageLocked.value) - ? routePackageName.value - : getPackageName(packageConfigs.value[0]) + const matchedPackage = findWriteOffItem(packageConfigs.value, { + orderWriteOffItemId: routeWriteOffItemId.value, + packageName: routePackageName.value + }) + const firstAvailablePackage = getFirstAvailableWriteOffItem(packageOptions.value) + const fallbackPackage = packageOptions.value[0] || packageConfigs.value[0] + selectedItemId.value = getWriteOffItemId(matchedPackage || firstAvailablePackage || fallbackPackage) } finally { loading.value = false } @@ -120,47 +138,52 @@ const submit = async () => { return } if (packageMismatch.value) { - showToast('扫码套餐不属于当前订单') + showToast(routeWriteOffItemId.value ? '扫码明细不属于当前订单' : '扫码套餐不属于当前订单') return } - if (!packageName.value) { - showToast('请选择核销套餐') + if (!selectedItemId.value || !selectedPackage.value) { + showToast('请选择核销明细') return } - if (quantityInfo.value.writable <= 0) { - showToast('当前套餐商品已核销完') + if (!selectedItemAvailability.value.available) { + showToast(selectedItemAvailability.value.reason) + return + } + try { + await showConfirmDialog({ + title: '确认核销', + message: `订单 ${detail.value.orderId} 将核销「${selectedPackageName.value}」,核销后不可撤回。` + }) + } catch { return } - await showConfirmDialog({ - title: '确认核销', - message: `订单 ${detail.value.orderId} 将核销「${packageName.value}」,核销后不可撤回。` - }) submitting.value = true + const requestNo = getReusableWriteOffRequestNo( + writeOffRequestNoState.value, + `${detail.value.orderId}:${selectedItemId.value}` + ) try { const result = await writeOffOrder({ orderId: detail.value.orderId, - packageName: packageName.value + orderWriteOffItemId: selectedItemId.value, + writeOffRequestNo: requestNo }) router.replace({ path: '/verify/result', query: { success: String(result.success), orderId: result.orderId, - packageName: result.packageName, + orderWriteOffItemId: result.orderWriteOffItemId || selectedItemId.value, + packageName: selectedPackageName.value, message: result.message, operatedAt: result.operatedAt } }) } catch (error) { - router.replace({ - path: '/verify/result', - query: { - success: 'false', - orderId: detail.value.orderId, - packageName: packageName.value, - message: error instanceof Error ? error.message : '核销失败' - } - }) + const message = getErrorMessage(error) + if (!hasShownToast(error)) { + showToast(message) + } } finally { submitting.value = false } @@ -190,25 +213,41 @@ onMounted(loadDetail)

核销内容

- + - + + - @@ -243,6 +282,10 @@ onMounted(loadDetail) 该订单当前不可核销,请返回订单详情核对状态。
+
+ + {{ selectedItemAvailability.reason }} +
@@ -309,6 +352,15 @@ onMounted(loadDetail) line-height: 1.5; } +.package-label { + display: grid; + gap: 3px; +} + +.package-label__warning { + color: var(--rose); +} + .warning-panel { display: flex; gap: 8px; diff --git a/src/views/verify/VerifyView.vue b/src/views/verify/VerifyView.vue index a8a627f..b324fe5 100644 --- a/src/views/verify/VerifyView.vue +++ b/src/views/verify/VerifyView.vue @@ -57,6 +57,7 @@ const goConfirm = (payload: WriteOffCodePayload) => { query: { orderId: payload.orderId, source: 'scan', + ...(payload.orderWriteOffItemId ? { orderWriteOffItemId: payload.orderWriteOffItemId } : {}), ...(payload.packageName ? { packageName: payload.packageName } : {}) } })