diff --git a/klp-ui/src/router/index.js b/klp-ui/src/router/index.js index cbf559ee8..f2639818e 100644 --- a/klp-ui/src/router/index.js +++ b/klp-ui/src/router/index.js @@ -183,6 +183,33 @@ export const dynamicRoutes = [ } ] }, + // APS 排产独立页面(用于产需单跳转排产单) + { + path: '/aps/requirement', + component: Layout, + hidden: true, + children: [ + { + path: '', + component: () => import('@/views/wms/post/aps/requirement'), + name: 'ApsRequirement', + meta: { title: '产需单' } + } + ] + }, + { + path: '/aps/schedule', + component: Layout, + hidden: true, + children: [ + { + path: '', + component: () => import('@/views/wms/post/aps/schedule'), + name: 'ApsSchedule', + meta: { title: '排产单' } + } + ] + }, { path: '/system/dict-data', component: Layout, diff --git a/klp-ui/src/views/wms/post/aps/requirement.vue b/klp-ui/src/views/wms/post/aps/requirement.vue index d36e06b29..426f1255b 100644 --- a/klp-ui/src/views/wms/post/aps/requirement.vue +++ b/klp-ui/src/views/wms/post/aps/requirement.vue @@ -27,16 +27,23 @@
-
- {{ item.scheduleNo }} - {{ - statusMap[item.scheduleStatus] || '未知' }} -
-
- 生产日期:{{ item.prodDate || '-' }} 客户:{{ item.customerName || '-' }} 业务员:{{ item.businessUser || '-' }} -
-
- +
+
+
+ {{ item.scheduleNo }} + {{ + statusMap[item.scheduleStatus] || '未知' }} +
+
+ 生产日期:{{ item.prodDate || '-' }} 客户:{{ item.customerName || '-' }} 业务员:{{ item.businessUser || '-' }} +
+
+ +
+
+
+ 跳转排产 +
@@ -362,7 +369,7 @@
- +
@@ -382,6 +389,25 @@ 总数量:{{ bindPreviewTotalQty }} 吨 含税总额:{{ bindPreviewTotalAmount }}
+ +
+
+ 该订单已绑定以下产需单: +
+
+ + {{ rel.scheduleNo }} + {{ bindPreviewRelStatusMap[rel.scheduleStatus] || '' }} + +
+
@@ -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 { diff --git a/klp-ui/src/views/wms/post/aps/schedule.vue b/klp-ui/src/views/wms/post/aps/schedule.vue index cdc8fb3f8..b1784e73e 100644 --- a/klp-ui/src/views/wms/post/aps/schedule.vue +++ b/klp-ui/src/views/wms/post/aps/schedule.vue @@ -653,6 +653,13 @@ import ProcessSelect from '@/components/KLPService/ProcessSelect/index.vue' export default { name: 'ApsSchedule', components: { ProcessSelect }, + props: { + // 由 flow.vue 通过 switchApsPage 传入的参数 + apsParams: { + type: Object, + default: null + } + }, data() { const today = new Date() const y = today.getFullYear() @@ -726,8 +733,49 @@ export default { ) } }, - watch: {}, + watch: { + // 接收 flow.vue 传入的参数:设置日期并自动查询 + apsParams: { + handler(val) { + if (val && val.prodDate) { + this.queryDate = val.prodDate + } + if (val && val.scheduleStatus !== undefined) { + // 根据产需单状态自动切换 Tab + // 1=待审核 2=已接收 4=已排产 + const statusToTab = { 1: 'pending', 2: 'accepted', 4: 'scheduled' } + const tab = statusToTab[val.scheduleStatus] || 'pending' + this.activeTab = tab + } + this.$nextTick(() => { + this.handleQuery() + }) + }, + immediate: false + } + }, created() { + // 优先从路由参数获取(产需单点击"跳转排产"通过 $router.push 传参) + const query = this.$route.query + // 其次从 apsParams prop 获取(弹窗内由 flow.vue 切换组件传入) + const params = this.apsParams + + let hasExternal = false + if (query && query.prodDate) { + this.queryDate = query.prodDate + hasExternal = true + if (query.scheduleStatus !== undefined) { + const statusToTab = { 1: 'pending', 2: 'accepted', 4: 'scheduled' } + this.activeTab = statusToTab[Number(query.scheduleStatus)] || 'pending' + } + } else if (params && params.prodDate) { + this.queryDate = params.prodDate + hasExternal = true + if (params.scheduleStatus !== undefined) { + const statusToTab = { 1: 'pending', 2: 'accepted', 4: 'scheduled' } + this.activeTab = statusToTab[params.scheduleStatus] || 'pending' + } + } this.handleQuery() }, methods: { diff --git a/klp-ui/src/views/wms/post/flow.vue b/klp-ui/src/views/wms/post/flow.vue index 1343ef01a..db3ce6a13 100644 --- a/klp-ui/src/views/wms/post/flow.vue +++ b/klp-ui/src/views/wms/post/flow.vue @@ -44,6 +44,7 @@ v-if="dynamicComponent && !dialogLoading" :is="dynamicComponent" :key="dialogKey" + :aps-params="apsDialogParams" />
@@ -533,6 +534,8 @@ export default { dialogLoading: false, dynamicComponent: null, dialogKey: 0, + // APS 页面切换参数(传递给子组件) + apsDialogParams: null, } }, @@ -701,6 +704,7 @@ export default { this.dialogWidth = dialogWidth this.dialogLoading = true this.dynamicComponent = null + this.apsDialogParams = params || null this.resolveImport(componentPath) .then(module => { @@ -716,6 +720,36 @@ export default { }) }, + /** + * APS 页面间切换(由子组件调用 this.$parent.switchApsPage) + * @param {string} componentPath - 相对于 @/views/ 的路径,如 'wms/post/aps/schedule' + * @param {object} params - 传递给目标组件的参数 + * @param {string} title - 弹窗标题 + */ + switchApsPage(componentPath, params, title) { + if (!componentPath) { + this.$message.warning('组件路径不能为空') + return + } + + this.dialogLoading = true + this.dynamicComponent = null + this.apsDialogParams = params || null + if (title) this.dialogTitle = title + + this.resolveImport(componentPath) + .then(module => { + this.dynamicComponent = module.default || module + }) + .catch(err => { + console.error('[FlowChart] switchApsPage error:', err) + this.$message.error('组件加载失败: ' + (err.message || '未知错误')) + }) + .finally(() => { + this.dialogLoading = false + }) + }, + resolveImport(componentPath) { // 与 src/store/modules/permission.js 的 loadView 同款模式 // componentPath 相对于 @/views/,如 'crm/order/index' @@ -730,6 +764,7 @@ export default { handleDialogClosed() { this.dynamicComponent = null this.dialogKey++ + this.apsDialogParams = null }, }, }