Browse Source

齐套修改

dev
常熟吴彦祖 2 months ago
parent
commit
493c12e9a2
  1. 1
      .gitignore
  2. 13
      src/api/haianAutoWarehouse/cacheTransport.js
  3. 2
      src/router/index.js
  4. 5
      src/views/main.vue
  5. 211
      src/views/modules/haianAutoWarehouse/haianCacheTransport.vue

1
.gitignore

@ -18,3 +18,4 @@ node_modules/
# 本地行尾规范配置仅用于开发机,不参与版本提交 - rqrq # 本地行尾规范配置仅用于开发机,不参与版本提交 - rqrq
.gitattributes .gitattributes
.gitnexus

13
src/api/haianAutoWarehouse/cacheTransport.js

@ -0,0 +1,13 @@
import { createAPI } from '@/utils/httpRequest.js'
// 海安齐套运输:getCacheTransportAreas,POST实体必须显式传site,业务错误由页面展示。- rqrq
export const getCacheTransportAreas = data => createAPI('/haiAnCacheTransport/getCacheTransportAreas', 'post', data)
// 海安齐套运输:getCacheTransportOrders,POST实体必须显式传site,业务错误由页面展示。- rqrq
export const getCacheTransportOrders = data => createAPI('/haiAnCacheTransport/getCacheTransportOrders', 'post', data)
// 海安齐套运输:getCacheTransportLabels,POST实体必须显式传site,业务错误由页面展示。- rqrq
export const getCacheTransportLabels = data => createAPI('/haiAnCacheTransport/getCacheTransportLabels', 'post', data)
// 海安齐套运输:submitCacheTransport,POST实体必须显式传site,业务错误由页面展示。- rqrq
export const submitCacheTransport = data => createAPI('/haiAnCacheTransport/submitCacheTransport', 'post', data)

2
src/router/index.js

