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)