From d9b19df8128a058be2e2f104fad91169891fe20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?= Date: Mon, 17 Aug 2026 15:58:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E8=B4=A7=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/order/poOrder.js | 5 +- src/views/demo/echarts.vue | 2 +- src/views/modules/order/com_poOrderDetail.vue | 488 +++++++++--------- src/views/modules/order/poOrder.vue | 264 ++++++++-- .../modules/order/poOrderStatusOptions.js | 9 +- src/views/modules/order/poOrder_search.vue | 4 +- 6 files changed, 480 insertions(+), 292 deletions(-) diff --git a/src/api/order/poOrder.js b/src/api/order/poOrder.js index ad2b05e..ae2fcd7 100644 --- a/src/api/order/poOrder.js +++ b/src/api/order/poOrder.js @@ -25,7 +25,10 @@ export const openPoDetail = (data) => createAPI(`/pODetail/openPoDetail`, 'post' /** 下达 PO 订单行(草稿 → 已下达) */ export const issuePoDetail = (data) => createAPI(`/pODetail/issuePoDetail`, 'post', data) -/** 发货 PO 订单行(验货完成 → 已发货) */ +/** 发货弹窗预览(返回订单数量、可发货数量、默认本次发货数量) */ +export const shipPoDetailPreview = (data) => createAPI(`/pODetail/shipPoDetailPreview`, 'post', data) + +/** 提交发货(回写 qty/c_ship_qty,并按规则判定部分发货或已发货) */ export const shipPoDetail = (data) => createAPI(`/pODetail/shipPoDetail`, 'post', data) // 根据PO订单查询验货申请明细 diff --git a/src/views/demo/echarts.vue b/src/views/demo/echarts.vue index 5946a64..525a2b5 100644 --- a/src/views/demo/echarts.vue +++ b/src/views/demo/echarts.vue @@ -9,7 +9,7 @@ - + < :gutter="20">
diff --git a/src/views/modules/order/com_poOrderDetail.vue b/src/views/modules/order/com_poOrderDetail.vue index ab91183..a84cf50 100644 --- a/src/views/modules/order/com_poOrderDetail.vue +++ b/src/views/modules/order/com_poOrderDetail.vue @@ -1,254 +1,20 @@ @@ -284,6 +270,7 @@ export default { .el-form-item { margin-bottom: 6px; } + /deep/ .el-form-item__label { font-size: 14px; color: #606266; @@ -312,5 +299,4 @@ export default { border-color: #409eff; outline: none; } - diff --git a/src/views/modules/order/poOrder.vue b/src/views/modules/order/poOrder.vue index 7e9e960..540d589 100644 --- a/src/views/modules/order/poOrder.vue +++ b/src/views/modules/order/poOrder.vue @@ -67,24 +67,26 @@ label="操作" header-align="center" align="center" - width="90"> + width="170"> - +
请选择文件 @@ -296,6 +298,55 @@
+ + + + + + + + + + + + + + + + + + + + + + + + {}) }, + /** + * 生成发货弹窗默认模型。 + * 说明:所有数量字段默认按 0 初始化,避免出现 null 导致的显示/比较异常。 + */ + createEmptyShipDialogForm () { + return { + site: '', + orderNo: '', + itemNo: null, + status: '', + orderQty: 0, + inspectQty: 0, + inspectApproveQty: 0, + currentShipQty: 0, + canShipQty: 0, + shipQty: 0 + } + }, + + /** + * 关闭发货弹窗时统一重置状态,避免上一次缓存数据污染下一次操作。 + */ + resetShipDialog () { + this.shipDialogSaving = false + this.shipDialogForm = this.createEmptyShipDialogForm() + }, + + /** + * 发货弹窗只读数量显示格式化。 + * 规则:null/空字符串显示为0,其余保持原值,避免出现 "undefined"。 + */ + formatShipDialogDisplay (value) { + if (value === null || value === undefined || value === '') { + return '0' + } + return String(value) + }, + + /** + * 将发货弹窗数值输入统一转换为 Number。 + * 规则:空值返回 NaN,便于后续统一走前端校验提示。 + */ + normalizeShipDialogNumber (value) { + if (value === '' || value === null || value === undefined) { + return Number.NaN + } + const num = Number(value) + return Number.isFinite(num) ? num : Number.NaN + }, + + /** + * 点击 shipped: + * 1) 先按 site + orderNo + itemNo 查询后端实时快照; + * 2) 弹出发货确认框并回填默认值(本次发货数量=可发货数量); + * 3) 由用户确认后再提交发货。 + */ handleShipPoOrder (row) { const params = buildPoDetailActionParams(row, this.$store.state.user.site) - if (!params.id && !(params.orderNo && params.site && params.itemNo != null)) { + if (!params.orderNo || !params.site || params.itemNo == null) { this.$message.error('无法识别订单行,请刷新后重试') return } - const poLabel = row.poNo ? `PO ${row.poNo}` : '该订单' - const itemLabel = row.itemNo != null ? ` 行 ${row.itemNo}` : '' - this.$confirm(`确定将${poLabel}${itemLabel}标记为已发货?`, '提示', { type: 'warning' }).then(() => { - shipPoDetail(params).then(({ data }) => { - if (data && data.code === 0) { - this.$message.success('发货成功') - this.getDataList() - } else { - this.$message.error((data && data.msg) || '发货失败') - } - }).catch(err => { - this.$message.error((err && err.message) || '发货失败') - }) - }).catch(() => {}) + shipPoDetailPreview({ + site: params.site, + orderNo: params.orderNo, + itemNo: params.itemNo + }).then(({ data }) => { + if (!(data && data.code === 0 && data.data)) { + this.$message.error((data && data.msg) || '加载发货数据失败') + return + } + const preview = data.data + this.shipDialogForm = { + site: preview.site || params.site, + orderNo: preview.orderNo || params.orderNo, + itemNo: preview.itemNo != null ? preview.itemNo : params.itemNo, + status: preview.status || '', + orderQty: preview.orderQty != null ? Number(preview.orderQty) : 0, + inspectQty: preview.inspectQty != null ? Number(preview.inspectQty) : 0, + inspectApproveQty: preview.inspectApproveQty != null ? Number(preview.inspectApproveQty) : 0, + currentShipQty: preview.currentShipQty != null ? Number(preview.currentShipQty) : 0, + canShipQty: preview.canShipQty != null ? Number(preview.canShipQty) : 0, + shipQty: preview.shipQty != null ? Number(preview.shipQty) : 0 + } + this.shipDialogVisible = true + }).catch(err => { + this.$message.error((err && err.message) || '加载发货数据失败') + }) + }, + + /** + * 提交发货确认: + * 1) 仅校验本次发货数量 > 0 且 <= 未发货数量; + * 2) 提交后端回写 qty / c_ship_qty / status; + * 3) 成功后关闭弹窗并刷新列表。 + */ + submitShipDialog () { + const orderQty = this.normalizeShipDialogNumber(this.shipDialogForm.orderQty) + const unshippedQty = this.normalizeShipDialogNumber(this.shipDialogForm.canShipQty) + const shipQty = this.normalizeShipDialogNumber(this.shipDialogForm.shipQty) + + if (!Number.isFinite(shipQty) || shipQty <= 0) { + this.$message.error('本次发货数量必须大于0') + return + } + if (!Number.isFinite(unshippedQty) || shipQty > unshippedQty) { + this.$message.error('本次发货数量不能大于未发货数量') + return + } + + const payload = { + site: this.shipDialogForm.site, + orderNo: this.shipDialogForm.orderNo, + itemNo: this.shipDialogForm.itemNo, + orderQty, + shipQty + } + this.shipDialogSaving = true + shipPoDetail(payload).then(({ data }) => { + this.shipDialogSaving = false + if (data && data.code === 0) { + this.$message.success('发货成功') + this.shipDialogVisible = false + this.getDataList() + } else { + this.$message.error((data && data.msg) || '发货失败') + } + }).catch(err => { + this.shipDialogSaving = false + this.$message.error((err && err.message) || '发货失败') + }) }, handleOpenPoOrder (row) { @@ -4135,6 +4316,21 @@ export default { color: #606266; } + + +.ship-dialog-form { + padding: 0 4px; +} + +.ship-dialog-input { + width: 120px; + text-align: right; +} + +.ship-dialog-footer { + text-align: center; +} + .el-table /deep/ .cell { height: auto; line-height: 1.5; diff --git a/src/views/modules/order/poOrderStatusOptions.js b/src/views/modules/order/poOrderStatusOptions.js index ab0f8a5..06b86a8 100644 --- a/src/views/modules/order/poOrderStatusOptions.js +++ b/src/views/modules/order/poOrderStatusOptions.js @@ -7,6 +7,7 @@ export const PO_ORDER_STATUS_OPTIONS = [ { label: '待验货', value: '待验货' }, { label: '验货中', value: '验货中' }, { label: '验货完成', value: '验货完成' }, + { label: '部分发货', value: '部分发货' }, { label: '已发货', value: '已发货' }, { label: '已取消', value: '已取消' }, { label: '已关闭', value: '已关闭' } @@ -35,14 +36,14 @@ export function canEditPoColumnByStatus (status, columnProp) { return true } -/** 是否可「关闭」 */ +/** 是否可「关闭」:除已关闭、已取消外显示关闭按钮(最终可否关闭以后端校验为准) */ export function canClosePoOrder (status) { - return !!status && status !== '草稿' && status !== '已关闭' && status !== '已取消' && status !== '已发货' + return !!status && status !== '已关闭' && status !== '已取消' } -/** 是否可「shipped」(仅验货完成) */ +/** 是否可「shipped」:验货中 / 验货完成 / 部分发货(兼容历史状态:部分验货)均允许发货弹窗入口 */ export function canShipPoOrder (status) { - return status === '验货完成' + return status === '验货中' || status === '验货完成' || status === '部分发货' || status === '部分验货' } /** 是否可「打开」(仅已关闭) */ diff --git a/src/views/modules/order/poOrder_search.vue b/src/views/modules/order/poOrder_search.vue index 17b9956..1d0af27 100644 --- a/src/views/modules/order/poOrder_search.vue +++ b/src/views/modules/order/poOrder_search.vue @@ -92,7 +92,9 @@ - +