恢复账单明细入口并完善采购状态展示
This commit is contained in:
@@ -126,7 +126,7 @@ function transportHarness(kind = 'trucking', failFirst = false, budgetCheck = as
|
||||
const script = view.match(/<script setup lang="ts">([\s\S]*?)<\/script>/)[1]
|
||||
const compiled = ts.transpileModule(script, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText
|
||||
.replace(/^import .*?;$/gm, '').replace(/^export \{\};$/gm, '')
|
||||
const harness = runInNewContext(`${compiled}\n({ form, formRef, submit, detail, detailFields })`, {
|
||||
const harness = runInNewContext(`${compiled}\n({ form, formRef, submit, detail, detailFields, configuration })`, {
|
||||
defineProps: () => ({ kind, createPage: true, detailPage: false }),
|
||||
withDefaults: props => props,
|
||||
computed: getter => ({ get value() { return typeof getter === 'function' ? getter() : getter.get() } }),
|
||||
@@ -176,13 +176,18 @@ test('truck retry submits the complete new contract with identical local times a
|
||||
|
||||
test('truck details render saved minute times and unknown pool demand without timezone conversion', () => {
|
||||
const current = transportHarness()
|
||||
current.detail.value = { summary: { vehicleType: null, pickupAt: '2026-10-20T09:30:00', deliveryAt: null }, originAddress: null, destinationAddress: null, remark: null }
|
||||
current.detail.value = { summary: { vehicleType: null, palletCount: 3, packageCount: 0, pickupAt: '2026-10-20T09:30:00', deliveryAt: null }, originAddress: null, destinationAddress: null, remark: null }
|
||||
const fields = new Map(current.detailFields.value)
|
||||
assert.equal(fields.get('车辆类型'), '—')
|
||||
assert.equal(fields.get('取货时间'), '2026-10-20 09:30')
|
||||
assert.equal(fields.get('送达时间'), '—')
|
||||
assert.equal(fields.has('柜型'), false)
|
||||
assert.equal(fields.has('托盘数'), false)
|
||||
assert.equal(fields.get('托数'), 3)
|
||||
assert.equal(fields.has('件数'), false)
|
||||
const columns = current.configuration.value.columns
|
||||
assert.equal(columns.find(column => column.label === '托数').key, 'palletCount')
|
||||
assert.equal(columns.some(column => column.key === 'packageCount'), false)
|
||||
})
|
||||
|
||||
|
||||
@@ -199,6 +204,12 @@ test('looseboard saves split contacts and both local minute times without obsole
|
||||
assert.equal(payload.destinationContactPhone, '2')
|
||||
assert.equal(payload.deliveryAt, '2026-10-20T15:30:00')
|
||||
assert.equal(payload.idempotencyKey, current.calls[0].payload.idempotencyKey)
|
||||
current.detail.value = { summary: { ...payload }, originAddress: null, destinationAddress: null, remark: null }
|
||||
const fields = new Map(current.detailFields.value)
|
||||
assert.equal(fields.get('件数'), 8)
|
||||
assert.equal(fields.get('预计托数'), 3)
|
||||
assert.equal(fields.has('托数'), false)
|
||||
assert.equal(current.configuration.value.columns.some(column => column.key === 'palletCount'), false)
|
||||
for (const field of ['palletRequired', 'transportType', 'transportMode', 'containerType', 'contactName', 'contactInfo', 'requestedDate']) assert.equal(Object.hasOwn(payload, field), false)
|
||||
})
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ function transportColumns(looseboard: boolean): ColumnDefinition[] {
|
||||
{ key: 'origin', label: originLabel, width: 150 },
|
||||
{ key: 'destination', label: destinationLabel, width: 150 },
|
||||
...(looseboard ? [{ key: 'productName', label: '商品名称', width: 150 }, { key: 'estimatedPalletCount', label: '预计托数', width: 100 }] : []),
|
||||
...(!looseboard ? [{ key: 'palletCount', label: '托数', width: 80 }] : []),
|
||||
{ key: 'totalWeightKg', label: '总重量(kg)', width: 120 },
|
||||
{ key: 'budgetAmount', label: '预算总价', width: 110 },
|
||||
...([
|
||||
@@ -136,7 +137,7 @@ const detailFields = computed(() => {
|
||||
] : [['车辆类型', vehicleTypeLabel(summary.vehicleType)]]),
|
||||
[props.kind === 'trucking' ? '取货地' : '起运地', read(summary, 'origin')], [props.kind === 'trucking' ? '取货地址' : '起运地址', current.originAddress],
|
||||
[props.kind === 'trucking' ? '送达地' : '目的地', read(summary, 'destination')], [props.kind === 'trucking' ? '送达地址' : '目的地址', current.destinationAddress],
|
||||
['件数', read(summary, 'packageCount')], ['总重量(kg)', read(summary, 'totalWeightKg')],
|
||||
[props.kind === 'trucking' ? '托数' : '件数', read(summary, props.kind === 'trucking' ? 'palletCount' : 'packageCount')], ['总重量(kg)', read(summary, 'totalWeightKg')],
|
||||
['总体积(m³)', read(summary, 'totalVolumeCbm')], ['预算总价', money(read(summary, 'budgetAmount'), read(summary, 'currency'))],
|
||||
[props.kind === 'trucking' ? '取货联系人' : '起运地联系人', summary.originContactName], [props.kind === 'trucking' ? '取货联系电话' : '起运地联系电话', summary.originContactPhone],
|
||||
[props.kind === 'trucking' ? '送达联系人' : '目的地联系人', summary.destinationContactName], [props.kind === 'trucking' ? '送达联系电话' : '目的地联系电话', summary.destinationContactPhone],
|
||||
@@ -294,7 +295,7 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
<h2>{{ configuration.title }}下单</h2>
|
||||
|
||||
</div>
|
||||
<el-button @click="returnToList">返回列表</el-button>
|
||||
<el-button v-if="kind === 'looseboard'" @click="returnToList">返回列表</el-button>
|
||||
</header>
|
||||
|
||||
<template v-if="mode === 'list'">
|
||||
|
||||
@@ -6,6 +6,7 @@ import { runInNewContext } from 'node:vm'
|
||||
import ts from 'typescript'
|
||||
import * as vue from 'vue'
|
||||
import { parse, compileScript } from 'vue/compiler-sfc'
|
||||
import { renderToString } from 'vue/server-renderer'
|
||||
|
||||
const { default: Schema } = createRequire(import.meta.resolve('element-plus'))('async-validator')
|
||||
|
||||
@@ -63,6 +64,27 @@ test('new requests get unique keys without restoring stored submissions', () =>
|
||||
|
||||
class ApiError extends Error { constructor(message, code, status) { super(message); this.code = code; this.status = status } }
|
||||
const flush = async () => { await vue.nextTick(); await new Promise(resolve => setImmediate(resolve)); await vue.nextTick() }
|
||||
|
||||
test('shows only the active procurement rejection, hiding it after reupload, resubmission and confirmation', async () => {
|
||||
const source = readFileSync(new URL('./views/ProcurementView.vue', import.meta.url), 'utf8')
|
||||
const template = source.match(/<el-alert\b[^>]*title="采购结果驳回原因"[^>]*\/>/)?.[0]
|
||||
assert.ok(template)
|
||||
for (const [status, photosNeedUpdate, rejectionReason, visible] of [
|
||||
['RECEIVING', true, '照片不清晰', true],
|
||||
['RECEIVING', false, '照片不清晰', true],
|
||||
['RECEIVING', false, null, false],
|
||||
['WAIT_CUSTOMER_CONFIRM', true, '照片不清晰', false],
|
||||
['CONFIRMED', true, '照片不清晰', false],
|
||||
['RECEIVING', true, null, false],
|
||||
]) {
|
||||
const app = vue.createSSRApp({ render: vue.compile(template), setup: () => ({ workflow: { status, photosNeedUpdate, rejectionReason } }) })
|
||||
app.component('ElAlert', { props: ['title', 'description'], setup: props => () => vue.h('aside', `${props.title} ${props.description}`) })
|
||||
const html = await renderToString(app)
|
||||
assert.equal(html.includes('采购结果驳回原因'), visible, `${status}, photosNeedUpdate=${photosNeedUpdate}`)
|
||||
assert.equal(html.includes('照片不清晰'), visible)
|
||||
}
|
||||
})
|
||||
|
||||
function viewHarness({ createPage = false, detailPage = false, api = {}, storage = new Map() } = {}) {
|
||||
const props = vue.reactive({ createPage, detailPage })
|
||||
const route = vue.reactive({ params: { orderNo: detailPage ? 'PO-1' : '' } })
|
||||
|
||||
@@ -164,7 +164,7 @@ onBeforeUnmount(() => { active = false; ++requestSequence })
|
||||
<header class="procurement-heading"><div><el-button link type="primary" @click="returnToList">← 返回列表</el-button><h2>{{ detail?.order.orderNo || '采购订单详情' }}</h2></div><div><el-tag v-if="detail" :type="statusTone(workflow?.status || detail.order.status)">{{ statusLabel(workflow?.status || detail.order.status, detail.order.procurementDirection) }}</el-tag><el-button :disabled="loading" @click="loadDetail">刷新</el-button></div></header>
|
||||
<OrderFundingStatus v-if="detail" kind="procurement" :order-no="detail.order.orderNo" :status="detail.order.status" :can-retry="canCreate" @changed="loadDetail" />
|
||||
<div v-if="error" class="procurement-error" role="alert"><span>{{ error }}</span><el-button :disabled="loading" @click="loadDetail">重新加载</el-button></div>
|
||||
<template v-else-if="detail && workflow"><el-alert v-if="workflow.rejectionReason" title="采购结果驳回原因" :description="workflow.rejectionReason" type="warning" :closable="false" /><ProcurementDetailPanel :detail="detail" :workflow="workflow" /></template><el-skeleton v-else :rows="8" animated />
|
||||
<template v-else-if="detail && workflow"><el-alert v-if="workflow.status === 'RECEIVING' && workflow.rejectionReason" title="采购结果驳回原因" :description="workflow.rejectionReason" type="warning" :closable="false" /><ProcurementDetailPanel :detail="detail" :workflow="workflow" /></template><el-skeleton v-else :rows="8" animated />
|
||||
</section>
|
||||
<section v-else class="procurement-create" aria-label="采购下单">
|
||||
<header class="procurement-create-heading">
|
||||
|
||||
Reference in New Issue
Block a user