初始化柏悦物流海外版 PDA

This commit is contained in:
2026-08-20 20:10:20 +08:00
commit 02a187377d
377 changed files with 49737 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
<template>
<view v-if="user" class="page-shell portal-page">
<PortalHeader :title="operationName" :user="user" :fallback-url="`/pages/module/module?key=${moduleKey}`" />
<view class="portal-content operation-page">
<view class="operation-page-title-row"><view><text class="operation-page-title">{{ operationName }}</text><text class="operation-page-subtitle">{{ prototype.subtitle }}</text></view><text class="prototype-badge">静态原型</text></view>
<view class="operation-scan-card"><text class="operation-scan-label">{{ prototype.scanLabel }}</text><view class="operation-scan-row"><input v-model="scanValue" class="operation-scan-input" :aria-label="prototype.scanLabel" :placeholder="prototype.scanPlaceholder" confirm-type="search" @confirm="prototypeScan" /><button class="operation-scan-button" @tap="prototypeScan">确认</button></view><text class="operation-scan-tip">支持 Android PDA 广播扫码,也可手工输入单号</text></view>
<view class="operation-metrics"><view v-for="metric in prototype.metrics" :key="metric.label" class="operation-metric"><text class="operation-metric-value" :class="metric.tone">{{ metric.value }}</text><text class="operation-metric-label">{{ metric.label }}</text></view></view>
<view class="task-toolbar"><text class="group-title operation-group-title">任务列表</text><button class="filter-button" @tap="showToast('筛选面板为静态原型', 'warning')">筛选</button></view>
<view class="prototype-tabs"><button v-for="item in tabs" :key="item" class="prototype-tab" :class="{ active: tab === item }" @tap="tab = item">{{ item }}</button></view>
<view v-if="filteredTasks.length" class="prototype-task-list"><view v-for="task in filteredTasks" :key="task.code" class="prototype-task-card"><view class="prototype-task-head"><text class="prototype-task-code">{{ task.code }}</text><text class="prototype-task-status" :class="task.tone">{{ task.status }}</text></view><text class="prototype-task-title">{{ task.title }}</text><view class="prototype-task-meta"><text>{{ task.meta }}</text><text>{{ task.location }}</text></view><view class="prototype-task-foot"><text class="prototype-task-qty">{{ task.quantity }}</text><button class="prototype-task-action" @tap="showToast(`${task.action}:${task.code}`, 'success')">{{ task.action }}</button></view></view></view>
<view v-else class="operation-empty"><text class="operation-empty-icon">✓</text><text class="history-empty-title">暂无{{ tab }}任务</text><text class="history-empty-desc">切换其他状态查看演示数据</text></view>
</view>
<view v-if="toast.visible" class="app-toast" :class="toast.type" role="status">{{ toast.message }}</view>
</view>
</template>
<script>
import PortalHeader from '@/components/PortalHeader.vue'
import { MODULES, getOperationPrototype } from '@/data/overseas-workbench.js'
import { session, requireSession } from '@/stores/session.js'
import { startScanBroadcast } from '@/utils/scan-broadcast.js'
import { playSuccessSound } from '@/utils/audio-feedback.js'
export default {
components: { PortalHeader },
data() { return { user: session.currentUser, moduleKey: 'query', operationName: '库存查询', scanValue: '', tabs: ['待处理', '进行中', '已完成'], tab: '待处理', toast: { visible: false, message: '', type: '' } } },
computed: { currentModule() { return MODULES.find((module) => module.key === this.moduleKey) || MODULES[0] }, prototype() { return getOperationPrototype(this.operationName) }, filteredTasks() { return this.prototype.tasks.filter((task) => task.status === this.tab) } },
onLoad(options) { this.moduleKey = options.module || 'query'; this.operationName = decodeURIComponent(options.name || '库存查询') },
onShow() { if (!requireSession()) return; this.user = session.currentUser; this.startScanner() },
onHide() { this.stopScanner() },
onUnload() { this.stopScanner() },
beforeUnmount() { clearTimeout(this._toastTimer); this.stopScanner() },
methods: {
startScanner() { this.stopScanner(); this._stopScanner = startScanBroadcast({ onScan: (value) => { this.scanValue = value; this.prototypeScan() } }) },
stopScanner() { if (typeof this._stopScanner === 'function') this._stopScanner(); this._stopScanner = null },
prototypeScan() { const value = String(this.scanValue || '').trim(); if (!value) return this.showToast('请先扫描或输入编码', 'warning'); playSuccessSound(); this.showToast(`已读取 ${value};业务接口待接入`, 'success') },
showToast(message, type) { clearTimeout(this._toastTimer); this.toast = { visible: true, message, type }; this._toastTimer = setTimeout(() => { this.toast.visible = false }, 2200) }
}
}
</script>