feat(wms): 新增APS排产相关页面及产需单跳转排产功能

1. 新增/aps/requirement和/aps/schedule路由页面
2. 实现产需单列表跳转排产单功能
3. 为排产页面添加参数接收与自动查询逻辑
4. 新增弹窗组件间传递APS页面参数的能力
5. 优化产需单列表UI布局与绑定状态展示
This commit is contained in:
王文昊
2026-07-09 17:15:24 +08:00
parent 2150fa1fda
commit e7d96e2c3d
4 changed files with 213 additions and 16 deletions

View File

@@ -27,16 +27,23 @@
<div class="list-container">
<div v-for="item in reqList" :key="item.scheduleId" class="list-item"
:class="{ active: currentReq && currentReq.scheduleId === item.scheduleId }" @click="handleReqClick(item)">
<div class="item-title">
{{ item.scheduleNo }}
<span class="badge" :class="'badge-' + statusBadgeType(item.scheduleStatus)">{{
statusMap[item.scheduleStatus] || '未知' }}</span>
</div>
<div class="item-sub">
生产日期{{ item.prodDate || '-' }} 客户{{ item.customerName || '-' }} 业务员{{ item.businessUser || '-' }}
</div>
<div class="item-actions">
<button class="link-btn" @click.stop="handleDelete(item)">删除</button>
<div class="list-item-body">
<div class="list-item-left">
<div class="item-title">
{{ item.scheduleNo }}
<span class="badge" :class="'badge-' + statusBadgeType(item.scheduleStatus)">{{
statusMap[item.scheduleStatus] || '未知' }}</span>
</div>
<div class="item-sub">
生产日期{{ item.prodDate || '-' }} 客户{{ item.customerName || '-' }} 业务员{{ item.businessUser || '-' }}
</div>
<div class="item-actions">
<button class="link-btn" @click.stop="handleDelete(item)">删除</button>
</div>
</div>
<div class="list-item-right">
<el-button size="mini" plain @click.stop="handleJumpToSchedule(item)">跳转排产</el-button>
</div>
</div>
</div>
<div v-if="reqList.length === 0 && !reqLoading" style="padding: 40px; text-align: center; color: #909399;">
@@ -362,7 +369,7 @@
</div>
</div>
<!-- 右侧产品内容预览 -->
<!-- 右侧产品内容预览 + 已绑定产需单信息 -->
<div style="width: 55%; display: flex; flex-direction: column;">
<div
style="font-size:13px; font-weight:600; color:#2c3e50; margin-bottom:8px; padding-left:8px; border-left:3px solid #ff4d4f;">
@@ -382,6 +389,25 @@
<span>总数量{{ bindPreviewTotalQty }} </span>
<span>含税总额{{ bindPreviewTotalAmount }}</span>
</div>
<!-- 已绑定产需单信息 -->
<div v-if="bindPreviewExistingRels.length > 0" style="margin-top:12px; padding-top:10px; border-top:1px dashed #e4e7ed;">
<div style="font-size:12px; font-weight:600; color:#e74c3c; margin-bottom:6px;">
该订单已绑定以下产需单
</div>
<div style="display:flex; flex-wrap:wrap; gap:6px;">
<el-tag
v-for="rel in bindPreviewExistingRels"
:key="rel.scheduleId"
size="small"
:type="rel.scheduleStatus === 3 ? 'danger' : 'info'"
effect="plain"
:style="rel.scheduleStatus === 2 ? 'color:#555;border-color:#ccc;background:#f5f5f5;' : ''"
>
{{ rel.scheduleNo }}
<span style="margin-left:4px; opacity:0.7;">{{ bindPreviewRelStatusMap[rel.scheduleStatus] || '' }}</span>
</el-tag>
</div>
</div>
</div>
<div v-else
style="flex:1; display:flex; align-items:center; justify-content:center; color:#bfbfbf; font-size:13px;">
@@ -471,6 +497,10 @@ export default {
bindPreviewProductName: '',
bindPreviewTotalQty: 0,
bindPreviewTotalAmount: 0,
// 当前预览订单已绑定的产需单列表
bindPreviewExistingRels: [],
// 产需单状态映射(用于展示绑定状态)
bindPreviewRelStatusMap: { 0: '草稿', 1: '待审核', 2: '已下达', 3: '已退回' },
// 排产明细
detailLoading: false,
@@ -559,6 +589,18 @@ export default {
this.getList()
},
// 跳转到排产单页面(路由跳转)
handleJumpToSchedule(item) {
this.$router.push({
path: '/aps/schedule',
query: {
prodDate: item.prodDate || '',
scheduleNo: item.scheduleNo || '',
scheduleStatus: item.scheduleStatus
}
})
},
statusBadgeType(status) {
return this.statusBadgeMap[status] || 'gray'
},
@@ -738,6 +780,7 @@ export default {
this.bindPreviewProductName = ''
this.bindPreviewTotalQty = 0
this.bindPreviewTotalAmount = 0
this.bindPreviewExistingRels = []
this.searchBindOrders()
},
@@ -780,6 +823,29 @@ export default {
this.bindPreviewTotalQty = 0
this.bindPreviewTotalAmount = 0
}
// 查询该订单已关联了哪些产需单
this.bindPreviewExistingRels = []
listRel({ orderId: order.orderId }).then(res => {
const rows = res.rows || []
// 按 scheduleId 去重,并与当前已有的 reqList 匹配获取单号
const seen = new Set()
const reqMap = new Map()
;(this.reqList || []).forEach(r => reqMap.set(r.scheduleId, r))
const unique = []
rows.forEach(r => {
const key = r.scheduleId
if (!key || seen.has(key)) return
seen.add(key)
// 从已加载的 reqList 中找单号,找不到则不展示(已删除或不在当前页)
const match = reqMap.get(key)
if (match) {
unique.push({ ...r, scheduleNo: match.scheduleNo, scheduleStatus: match.scheduleStatus })
}
})
this.bindPreviewExistingRels = unique
}).catch(() => {
this.bindPreviewExistingRels = []
})
},
confirmBind() {
@@ -1038,6 +1104,31 @@ export default {
transition: background 0.15s;
}
.list-item-body {
display: flex;
align-items: stretch;
gap: 8px;
}
.list-item-left {
flex: 1;
min-width: 0;
}
.list-item-right {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
padding-left: 4px;
}
.item-actions {
display: flex;
gap: 8px;
margin-top: 4px;
}
.list-item:hover {
background: $aps-silver-1;
}
@@ -1063,10 +1154,6 @@ export default {
margin-bottom: 4px;
}
.list-item .item-actions {
display: flex;
gap: 8px;
}
// ====== 徽标 ======
.badge {