@ -155,6 +155,8 @@ const globalRoutes = [
{path: "/haianPalletSorting",name: "haianPalletSorting", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletSorting.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/haianPalletSorting",name: "haianPalletSorting", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletSorting.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianPalletSearch",name: "haianPalletSearch", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletSearch.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/haianPalletSearch",name: "haianPalletSearch", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletSearch.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianPalletChangeStation",name: "haianPalletChangeStation", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletChangeStation.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/haianPalletChangeStation",name: "haianPalletChangeStation", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletChangeStation.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
// 海安缓存区齐套运输独立页面;重新进入读取当前区域和可调用托盘。- rqrq
{path: "/haianCacheTransport", name: "haianCacheTransport", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianCacheTransport.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: false }},
{path: "/haianEmptyPalletAssembly",name: "haianEmptyPalletAssembly", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianEmptyPalletAssembly.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/haianEmptyPalletAssembly",name: "haianEmptyPalletAssembly", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianEmptyPalletAssembly.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianCancelWcsPallet",name: "haianCancelWcsPallet", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianCancelWcsPallet.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/haianCancelWcsPallet",name: "haianCancelWcsPallet", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianCancelWcsPallet.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianPalletMerge",name: "haianPalletMerge", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletMerge.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/haianPalletMerge",name: "haianPalletMerge", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletMerge.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},

5
src/views/main.vue

@ -181,6 +181,11 @@
</div> </div>
<div class="menu-text">栈板合托</div> <div class="menu-text">栈板合托</div>
</div> </div>
<!-- 海安齐套运输入口,沿用当前仓库选择校验,业务site由新页面显式传递。- rqrq -->
<div class="menu-item" v-site-auth="'54'" @click="navigateWithWarehouseCheck('haianCacheTransport')">
<div class="menu-icon transport"><van-icon name="logistics" size="24" /></div>
<div class="menu-text">齐套运输</div>
</div>
</div> </div>
</div> </div>
<div class="section" v-site-auth="'54'"> <div class="section" v-site-auth="'54'">

211
src/views/modules/haianAutoWarehouse/haianCacheTransport.vue

@ -0,0 +1,211 @@
<template>
<div class="pda-container cache-page">
<!-- 当前缓存区只展示calling=N的托盘;齐套色彩完全使用单据transport_flag。- rqrq -->
<!-- 对齐库存移库页的青绿色三栏导航,保留提交中及结果待确认时的离页保护。- rqrq -->
<header class="status-bar cache-header">
<button type="button" class="nav-button" :disabled="submitLoading || !!submission" @click="back"><i class="el-icon-arrow-left"></i>上一页</button>
<strong class="header-title">{{ selected ? '订单运输' : '缓存区齐套运输' }}</strong>
<button type="button" class="nav-button home-button" :disabled="submitLoading || !!submission" @click="$router.push({ path: '/' })">🏠首页</button>
</header>
<div v-if="!selected" class="cache-body">
<!-- 查询区使用现有PDA白色表单卡片及胶囊按钮,仅调整布局和外观。- rqrq -->
<div class="query-panel">
<label class="field-label">缓存区域</label>
<el-select v-model="sourceAreaId" :disabled="queryLoading || areaLoading || openLoading" placeholder="请选择缓存区" @change="loadOrders">
<el-option v-for="a in cacheAreas" :key="a.areaId" :label="a.areaDesc || a.areaId" :value="a.areaId" />
</el-select>
<div class="query-actions">
<el-checkbox v-model="showIncomplete" :disabled="queryLoading || openLoading" @change="loadOrders">显示未齐套订单</el-checkbox>
<button type="button" class="action-btn secondary" :disabled="queryLoading || areaLoading || openLoading" @click="refresh"><i v-if="queryLoading || areaLoading" class="el-icon-loading"></i>刷新</button>
</div>
</div>
<p v-if="!areaLoading && !cacheAreas.length" class="empty">尚未维护缓存区,请在PC“齐套运输任务 → 缓存区设置”维护。</p>
<p v-else-if="!queryLoading && !orders.length" class="empty">当前没有符合条件的订单</p>
<section v-for="o in orders" :key="orderKey(o)" class="order-card" @click="openOrder(o)">
<div class="order-title"><strong>{{ o.orderPartNo && o.orderPartNo !== '-' ? o.soorderNo + ' - ' + o.orderPartNo : o.soorderNo }}</strong><span :class="o.transportFlag === 'Y' ? 'kit-ready' : 'kit-wait'">{{ o.transportFlag === 'Y' ? '已齐套' : '未齐套' }}</span></div>
<div class="info-row"><span>工厂:{{ o.subSite }}</span><span>申请单类型:{{ o.orderType || '—' }}</span></div>
<div>领料单号:{{ o.notifyNo }}</div>
<div class="card-bottom"><strong>托盘数量 {{ Number(o.palletCount) || 0 }}</strong><button type="button" class="action-btn secondary" :disabled="openLoading || queryLoading" @click.stop="openOrder(o)"><i v-if="openLoading && openingKey === orderKey(o)" class="el-icon-loading"></i>查看 / 运输</button></div>
</section>
</div>
<div v-else class="cache-body">
<section class="order-card">
<div class="order-title"><strong>{{ selected.orderPartNo && selected.orderPartNo !== '-' ? selected.soorderNo + ' - ' + selected.orderPartNo : selected.soorderNo }}</strong><span :class="selected.transportFlag === 'Y' ? 'kit-ready' : 'kit-wait'">{{ selected.transportFlag === 'Y' ? '已齐套' : '未齐套' }}</span></div>
<div class="info-row"><span>工厂:{{ selected.subSite }}</span><span>申请单类型:{{ selected.orderType || '—' }}</span></div>
<div>领料单号:{{ selected.notifyNo }}</div>
</section>
<div class="query-panel">
<label class="field-label">目标区域</label>
<el-select v-model="targetAreaId" :disabled="submitLoading || !!submission" placeholder="请选择目标区域">
<el-option v-for="a in targetAreas" :key="a.areaId" :label="a.areaDesc || a.areaId" :value="a.areaId" />
</el-select>
<button type="button" class="action-btn primary submit-button" :disabled="submitLoading || (!submission && (!targetAreaId || !palletGroups.length || selected.transportFlag !== 'Y'))" @click="submit"><i v-if="submitLoading" class="el-icon-loading"></i>{{ submission ? '重试确认提交结果' : '运输当前托盘' }}</button>
<p v-if="selected.transportFlag !== 'Y'" class="kit-wait">订单尚未齐套,暂不能运输。</p>
<p class="hint">本次只运输当前缓存区内可调用的托盘,后到托盘到达后可再建单。</p>
</div>
<h3 class="detail-title">托盘明细({{ palletGroups.length }})· 本订单标签</h3>
<p v-if="!palletGroups.length" class="empty">当前没有可运输托盘,请返回刷新</p>
<el-collapse>
<el-collapse-item v-for="p in palletGroups" :key="p.palletId" :name="p.palletId" :title="p.palletId + ' · ' + p.labels.length + ' 个标签'">
<div v-for="label in p.labels" :key="label.subSite + ':' + label.serialNo" class="label-card" :class="labelClass(label)">
<strong>{{ label.serialNo }}</strong>
<div>{{ label.partNo }} · {{ label.subSite }}</div>
<div>数量 {{ Number(label.qty) || 0 }}<span v-if="Number(label.wcsFlag) === -1"> · 发料成功</span><span v-if="Number(label.wcsFlag) === -2"> · 移库/发料失败</span></div>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
</template>
<script>
import { getCacheTransportAreas, getCacheTransportOrders, getCacheTransportLabels, submitCacheTransport } from '@/api/haianAutoWarehouse/cacheTransport'
// 海安独立PDA页面;服务重查当前托盘,页面展示不作为占用或调度依据。- rqrq
export default {
data () {
return { site: '', areas: [], sourceAreaId: '', showIncomplete: false, orders: [], selected: null, labels: [], targetAreaId: '', areaLoading: false, queryLoading: false, openLoading: false, openingKey: '', submitLoading: false, submission: null }
},
computed: {
cacheAreas () { return this.areas.filter(a => a.cacheAreaFlag === 'Y') },
targetAreas () { return this.areas.filter(a => a.chooseAble === 'Y' && a.wcsAreaCode && a.areaId !== this.sourceAreaId) },
// 相同托盘只展示一个折叠块,标签使用子工厂+标签号作为唯一键。- rqrq
palletGroups () {
const groups = []
this.labels.forEach(label => {
let pallet = groups.find(p => p.palletId === label.palletId)
if (!pallet) { pallet = { palletId: label.palletId, labels: [] }; groups.push(pallet) }
pallet.labels.push(label)
})
return groups
}
},
created () {
// 显式业务site来自当前工厂,缓存区初始选择第一项。- rqrq
this.site = this.$store.state.user.site
this.refresh()
},
beforeRouteLeave (to, from, next) {
// 请求结果未知时先原号重试,避免页面返回后另建请求掩盖原单。- rqrq
if (this.submitLoading || this.submission) {
this.$message.warning('请先确认本次提交结果')
next(false)
} else next()
},
methods: {
orderKey (o) { return [o.subSite, o.notifyNo, o.orderItemNo, o.soorderNo].join('|') },
labelClass (row) { return Number(row.wcsFlag) === -1 ? 'label-issued' : Number(row.wcsFlag) === -2 ? 'label-failed' : '' },
// 返回列表时重新获取当前N托盘,运输成功的盘自然不再显示。- rqrq
back () {
if (this.submitLoading || this.submission) return
if (this.selected) { this.selected = null; this.labels = []; this.loadOrders() } else this.$router.push('/')
},
// 每次刷新同时读取区域配置,失败清空旧列表防止误选。- rqrq
async refresh () {
if (this.areaLoading || this.queryLoading || this.openLoading) return
this.site = this.$store.state.user.site
this.areaLoading = true
try {
const { data } = await getCacheTransportAreas({ site: this.site })
if (data && data.code === 0) {
this.areas = data.rows || []
if (!this.cacheAreas.some(a => a.areaId === this.sourceAreaId)) this.sourceAreaId = this.cacheAreas.length ? this.cacheAreas[0].areaId : ''
await this.loadOrders()
} else { this.areas = []; this.orders = []; this.$alert((data && data.msg) || '读取缓存区域失败', '提示') }
} catch (e) { this.areas = []; this.orders = []; this.$message.error('读取缓存区域网络异常') } finally { this.areaLoading = false }
},
// 齐套过滤随请求显式传入,不能在页面通过托盘数量推断齐套。- rqrq
async loadOrders () {
if (this.queryLoading || this.openLoading) return
this.orders = []
if (!this.sourceAreaId) return
this.queryLoading = true
try {
const { data } = await getCacheTransportOrders({ site: this.$store.state.user.site, sourceAreaId: this.sourceAreaId, showIncomplete: this.showIncomplete })
if (data && data.code === 0) this.orders = data.rows || []
else this.$alert((data && data.msg) || '查询订单失败', '提示')
} catch (e) { this.$message.error('查询订单网络异常') } finally { this.queryLoading = false }
},
// 打开时重查当前缓存区N托盘的订单标签,防止列表查询后已被其它任务占用。- rqrq
async openOrder (order) {
if (this.openLoading || this.queryLoading) return
this.openLoading = true; this.openingKey = this.orderKey(order)
try {
const { data } = await getCacheTransportLabels(Object.assign({}, order, { site: this.$store.state.user.site, sourceAreaId: this.sourceAreaId }))
if (data && data.code === 0) { this.selected = order; this.labels = data.rows || []; this.targetAreaId = ''; this.submission = null } else this.$alert((data && data.msg) || '读取订单托盘失败', '提示')
} catch (e) { this.$message.error('读取订单托盘网络异常') } finally { this.openLoading = false }
},
// 同一次提交保留请求号和完整快照;网络错误只允许原参数重试,后端幂等返回原单。- rqrq
async submit () {
if (this.submitLoading || !this.selected) return
if (!this.submission && (!this.targetAreaId || !this.palletGroups.length || this.selected.transportFlag !== 'Y')) return
if (!this.submission) {
this.submission = Object.assign({}, this.selected, {
site: this.$store.state.user.site,
sourceAreaId: this.sourceAreaId,
targetAreaId: this.targetAreaId,
requestNo: 'PDA-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2) + '-' + Math.random().toString(36).slice(2)
})
}
this.submitLoading = true
try {
const { data } = await submitCacheTransport(this.submission)
if (data && data.code === 0) {
const row = data.row || {}
this.submission = null; this.selected = null; this.labels = []
this.$message.success('已创建齐套运输单,共 ' + (Number(row.palletCount) || 0) + ' 盘')
await this.loadOrders()
} else {
this.submission = null
this.$alert((data && data.msg) || '提交失败,请返回刷新托盘状态', '提示')
}
} catch (e) { this.$message.error('提交结果未确认,请点击重试确认;不会重复建单') } finally { this.submitLoading = false }
}
}
}
</script>
<style scoped>
/* 对齐库存移库的40px青绿色顶栏和灰底白卡;局部覆盖,避免改变其它PDA页面。- rqrq */
.cache-page { width: 100%; height: 100vh; min-height: 0; padding-bottom: 0; display: flex; flex-direction: column; overflow: hidden; background: #f5f5f5; color: #333; }
.cache-header { display: grid; grid-template-columns: 72px minmax(0, 1fr) 60px; align-items: center; flex-shrink: 0; height: 40px; min-height: 40px; margin: 0; padding: 0 12px; box-sizing: border-box; background: #17b3a3; color: #fff; }
.header-title { text-align: center; font-size: 16px; font-weight: 500; white-space: nowrap; }
.nav-button { height: 40px; padding: 0; border: 0; border-radius: 0; background: transparent; color: #fff; font: inherit; font-size: 16px; text-align: left; cursor: pointer; }
.home-button { font-size: 14px; text-align: right; }
.nav-button:disabled { opacity: 0.5; cursor: not-allowed; }
.cache-body { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0 20px; }
.query-panel, .order-card { background: #fff; margin: 4px; padding: 10px 16px; border: 1px solid #f0f0f0; border-radius: 8px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); }
.field-label { display: block; font-size: 12px; font-weight: 500; color: #666; margin: 0 0 4px; }
.cache-body .el-select { width: 100%; }
.query-actions, .order-title, .card-bottom { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.query-actions { margin-top: 10px; }
.order-card { line-height: 1.45; overflow-wrap: anywhere; }
/* 覆盖全局info-row的分隔线和上下留白,订单卡片保持无横线的紧凑布局。- rqrq */
.cache-page .order-card .info-row { display: flex; justify-content: space-between; gap: 12px; padding: 0; border-bottom: none; }
.info-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.order-title { margin-bottom: 2px; line-height: 1.35; }
.order-title strong { font-size: 16px; }
.card-bottom { margin-top: 4px; }
.kit-ready { color: #21823e; font-weight: bold; white-space: nowrap; }
.kit-wait { color: #c23838; font-weight: bold; white-space: nowrap; }
/* 刷新/查看使用PDA描边胶囊按钮,运输使用实心主按钮,保留加载及禁用反馈。- rqrq */
.cache-page .action-btn { flex: none; min-width: 72px; min-height: 34px; padding: 8px 16px; border: 1px solid #17b3a3; border-radius: 20px; background: #fff; color: #17b3a3; font-size: 14px; line-height: 18px; cursor: pointer; }
.cache-page .action-btn.primary { background: #17b3a3; color: #fff; }
.cache-page .action-btn:hover:not(:disabled) { background: #0d8f7f; border-color: #0d8f7f; color: #fff; }
.cache-page .action-btn:disabled { background: #f5f7fa; border-color: #e4e7ed; color: #c0c4cc; cursor: not-allowed; transform: none; }
.cache-page .action-btn.primary:disabled { background: #c0c4cc; border-color: #c0c4cc; color: #fff; }
.cache-page .action-btn i { margin-right: 4px; }
.cache-page .submit-button { width: 100%; min-height: 40px; margin: 12px 0 6px; }
.hint { color: #999; font-size: 12px; line-height: 1.7; }
.empty { margin: 4px; padding: 32px 16px; border-radius: 8px; background: #fff; color: #999; line-height: 1.7; text-align: center; }
.detail-title { margin: 4px 4px 0; padding: 8px 16px; border-radius: 8px 8px 0 0; border-bottom: 2px solid #17b3a3; background: #fff; color: #17b3a3; font-size: 14px; font-weight: 500; }
.label-card { padding: 12px; border-bottom: 1px solid #e8edf3; line-height: 1.8; overflow-wrap: anywhere; }
.label-issued { background: #e1f3d8; color: #286317; }
.label-failed { background: #fff2b3; color: #775500; }
.cache-page /deep/ .el-input__inner { height: 32px; line-height: 32px; }
.cache-page /deep/ .el-input__icon { line-height: 32px; }
.cache-page /deep/ .el-checkbox__label { font-size: 12px; padding-left: 6px; }
.cache-page /deep/ .el-collapse { margin: 0 4px; }
.cache-page /deep/ .el-collapse-item__header { padding: 0 12px; min-height: 44px; font-size: 14px; }
.cache-page /deep/ .el-collapse-item__content { padding-bottom: 0; }
</style>
Loading…
Cancel
Save