From 4c41e1ec13daccd893654ebc252828ba13e589c4 Mon Sep 17 00:00:00 2001 From: yueli Date: Mon, 31 Aug 2026 14:00:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(purchase):=20=E9=87=87=E8=B4=AD=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8C=89=E6=89=B9=E6=AC=A1=E5=88=86=E7=BB=84=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=20+=20=E6=89=B9=E6=AC=A1=E7=BA=A7=E4=B8=80=E9=94=AE?= =?UTF-8?q?=E5=AE=A1=E6=89=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 列表按批次分组(树形展开):一个批次一行,显示物品数/批次总价/申请人/状态汇总 - 展开批次行显示批内明细(每条记录状态/价格/操作) - 批次行提供「审批本批」「驳回本批」一键操作(按批次前缀批量处理待审批记录) - 保留逐条展开明细内的通过/驳回,以及顶部多选批量审批 - fetchData 按批次前缀聚合当前页数据 --- inventory-web/src/views/purchase/index.vue | 222 ++++++++++++++++----- 1 file changed, 174 insertions(+), 48 deletions(-) diff --git a/inventory-web/src/views/purchase/index.vue b/inventory-web/src/views/purchase/index.vue index 4da8dcf..018326d 100644 --- a/inventory-web/src/views/purchase/index.vue +++ b/inventory-web/src/views/purchase/index.vue @@ -17,62 +17,89 @@ - -
- 已选 {{ selectedRows.length }} 条待审批申请 - 批量通过 - 批量驳回 - 取消选择 -
+ + + + + + - - - - - - - - - - + + - - - - - - - - - - - - - + - + + + + + + {{ rejectBatchKey }} + + + + + + + + @@ -400,6 +443,60 @@ const clearSelection = () => { selectedRows.value = [] } +// ★ 审批本批:一键通过批次内所有待审批记录 +const handleApproveBatch = async (batchKey: string) => { + const batch = list.value.find(b => b.batchKey === batchKey) + if (!batch || batch.pendingCount === 0) return ElMessage.warning('本批没有待审批记录') + try { + await ElMessageBox.confirm( + `确定通过批次【${batchKey}】的 ${batch.pendingCount} 条待审批记录吗?`, + '审批本批', + { confirmButtonText: '全部通过', cancelButtonText: '取消', type: 'info' } + ) + } catch { return } + + batchLoading.value = true + try { + const res: any = await batchApprovePurchase({ batch_key: batchKey, action: 'approve' }) + ElMessage.success(res?.msg || '本批已全部通过') + await fetchData() + } catch (err: any) { + ElMessage.error(err?.msg || '审批失败') + } finally { + batchLoading.value = false + } +} + +// ★ 驳回本批:批次内所有待审批记录统一驳回 +const rejectBatchKey = ref('') +const rejectBatchDialogVisible = ref(false) +const rejectBatchReason = ref('') + +const openRejectBatchDialog = (batchKey: string) => { + rejectBatchKey.value = batchKey + rejectBatchReason.value = '' + rejectBatchDialogVisible.value = true +} + +const confirmRejectBatch = async () => { + if (!rejectBatchReason.value.trim()) { ElMessage.warning('请填写驳回原因'); return } + batchLoading.value = true + try { + const res: any = await batchApprovePurchase({ + batch_key: rejectBatchKey.value, + action: 'reject', + reject_reason: rejectBatchReason.value + }) + ElMessage.success(res?.msg || '本批已驳回') + rejectBatchDialogVisible.value = false + await fetchData() + } catch (err: any) { + ElMessage.error(err?.msg || '驳回失败') + } finally { + batchLoading.value = false + } +} + // 批量通过 const handleBatchApprove = async () => { if (selectedRows.value.length === 0) return @@ -617,8 +714,36 @@ const fetchData = async () => { if (filterStatus.value !== '') params.status = filterStatus.value const res: any = await getPurchaseList(params) - list.value = res.data?.items || [] + const items = res.data?.items || [] total.value = res.data?.total || 0 + + // ★ 按批次分组:同批次(单号去末尾-批内序号)聚合为一行 + const groupMap = new Map() + items.forEach(item => { + const key = getBatchKey(item.request_no) || '独立' + if (!groupMap.has(key)) groupMap.set(key, []) + groupMap.get(key)!.push(item) + }) + + list.value = Array.from(groupMap.entries()).map(([batchKey, batchItems]) => { + const totalAmount = batchItems.reduce((sum, it) => sum + (Number(it.total_price) || 0), 0) + const pendingCount = batchItems.filter(it => it.status === 0).length + // 状态汇总:全通过=1,全驳回=2,混合/待审=0 + const statuses = new Set(batchItems.map(it => it.status)) + let summaryStatus = batchItems[0]?.status ?? 0 + if (statuses.size > 1) summaryStatus = 0 // 混合状态按待审处理 + return { + batchKey, + items: batchItems, + itemCount: batchItems.length, + totalAmount, + pendingCount, + summaryStatus, + requesterName: batchItems[0]?.requester_name || '', + purchaseDate: batchItems[0]?.purchase_date || '', + statusTexts: batchItems.map(it => it.status_text).filter((v, i, a) => a.indexOf(v) === i) + } + }) } catch (err: any) { ElMessage.error(err?.msg || '加载失败') } finally { @@ -626,6 +751,7 @@ const fetchData = async () => { } } + const fetchApprovers = async () => { try { const res: any = await getPurchaseApprovers()