优化
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<view v-if="user" class="page-shell palletization-page">
|
||||
<PortalHeader title="合托作业" :user="user" :fallback-url="'/pages/dropship-tasks/dropship-tasks'" />
|
||||
<PortalHeader title="一件代发入库" :user="user" :fallback-url="'/pages/dropship-tasks/dropship-tasks'" />
|
||||
<view class="content">
|
||||
<view v-if="error" class="message error" role="alert">{{ error }}</view>
|
||||
<view v-if="notice" class="message success" role="status">{{ notice }}</view>
|
||||
<view v-if="loading && !task" class="state">正在加载合托任务…</view>
|
||||
<view v-if="loading && !task" class="state">正在加载入库任务…</view>
|
||||
<template v-if="task">
|
||||
<view class="summary-card">
|
||||
<view class="task-summary-card">
|
||||
<view class="summary-head"><view><text class="eyebrow">入仓码</text><text class="inbound-code">{{ task.inboundCode || '—' }}</text></view><text class="status">{{ statusLabel }}</text></view>
|
||||
<text class="customer">{{ task.customerName || '客户未关联' }} · {{ task.warehouseName || '仓库未关联' }}</text>
|
||||
<view class="metrics">
|
||||
@@ -15,7 +15,7 @@
|
||||
<view><strong>{{ task.boundCartons || 0 }}</strong><text>已归托</text></view>
|
||||
<view><strong>{{ task.unboundCartons || 0 }}</strong><text>待归托</text></view>
|
||||
</view>
|
||||
<button v-if="task.taskStatus === 'PENDING'" class="primary-button" :disabled="submitting" @tap="claimTask">领取并开始合托</button>
|
||||
<button v-if="task.taskStatus === 'PENDING'" class="primary-button" :disabled="submitting" @tap="claimTask">领取并开始入库</button>
|
||||
</view>
|
||||
|
||||
<view v-if="task.taskStatus === 'CLAIMED'" class="section-card">
|
||||
@@ -33,20 +33,18 @@
|
||||
</view>
|
||||
|
||||
<view v-if="task.taskStatus === 'CLAIMED'" class="section-card">
|
||||
<text class="section-title">2. 归托</text>
|
||||
<text class="section-desc">把已清点待归托箱绑定到现有 DP 托盘,或由系统生成新托盘。</text>
|
||||
<ScanTargetInput v-model="palletNo" name="palletNo" label="托盘码" placeholder="扫描 DP-YYMMDD-NNNN" :active="activeScan === 'palletNo'" @activate="activeScan = 'palletNo'" @submit="bindPending" />
|
||||
<button class="secondary-button" :disabled="!validPalletNo || !task.unboundCartons || submitting" @tap="bindPending">绑定到扫描托盘</button>
|
||||
<button class="primary-button" :disabled="!task.unboundCartons || submitting" @tap="createAndBind">生成 DP 托盘并绑定</button>
|
||||
<text class="section-title">2. 完成入库</text>
|
||||
<text class="section-desc">全部箱码清点完成后,系统一次性完成归托、封托并生成正式 DP 托盘码。</text>
|
||||
<button class="primary-button" :disabled="!allCartonsCounted || !task.unboundCartons || submitting" @tap="completeInbound">完成入库并生成托盘码</button>
|
||||
</view>
|
||||
|
||||
<view class="section-card">
|
||||
<view class="section-heading"><view><text class="section-title">3. 托盘与封托</text><text class="section-desc">所有箱清点并归托后,逐托确认封托。</text></view><button class="text-button" :disabled="loading" @tap="loadTask">刷新</button></view>
|
||||
<view class="section-heading"><view><text class="section-title">3. 托盘码与打印</text><text class="section-desc">完成入库后显示最终托盘码,可立即打印并粘贴。</text></view><button class="text-button" :disabled="loading" @tap="loadTask">刷新</button></view>
|
||||
<view v-if="!task.pallets || !task.pallets.length" class="empty">暂无托盘</view>
|
||||
<view v-for="pallet in task.pallets" :key="pallet.palletId" class="pallet-card">
|
||||
<view class="pallet-head"><text class="pallet-code">{{ pallet.palletNo }}</text><text class="pallet-status" :class="pallet.status === 'SEALED' ? 'sealed' : ''">{{ pallet.status === 'SEALED' ? '已封托' : '待封托' }}</text></view>
|
||||
<text class="pallet-meta">{{ pallet.cartonCount || 0 }} 箱 · {{ pallet.skuCount || 0 }} SKU · {{ pallet.weightKg || 0 }} kg · {{ pallet.volumeCbm || 0 }} m³</text>
|
||||
<button v-if="pallet.status === 'OPEN'" class="primary-button" :disabled="submitting || !canSeal" @tap="sealPallet(pallet)">确认封托</button>
|
||||
<button v-if="pallet.status === 'SEALED'" class="primary-button" :disabled="printing" @tap="printPallet(pallet)">{{ printing ? '正在生成打印文件…' : '打印托盘码' }}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -57,20 +55,19 @@
|
||||
<script>
|
||||
import PortalHeader from '@/components/PortalHeader.vue'
|
||||
import ScanTargetInput from '@/components/ScanTargetInput.vue'
|
||||
import { bindDropshipPendingCartons, claimDropshipPalletizationTask, countDropshipCarton, createAndBindDropshipPallet, getDropshipPalletizationTask, resolveDropshipCarton, sealDropshipPallet } from '@/api/pda-dropship.js'
|
||||
import { claimDropshipPalletizationTask, countDropshipCarton, createAndBindDropshipPallet, downloadDropshipPalletLabel, getDropshipPalletizationTask, resolveDropshipCarton } from '@/api/pda-dropship.js'
|
||||
import { session, requireSession } from '@/stores/session.js'
|
||||
import { formatApiError } from '@/utils/user-facing.js'
|
||||
import { startScanBroadcast } from '@/utils/scan-broadcast.js'
|
||||
|
||||
export default {
|
||||
components: { PortalHeader, ScanTargetInput },
|
||||
data() { return { user: session.currentUser, taskId: '', warehouseId: '', task: null, boxCode: '', palletNo: '', carton: null, actualQuantity: '', discrepancyRemark: '', activeScan: 'boxCode', loading: false, submitting: false, error: '', notice: '' } },
|
||||
data() { return { user: session.currentUser, taskId: '', warehouseId: '', task: null, boxCode: '', carton: null, actualQuantity: '', discrepancyRemark: '', activeScan: 'boxCode', loading: false, submitting: false, printing: false, error: '', notice: '' } },
|
||||
computed: {
|
||||
statusLabel() { return this.task?.taskStatus === 'COMPLETED' ? '已完成' : (this.task?.taskStatus === 'CLAIMED' ? '作业中' : '待领取') },
|
||||
quantityDiffers() { return this.carton && Number(this.actualQuantity) !== Number(this.carton.expectedSkuQuantity) },
|
||||
canCount() { return Boolean(this.carton?.canCount && Number(this.actualQuantity) > 0 && (!this.quantityDiffers || this.discrepancyRemark.trim())) },
|
||||
validPalletNo() { return /^DP-\d{6}-\d{4}$/.test(this.palletNo.trim().toUpperCase()) },
|
||||
canSeal() { return Number(this.task?.countedCartons || 0) === Number(this.task?.totalCartons || 0) && Number(this.task?.unboundCartons || 0) === 0 }
|
||||
allCartonsCounted() { return Number(this.task?.totalCartons || 0) > 0 && Number(this.task?.countedCartons || 0) === Number(this.task?.totalCartons || 0) }
|
||||
},
|
||||
onLoad(options) { this.taskId = String(options.taskId || ''); this.warehouseId = String(options.warehouseId || '') },
|
||||
onShow() { if (!requireSession()) return; this.user = session.currentUser; this.startScanner(); this.loadTask() },
|
||||
@@ -78,16 +75,16 @@
|
||||
methods: {
|
||||
startScanner() { this.stopScanner(); this._stopScanner = startScanBroadcast({ onScan: (value) => this.handleScan(value), onError: () => { this.error = '扫码头连接失败,可使用输入框继续作业' } }) },
|
||||
stopScanner() { if (this._stopScanner) this._stopScanner(); this._stopScanner = null },
|
||||
handleScan(value) { if (this.activeScan === 'palletNo') { this.palletNo = String(value).trim().toUpperCase(); this.bindPending() } else { this.boxCode = String(value).trim().toUpperCase(); this.resolveCarton() } },
|
||||
handleScan(value) { this.boxCode = String(value).trim().toUpperCase(); this.resolveCarton() },
|
||||
resetMessages() { this.error = ''; this.notice = '' },
|
||||
async loadTask() {
|
||||
if (!this.taskId || !this.warehouseId) { this.error = '缺少合托任务或仓库信息,请返回任务列表'; return }
|
||||
this.loading = true; this.resetMessages()
|
||||
try { this.task = await getDropshipPalletizationTask(this.taskId, this.warehouseId) }
|
||||
catch (error) { this.error = formatApiError(error, '合托任务加载失败') }
|
||||
catch (error) { this.error = formatApiError(error, '一件代发入库任务加载失败') }
|
||||
finally { this.loading = false }
|
||||
},
|
||||
async claimTask() { await this.runMutation(() => claimDropshipPalletizationTask(this.taskId, Number(this.warehouseId)), '任务领取成功') },
|
||||
async claimTask() { await this.runMutation(() => claimDropshipPalletizationTask(this.taskId, this.warehouseId), '任务领取成功') },
|
||||
async resolveCarton(value) {
|
||||
const code = String(value || this.boxCode || '').trim().toUpperCase(); if (!code || this.loading) return
|
||||
this.boxCode = code; this.loading = true; this.resetMessages(); this.carton = null
|
||||
@@ -96,12 +93,25 @@
|
||||
finally { this.loading = false }
|
||||
},
|
||||
async countCarton() {
|
||||
const result = await this.runMutation(() => countDropshipCarton(this.taskId, { warehouseId: Number(this.warehouseId), boxCode: this.carton.boxCode, actualSkuQuantity: Number(this.actualQuantity), discrepancyAction: this.quantityDiffers ? 'ACCEPT_VARIANCE' : 'MATCH', discrepancyRemark: this.quantityDiffers ? this.discrepancyRemark.trim() : null, palletNo: null }), '本箱已清点,等待归托')
|
||||
const result = await this.runMutation(() => countDropshipCarton(this.taskId, { warehouseId: this.warehouseId, boxCode: this.carton.boxCode, actualSkuQuantity: Number(this.actualQuantity), discrepancyAction: this.quantityDiffers ? 'ACCEPT_VARIANCE' : 'MATCH', discrepancyRemark: this.quantityDiffers ? this.discrepancyRemark.trim() : null }), '本箱已完成入库清点')
|
||||
if (result) { this.boxCode = ''; this.carton = null; this.actualQuantity = ''; this.discrepancyRemark = '' }
|
||||
},
|
||||
async bindPending(value) { const code = String(value || this.palletNo || '').trim().toUpperCase(); if (!/^DP-\d{6}-\d{4}$/.test(code)) { this.error = '请输入正确的 DP 托盘码'; return }; this.palletNo = code; await this.runMutation(() => bindDropshipPendingCartons(this.taskId, Number(this.warehouseId), code), '待归托箱已绑定') },
|
||||
async createAndBind() { await this.runMutation(() => createAndBindDropshipPallet(this.taskId, Number(this.warehouseId)), '已生成 DP 托盘并绑定') },
|
||||
async sealPallet(pallet) { await this.runMutation(() => sealDropshipPallet(this.taskId, Number(this.warehouseId), pallet), `${pallet.palletNo} 已封托`) },
|
||||
async completeInbound() { await this.runMutation(() => createAndBindDropshipPallet(this.taskId, this.warehouseId), '入库已完成,正式托盘码已生成') },
|
||||
async printPallet(pallet) {
|
||||
if (this.printing || pallet.status !== 'SEALED') return
|
||||
this.printing = true; this.resetMessages()
|
||||
try {
|
||||
const filePath = await downloadDropshipPalletLabel(this.taskId, this.warehouseId, pallet.palletId)
|
||||
// #ifdef H5
|
||||
const link = document.createElement('a'); link.href = filePath; link.download = `${pallet.palletNo}-托盘码.pdf`; link.click()
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
await new Promise((resolve, reject) => uni.openDocument({ filePath, fileType: 'pdf', showMenu: true, success: resolve, fail: reject }))
|
||||
// #endif
|
||||
this.notice = `${pallet.palletNo} 打印文件已打开`
|
||||
} catch (error) { this.error = formatApiError(error, '托盘码打印失败') }
|
||||
finally { this.printing = false }
|
||||
},
|
||||
async runMutation(action, message) {
|
||||
if (this.submitting) return null
|
||||
this.submitting = true; this.resetMessages()
|
||||
@@ -124,7 +134,8 @@
|
||||
.content { padding: 12px 12px 42px; }
|
||||
.state, .message { margin-bottom: 10px; padding: 12px; border-radius: 9px; color: #667085; font-size: 12px; line-height: 18px; text-align: center; background: #fff; }
|
||||
.message.error { color: #b42318; background: #fff1f0; }.message.success { color: #067647; background: #ecfdf3; }
|
||||
.summary-card, .section-card { margin-bottom: 12px; padding: 13px; border: 1px solid #dce6f1; border-radius: 12px; background: #fff; box-shadow: 0 2px 8px rgba(23,55,93,.05); }
|
||||
.task-summary-card, .section-card { margin-bottom: 12px; padding: 13px; border: 1px solid #dce6f1; border-radius: 12px; background: #fff; box-shadow: 0 2px 8px rgba(23,55,93,.05); }
|
||||
.task-summary-card { display: block; }
|
||||
.summary-head, .section-heading, .pallet-head, .carton-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
|
||||
.summary-head > view { display: flex; min-width: 0; flex-direction: column; }.eyebrow { color: #667085; font-size: 10px; }.inbound-code { margin-top: 2px; color: #12233f; font-size: 19px; font-weight: 700; overflow-wrap: anywhere; }
|
||||
.status, .pallet-status { flex-shrink: 0; padding: 4px 8px; border-radius: 99px; color: #155eef; font-size: 10px; background: #eff4ff; }.pallet-status.sealed { color: #067647; background: #ecfdf3; }
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<view v-if="user" class="page-shell dropship-task-page">
|
||||
<PortalHeader title="一件代发合托" :user="user" :fallback-url="'/pages/home/home'" />
|
||||
<PortalHeader title="一件代发" :user="user" :fallback-url="'/pages/home/home'" />
|
||||
<view class="content">
|
||||
<view class="search-card">
|
||||
<ScanTargetInput v-model="keyword" name="taskKeyword" label="入仓码查询" placeholder="扫描或输入入仓码" :active="true" @submit="loadTasks" />
|
||||
<button class="primary-button search-button" :disabled="loading" @tap="loadTasks">{{ loading ? '查询中…' : '查询任务' }}</button>
|
||||
</view>
|
||||
<view class="heading-row">
|
||||
<view><text class="heading">待合托任务</text><text class="summary">{{ loading ? '正在同步' : `共 ${tasks.length} 个任务` }}</text></view>
|
||||
<view><text class="heading">待入库任务</text><text class="summary">{{ loading ? '正在同步' : `共 ${tasks.length} 个任务` }}</text></view>
|
||||
<button class="refresh-button" :disabled="loading" @tap="refresh">刷新</button>
|
||||
</view>
|
||||
<view v-if="error" class="state error" role="alert">{{ error }}</view>
|
||||
<view v-else-if="!loading && !tasks.length" class="state">暂无待合托任务</view>
|
||||
<view v-else-if="!loading && !tasks.length" class="state">暂无待入库任务</view>
|
||||
<view class="task-list">
|
||||
<button v-for="task in tasks" :key="task.taskId" class="task-card" :aria-label="`进入合托任务,入仓码 ${task.inboundCode || '未关联'}`" @tap="openTask(task)">
|
||||
<button v-for="task in tasks" :key="task.taskId" class="task-card" :aria-label="`进入一件代发入库任务,入仓码 ${task.inboundCode || '未关联'}`" @tap="openTask(task)">
|
||||
<view class="task-head"><text class="business-code">{{ task.inboundCode || '入仓码 —' }}</text><text class="status" :class="task.taskStatus === 'CLAIMED' ? 'claimed' : ''">{{ statusLabel(task.taskStatus) }}</text></view>
|
||||
<text class="customer">{{ task.customerName || '客户未关联' }}</text>
|
||||
<view class="metrics">
|
||||
@@ -45,12 +45,13 @@
|
||||
refresh() { this.keyword = ''; this.loadTasks() },
|
||||
async loadTasks() {
|
||||
if (this.loading) return
|
||||
if (!this.user?.warehouseId) { this.error = '请返回首页选择作业仓库'; return }
|
||||
this.loading = true; this.error = ''
|
||||
try {
|
||||
const records = await listDropshipPalletizationTasks(this.keyword)
|
||||
const records = await listDropshipPalletizationTasks(this.keyword, this.user.warehouseId)
|
||||
this.tasks = Array.isArray(records) ? records : []
|
||||
}
|
||||
catch (error) { this.tasks = []; this.error = formatApiError(error, '合托任务加载失败') }
|
||||
catch (error) { this.tasks = []; this.error = formatApiError(error, '一件代发入库任务加载失败') }
|
||||
finally { this.loading = false }
|
||||
},
|
||||
openTask(task) { uni.navigateTo({ url: `/pages/dropship-palletization/dropship-palletization?taskId=${encodeURIComponent(task.taskId)}&warehouseId=${encodeURIComponent(task.warehouseId)}` }) }
|
||||
@@ -59,28 +60,36 @@
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.content { padding: 12px 12px 40px; }
|
||||
.search-card { padding: 12px; border: 1px solid #dce6f1; border-radius: 12px; background: #fff; box-shadow: 0 2px 8px rgba(23,55,93,.05); }
|
||||
.primary-button { height: 46px; border: 0; border-radius: 9px; color: #fff; font-size: 15px; font-weight: 700; line-height: 46px; background: #1a73e8; }
|
||||
.search-button { width: 100%; margin-top: 10px; }
|
||||
.heading-row { display: flex; align-items: center; justify-content: space-between; margin: 16px 0 10px; }
|
||||
.heading-row > view { display: flex; flex-direction: column; }
|
||||
.heading { color: #12233f; font-size: 18px; font-weight: 700; }
|
||||
.summary { margin-top: 2px; color: #667085; font-size: 11px; }
|
||||
.refresh-button { min-width: 72px; height: 42px; border: 0; border-radius: 9px; color: #155eef; font-size: 14px; line-height: 42px; background: #eaf2ff; }
|
||||
.content { padding: 8px 10px 32px; }
|
||||
.search-card { display: flex; align-items: center; gap: 8px; padding: 0; border: 0; background: transparent; box-shadow: none; }
|
||||
.search-card :deep(.scan-target-input) { min-width: 0; height: 44px; flex: 1; border-radius: 6px; }
|
||||
.search-card :deep(.scan-target-value) { height: 42px; }
|
||||
.search-card :deep(.scan-target-icon) { top: 10px; }
|
||||
.search-card :deep(.scan-target-input-active .scan-target-icon) { top: 9px; }
|
||||
.search-card :deep(.scan-target-badge) { top: 10px; }
|
||||
.primary-button { height: 44px; border: 0; border-radius: 6px; color: #fff; font-size: 14px; font-weight: 700; line-height: 44px; background: #1a73e8; }
|
||||
.search-button { width: 92px; margin: 0; flex-shrink: 0; }
|
||||
.heading-row { display: flex; align-items: center; justify-content: space-between; margin: 10px 0 7px; }
|
||||
.heading-row > view { display: flex; align-items: baseline; gap: 8px; }
|
||||
.heading { color: #12233f; font-size: 17px; font-weight: 700; }
|
||||
.summary { color: #667085; font-size: 11px; }
|
||||
.refresh-button { min-width: 64px; height: 40px; border: 0; border-radius: 6px; color: #155eef; font-size: 13px; line-height: 40px; background: #eaf2ff; }
|
||||
.state { padding: 24px 12px; border-radius: 10px; color: #667085; font-size: 13px; text-align: center; background: #fff; }
|
||||
.state.error { color: #b42318; background: #fff1f0; }
|
||||
.task-card { box-sizing: border-box; width: 100%; margin: 0 0 12px; padding: 13px; border: 1px solid #dce6f1; border-radius: 12px; color: #12233f; text-align: left; background: #fff; box-shadow: 0 2px 8px rgba(23,55,93,.05); }
|
||||
.task-list { overflow: hidden; border: 1px solid #dce6f1; border-radius: 7px; background: #fff; }
|
||||
.task-card { box-sizing: border-box; width: 100%; margin: 0; padding: 9px 11px 7px; border: 0; border-bottom: 1px solid #dce6f1; border-radius: 0; color: #12233f; text-align: left; background: #fff; box-shadow: none; }
|
||||
.task-card:last-child { border-bottom: 0; }
|
||||
.task-card:active { background: #f5f8fc; }
|
||||
.task-head, .task-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
||||
.business-code { min-width: 0; font-size: 17px; font-weight: 700; overflow-wrap: anywhere; }
|
||||
.status { flex-shrink: 0; padding: 4px 8px; border-radius: 99px; color: #9a5b13; font-size: 10px; background: #fff4e5; }
|
||||
.business-code { min-width: 0; font-size: 16px; font-weight: 700; line-height: 22px; overflow-wrap: anywhere; }
|
||||
.status { flex-shrink: 0; padding: 2px 7px; border-radius: 4px; color: #9a5b13; font-size: 10px; line-height: 18px; background: #fff4e5; }
|
||||
.status.claimed { color: #155eef; background: #eff4ff; }
|
||||
.customer { display: block; margin-top: 5px; color: #667085; font-size: 11px; }
|
||||
.metrics { display: grid; grid-template-columns: repeat(4, 1fr); margin-top: 12px; padding: 10px 0; border-top: 1px solid #edf1f5; border-bottom: 1px solid #edf1f5; }
|
||||
.customer { display: block; margin-top: 1px; color: #667085; font-size: 11px; line-height: 17px; }
|
||||
.metrics { display: grid; grid-template-columns: repeat(4, 1fr); margin-top: 6px; padding: 6px 0; border-top: 1px solid #edf1f5; border-bottom: 1px solid #edf1f5; }
|
||||
.metrics view { display: flex; align-items: center; flex-direction: column; border-right: 1px solid #edf1f5; }
|
||||
.metrics view:last-child { border-right: 0; }
|
||||
.metrics strong { font-size: 17px; }
|
||||
.metrics text { margin-top: 2px; color: #667085; font-size: 10px; }
|
||||
.task-foot { margin-top: 10px; color: #667085; font-size: 11px; }
|
||||
.enter { min-height: 40px; color: #155eef; font-size: 12px; font-weight: 700; line-height: 40px; }
|
||||
.metrics strong { font-size: 16px; line-height: 22px; }
|
||||
.metrics text { color: #667085; font-size: 10px; line-height: 16px; }
|
||||
.task-foot { margin-top: 3px; color: #667085; font-size: 11px; line-height: 30px; }
|
||||
.enter { color: #155eef; font-size: 12px; font-weight: 700; }
|
||||
</style>
|
||||
|
||||
+19
-6
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view v-if="user" class="page-shell portal-page home-page">
|
||||
<PortalHeader ref="portalHeader" title="首页" :user="user" menu @menu-change="menuOpen = $event" />
|
||||
<PortalHeader ref="portalHeader" :title="user.warehouse ? `首页 · ${user.warehouse}` : '首页'" :user="user" menu :show-profile="false" :warehouses="warehouses" :selected-warehouse-id="user.warehouseId" :warehouse-loading="warehouseLoading" :warehouse-error="warehouseError" @warehouse-select="changeWarehouse" @menu-change="menuOpen = $event" />
|
||||
<view class="home-menu">
|
||||
<view v-for="group in groups" :key="group.key" class="home-group" :class="{ 'home-group-disabled': !group.available }">
|
||||
<view class="home-group-title"><view class="home-group-mark" :class="`home-group-mark-${group.key}`"></view><text>{{ group.name }}</text></view>
|
||||
@@ -20,11 +20,12 @@
|
||||
<script>
|
||||
import PortalHeader from '@/components/PortalHeader.vue'
|
||||
import { MODULES } from '@/data/demo-data.js'
|
||||
import { session, requireSession } from '@/stores/session.js'
|
||||
import { listPdaWarehouses } from '@/api/pda-loading.js'
|
||||
import { session, requireSession, selectWarehouse } from '@/stores/session.js'
|
||||
|
||||
const ICON_TYPES = {
|
||||
'到货收货': 'download', '商品上架': 'upload', '入库质检': 'checkbox',
|
||||
'一件代发合托': 'map', '出库拣货': 'cart', '出库复核': 'compose', '装箱交接': 'paperplane',
|
||||
'一件代发': 'map', '出库拣货': 'cart', '出库复核': 'compose', '装箱交接': 'paperplane',
|
||||
'库存盘点': 'list', '商品移库': 'loop', '库存调整': 'compose',
|
||||
'商品查询': 'search', '库位查询': 'location', '任务查询': 'flag'
|
||||
}
|
||||
@@ -39,18 +40,30 @@
|
||||
|
||||
export default {
|
||||
components: { PortalHeader },
|
||||
data() { return { user: session.currentUser, groups: HOME_GROUPS, menuOpen: false } },
|
||||
onShow() { if (!requireSession()) return; this.user = session.currentUser },
|
||||
data() { return { user: session.currentUser, groups: HOME_GROUPS, menuOpen: false, warehouses: [], warehouseLoading: false, warehouseError: '' } },
|
||||
onShow() { if (!requireSession()) return; this.user = session.currentUser; this.loadWarehouses() },
|
||||
onBackPress() {
|
||||
if (!this.menuOpen) return false
|
||||
this.$refs.portalHeader.closeMenu()
|
||||
return true
|
||||
},
|
||||
methods: {
|
||||
async loadWarehouses() {
|
||||
if (this.warehouseLoading) return
|
||||
this.warehouseLoading = true; this.warehouseError = ''
|
||||
try {
|
||||
this.warehouses = await listPdaWarehouses()
|
||||
if (!this.user.warehouseId) this.$nextTick(() => this.$refs.portalHeader.openMenu())
|
||||
} catch (error) {
|
||||
this.warehouseError = error.message || '仓库加载失败,请稍后重试'
|
||||
} finally { this.warehouseLoading = false }
|
||||
},
|
||||
changeWarehouse(warehouse) { this.user = selectWarehouse(warehouse) },
|
||||
openOperation(operation) {
|
||||
if (!operation.available) return
|
||||
if (!this.user.warehouseId) { this.$refs.portalHeader.openMenu(); return }
|
||||
const routes = {
|
||||
'一件代发合托': '/pages/dropship-tasks/dropship-tasks',
|
||||
'一件代发': '/pages/dropship-tasks/dropship-tasks',
|
||||
'出库拣货': '/pages/tasks/tasks',
|
||||
'库位查询': `/pages/operation/operation?module=query&name=${encodeURIComponent('库位查询')}`
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<view class="module-hero" :class="`module-hero-${currentModule.key}`"><view class="module-hero-icon">{{ currentModule.icon }}</view><view><text class="module-hero-title">{{ currentModule.name }}</text><text class="module-hero-desc">{{ currentModule.description }}</text></view></view>
|
||||
<text class="group-title">业务功能</text>
|
||||
<view class="operation-list"><button v-for="operation in currentModule.operations" :key="operation.name" class="operation-item" :class="{ 'operation-item-disabled': !operation.available }" :disabled="!operation.available" @tap="openOperation(operation)"><view class="operation-icon">{{ operation.icon }}</view><view class="operation-info"><text class="operation-name">{{ operation.name }}</text><text class="operation-desc">{{ operation.description }}</text></view><text v-if="operation.available" class="operation-count">{{ overview.pendingBoxCount }}</text><text v-else class="operation-prototype">未开放</text><text v-if="operation.available" class="operation-arrow">›</text></button></view>
|
||||
<view class="module-empty-note">当前展示“一件代发合托”“出库拣货”和“库位查询”。</view>
|
||||
<view class="module-empty-note">当前展示“一件代发”“出库拣货”和“库位查询”。</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -29,7 +29,7 @@
|
||||
methods: {
|
||||
openOperation(operation) {
|
||||
if (!operation.available) return
|
||||
const routes = { '一件代发合托': '/pages/dropship-tasks/dropship-tasks', '出库拣货': '/pages/tasks/tasks' }
|
||||
const routes = { '一件代发': '/pages/dropship-tasks/dropship-tasks', '出库拣货': '/pages/tasks/tasks' }
|
||||
const url = routes[operation.name]
|
||||
|| `/pages/operation/operation?module=${encodeURIComponent(this.moduleKey)}&name=${encodeURIComponent(operation.name)}`
|
||||
uni.navigateTo({ url })
|
||||
|
||||
@@ -598,7 +598,7 @@
|
||||
async refreshAvailableBoxes() {
|
||||
if (!session.token) return
|
||||
try {
|
||||
const result = await listLoadingOrders({ page: 1, size: 50 })
|
||||
const result = await listLoadingOrders({ page: 1, size: 50, warehouseId: session.currentUser?.warehouseId })
|
||||
const records = (result.records || []).filter((task) => this.isSelectableTask(task))
|
||||
const previousBoxes = [...this.boxes]
|
||||
const selectedTaskId = String(this.remoteTaskId || this.currentBox.taskId || '')
|
||||
|
||||
@@ -67,9 +67,10 @@
|
||||
isTaskVisible(task) { return Boolean(task.recordStatus === 'ACTIVE' && !task.mergedIntoContainerBookingId && task.taskId && ['UNASSIGNED', 'IN_PROGRESS', 'AWAITING_REVIEW', 'PROCESSING', 'COMPLETION_FAILED'].includes(task.workflowStatus)) },
|
||||
async loadTasks() {
|
||||
if (!isOnline()) { this.error = '当前网络不可用,请联网后刷新'; return }
|
||||
if (!this.user?.warehouseId) { this.error = '请返回首页选择作业仓库'; return }
|
||||
this.loading = true; this.error = ''; this.notice = ''
|
||||
try {
|
||||
const result = await listLoadingOrders({ page: 1, size: 50 })
|
||||
const result = await listLoadingOrders({ page: 1, size: 50, warehouseId: this.user.warehouseId })
|
||||
const records = result.records || []
|
||||
records.filter((task) => this.isMergedTask(task)).forEach((task) => this.clearMergedTaskDraft(task))
|
||||
this.tasks = records.filter((task) => this.isTaskVisible(task))
|
||||
|
||||
Reference in New Issue
Block a user