优化
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# 本土卡车字段调整核对
|
||||
|
||||
## 2026-11-02 用户截图问题修复
|
||||
|
||||
| 页面 | 操作及承载 | 截图依据与调整 | 验收 |
|
||||
|---|---|---|---|
|
||||
| 美本土散板 | 既有独立详情页 | 本轮第1张截图:地址跨两列时由网格紧密填补空位,备注占满一行,保留所有字段 | 定向测试与类型检查通过;待人工1920×1080、100%截图确认 |
|
||||
| 美国本土卡车 | 既有独立新增页 | 本轮第6、10张截图与文字确认:双地址必填;标题右侧补返回列表,沿用Client新增页按钮外观 | 定向测试与类型检查通过;待人工截图确认 |
|
||||
| 美国本土卡车 | 列表、详情及状态筛选 | 本轮第7、11张截图:补齐当前正式状态中文文案,DISPATCHED显示待取货 | 当前全部正式状态的定向测试通过 |
|
||||
|
||||
依据:用户提供的下单页截图 `codex-clipboard-c458c2e1-e9a8-4726-a8cd-4581e5e7102f.png` 及本轮字段、必填和时分确认。当前需求规则见 `docs/海外仓业务/README.md`“美国本土卡独立下单”。
|
||||
|
||||
| 页面 | 操作 | 依据及承载 | 当前调整 | 验收 |
|
||||
|
||||
@@ -165,3 +165,8 @@ export function updateTransport(kind: CrossBorderBusinessKind, orderNo: string,
|
||||
data: payload,
|
||||
})
|
||||
}
|
||||
|
||||
/** 客户按当前版本取消待审核本土卡车订单。 */
|
||||
export function cancelTruckOrder(orderNo: string, payload: { version: number; status: 'CANCELLED'; idempotencyKey: string; remark: string }) {
|
||||
return apiRequest<TransportDetail>({ method: 'PATCH', url: endpointByKind.trucking + '/' + encodeURIComponent(orderNo) + '/status', data: payload })
|
||||
}
|
||||
|
||||
@@ -13,6 +13,19 @@ const demandHelpers = runInNewContext(`${demandLogic}\n({ createTransportDemandF
|
||||
const procurementApi = readFileSync(new URL('./api/procurement.ts', import.meta.url), 'utf8')
|
||||
const procurementView = readFileSync(new URL('./views/ProcurementView.vue', import.meta.url), 'utf8')
|
||||
|
||||
test('all current truck statuses display Chinese labels in lists and details', () => {
|
||||
const labelsCode = ts.transpileModule(readFileSync(new URL('./fleetArrangement.ts', import.meta.url), 'utf8'), { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText.replace(/^export /gm, '')
|
||||
const { poolOrderStatusLabels } = runInNewContext(`${labelsCode}\n({ poolOrderStatusLabels })`)
|
||||
const helpers = view.slice(view.indexOf('function read('), view.indexOf('function idempotencyKey('))
|
||||
const compiled = ts.transpileModule(helpers, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText
|
||||
const { statusLabel, displayCell } = runInNewContext(`${compiled}\n({ statusLabel, displayCell })`, { poolOrderStatusLabels })
|
||||
for (const status of ['PENDING_REVIEW', 'FUNDING_PENDING', 'FUNDING_FAILED', 'WAITING_INBOUND', 'RECEIVING', 'WAITING_CONSOLIDATION', 'PALLET_OVERAGE_REVIEW', 'PARTIALLY_ALLOCATED', 'ALLOCATED', 'PENDING_DISPATCH', 'DISPATCHED', 'IN_TRANSIT', 'COMPLETED', 'REJECTED', 'CANCELLED']) {
|
||||
assert.match(statusLabel(status), /[\u4e00-\u9fff]/, status)
|
||||
assert.equal(displayCell({ status }, 'status'), statusLabel(status))
|
||||
}
|
||||
assert.equal(statusLabel('DISPATCHED'), '待取货')
|
||||
})
|
||||
|
||||
test('renders unknown pallet service and container type as dashes while preserving explicit values', () => {
|
||||
const helpers = view.slice(view.indexOf('function read('), view.indexOf('function idempotencyKey('))
|
||||
const compiled = ts.transpileModule(helpers, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText
|
||||
@@ -136,6 +149,7 @@ function transportHarness(kind = 'trucking', failFirst = false, budgetCheck = as
|
||||
ElMessage: { success: () => {}, error: () => {} },
|
||||
createTransport: async (business, payload) => { calls.push({ business, payload: { ...payload } }); if (failFirst && calls.length === 1) throw new Error('retry'); },
|
||||
})
|
||||
Object.assign(harness.form, { deliveryMode: 'WAREHOUSE_PICKUP', operatingWarehouseId: '9', destinationType: 'FBA', originAddress: '123 Pickup Road', destinationAddress: '456 Delivery Road' })
|
||||
harness.formRef.value = { validate: async () => true, clearValidate: () => {} }
|
||||
return { ...harness, calls, rules: { get value() { return demandHelpers.transportDemandRules(kind === 'trucking' ? 'truck' : 'looseboard', harness.form) } } }
|
||||
}
|
||||
@@ -230,3 +244,17 @@ test('truck creation does not block on a separate budget reservation', async ()
|
||||
await current.submit()
|
||||
assert.equal(current.calls.length, 1)
|
||||
})
|
||||
|
||||
|
||||
test('customer truck cancellation uses encoded order identity and current version without client scope', async () => {
|
||||
const compiled = ts.transpileModule(api.replace(/^import .*$/gm, ''), { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText.replace(/^export /gm, '')
|
||||
let sent
|
||||
const { cancelTruckOrder } = runInNewContext(compiled + '\n({ cancelTruckOrder })', { apiRequest: input => { sent = input; return Promise.resolve({}) } })
|
||||
const payload = { version: 3, status: 'CANCELLED', idempotencyKey: 'cancel-1', remark: '客户取消' }
|
||||
await cancelTruckOrder('TR/1', payload)
|
||||
assert.equal(sent.method, 'PATCH')
|
||||
assert.equal(sent.url, '/merchant/v1/last-leg/us-truck-orders/TR%2F1/status')
|
||||
assert.equal(sent.data, payload)
|
||||
assert.match(view, /summary.status === 'PENDING_REVIEW'/)
|
||||
assert.match(view, /merchant:cross-border:domestic-trucking:edit/)
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, type FormInstance } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox, type FormInstance } from 'element-plus'
|
||||
import TransportDemandForm from './TransportDemandForm.vue'
|
||||
import OrderFundingStatus from './OrderFundingStatus.vue'
|
||||
import { createTransportDemandForm, transportDemandError, buildTransportDemand, type TransportDemandForm as DemandFormModel } from '../transportDemandForm'
|
||||
@@ -10,6 +10,7 @@ import QueryToolbar, { type QueryField, type QueryModel } from '@/components/com
|
||||
import type { TableAction } from '@/components/common/tableActions'
|
||||
import { useAuthStore } from '@/modules/auth/public'
|
||||
import {
|
||||
cancelTruckOrder,
|
||||
createTransport,
|
||||
getBusinessOrder,
|
||||
listBusinessOrders,
|
||||
@@ -108,7 +109,17 @@ const queryFields = computed<QueryField[]>(() => [
|
||||
label: '状态',
|
||||
type: 'select',
|
||||
placeholder: '全部',
|
||||
options: [
|
||||
options: props.kind === 'trucking' ? [
|
||||
{ label: '订单受理中', value: 'FUNDING_PENDING' },
|
||||
{ label: '订单处理失败', value: 'FUNDING_FAILED' },
|
||||
{ label: '待审核', value: 'PENDING_REVIEW' },
|
||||
{ label: '待排车', value: 'PENDING_DISPATCH' },
|
||||
{ label: '待取货', value: 'DISPATCHED' },
|
||||
{ label: '运输中', value: 'IN_TRANSIT' },
|
||||
{ label: '已完成', value: 'COMPLETED' },
|
||||
{ label: '已拒绝', value: 'REJECTED' },
|
||||
{ label: '已取消', value: 'CANCELLED' },
|
||||
] : [
|
||||
{ label: '订单受理中', value: 'FUNDING_PENDING' },
|
||||
{ label: '订单处理失败', value: 'FUNDING_FAILED' },
|
||||
{ label: '待审核', value: 'PENDING_REVIEW' },
|
||||
@@ -155,6 +166,24 @@ const tableColumns = computed<DataTableColumn[]>(() => [
|
||||
})),
|
||||
])
|
||||
|
||||
const canCancelTruck = computed(() => props.kind === 'trucking' && detail.value?.summary.status === 'PENDING_REVIEW'
|
||||
&& auth.hasPermission('merchant:cross-border:domestic-trucking:edit'))
|
||||
/** 取消前核对客户意愿,失败保留订单并刷新服务端状态。 */
|
||||
async function cancelTruck() {
|
||||
if (!canCancelTruck.value || !detail.value || submitting.value) return
|
||||
let reason: string
|
||||
try {
|
||||
const result = await ElMessageBox.prompt('请填写取消原因', '取消订单', { inputValidator: value => Boolean(value?.trim()) || '请填写取消原因', confirmButtonText: '确认取消', cancelButtonText: '保留订单', type: 'warning' })
|
||||
reason = result.value.trim()
|
||||
} catch { return }
|
||||
submitting.value = true
|
||||
try {
|
||||
detail.value = await cancelTruckOrder(detail.value.summary.orderNo, { version: detail.value.summary.version, status: 'CANCELLED', idempotencyKey: idempotencyKey(), remark: reason })
|
||||
ElMessage.success('订单已取消')
|
||||
} catch (cause) { ElMessage.error(errorMessage(cause)); await loadDetail() }
|
||||
finally { submitting.value = false }
|
||||
}
|
||||
|
||||
const detailStatus = computed(() => detail.value ? statusLabel(detail.value.summary.status) : '—')
|
||||
|
||||
function emptyForm(): BusinessForm { return createTransportDemandForm() }
|
||||
@@ -224,7 +253,8 @@ function getRowActions(candidate: object): TableAction[] {
|
||||
}
|
||||
|
||||
function detailFieldClass(label: unknown) {
|
||||
return ['备注', props.kind === 'trucking' ? '取货地址' : '起运地址', props.kind === 'trucking' ? '送达地址' : '目的地址'].includes(String(label)) ? 'is-wide' : ''
|
||||
if (label === '备注') return 'is-full'
|
||||
return [props.kind === 'trucking' ? '取货地址' : '起运地址', props.kind === 'trucking' ? '送达地址' : '目的地址'].includes(String(label)) ? 'is-wide' : ''
|
||||
}
|
||||
|
||||
const listRouteName = computed(() => ({
|
||||
@@ -295,7 +325,7 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
<h2>{{ configuration.title }}下单</h2>
|
||||
|
||||
</div>
|
||||
<el-button v-if="kind === 'looseboard'" @click="returnToList">返回列表</el-button>
|
||||
<el-button @click="returnToList">返回列表</el-button>
|
||||
</header>
|
||||
|
||||
<template v-if="mode === 'list'">
|
||||
@@ -315,13 +345,13 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
<section v-else-if="mode === 'detail'" class="business-detail-page" aria-label="订单详情">
|
||||
<header class="business-detail-heading">
|
||||
<div class="business-detail-heading-main"><el-button link type="primary" @click="returnToList">← 返回列表</el-button><div><h2>{{ detail?.summary.orderNo || '订单详情' }}</h2></div></div>
|
||||
<div class="business-detail-heading-actions"><el-tag :type="statusTone(detail?.summary.status)" effect="light">{{ detailStatus }}</el-tag><el-button :disabled="loading" @click="loadDetail">刷新</el-button></div>
|
||||
<div class="business-detail-heading-actions"><el-button v-if="canCancelTruck" type="danger" :loading="submitting" :disabled="loading" @click="cancelTruck">取消订单</el-button><el-tag :type="statusTone(detail?.summary.status)" effect="light">{{ detailStatus }}</el-tag><el-button :disabled="loading" @click="loadDetail">刷新</el-button></div>
|
||||
</header>
|
||||
<OrderFundingStatus v-if="kind === 'trucking' && detail" kind="trucking" :order-no="detail.summary.orderNo" :status="detail.summary.status" :can-retry="canCreate" @changed="loadDetail" />
|
||||
<div v-if="error" class="business-detail-error" role="alert"><strong>{{ error }}</strong><el-button size="small" @click="loadDetail">重新加载</el-button></div>
|
||||
<section v-else class="business-detail-section">
|
||||
<h3>订单信息</h3>
|
||||
<dl class="detail-grid" :class="{ 'trucking-detail-grid': kind === 'trucking' }">
|
||||
<dl class="detail-grid" :class="{ 'trucking-detail-grid': kind === 'trucking', 'looseboard-detail-grid': kind === 'looseboard' }">
|
||||
<div v-for="field in detailFields" :key="String(field[0])" :class="detailFieldClass(field[0])"><dt>{{ field[0] }}</dt><dd>{{ text(field[1]) }}</dd></div>
|
||||
</dl>
|
||||
</section>
|
||||
@@ -374,6 +404,8 @@ onMounted(() => { if (props.detailPage) void loadDetail(); else if (!props.creat
|
||||
.detail-grid div { display: grid; min-width: 0; min-height: 34px; grid-template-columns: 76px minmax(0, 1fr); align-items: center; gap: 7px; padding: 3px 8px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); }
|
||||
.trucking-detail-grid div { grid-template-columns: 112px minmax(0, 1fr); }
|
||||
.detail-grid div.is-wide { grid-column: span 2; }
|
||||
.detail-grid div.is-full { grid-column: 1 / -1; }
|
||||
.looseboard-detail-grid { grid-auto-flow: row dense; }
|
||||
.detail-grid dt { color: var(--muted); font-size: 10px; white-space: nowrap; }
|
||||
.arrangement-grid div { grid-template-columns: 124px minmax(0, 1fr); }
|
||||
.arrangement-grid dt { white-space: normal; overflow-wrap: anywhere; }
|
||||
|
||||
@@ -71,7 +71,7 @@ defineExpose({
|
||||
</template>
|
||||
<el-form-item :label="kind === 'truck' ? '送达联系电话' : '目的地联系电话'" prop="destinationContactPhone"><el-input v-model.trim="model.destinationContactPhone" type="tel" maxlength="128" :placeholder="isCreate ? (kind === 'truck' ? '请输入送达联系电话' : '请输入目的地联系电话') : ''" /></el-form-item>
|
||||
<el-form-item v-if="kind === 'truck' || model.deliveryMode === 'WAREHOUSE_PICKUP'" class="transport-demand-address" :label="kind === 'truck' ? '取货地址' : '起运详细地址'" prop="originAddress"><el-input v-model.trim="model.originAddress" maxlength="500" placeholder="请输入详细地址" /></el-form-item>
|
||||
<el-form-item class="transport-demand-address" :label="kind === 'truck' ? '送达地址' : '目的详细地址'" prop="destinationAddress"><el-input v-model.trim="model.destinationAddress" maxlength="500" :placeholder="kind === 'looseboard' && model.destinationType === 'PRIVATE' ? '请输入目的详细地址' : '街道 / 门牌等补充信息(选填)'" /></el-form-item>
|
||||
<el-form-item class="transport-demand-address" :label="kind === 'truck' ? '送达地址' : '目的详细地址'" prop="destinationAddress"><el-input v-model.trim="model.destinationAddress" maxlength="500" :placeholder="kind === 'truck' ? '请输入详细地址' : model.destinationType === 'PRIVATE' ? '请输入目的详细地址' : '街道 / 门牌等补充信息(选填)'" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
<section class="transport-demand-section">
|
||||
|
||||
@@ -24,5 +24,6 @@ export interface FleetArrangement {
|
||||
}
|
||||
export const poolOrderStatusLabels: Record<string, string> = {
|
||||
WAITING_INBOUND: '待入仓', RECEIVING: '收货中', WAITING_CONSOLIDATION: '待合托',
|
||||
PALLET_OVERAGE_REVIEW: '托数超量待审核', PARTIALLY_ALLOCATED: '部分已排车', ALLOCATED: '已排车', DISPATCHED: '待取货',
|
||||
PENDING_DISPATCH: '待派车', IN_TRANSIT: '运输中', COMPLETED: '已完成', CANCELLED: '已取消',
|
||||
}
|
||||
|
||||
@@ -6,8 +6,19 @@ import ts from 'typescript'
|
||||
|
||||
const source = readFileSync(new URL('./transportDemandForm.ts', import.meta.url), 'utf8')
|
||||
const code = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText.replace(/^export /gm, '')
|
||||
const { createTransportDemandForm, transportDemandError, buildTransportDemand } = runInNewContext(`${code}\n({ createTransportDemandForm, transportDemandError, buildTransportDemand })`)
|
||||
const valid = () => ({ ...createTransportDemandForm(), deliveryMode: 'WAREHOUSE_PICKUP', operatingWarehouseId: '9', destinationType: 'FBA', packageCount: 8, vehicleType: 'PALLET_15', estimatedPalletCount: 3, budgetAmount: 100, origin: ' LA ', originAddress: '123 Test Road', destination: ' ONT ', originContactName: ' 发货人 ', originContactPhone: ' +1-555-0100 ', destinationContactName: ' 收货人 ', destinationContactPhone: ' +1-555-0101 ', pickupAt: '2026-10-20T09:30:45', deliveryAt: '2026-10-20T15:45:12' })
|
||||
const { createTransportDemandForm, transportDemandRules, transportDemandError, buildTransportDemand } = runInNewContext(`${code}\n({ createTransportDemandForm, transportDemandRules, transportDemandError, buildTransportDemand })`)
|
||||
const valid = () => ({ ...createTransportDemandForm(), deliveryMode: 'WAREHOUSE_PICKUP', operatingWarehouseId: '9', destinationType: 'FBA', packageCount: 8, vehicleType: 'PALLET_15', estimatedPalletCount: 3, budgetAmount: 100, origin: ' LA ', originAddress: '123 Test Road', destinationAddress: '456 Delivery Road', destination: ' ONT ', originContactName: ' 发货人 ', originContactPhone: ' +1-555-0100 ', destinationContactName: ' 收货人 ', destinationContactPhone: ' +1-555-0101 ', pickupAt: '2026-10-20T09:30:45', deliveryAt: '2026-10-20T15:45:12' })
|
||||
|
||||
test('truck requires both full addresses in form validation and submission', () => {
|
||||
for (const [field, label] of [['originAddress', '取货地址'], ['destinationAddress', '送达地址']]) {
|
||||
for (const value of ['', ' ']) {
|
||||
const form = { ...valid(), [field]: value }
|
||||
assert.equal(transportDemandRules('truck', form)[field][0].required, true)
|
||||
assert.equal(transportDemandError('truck', form), `请输入${label}`)
|
||||
assert.throws(() => buildTransportDemand('truck', form), new RegExp(label))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('delivery to warehouse permits no tracking number while requiring receiving contacts and arrival time', () => {
|
||||
const form = { ...valid(), deliveryMode: 'DELIVERY_TO_WAREHOUSE', deliveryContactName: '仓库收货员', deliveryContactPhone: '10003', estimatedArrivalAt: '2026-10-20T09:00:00', trackingNo: '' }
|
||||
|
||||
@@ -42,6 +42,7 @@ export function createTransportDemandForm(): TransportDemandForm {
|
||||
}
|
||||
|
||||
const requiredText = (kind: TransportDemandKind, form: TransportDemandForm) => ({
|
||||
...(kind === 'truck' ? { originAddress: '取货地址', destinationAddress: '送达地址' } : {}),
|
||||
...(kind === 'truck' || form.deliveryMode === 'WAREHOUSE_PICKUP' ? { origin: kind === 'truck' ? '取货地' : '起运地', originContactName: kind === 'truck' ? '取货联系人' : '起运地联系人', originContactPhone: kind === 'truck' ? '取货联系电话' : '起运地联系电话' } : {}),
|
||||
destination: kind === 'truck' ? '送达地' : '目的地',
|
||||
destinationContactName: kind === 'truck' ? '送达联系人' : '目的地联系人',
|
||||
|
||||
@@ -13,7 +13,7 @@ export const overseasWarehouseModule = {
|
||||
{
|
||||
path: 'overseas-warehouse/cargo-disposal/create', name: 'overseas-cargo-disposal-create',
|
||||
component: () => import('./views/WarehouseServiceView.vue'), props: { service: 'disposal', createPage: true }, release: 'active',
|
||||
meta: { title: '新增货物废弃申请', workspaceTitle: '货物废弃 · 新建', description: '填写并提交货物废弃申请', permission: 'merchant:overseas-warehouse:discard:create', keepAlive: false },
|
||||
meta: { title: '货物废弃', workspaceTitle: '货物废弃 · 新建', description: '填写并提交货物废弃申请', permission: 'merchant:overseas-warehouse:discard:create', keepAlive: false },
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
@@ -252,7 +252,6 @@ async function printReturnLabel(receipt: ReturnReceipt | ReturnReceipt[]) {
|
||||
}
|
||||
function openDetail(returnNo: string) { void router.push({ name: 'overseas-return-relabel-detail', params: { returnNo } }) }
|
||||
function returnToList() { void router.push({ name: 'overseas-return-relabel' }) }
|
||||
function cancelCreate() { resetForm(); void router.push({ name: 'overseas-return-relabel' }) }
|
||||
function canApplyRelabel(order: { status?: unknown; needRelabel?: unknown; relabelNo?: unknown }) { return order.status === 'COMPLETED' && order.needRelabel === true && !order.relabelNo }
|
||||
function openRelabel(order: Pick<ReturnOrderSummary, 'returnNo' | 'overseasWarehouseId'>, cartonMark?: string) {
|
||||
void router.push({ name: 'overseas-labeling-create', query: { returnNo: order.returnNo, warehouseId: String(order.overseasWarehouseId), ...(cartonMark ? { cartonMark } : {}) } })
|
||||
@@ -354,7 +353,7 @@ onBeforeUnmount(clearPhotoUrls)
|
||||
</div>
|
||||
</section>
|
||||
</el-form>
|
||||
<footer class="return-create-actions"><el-button :disabled="creating" @click="cancelCreate">返回列表</el-button><el-button type="primary" :loading="creating" @click="submit">提交预报</el-button></footer>
|
||||
<footer class="return-create-actions"><el-button type="primary" :loading="creating" @click="submit">提交预报</el-button></footer>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ const listQueryModel = computed<QueryModel>({
|
||||
const statusOptions = computed(() => props.service === 'labeling'
|
||||
? [{ label: '待审核', value: 'PENDING_REVIEW' }, { label: '待处理', value: 'PENDING_PROCESSING' }, { label: '处理中', value: 'PROCESSING' }, { label: '换标完成', value: 'COMPLETED' }, { label: '已驳回', value: 'REJECTED' }]
|
||||
: props.service === 'disposal'
|
||||
? [{ label: '待审核', value: 'PENDING_REVIEW' }, { label: '待 PDA 废弃', value: 'APPROVED' }, { label: '待客户确认', value: 'PDA_COMPLETED' }, { label: '已完成', value: 'COMPLETED' }, { label: '已拒绝', value: 'REJECTED' }, { label: '已取消', value: 'CANCELLED' }]
|
||||
? [{ label: '待审核', value: 'PENDING_REVIEW' }, { label: '已审核', value: 'APPROVED' }, { label: '待客户确认', value: 'PDA_COMPLETED' }, { label: '已完成', value: 'COMPLETED' }, { label: '已驳回', value: 'REJECTED' }, { label: '已取消', value: 'CANCELLED' }]
|
||||
: props.service === 'transfer'
|
||||
? [{ label: '草稿', value: 'DRAFT' }, { label: '待审核', value: 'PENDING_REVIEW' },
|
||||
{ label: '待PDA收货', value: 'WAIT_PDA_RECEIVING' }, { label: '入库测量中', value: 'INBOUND_MEASURING' },
|
||||
@@ -1049,7 +1049,7 @@ function statusLabel(value: string) {
|
||||
|
||||
PENDING_PROCESSING: '待处理', PROCESSING: '处理中', CUSTOMER_CONFIRM_PENDING: '待客户确认',
|
||||
READY_FOR_OUTBOUND: '换标完成', COMPLETED: '已完成', CANCELLED: '已取消',
|
||||
DRAFT: '草稿', PENDING_REVIEW: '待审核', APPROVED: '待 PDA 废弃', PDA_COMPLETED: '待客户确认', REJECTED: '已拒绝', PENDING_ASSIGNMENT: '待分配',
|
||||
DRAFT: '草稿', PENDING_REVIEW: '待审核', APPROVED: '已审核', PDA_COMPLETED: '待客户确认', REJECTED: '已驳回', PENDING_ASSIGNMENT: '待分配',
|
||||
WAIT_PDA_RECEIVING: '待PDA收货', WAIT_CUSTOMER_CONFIRMATION: '待客户确认实测', WAIT_FBA_DESTINATION: '待确认目的地', WAIT_RELABEL: '待换标', READY_FOR_DISPATCH: '待排车', WAIT_OUTBOUND: '待出库',
|
||||
ALLOCATED: '已分配', OUTBOUNDED: '已出库', PARTIALLY_RECEIVED: '部分收货', RECEIVED: '已收货', INBOUND_COMPLETED: '入库完成', PENDING_DELIVERY: '待派送', DELIVERING: '派送中', DELIVERED: '派送完成',
|
||||
|
||||
@@ -1743,7 +1743,7 @@ function addReturnBoxBinding(source: RelabelInventoryCandidate) {
|
||||
</template>
|
||||
|
||||
<template v-else-if="mode === 'create' || mode === 'edit'">
|
||||
<div class="warehouse-page-heading"><h2>{{ mode === 'edit' ? `编辑转运草稿 ${editingTransferNo}` : config.createTitle }}</h2><el-button @click="returnToList"><ArrowLeft :size="16" />返回列表</el-button></div>
|
||||
<div class="warehouse-page-heading"><h2 v-if="props.service !== 'disposal'">{{ mode === 'edit' ? `编辑转运草稿 ${editingTransferNo}` : config.createTitle }}</h2><el-button @click="returnToList"><ArrowLeft :size="16" />返回列表</el-button></div>
|
||||
<component :is="isServiceCreate ? ElForm : 'form'" ref="labelingFormRef" :model="isLabelingCreate ? labelingFormModel : isTransferCreate ? transferFormModel : isDisposalCreate ? disposalFormModel : undefined" :rules="isLabelingCreate ? labelingFormRules : isTransferCreate ? transferFormRules : isDisposalCreate ? disposalFormRules : undefined" :disabled="isServiceCreate ? saving : undefined" label-position="top" :validate-on-rule-change="false" :scroll-to-error="isServiceCreate" :class="{ 'warehouse-transfer-form': props.service === 'transfer', 'warehouse-transfer-form--relabel': props.service === 'transfer' && form.relabel }" :style="props.service === 'transfer' ? { '--transfer-left': `${transferPaneShare}fr`, '--transfer-right': `${100 - transferPaneShare}fr` } : undefined" @submit.prevent="submit('submit')">
|
||||
<div id="transfer-main-pane" class="warehouse-card warehouse-form-section warehouse-transfer-main-card">
|
||||
<div v-if="isTransferCreate || isDisposalCreate" class="warehouse-order-info-heading"><h3>{{ isTransferCreate ? '转运信息' : '基础信息' }}</h3></div>
|
||||
@@ -1981,7 +1981,7 @@ function addReturnBoxBinding(source: RelabelInventoryCandidate) {
|
||||
<div v-else class="warehouse-table-scroll"><table class="warehouse-edit-table warehouse-transfer-mark-table"><thead><tr><th>仓库唛头 *</th><th>旧 SKU *</th><th>新 SKU *</th><th>换标数量(件)*</th><th>新 FBA 箱唛 *</th><th>备注</th><th>操作</th></tr></thead><tbody><tr v-for="row in transferRelabelRows" :key="row.id"><td><el-input v-model="row.customerCartonMarks" :placeholder="isTransferCreate ? '请输入仓库唛头' : ''" /></td><td><el-input :model-value="row.sku" readonly /></td><td><el-input v-model="row.newSkuCode" :placeholder="isTransferCreate ? '请输入新 SKU' : ''" /></td><td><el-input-number v-model="row.quantity" :min="1" :precision="0" controls-position="right" :placeholder="isTransferCreate ? '请输入数量' : ''" /></td><td><el-input v-model="row.fbaCartonMark" :placeholder="isTransferCreate ? '请输入新 FBA 箱唛' : ''" /></td><td><el-input v-model="row.remark" type="textarea" :rows="2" :placeholder="isTransferCreate ? '选填' : ''" /></td><td><button type="button" class="warehouse-delete" title="删除该明细" @click="transferRelabelRows = transferRelabelRows.filter((item) => item.id !== row.id)"><Trash2 :size="16" />删除</button></td></tr><tr v-if="transferRelabelRows.length === 0"><td colspan="7"><div class="warehouse-empty">暂无绑定明细</div></td></tr></tbody></table></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="warehouse-submit-bar warehouse-transfer-submit-bar"><el-button v-if="isServiceCreate" native-type="button" :disabled="saving" @click="returnToList">返回列表</el-button><el-button v-if="mode === 'create'" native-type="button" @click="resetForm">重置</el-button><el-button v-if="props.service === 'transfer' && !inventoryTransfer" native-type="button" :loading="saving" @click="submit('draft')">保存草稿</el-button><el-button v-if="props.service === 'transfer'" type="primary" native-type="submit" :loading="saving">提交订单</el-button><el-button v-if="props.service !== 'transfer'" type="primary" native-type="submit" :loading="saving">提交{{ config.title }}</el-button></div>
|
||||
<div class="warehouse-submit-bar warehouse-transfer-submit-bar"><el-button v-if="mode === 'create'" native-type="button" @click="resetForm">重置</el-button><el-button v-if="props.service === 'transfer' && !inventoryTransfer" native-type="button" :loading="saving" @click="submit('draft')">保存草稿</el-button><el-button v-if="props.service === 'transfer'" type="primary" native-type="submit" :loading="saving">提交订单</el-button><el-button v-if="props.service !== 'transfer'" type="primary" native-type="submit" :loading="saving">提交{{ config.title }}</el-button></div>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
@@ -2336,6 +2336,7 @@ function addReturnBoxBinding(source: RelabelInventoryCandidate) {
|
||||
font: 14px/1.5 "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
|
||||
}
|
||||
.warehouse-create .warehouse-page-heading { margin-bottom: 12px; }
|
||||
.warehouse-create .warehouse-page-heading :deep(.el-button) { margin-left: auto; }
|
||||
.warehouse-create .warehouse-page-heading h2 { margin: 0; color: #1f2937; font-size: 26px; font-weight: 700; }
|
||||
.warehouse-create .warehouse-form-section { min-width: 0; margin-bottom: 12px; padding: 0; border: 0; background: transparent; box-shadow: none; }
|
||||
.warehouse-create .warehouse-order-info-heading,
|
||||
|
||||
Reference in New Issue
Block a user