From f630e7e4d50ba22da8f42336196a02dbae850ced Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 10 八月 2026 17:54:32 +0800
Subject: [PATCH] refactor(erp): 优化采购发票和财务付款审核流程
---
src/views/erp/purchase/invoice/index.vue | 55 ++++------
src/views/erp/purchase/invoice/data.ts | 13 +-
src/api/erp/purchase/invoice/index.ts | 8 +
src/views/erp/finance/payment/index.vue | 71 +++++++++----
src/api/crm/receivable/index.ts | 8 +
src/api/erp/finance/payment/index.ts | 14 ++
src/components/upload/file-upload.vue | 8 +
src/views/crm/backlog/modules/receivable-audit-list.vue | 31 ++++-
src/views/crm/receivable/index.vue | 38 +++----
9 files changed, 142 insertions(+), 104 deletions(-)
diff --git a/src/api/crm/receivable/index.ts b/src/api/crm/receivable/index.ts
index 35940b4..974be6e 100644
--- a/src/api/crm/receivable/index.ts
+++ b/src/api/crm/receivable/index.ts
@@ -98,9 +98,11 @@
return requestClient.download('/crm/receivable/export-excel', { params });
}
-/** 鎻愪氦瀹℃牳 */
-export function submitReceivable(id: number) {
- return requestClient.put(`/crm/receivable/submit?id=${id}`);
+/** 鏇存柊鍥炴鐨勭姸鎬侊紙瀹℃牳/鍙嶅鏍革級 */
+export function updateReceivableStatus(id: number, status: number) {
+ return requestClient.put('/crm/receivable/update-status', null, {
+ params: { id, status },
+ });
}
/** 鑾峰緱寰呭鏍稿洖娆炬暟閲� */
diff --git a/src/api/erp/finance/payment/index.ts b/src/api/erp/finance/payment/index.ts
index 6efa6e3..276c047 100644
--- a/src/api/erp/finance/payment/index.ts
+++ b/src/api/erp/finance/payment/index.ts
@@ -18,6 +18,7 @@
discountPrice: number; // 浼樻儬閲戦
paymentPrice: number; // 瀹為檯浠樻閲戦
status: number; // 鐘舵��
+ processInstanceId?: string; // 宸ヤ綔娴佺紪鍙�
remark: string; // 澶囨敞
attachmentList?: { id: number; name?: string; url?: string }[]; // 闄勪欢鍒楄〃
accountId?: number; // 浠樻璐︽埛
@@ -75,13 +76,18 @@
return requestClient.put('/erp/finance-payment/update', data);
}
-/** 鏇存柊浠樻鍗曠殑鐘舵�� */
-export function updateFinancePaymentStatus(id: number, status: number) {
- return requestClient.put('/erp/finance-payment/update-status', null, {
- params: { id, status },
+/** 鎻愪氦浠樻鍗曞鎵� */
+export function submitFinancePayment(id: number, processDefinitionKey: string) {
+ return requestClient.post('/erp/finance-payment/submit', null, {
+ params: { id, processDefinitionKey },
});
}
+/** 鑾峰彇浠樻鍗曞鎵规祦绋嬪垪琛� */
+export function getFinancePaymentApproveProcessList() {
+ return requestClient.get('/erp/finance-payment/approve-process-list');
+}
+
/** 鍒犻櫎浠樻鍗� */
export function deleteFinancePayment(ids: number[]) {
return requestClient.delete('/erp/finance-payment/delete', {
diff --git a/src/api/erp/purchase/invoice/index.ts b/src/api/erp/purchase/invoice/index.ts
index cac70f5..bf69aaa 100644
--- a/src/api/erp/purchase/invoice/index.ts
+++ b/src/api/erp/purchase/invoice/index.ts
@@ -89,9 +89,11 @@
return requestClient.download('/erp/purchase-invoice/export-excel', { params });
}
-/** 鎻愪氦鏉ョエ瀹℃牳 */
-export function submitPurchaseInvoice(id: number) {
- return requestClient.put(`/erp/purchase-invoice/submit?id=${id}`);
+/** 鏇存柊鏉ョエ鐨勭姸鎬侊紙瀹℃牳/鍙嶅鏍革級 */
+export function updatePurchaseInvoiceStatus(id: number, status: number) {
+ return requestClient.put('/erp/purchase-invoice/update-status', null, {
+ params: { id, status },
+ });
}
/** 鑾峰緱寰呭鏍告潵绁ㄦ暟閲� */
diff --git a/src/components/upload/file-upload.vue b/src/components/upload/file-upload.vue
index 6296579..3692d2e 100644
--- a/src/components/upload/file-upload.vue
+++ b/src/components/upload/file-upload.vue
@@ -292,14 +292,14 @@
:progress="{ showInfo: true }"
:show-upload-list="{
showPreviewIcon: true,
- showRemoveIcon: true,
+ showRemoveIcon: !disabled,
showDownloadIcon,
}"
@remove="handleRemove"
@preview="handlePreview"
@reject="handleExceed"
>
- <div v-if="drag" class="upload-drag-area">
+ <div v-if="drag && !disabled" class="upload-drag-area">
<p class="ant-upload-drag-icon">
<IconifyIcon icon="lucide:cloud-upload" />
</p>
@@ -308,7 +308,9 @@
鏀寔{{ accept.join('/') }}鏍煎紡鏂囦欢锛屼笉瓒呰繃{{ maxSize }}MB
</p>
</div>
- <div v-else-if="fileList && fileList.length < maxNumber">
+ <div
+ v-else-if="!disabled && fileList && fileList.length < maxNumber"
+ >
<Button>
<IconifyIcon icon="lucide:cloud-upload" />
{{ $t('ui.upload.upload') }}
diff --git a/src/views/crm/backlog/modules/receivable-audit-list.vue b/src/views/crm/backlog/modules/receivable-audit-list.vue
index 83aeff5..a2a80be 100644
--- a/src/views/crm/backlog/modules/receivable-audit-list.vue
+++ b/src/views/crm/backlog/modules/receivable-audit-list.vue
@@ -5,22 +5,29 @@
import { useRouter } from 'vue-router';
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getReceivablePage } from '#/api/crm/receivable';
+import { getReceivablePage, updateReceivableStatus } from '#/api/crm/receivable';
import { useGridColumns } from '#/views/crm/receivable/data';
import { AUDIT_STATUS } from '../data';
const { push } = useRouter();
-/** 鏌ョ湅瀹℃壒 */
-function handleProcessDetail(row: CrmReceivableApi.Receivable) {
- push({
- name: 'BpmProcessInstanceDetail',
- query: { id: row.processInstanceId },
+/** 瀹℃牳 */
+async function handleAudit(row: CrmReceivableApi.Receivable) {
+ const hideLoading = message.loading({
+ content: '瀹℃牳涓�...',
+ duration: 0,
});
+ try {
+ await updateReceivableStatus(row.id!, 20);
+ message.success('瀹℃牳鎴愬姛');
+ gridApi.query();
+ } finally {
+ hideLoading();
+ }
}
/** 鎵撳紑鍥炴璇︽儏 */
@@ -38,7 +45,7 @@
push({ name: 'CrmContractDetail', params: { id: row.contractId } });
}
-const [Grid] = useVbenVxeGrid({
+const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: [
{
@@ -98,7 +105,13 @@
</Button>
</template>
<template #actions="{ row }">
- <Button type="link" @click="handleProcessDetail(row)">鏌ョ湅瀹℃壒</Button>
+ <Button
+ v-if="row.auditStatus === 10"
+ type="link"
+ @click="handleAudit(row)"
+ >
+ 瀹℃牳
+ </Button>
</template>
</Grid>
</template>
diff --git a/src/views/crm/receivable/index.vue b/src/views/crm/receivable/index.vue
index 329fdec..289a143 100644
--- a/src/views/crm/receivable/index.vue
+++ b/src/views/crm/receivable/index.vue
@@ -15,7 +15,7 @@
deleteReceivable,
exportReceivable,
getReceivablePage,
- submitReceivable,
+ updateReceivableStatus,
} from '#/api/crm/receivable';
import { $t } from '#/locales';
@@ -76,15 +76,18 @@
}
}
-/** 鎻愪氦瀹℃牳 */
-async function handleSubmit(row: CrmReceivableApi.Receivable) {
+/** 鏇存柊鍥炴鐘舵�侊紙瀹℃牳/鍙嶅鏍革級 */
+async function handleUpdateStatus(
+ row: CrmReceivableApi.Receivable,
+ status: number,
+) {
const hideLoading = message.loading({
- content: '鎻愪氦瀹℃牳涓�...',
+ content: '鏇存柊鐘舵�佷腑...',
duration: 0,
});
try {
- await submitReceivable(row.id!);
- message.success('鎻愪氦瀹℃牳鎴愬姛');
+ await updateReceivableStatus(row.id!, status);
+ message.success('鏇存柊鐘舵�佹垚鍔�');
handleRefresh();
} finally {
hideLoading();
@@ -109,14 +112,6 @@
/** 鏌ョ湅寮�绁ㄨ鎯� */
function handleInvoiceDetail(row: CrmReceivableApi.Receivable) {
push({ name: 'CrmInvoiceDetail', params: { id: row.invoiceId } });
-}
-
-/** 鏌ョ湅瀹℃壒璇︽儏 */
-function handleProcessDetail(row: CrmReceivableApi.Receivable) {
- push({
- name: 'BpmProcessInstanceDetail',
- query: { id: row.processInstanceId },
- });
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -221,21 +216,24 @@
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['crm:receivable:update'],
+ ifShow: row.auditStatus === 10,
onClick: handleEdit.bind(null, row),
},
{
- label: '鎻愪氦瀹℃牳',
+ label: '瀹℃牳',
type: 'link',
+ icon: ACTION_ICON.AUDIT,
auth: ['crm:receivable:update'],
- onClick: handleSubmit.bind(null, row),
- ifShow: row.auditStatus === 0,
+ ifShow: row.auditStatus === 10,
+ onClick: handleUpdateStatus.bind(null, row, 20),
},
{
- label: '鏌ョ湅瀹℃壒',
+ label: '鍙嶅鏍�',
type: 'link',
+ icon: ACTION_ICON.VIEW,
auth: ['crm:receivable:update'],
- onClick: handleProcessDetail.bind(null, row),
- ifShow: row.auditStatus !== 0,
+ ifShow: row.auditStatus === 20,
+ onClick: handleUpdateStatus.bind(null, row, 10),
},
{
label: $t('common.delete'),
diff --git a/src/views/erp/finance/payment/index.vue b/src/views/erp/finance/payment/index.vue
index a2aa1bc..8a9658e 100644
--- a/src/views/erp/finance/payment/index.vue
+++ b/src/views/erp/finance/payment/index.vue
@@ -3,6 +3,7 @@
import type { ErpFinancePaymentApi } from '#/api/erp/finance/payment';
import { ref } from 'vue';
+import { useRouter } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui';
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
@@ -13,19 +14,27 @@
import {
deleteFinancePayment,
exportFinancePayment,
+ getFinancePaymentApproveProcessList,
getFinancePaymentPage,
- updateFinancePaymentStatus,
} from '#/api/erp/finance/payment';
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
+import ProcessSelectModal from './modules/process-select-modal.vue';
/** ERP 浠樻鍗曞垪琛� */
defineOptions({ name: 'ErpFinancePayment' });
+const router = useRouter();
+
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
+ destroyOnClose: true,
+});
+
+const [ProcessModal, processModalApi] = useVbenModal({
+ connectedComponent: ProcessSelectModal,
destroyOnClose: true,
});
@@ -65,22 +74,36 @@
}
}
-/** 瀹℃壒/鍙嶅鎵规搷浣� */
-async function handleUpdateStatus(
- row: ErpFinancePaymentApi.FinancePayment,
- status: number,
-) {
+/** 鎻愪氦瀹℃壒 - 鍏堣幏鍙栨祦绋嬪垪琛� */
+async function handleSubmit(row: ErpFinancePaymentApi.FinancePayment) {
const hideLoading = message.loading({
- content: `纭畾${status === 20 ? '瀹℃壒' : '鍙嶅鎵�'}璇ヤ粯娆惧崟鍚楋紵`,
+ content: '鑾峰彇瀹℃壒娴佺▼...',
duration: 0,
});
try {
- await updateFinancePaymentStatus(row.id!, status);
- message.success(`${status === 20 ? '瀹℃壒' : '鍙嶅鎵�'}鎴愬姛`);
- handleRefresh();
- } finally {
+ const processList = await getFinancePaymentApproveProcessList();
+ hideLoading();
+ if (!processList || processList.length === 0) {
+ message.warning('鏆傛棤鍙敤瀹℃壒娴佺▼锛岃鍏堥厤缃� BPM 娴佺▼');
+ return;
+ }
+ // 鎵撳紑娴佺▼閫夋嫨寮圭獥
+ processModalApi.setData({ id: row.id, processList }).open();
+ } catch {
hideLoading();
}
+}
+
+/** 鏌ョ湅瀹℃壒璇︽儏 */
+function handleProcessDetail(row: ErpFinancePaymentApi.FinancePayment) {
+ if (!row.processInstanceId) {
+ message.warning('璇ヤ粯娆惧崟灏氭湭鎻愪氦瀹℃壒');
+ return;
+ }
+ router.push({
+ name: 'BpmProcessInstanceDetail',
+ query: { id: row.processInstanceId },
+ });
}
const checkedIds = ref<number[]>([]);
@@ -134,6 +157,7 @@
<template>
<Page auto-content-height><FormModal @success="handleRefresh" />
+ <ProcessModal @success="handleRefresh" />
<Grid table-title="浠樻鍗曞垪琛�">
<template #toolbar-tools>
<TableAction
@@ -189,22 +213,24 @@
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['erp:finance-payment:update'],
- ifShow: () => row.status !== 20,
+ ifShow: () => row.status !== 20 && row.status !== 15,
onClick: handleEdit.bind(null, row),
},
{
- label: row.status === 10 ? '瀹℃壒' : '鍙嶅鎵�',
+ label: '鎻愪氦瀹℃牳',
type: 'link',
icon: ACTION_ICON.AUDIT,
- auth: ['erp:finance-payment:update-status'],
- popConfirm: {
- title: `纭${row.status === 10 ? '瀹℃壒' : '鍙嶅鎵�'}${row.no}鍚楋紵`,
- confirm: handleUpdateStatus.bind(
- null,
- row,
- row.status === 10 ? 20 : 10,
- ),
- },
+ auth: ['erp:finance-payment:update'],
+ ifShow: () => row.status === 10,
+ onClick: handleSubmit.bind(null, row),
+ },
+ {
+ label: '鏌ョ湅瀹℃壒',
+ type: 'link',
+ icon: ACTION_ICON.VIEW,
+ auth: ['erp:finance-payment:query'],
+ ifShow: () => row.status !== 10 && !!row.processInstanceId,
+ onClick: handleProcessDetail.bind(null, row),
},
{
label: $t('common.delete'),
@@ -212,6 +238,7 @@
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['erp:finance-payment:delete'],
+ ifShow: () => row.status !== 15,
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
confirm: handleDelete.bind(null, [row.id!]),
diff --git a/src/views/erp/purchase/invoice/data.ts b/src/views/erp/purchase/invoice/data.ts
index e222159..c70e185 100644
--- a/src/views/erp/purchase/invoice/data.ts
+++ b/src/views/erp/purchase/invoice/data.ts
@@ -150,17 +150,14 @@
},
{
fieldName: 'auditStatus',
- label: '瀹℃壒鐘舵��',
+ label: '瀹℃牳鐘舵��',
component: 'Select',
componentProps: {
options: [
- { label: '鏈彁浜�', value: 0 },
- { label: '瀹℃壒涓�', value: 10 },
- { label: '瀹℃牳閫氳繃', value: 20 },
- { label: '瀹℃牳涓嶉�氳繃', value: 30 },
- { label: '宸蹭綔搴�', value: 40 },
+ { label: '鏈鏍�', value: 10 },
+ { label: '宸插鏍�', value: 20 },
],
- placeholder: '璇烽�夋嫨瀹℃壒鐘舵��',
+ placeholder: '璇烽�夋嫨瀹℃牳鐘舵��',
allowClear: true,
},
},
@@ -233,7 +230,7 @@
{
title: '鎿嶄綔',
field: 'actions',
- minWidth: 200,
+ minWidth: 280,
fixed: 'right',
slots: { default: 'actions' },
},
diff --git a/src/views/erp/purchase/invoice/index.vue b/src/views/erp/purchase/invoice/index.vue
index 6c1dd21..c0cbd7b 100644
--- a/src/views/erp/purchase/invoice/index.vue
+++ b/src/views/erp/purchase/invoice/index.vue
@@ -2,8 +2,6 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { ErpPurchaseInvoiceApi } from '#/api/erp/purchase/invoice';
-import { useRouter } from 'vue-router';
-
import { Page, useVbenModal } from '@vben/common-ui';
import { downloadFileFromBlobPart } from '@vben/utils';
@@ -14,7 +12,7 @@
deletePurchaseInvoice,
exportPurchaseInvoice,
getPurchaseInvoicePage,
- submitPurchaseInvoice,
+ updatePurchaseInvoiceStatus,
} from '#/api/erp/purchase/invoice';
import { $t } from '#/locales';
@@ -22,8 +20,6 @@
import Form from './modules/form.vue';
defineOptions({ name: 'ErpPurchaseInvoice' });
-
-const { push } = useRouter();
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
@@ -72,27 +68,22 @@
}
}
-/** 鎻愪氦瀹℃牳 */
-async function handleSubmit(row: ErpPurchaseInvoiceApi.PurchaseInvoice) {
+/** 鏇存柊鏉ョエ鐘舵�侊紙瀹℃牳/鍙嶅鏍革級 */
+async function handleUpdateStatus(
+ row: ErpPurchaseInvoiceApi.PurchaseInvoice,
+ status: number,
+) {
const hideLoading = message.loading({
- content: '鎻愪氦瀹℃牳涓�...',
+ content: '鏇存柊鐘舵�佷腑...',
duration: 0,
});
try {
- await submitPurchaseInvoice(row.id!);
- message.success('鎻愪氦瀹℃牳鎴愬姛');
+ await updatePurchaseInvoiceStatus(row.id!, status);
+ message.success('鏇存柊鐘舵�佹垚鍔�');
handleRefresh();
} finally {
hideLoading();
}
-}
-
-/** 鏌ョ湅瀹℃壒璇︽儏 */
-function handleProcessDetail(row: ErpPurchaseInvoiceApi.PurchaseInvoice) {
- push({
- name: 'BpmProcessInstanceDetail',
- query: { id: row.processInstanceId },
- });
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -163,11 +154,9 @@
<Tag v-else color="success">宸蹭笂浼�</Tag>
</template>
<template #auditStatus="{ row }">
- <Tag v-if="row.auditStatus === 0" color="default">鏈彁浜�</Tag>
- <Tag v-else-if="row.auditStatus === 10" color="warning">瀹℃壒涓�</Tag>
- <Tag v-else-if="row.auditStatus === 20" color="success">瀹℃牳閫氳繃</Tag>
- <Tag v-else-if="row.auditStatus === 30" color="error">瀹℃牳涓嶉�氳繃</Tag>
- <Tag v-else-if="row.auditStatus === 40" color="default">宸蹭綔搴�</Tag>
+ <Tag v-if="row.auditStatus === 10" color="warning">鏈鏍�</Tag>
+ <Tag v-else-if="row.auditStatus === 20" color="success">宸插鏍�</Tag>
+ <Tag v-else color="default">--</Tag>
</template>
<template #actions="{ row }">
<TableAction
@@ -184,22 +173,24 @@
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['erp:purchase-invoice:update'],
- ifShow: row.auditStatus === 0,
+ ifShow: row.auditStatus === 10,
onClick: handleEdit.bind(null, row),
},
{
- label: '鎻愪氦瀹℃牳',
+ label: '瀹℃牳',
type: 'link',
- auth: ['erp:purchase-invoice:update'],
- onClick: handleSubmit.bind(null, row),
- ifShow: row.auditStatus === 0,
+ icon: ACTION_ICON.AUDIT,
+ auth: ['erp:purchase-invoice:update-status'],
+ ifShow: row.auditStatus === 10,
+ onClick: handleUpdateStatus.bind(null, row, 20),
},
{
- label: '鏌ョ湅瀹℃壒',
+ label: '鍙嶅鏍�',
type: 'link',
- auth: ['erp:purchase-invoice:query'],
- onClick: handleProcessDetail.bind(null, row),
- ifShow: row.auditStatus !== 0 && !!row.processInstanceId,
+ icon: ACTION_ICON.VIEW,
+ auth: ['erp:purchase-invoice:update-status'],
+ ifShow: row.auditStatus === 20,
+ onClick: handleUpdateStatus.bind(null, row, 10),
},
{
label: $t('common.delete'),
--
Gitblit v1.9.3