This commit is contained in:
2026-09-21 11:17:17 +08:00
parent cec0027376
commit e4f02c5e73
9 changed files with 66 additions and 26 deletions
+8 -6
View File
@@ -4,6 +4,7 @@
<scroll-view class="fulfillment-scroll" scroll-y>
<view class="portal-content fulfillment-content">
<view class="fulfillment-heading"><text class="fulfillment-title">出库任务</text><text class="fulfillment-subtitle">一件代发扫描托盘码可整托出库;扫描排车业务号会转入“排车拣货”</text></view>
<view v-if="current" class="detail-toolbar"><view><text class="detail-kicker">当前任务</text><text class="detail-title">出库作业详情</text></view><button :disabled="busy" @tap="closeTask">‹ 返回列表</button></view>
<view class="fulfillment-card">
<ScanTargetInput name="outbound" :model-value="scanCode" label="任务号、出库单号、排车单号、托盘码或箱码" placeholder="扫描任务号 / 出库单号 / 排车单号 / 托盘码 / 箱码" :active="true" @update:modelValue="updateScanCode" @submit="handleScan" />
<button class="secondary-button" :disabled="!scanCode || loading || busy" @tap="handleScan(scanCode)">{{ current ? '匹配出库货物' : '打开出库任务' }}</button>
@@ -14,15 +15,15 @@
<view v-else-if="error" class="fulfillment-error" role="alert"><text class="state-title">{{ error.message }}</text><text v-if="error.code">错误码:{{ error.code }}</text><text v-if="error.requestId">requestId:{{ error.requestId }}</text><text v-if="error.traceId">traceId:{{ error.traceId }}</text><text v-if="error.network" class="offline-note">网络连接失败,当前任务、扫码草稿和幂等键均已保留。</text><button class="secondary-button" :disabled="loading || busy" @tap="retry">重试</button></view>
<template v-if="!loading && !current">
<view class="list-toolbar"><text>待处理出库任务</text><button :disabled="loading" @tap="loadTasks">刷新</button></view>
<view class="list-toolbar"><view><text class="list-title">待处理出库任务</text><text class="list-count">{{ tasks.length }} 个任务</text></view><button :disabled="loading" @tap="loadTasks">刷新</button></view>
<view v-if="tasks.length" class="task-list">
<button v-for="task in tasks" :key="task.taskNo" class="task-card" @tap="openTask(task.taskNo)"><view class="task-head"><text class="business-code">{{ task.taskNo || '—' }}</text><text class="status-badge">{{ statusLabel(task.status) }}</text></view><text class="task-meta">出库单 {{ task.outboundNo || '—' }} · {{ taskType(task) }}</text></button>
<button v-for="task in tasks" :key="task.taskNo" class="task-card" @tap="openTask(task.taskNo)"><view class="task-head"><view class="task-code-row"><text class="business-code">{{ task.taskNo || '—' }}</text><text v-if="task.taskNo === recentTaskNo" class="recent-badge">上次作业</text></view><text class="status-badge">{{ statusLabel(task.status) }}</text></view><text class="task-meta">出库单 {{ task.outboundNo || '—' }} · {{ taskType(task) }}</text><text class="task-enter">查看并开始出库 ›</text></button>
</view>
<view v-else-if="!error" class="fulfillment-state"><text class="state-title">暂无出库任务</text><text>可刷新列表,或扫描任务号恢复未完成作业。</text></view>
</template>
<template v-if="current">
<view class="fulfillment-card summary-card"><view class="task-head"><text class="business-code">{{ current.taskNo || '—' }}</text><text class="status-badge">{{ statusLabel(current.status) }}</text></view><text class="task-meta">出库单 {{ current.outboundNo || '—' }} · {{ taskType(current) }}</text><view class="metrics"><view><text class="metric-value">{{ plannedPackages }}</text><text>计划箱数</text></view><view><text class="metric-value success">{{ pickedPackages }}</text><text>已拣箱数</text></view><view><text class="metric-value warning">{{ remainingPackages }}</text><text>待拣箱数</text></view></view><button class="link-button" :disabled="busy" @tap="closeTask">返回任务列表</button></view>
<view class="fulfillment-card summary-card"><view class="task-head"><text class="business-code">{{ current.taskNo || '—' }}</text><text class="status-badge">{{ statusLabel(current.status) }}</text></view><text class="task-meta">出库单 {{ current.outboundNo || '—' }} · {{ taskType(current) }}</text><view class="metrics"><view><text class="metric-value">{{ plannedPackages }}</text><text>计划箱数</text></view><view><text class="metric-value success">{{ pickedPackages }}</text><text>已拣箱数</text></view><view><text class="metric-value warning">{{ remainingPackages }}</text><text>待拣箱数</text></view></view></view>
<view v-if="current.items.length" class="item-list">
<view v-for="item in current.items" :key="item.outboundPalletItemId" class="fulfillment-card item-card">
@@ -57,8 +58,9 @@
export default {
components: { PortalHeader, ScanTargetInput },
data() { return { user: session.currentUser, tasks: [], current: null, selectedItem: null, selectedPosition: null, scanCode: '', loading: false, busy: false, busyAction: '', error: null, successMessage: '' } },
data() { return { user: session.currentUser, tasks: [], current: null, selectedItem: null, selectedPosition: null, scanCode: '', loading: false, busy: false, busyAction: '', error: null, successMessage: '', bootstrapped: false } },
computed: {
recentTaskNo() { return fulfillment.outbound.currentTaskNo || '' },
packages() { return fulfillment.outbound.packages },
plannedPackages() { return (this.current?.items || []).reduce((total, item) => total + item.plannedPackages, 0) },
pickedPackages() { return (this.current?.items || []).reduce((total, item) => total + item.pickedPackages, 0) },
@@ -67,7 +69,7 @@
canPick() { return this.current?.status !== 'COMPLETED' && this.selectedItem && this.selectedPosition && Number(this.packages) > 0 && Number(this.packages) <= this.selectedRemaining },
canComplete() { return this.plannedPackages > 0 && this.remainingPackages === 0 && this.current?.status !== 'COMPLETED' }
},
onShow() { if (!requireSession()) return; this.user = session.currentUser; restoreFulfillmentDraft(`${this.user?.id || ''}:${this.user?.warehouseId || ''}`); this.scanCode = fulfillment.outbound.scanCode; this.startScanner(); if (fulfillment.outbound.currentTaskNo) this.openTask(fulfillment.outbound.currentTaskNo); else this.loadTasks() },
onShow() { if (!requireSession()) return; this.user = session.currentUser; restoreFulfillmentDraft(`${this.user?.id || ''}:${this.user?.warehouseId || ''}`); this.startScanner(); if (!this.bootstrapped) { this.bootstrapped = true; this.scanCode = ''; this.loadTasks(); return } if (this.current?.taskNo) this.openTask(this.current.taskNo); else this.loadTasks() },
onHide() { this.stopScanner() },
beforeUnmount() { this.stopScanner() },
methods: {
@@ -83,7 +85,7 @@
if (resolution?.workflow === 'DISPATCH' && resolution.dispatchNo) {
updateFulfillmentDraft('outbound', { currentTaskNo: '', scanCode: '', packages: 1 })
updateFulfillmentDraft('dispatch', { currentNo: resolution.dispatchNo, palletCode: '', packages: 1 })
uni.navigateTo({ url: '/pages/dispatch/dispatch' })
uni.navigateTo({ url: '/pages/dispatch/dispatch?resume=1' })
return
}
if (resolution?.workflow !== 'OUTBOUND' || !resolution.taskNo) throw new Error('服务端未返回可执行的出库任务')