From 4e09860b3665b05fe4f915b9499fe4f3838a896a Mon Sep 17 00:00:00 2001 From: yueli Date: Tue, 1 Sep 2026 16:21:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=87=E8=B4=AD=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E5=AE=8C=E7=BB=93=E5=8A=9F=E8=83=BD=E7=A7=BB=E5=88=B0=E6=89=B9?= =?UTF-8?q?=E6=AC=A1=E4=B8=BB=E8=A1=8C,=E4=B8=8E=E5=87=BA=E5=BA=93?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除展开行内的单条完结按钮(需点开),改为主行'完结本批'直接可见 - 后端 batch-approve 支持 action=close(批次内已通过→已完结) - 超管/库管在主行操作列即可看到并完结 --- inventory-backend/app/api/v1/purchase.py | 11 ++++--- inventory-web/src/views/purchase/index.vue | 35 ++++++++++++++++++++-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/inventory-backend/app/api/v1/purchase.py b/inventory-backend/app/api/v1/purchase.py index e270639..fe16b69 100644 --- a/inventory-backend/app/api/v1/purchase.py +++ b/inventory-backend/app/api/v1/purchase.py @@ -273,20 +273,23 @@ def batch_approve_purchase(): action = data.get('action', 'approve') reject_reason = data.get('reject_reason') - # 若传 batch_key(request_no 去掉末尾流水号的前缀),查出该批次所有待审批记录 + # 若传 batch_key(request_no 去掉末尾流水号的前缀),查出该批次对应状态的记录 if batch_key: from app.models.purchase import PurchaseRequest + # 完结本批 → 找「已通过(1)」的单;审批/驳回 → 找「待审批(0)」的单 + target_status = 1 if action == 'close' else 0 records = PurchaseRequest.query.filter( PurchaseRequest.request_no.like(f"{batch_key}-%"), - PurchaseRequest.status == 0 + PurchaseRequest.status == target_status ).all() ids = [r.id for r in records] if not ids: - return jsonify({'code': 400, 'msg': '该批次没有待审批的记录'}), 400 + status_text = '已通过' if action == 'close' else '待审批' + return jsonify({'code': 400, 'msg': f'该批次没有{status_text}的记录'}), 400 if not ids or not isinstance(ids, list): return jsonify({'code': 400, 'msg': 'ids 或 batch_key 不能为空'}), 400 - if action not in ('approve', 'reject'): + if action not in ('approve', 'reject', 'close'): return jsonify({'code': 400, 'msg': '无效的审批操作'}), 400 if action == 'reject' and not reject_reason: return jsonify({'code': 400, 'msg': '驳回时必须提供原因'}), 400 diff --git a/inventory-web/src/views/purchase/index.vue b/inventory-web/src/views/purchase/index.vue index 86f400a..235284b 100644 --- a/inventory-web/src/views/purchase/index.vue +++ b/inventory-web/src/views/purchase/index.vue @@ -58,9 +58,6 @@ 通过 驳回 - @@ -119,6 +116,10 @@ 审批本批 驳回本批 + + @@ -485,6 +486,34 @@ const handleApproveBatch = async (batchKey: string) => { } } +// ★ 批次内是否存在「已通过」的单(可完结) +const batchHasClosable = (row: any) => (row.items || []).some((it: any) => it.status === 1) + +// ★ 完结本批:一键完结批次内所有「已通过」记录(仿出库审批) +const handleCloseBatch = async (batchKey: string) => { + const batch = list.value.find(b => b.batchKey === batchKey) + const closable = batch ? (batch.items || []).filter((it: any) => it.status === 1) : [] + if (!closable.length) return ElMessage.warning('本批没有已通过记录可完结') + try { + await ElMessageBox.confirm( + `确定强制完结批次【${batchKey}】中 ${closable.length} 条已通过的记录吗?\n\n此操作不可恢复。`, + '⚠️ 完结本批确认', + { confirmButtonText: '确认完结', cancelButtonText: '取消', type: 'warning' } + ) + } catch { return } + + batchLoading.value = true + try { + const res: any = await batchApprovePurchase({ batch_key: batchKey, action: 'close' }) + ElMessage.success(res?.msg || '本批已完结') + await fetchData() + } catch (err: any) { + ElMessage.error(err?.msg || err?.message || '完结失败') + } finally { + batchLoading.value = false + } +} + // ★ 驳回本批:批次内所有待审批记录统一驳回 const rejectBatchKey = ref('') const rejectBatchDialogVisible = ref(false)