Files
pda-uniapp/pages/dropship-tasks/dropship-tasks.vue
T

96 lines
6.3 KiB
Vue
Raw Normal View History

2026-09-11 11:15:07 +08:00
<template>
<view v-if="user" class="page-shell dropship-task-page">
2026-09-11 11:51:35 +08:00
<PortalHeader title="一件代发" :user="user" :fallback-url="'/pages/home/home'" />
2026-09-11 11:15:07 +08:00
<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">
2026-09-11 11:51:35 +08:00
<view><text class="heading">待入库任务</text><text class="summary">{{ loading ? '正在同步' : `共 ${tasks.length} 个任务` }}</text></view>
2026-09-11 11:15:07 +08:00
<button class="refresh-button" :disabled="loading" @tap="refresh">刷新</button>
</view>
<view v-if="error" class="state error" role="alert">{{ error }}</view>
2026-09-11 11:51:35 +08:00
<view v-else-if="!loading && !tasks.length" class="state">暂无待入库任务</view>
2026-09-11 11:15:07 +08:00
<view class="task-list">
2026-09-11 11:51:35 +08:00
<button v-for="task in tasks" :key="task.taskId" class="task-card" :aria-label="`进入一件代发入库任务,入仓码 ${task.inboundCode || '未关联'}`" @tap="openTask(task)">
2026-09-11 11:15:07 +08:00
<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">
<view><strong>{{ task.totalCartons || 0 }}</strong><text>总箱</text></view>
<view><strong>{{ task.countedCartons || 0 }}</strong><text>已清点</text></view>
<view><strong>{{ task.boundCartons || 0 }}</strong><text>已归托</text></view>
<view><strong>{{ task.unboundCartons || 0 }}</strong><text>待归托</text></view>
</view>
<view class="task-foot"><text>仓库 {{ task.warehouseName || '—' }}</text><text class="enter">进入作业 ›</text></view>
</button>
</view>
</view>
</view>
</template>
<script>
import PortalHeader from '@/components/PortalHeader.vue'
import ScanTargetInput from '@/components/ScanTargetInput.vue'
import { listDropshipPalletizationTasks } from '@/api/pda-dropship.js'
import { session, requireSession } from '@/stores/session.js'
import { formatApiError } from '@/utils/user-facing.js'
export default {
components: { PortalHeader, ScanTargetInput },
data() { return { user: session.currentUser, keyword: '', tasks: [], loading: false, error: '' } },
onShow() { if (!requireSession()) return; this.user = session.currentUser; this.loadTasks() },
methods: {
statusLabel(status) { return status === 'CLAIMED' ? '作业中' : '待领取' },
refresh() { this.keyword = ''; this.loadTasks() },
async loadTasks() {
if (this.loading) return
2026-09-11 11:51:35 +08:00
if (!this.user?.warehouseId) { this.error = '请返回首页选择作业仓库'; return }
2026-09-11 11:15:07 +08:00
this.loading = true; this.error = ''
try {
2026-09-11 11:51:35 +08:00
const records = await listDropshipPalletizationTasks(this.keyword, this.user.warehouseId)
2026-09-11 11:15:07 +08:00
this.tasks = Array.isArray(records) ? records : []
}
2026-09-11 11:51:35 +08:00
catch (error) { this.tasks = []; this.error = formatApiError(error, '一件代发入库任务加载失败') }
2026-09-11 11:15:07 +08:00
finally { this.loading = false }
},
openTask(task) { uni.navigateTo({ url: `/pages/dropship-palletization/dropship-palletization?taskId=${encodeURIComponent(task.taskId)}&warehouseId=${encodeURIComponent(task.warehouseId)}` }) }
}
}
</script>
<style scoped>
2026-09-11 11:51:35 +08:00
.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; }
2026-09-11 11:15:07 +08:00
.state { padding: 24px 12px; border-radius: 10px; color: #667085; font-size: 13px; text-align: center; background: #fff; }
.state.error { color: #b42318; background: #fff1f0; }
2026-09-11 11:51:35 +08:00
.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; }
2026-09-11 11:15:07 +08:00
.task-head, .task-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
2026-09-11 11:51:35 +08:00
.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; }
2026-09-11 11:15:07 +08:00
.status.claimed { color: #155eef; background: #eff4ff; }
2026-09-11 11:51:35 +08:00
.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; }
2026-09-11 11:15:07 +08:00
.metrics view { display: flex; align-items: center; flex-direction: column; border-right: 1px solid #edf1f5; }
.metrics view:last-child { border-right: 0; }
2026-09-11 11:51:35 +08:00
.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; }
2026-09-11 11:15:07 +08:00
</style>