From 261f2ed00235d47df3754291a4fdca9ba5cb8e7a Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 21 五月 2026 17:16:09 +0800
Subject: [PATCH] fix: 合并财务数据
---
src/api/salesManagement/indicatorStats.js | 18
src/api/salesManagement/invoiceLedger.js | 94
src/api/financialManagement/accountPurchaseInvoice.js | 50
src/views/financialManagement/payable/payment.vue | 562 +--
src/views/salesManagement/receiptPaymentLedger/index.vue | 486 +-
src/api/financialManagement/accountPaymentApplication.js | 59
src/views/financialManagement/payable/input-invoice.vue | 918 +++++-
src/views/safeProduction/safetyTrainingAssessment/detail.vue | 2
src/api/procurementManagement/paymentLedger.js | 12
src/views/financialManagement/receivable/reconciliation.vue | 563 +++-
src/api/salesManagement/receiptPayment.js | 86
src/api/financialManagement/accountPurchasePayment.js | 32
src/store/modules/user.js | 14
src/views/financialManagement/receivable/receipt.vue | 1063 +++++--
src/views/financialManagement/receivable/invoiceApply.vue | 750 ++++
src/api/financialManagement/accountSalesInvoice.js | 41
src/views/financialManagement/payable/paymentApply.vue | 970 +++++-
src/views/procurementManagement/paymentLedger/index.vue | 494 +-
/dev/null | 279 --
src/api/financialManagement/invoiceApply.js | 59
src/views/financialManagement/payable/reconciliation.vue | 613 +++-
src/api/financialManagement/accountStatement.js | 41
src/views/financialManagement/payable/purchaseIn.vue | 283 +
src/api/viewIndex.js | 21
src/views/productionManagement/productionOrder/index.vue | 1
src/api/financialManagement/accountSalesCollection.js | 50
src/views/financialManagement/receivable/outputInvoice.vue | 489 ++
src/views/financialManagement/payable/purchaseReturn.vue | 113
28 files changed, 5,500 insertions(+), 2,663 deletions(-)
diff --git a/src/api/financialManagement/accountPaymentApplication.js b/src/api/financialManagement/accountPaymentApplication.js
new file mode 100644
index 0000000..0d5e438
--- /dev/null
+++ b/src/api/financialManagement/accountPaymentApplication.js
@@ -0,0 +1,59 @@
+import request from "@/utils/request";
+
+/** 鏍规嵁渚涘簲鍟嗘煡璇㈠彲鍏宠仈鍏ュ簱鍗� */
+export function getInboundBatchesBySupplier(params) {
+ return request({
+ url: "/accountPaymentApplication/getInboundBatchesBySupplier",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏂板浠樻鐢宠 */
+export function addAccountPaymentApplication(data) {
+ return request({
+ url: "/accountPaymentApplication/addAccountPaymentApplication",
+ method: "post",
+ data,
+ });
+}
+
+/** 浠樻鐢宠鍒嗛〉鍒楄〃 */
+export function listPageAccountPaymentApplication(params) {
+ return request({
+ url: "/accountPaymentApplication/listPageAccountPaymentApplication",
+ method: "get",
+ params,
+ });
+}
+
+/** 淇敼浠樻鐢宠 */
+export function updateAccountPaymentApplication(data) {
+ return request({
+ url: "/accountPaymentApplication/updateAccountPaymentApplication",
+ method: "put",
+ data,
+ });
+}
+
+/** 瀹℃牳浠樻鐢宠 */
+export function auditAccountPaymentApplication(data) {
+ return request({
+ url: "/accountPaymentApplication/auditAccountPaymentApplication",
+ method: "put",
+ data,
+ });
+}
+
+/** 鍒犻櫎浠樻鐢宠锛圫pring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountPaymentApplication(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountPaymentApplication/deleteAccountPaymentApplication?${query}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/financialManagement/accountPurchaseInvoice.js b/src/api/financialManagement/accountPurchaseInvoice.js
new file mode 100644
index 0000000..af391da
--- /dev/null
+++ b/src/api/financialManagement/accountPurchaseInvoice.js
@@ -0,0 +1,50 @@
+import request from "@/utils/request";
+
+/** 鏍规嵁渚涘簲鍟嗘煡璇㈠彲鍏宠仈鍏ュ簱鍗� */
+export function getInboundBatchesBySupplier(params) {
+ return request({
+ url: "/accountPurchaseInvoice/getInboundBatchesBySupplier",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏂板杩涢」鍙戠エ */
+export function addAccountPurchaseInvoice(data) {
+ return request({
+ url: "/accountPurchaseInvoice/addAccountPurchaseInvoice",
+ method: "post",
+ data,
+ });
+}
+
+/** 杩涢」鍙戠エ鍒嗛〉鍒楄〃 */
+export function listPageAccountPurchaseInvoice(params) {
+ return request({
+ url: "/accountPurchaseInvoice/listPageAccountPurchaseInvoice",
+ method: "get",
+ params,
+ });
+}
+
+/** 浣滃簾杩涢」鍙戠エ */
+export function cancelAccountPurchaseInvoice(data) {
+ return request({
+ url: "/accountPurchaseInvoice/cancelAccountPurchaseInvoice",
+ method: "put",
+ data,
+ });
+}
+
+/** 鍒犻櫎杩涢」鍙戠エ锛圫pring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountPurchaseInvoice(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountPurchaseInvoice/deleteAccountPurchaseInvoice?${query}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/financialManagement/accountPurchasePayment.js b/src/api/financialManagement/accountPurchasePayment.js
new file mode 100644
index 0000000..a10f05a
--- /dev/null
+++ b/src/api/financialManagement/accountPurchasePayment.js
@@ -0,0 +1,32 @@
+import request from "@/utils/request";
+
+/** 鏂板浠樻鍗曪紙鍏宠仈浠樻鐢宠锛� */
+export function addAccountPurchasePayment(data) {
+ return request({
+ url: "/accountPurchasePayment/addAccountPurchasePayment",
+ method: "post",
+ data,
+ });
+}
+
+/** 浠樻鍗曞垎椤靛垪琛� */
+export function listPageAccountPurchasePayment(params) {
+ return request({
+ url: "/accountPurchasePayment/listPageAccountPurchasePayment",
+ method: "get",
+ params,
+ });
+}
+
+/** 鍒犻櫎浠樻鍗曪紙Spring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountPurchasePayment(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountPurchasePayment/deleteAccountPurchasePayment?${query}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/financialManagement/accountSalesCollection.js b/src/api/financialManagement/accountSalesCollection.js
new file mode 100644
index 0000000..abeb977
--- /dev/null
+++ b/src/api/financialManagement/accountSalesCollection.js
@@ -0,0 +1,50 @@
+import request from "@/utils/request";
+
+/** 鏍规嵁瀹㈡埛鏌ヨ鍙叧鑱斿嚭搴撳崟 */
+export function getOutboundBatchesByCustomer(params) {
+ return request({
+ url: "/accountSalesCollection/getOutboundBatchesByCustomer",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏂板鏀舵鍗� */
+export function addAccountSalesCollection(data) {
+ return request({
+ url: "/accountSalesCollection/addAccountSalesCollection",
+ method: "post",
+ data,
+ });
+}
+
+/** 鏀舵鍗曞垎椤靛垪琛� */
+export function listPageAccountSalesCollection(params) {
+ return request({
+ url: "/accountSalesCollection/listPageAccountSalesCollection",
+ method: "get",
+ params,
+ });
+}
+
+/** 淇敼鏀舵鍗� */
+export function updateAccountSalesCollection(data) {
+ return request({
+ url: "/accountSalesCollection/updateAccountSalesCollection",
+ method: "put",
+ data,
+ });
+}
+
+/** 鍒犻櫎鏀舵鍗曪紙Spring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountSalesCollection(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountSalesCollection/deleteAccountSalesCollection?${query}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/financialManagement/accountSalesInvoice.js b/src/api/financialManagement/accountSalesInvoice.js
new file mode 100644
index 0000000..6e74c53
--- /dev/null
+++ b/src/api/financialManagement/accountSalesInvoice.js
@@ -0,0 +1,41 @@
+import request from "@/utils/request";
+
+/** 鏂板閿�椤瑰彂绁� */
+export function addAccountSalesInvoice(data) {
+ return request({
+ url: "/accountSalesInvoice/addAccountSalesInvoice",
+ method: "post",
+ data,
+ });
+}
+
+/** 閿�椤瑰彂绁ㄥ垎椤靛垪琛� */
+export function listPageAccountSalesInvoice(params) {
+ return request({
+ url: "/accountSalesInvoice/listPageAccountSalesInvoice",
+ method: "get",
+ params,
+ });
+}
+
+/** 浣滃簾閿�椤瑰彂绁� */
+export function cancelAccountSalesInvoice(data) {
+ return request({
+ url: "/accountSalesInvoice/cancelAccountSalesInvoice",
+ method: "put",
+ data,
+ });
+}
+
+/** 鍒犻櫎閿�椤瑰彂绁紙Spring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountSalesInvoice(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountSalesInvoice/deleteAccountSalesInvoice?${query}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/financialManagement/accountStatement.js b/src/api/financialManagement/accountStatement.js
new file mode 100644
index 0000000..bf80101
--- /dev/null
+++ b/src/api/financialManagement/accountStatement.js
@@ -0,0 +1,41 @@
+import request from "@/utils/request";
+
+/** 鎸夋湀浠芥煡璇㈠璐﹀崟鏄庣粏锛堢敓鎴愬墠棰勮锛� */
+export function getAccountStatementDetailsByMonth(params) {
+ return request({
+ url: "/accountStatement/getAccountStatementDetailsByMonth",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏂板瀵硅处鍗� */
+export function addAccountStatement(data) {
+ return request({
+ url: "/accountStatement/addAccountStatement",
+ method: "post",
+ data,
+ });
+}
+
+/** 瀵硅处鍗曞垎椤靛垪琛� */
+export function listPageAccountStatement(params) {
+ return request({
+ url: "/accountStatement/listPageAccountStatement",
+ method: "get",
+ params,
+ });
+}
+
+/** 鍒犻櫎瀵硅处鍗曪紙Spring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountStatement(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountStatement/deleteAccountStatement?${query}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/financialManagement/expenseManagement.js b/src/api/financialManagement/expenseManagement.js
deleted file mode 100644
index a22af1b..0000000
--- a/src/api/financialManagement/expenseManagement.js
+++ /dev/null
@@ -1,85 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ鍒楄〃
-export const listPage = (params) => {
- return request({
- url: "/account/accountExpense/listPage",
- method: "get",
- params,
- });
-};
-export const listPageAnalysis = (params) => {
- return request({
- url: "/account/accountExpense/report/analysis",
- method: "get",
- params,
- });
-};
-
-// 鏂板
-export function add(data) {
- return request({
- url: "/account/accountExpense/add",
- method: "post",
- data: data,
- });
-}
-
-// 缂栬緫
-export function update(data) {
- return request({
- url: "/account/accountExpense/update",
- method: "post",
- data: data,
- });
-}
-
-//瀵煎嚭
-export const exportAccountExpense = (query) => {
- return request({
- url: "/account/accountExpense/export",
- method: "post",
- data: query,
- responseType: "blob",
- });
-};
-
-export const delAccountExpense = (query) => {
- return request({
- url: `account/accountExpense/del`,
- method: "delete",
- data: query,
- });
-};
-
-export const getAccountExpense = (id) => {
- return request({
- url: `/account/accountExpense/${id}`,
- method: "get",
- });
-};
-
-// 鏌ヨ闄勪欢鍒楄〃
-export function fileListPage(query) {
- return request({
- url: "/account/accountFile/listPage",
- method: "get",
- params: query,
- });
-}
-// 淇濆瓨闄勪欢鍒楄〃
-export function fileAdd(query) {
- return request({
- url: "/account/accountFile/add",
- method: "post",
- data: query,
- });
-}
-// 鍒犻櫎闄勪欢鍒楄〃
-export function fileDel(query) {
- return request({
- url: "/account/accountFile/del",
- method: "delete",
- data: query,
- });
-}
diff --git a/src/api/financialManagement/invoiceApply.js b/src/api/financialManagement/invoiceApply.js
new file mode 100644
index 0000000..a567d1c
--- /dev/null
+++ b/src/api/financialManagement/invoiceApply.js
@@ -0,0 +1,59 @@
+import request from "@/utils/request";
+
+/** 鏍规嵁瀹㈡埛鏌ヨ鍙紑绁ㄥ嚭搴撳崟鍙峰垪琛� */
+export function getOutboundBatchesByCustomer(params) {
+ return request({
+ url: "/accountInvoiceApplication/getOutboundBatchesByCustomer",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏂板寮�绁ㄧ敵璇� */
+export function addAccountInvoiceApplication(data) {
+ return request({
+ url: "/accountInvoiceApplication/addAccountInvoiceApplication",
+ method: "post",
+ data,
+ });
+}
+
+/** 寮�绁ㄧ敵璇峰垎椤靛垪琛� */
+export function listPageAccountInvoiceApplication(params) {
+ return request({
+ url: "/accountInvoiceApplication/listPageAccountInvoiceApplication",
+ method: "get",
+ params,
+ });
+}
+
+/** 寮�绁ㄧ敵璇峰鎵� */
+export function auditAccountInvoiceApplication(data) {
+ return request({
+ url: "/accountInvoiceApplication/auditAccountInvoiceApplication",
+ method: "put",
+ data,
+ });
+}
+
+/** 淇敼寮�绁ㄧ敵璇� */
+export function updateAccountInvoiceApplication(data) {
+ return request({
+ url: "/accountInvoiceApplication/updateAccountInvoiceApplication",
+ method: "put",
+ data,
+ });
+}
+
+/** 鍒犻櫎寮�绁ㄧ敵璇凤紙Spring 瑕佹眰 ids=1&ids=2 鏌ヨ鍙傛暟锛� */
+export function deleteAccountInvoiceApplication(ids) {
+ const idList = Array.isArray(ids) ? ids : [ids];
+ const query = idList
+ .filter((id) => id !== undefined && id !== null && id !== "")
+ .map((id) => `ids=${encodeURIComponent(id)}`)
+ .join("&");
+ return request({
+ url: `/accountInvoiceApplication/deleteAccountInvoiceApplication?${query}`,
+ method: "delete",
+ });
+}
\ No newline at end of file
diff --git a/src/api/financialManagement/loanManagement.js b/src/api/financialManagement/loanManagement.js
deleted file mode 100644
index 46ea749..0000000
--- a/src/api/financialManagement/loanManagement.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ鍒楄〃
-export const listPage = (params) => {
- return request({
- url: "/borrowInfo/listPage",
- method: "get",
- params,
- });
-};
-
-// 鏂板
-export function add(data) {
- return request({
- url: "/borrowInfo/add",
- method: "post",
- data: data,
- });
-}
-
-// 缂栬緫
-export function update(data) {
- return request({
- url: "/borrowInfo/update",
- method: "post",
- data: data,
- });
-}
-
-// 鍒犻櫎
-export const delAccountLoan = (data) => {
- return request({
- url: "/borrowInfo/delete",
- method: "delete",
- data,
- });
-};
diff --git a/src/api/financialManagement/revenueManagement.js b/src/api/financialManagement/revenueManagement.js
deleted file mode 100644
index 090ddf8..0000000
--- a/src/api/financialManagement/revenueManagement.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ鍒楄〃
-export const listPage = (params) => {
- return request({
- url: "/account/accountIncome/listPage",
- method: "get",
- params,
- });
-};
-
-// 鏂板
-export function add(data) {
- return request({
- url: "/account/accountIncome/add",
- method: "post",
- data: data,
- });
-}
-
-// 缂栬緫
-export function update(data) {
- return request({
- url: "/account/accountIncome/update",
- method: "post",
- data: data,
- });
-}
-
-//瀵煎嚭
-export const exportAccountIncome = (query) => {
- return request({
- url: "/account/accountIncome/export",
- method: "post",
- data: query,
- responseType: "blob",
- });
-};
-
-export const delAccountIncome = (query) => {
- return request({
- url: `account/accountIncome/del`,
- method: "delete",
- data: query,
- });
-};
-
-export const getAccountIncome = (id) => {
- return request({
- url: `/account/accountIncome/${id}`,
- method: "get",
- });
-};
-
-// 鏌ヨ闄勪欢鍒楄〃
-export function fileListPage(query) {
- return request({
- url: "/account/accountFile/listPage",
- method: "get",
- params: query,
- });
-}
-// 淇濆瓨闄勪欢鍒楄〃
-export function fileAdd(query) {
- return request({
- url: "/account/accountFile/add",
- method: "post",
- data: query,
- });
-}
-// 鍒犻櫎闄勪欢鍒楄〃
-export function fileDel(query) {
- return request({
- url: "/account/accountFile/del",
- method: "delete",
- data: query,
- });
-}
diff --git a/src/api/financialManagement/salesRefund.js b/src/api/financialManagement/salesRefund.js
deleted file mode 100644
index 84b87fb..0000000
--- a/src/api/financialManagement/salesRefund.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ鍒楄〃
-// /salesRefundAmountOrder/page
-export const listPage = (params) => {
- return request({
- url: "/salesRefundAmountOrder/page",
- method: "get",
- params,
- });
-};
-
-// 鏂板
-// /salesRefundAmountOrder/add
-export function add(data) {
- return request({
- url: "/salesRefundAmountOrder/add",
- method: "post",
- data: data,
- });
-}
-
-// 淇敼
-// /salesRefundAmountOrder/update
-export function update(data) {
- return request({
- url: "/salesRefundAmountOrder/update",
- method: "put",
- data: data,
- });
-}
-
-// 鍒犻櫎
-// /salesRefundAmountOrder/deleteByIds
-export function del(data) {
- return request({
- url: "/salesRefundAmountOrder/deleteByIds",
- method: "delete",
- data: data,
- });
-}
\ No newline at end of file
diff --git a/src/api/procurementManagement/invoiceEntry.js b/src/api/procurementManagement/invoiceEntry.js
deleted file mode 100644
index 8325aa7..0000000
--- a/src/api/procurementManagement/invoiceEntry.js
+++ /dev/null
@@ -1,69 +0,0 @@
-// 閲囪喘-鏉ョエ鐧昏鎺ュ彛
-import request from "@/utils/request";
-
-// 鏌ヨ閲囪喘鍚堝悓鍙�
-export function getProduct(query) {
- return request({
- url: "/purchase/ledger/getProduct",
- method: "get",
- params: query,
- });
-}
-
-// 鏌ヨid閲囪喘鍚堝悓鍙�
-export function getPurchaseNoById(query) {
- return request({
- url: "/purchase/ledger/getPurchaseNoById",
- method: "get",
- params: query,
- });
-}
-// 鏍规嵁閲囪喘鍚堝悓鍙锋煡璇㈣缁嗕俊鎭�
-export function getInfo(query) {
- return request({
- url: "/purchase/ledger/getInfo",
- method: "get",
- params: query,
- });
-}
-// 涓诲垪琛ㄦ煡璇�
-export function gePurchaseList(query) {
- return request({
- url: "/purchase/ledger/list",
- method: "get",
- params: query,
- });
-}
-// 涓诲垪琛ㄦ煡璇�
-export function getRegistrationById(query) {
- return request({
- url: "/purchase/registration/getRegistrationById",
- method: "get",
- params: query,
- });
-}
-// 鏂板缂栬緫鏉ョエ鐧昏
-export function addOrUpdateRegistration(query) {
- return request({
- url: "/purchase/registration/addOrUpdateRegistration",
- method: "post",
- data: query,
- });
-}
-// 鍒犻櫎鏉ョエ鐧昏
-export function delRegistration(query) {
- return request({
- url: "/purchase/registration/delRegistration",
- method: "delete",
- data: query,
- });
-}
-
-// 涓诲垪琛ㄦ煡璇�
-export function gePurchaseListPage(query) {
- return request({
- url: "/purchase/ledger/listPage",
- method: "get",
- params: query,
- });
-}
diff --git a/src/api/procurementManagement/paymentEntry.js b/src/api/procurementManagement/paymentEntry.js
deleted file mode 100644
index 6ef0eb9..0000000
--- a/src/api/procurementManagement/paymentEntry.js
+++ /dev/null
@@ -1,81 +0,0 @@
-// 閲囪喘浠樻鐧昏椤甸潰鎺ュ彛
-import request from "@/utils/request";
-
-// 鍒嗛〉鏌ヨ
-export function registrationList(query) {
- return request({
- url: "/purchase/paymentRegistration/list",
- method: "get",
- params: query,
- });
-}
-// 鏌ヨ璇︽儏
-export function registrationInfo(query) {
- return request({
- url: "/purchase/paymentRegistration/" + query,
- method: "get",
- });
-}
-// 鏍规嵁閲囪喘鍚堝悓鍙锋煡璇㈣鎯�
-export function byPurchaseId(query) {
- return request({
- url: "/purchase/paymentRegistration/byPurchaseId/" + query,
- method: "get",
- });
-}
-// 鏌ヨ閲囪喘鍚堝悓鍙�
-export function getPurchaseNo() {
- return request({
- url: "/purchase/ledger/getPurchaseNo",
- method: "get",
- });
-}
-// 鏂板
-export function paymentRegistrationAdd(query) {
- return request({
- url: "/purchase/paymentRegistration",
- method: "post",
- data: query,
- });
-}
-// 淇敼
-export function paymentRegistrationEdit(query) {
- return request({
- url: "/purchase/paymentRegistration",
- method: "put",
- data: query,
- });
-}
-// 鍒犻櫎
-export function paymentRegistrationDel(query) {
- return request({
- url: "/purchase/paymentRegistration/delete",
- method: "delete",
- data: query,
- });
-}
-// 鑾峰彇鍙戠エ鍙峰拰鍙戠エ閲戦
-export function getTicketNo(query) {
- return request({
- url: "/purchase/registration/getTicketNo",
- method: "get",
- params: query,
- });
-}
-// 鍒嗛〉鏌ヨ
-export function paymentHistoryList(query) {
- return request({
- url: "/purchase/paymentRegistration/paymentHistoryList",
- method: "get",
- params: query,
- });
-}
-
-// 鍒嗛〉鏌ヨ
-export function paymentHistoryListPage(query) {
- return request({
- url: "/purchase/paymentRegistration/paymentHistoryListPage",
- method: "get",
- params: query,
- });
-}
diff --git a/src/api/procurementManagement/paymentLedger.js b/src/api/procurementManagement/paymentLedger.js
index 31aff29..6c5d9de 100644
--- a/src/api/procurementManagement/paymentLedger.js
+++ b/src/api/procurementManagement/paymentLedger.js
@@ -1,20 +1,20 @@
// 閲囪喘鍙拌处椤甸潰鎺ュ彛
import request from "@/utils/request";
-// 鍒嗛〉鏌ヨ
+/** 浠樻鍙拌处 - 渚涘簲鍟嗗線鏉ユ眹鎬� */
export function paymentLedgerList(query) {
return request({
- url: "/purchase/paymentRegistration/supplierNameListPage",
+ url: "/purchase/report/supplierTransactions",
method: "get",
params: query,
});
}
-// 鍒嗛〉鏌ヨ
-export function paymentRecordList(supplierId) {
+/** 浠樻鍙拌处 - 渚涘簲鍟嗗線鏉ユ槑缁� */
+export function paymentRecordList(params) {
return request({
- url: "/purchase/paymentRegistration/supplierNameListPageDetails",
+ url: "/purchase/report/supplierTransactionsDetails",
method: "get",
- params: supplierId,
+ params,
});
}
diff --git a/src/api/procurementManagement/procurementInvoiceLedger.js b/src/api/procurementManagement/procurementInvoiceLedger.js
deleted file mode 100644
index d0716f9..0000000
--- a/src/api/procurementManagement/procurementInvoiceLedger.js
+++ /dev/null
@@ -1,124 +0,0 @@
-// 閲囪喘-鏉ョエ鍙拌处鎺ュ彛
-import request from "@/utils/request";
-
-// 鏌ヨ鍒楄〃
-export function invoiceList(query) {
- return request({
- url: "/purchase/registration/list",
- method: "get",
- params: query,
- });
-}
-// 鏌ヨ璇︽儏
-// export function getInvoiceById(query) {
-// return request({
-// url: "/purchase/registration/getRegistrationById",
-// method: "get",
-// params: query,
-// });
-// }
-// 鏂板銆佺紪杈�
-export function addOrUpdateInvoice(query) {
- return request({
- url: "/purchase/invoice/addOrUpdateInvoice",
- method: "post",
- data: query,
- });
-}
-// 鍒犻櫎
-export function delInvoice(query) {
- return request({
- url: "/purchase/invoice/delInvoice",
- method: "delete",
- data: query,
- });
-}
-// 鍒犻櫎鏉ョエ鍙拌处
-export function delRegistration(query) {
- return request({
- url: "/purchase/registration/delRegistration",
- method: "delete",
- data: query,
- });
-}
-// 鍒犻櫎闄勪欢
-export function delCommonFile(query) {
- return request({
- url: "/commonFile/delCommonFile",
- method: "delete",
- data: query,
- });
-}
-// 瀛愯〃鏍兼煡璇�
-export function productRecordList(query) {
- return request({
- url: "/purchase/registration/productRecordList",
- method: "get",
- params: query,
- });
-}
-
-// 鏌ヨ鍒楄〃
-export function invoiceListPage(query) {
- return request({
- url: "/sales/product/listPagePurchaseLedger",
- method: "get",
- params: query,
- });
-}
-
-export function productRecordPage(query) {
- return request({
- url: "/purchase/registration/productRecordPage",
- method: "get",
- params: query,
- });
-}
-
-// export function getProductRecordById(params) {
-// return request({
-// url: "/purchase/registration/getProductRecordById",
-// method: "get",
-// params: params,
-// });
-// }
-export function getProductRecordById(data) {
- return request({
- url: "/purchase/registration/getProductRecordById",
- method: "post",
- data: data,
- });
-}
-
-export function updateRegistration(data) {
- return request({
- url: "/purchase/registration/updateRegistration",
- method: "post",
- data: data,
- });
-}
-
-// 鏌ヨ浠樻鐧昏瀛愬垪琛�
-export function registrationListPageGetById(query) {
- return request({
- url: "/purchase/registration/getById",
- method: "get",
- params: query,
- });
-}
-// 淇敼浠樻娴佹按
-export function updatePaymentRegistration(query) {
- return request({
- url: "/purchase/registration/updatePaymentRegistration",
- method: "put",
- data: query,
- });
-}
-// 鍒犻櫎浠樻娴佹按
-export function delPaymentRegistration(query) {
- return request({
- url: "/purchase/registration/delPaymentRegistration",
- method: "delete",
- data: query,
- });
-}
diff --git a/src/api/salesManagement/indicatorStats.js b/src/api/salesManagement/indicatorStats.js
index 47d7794..c29eac3 100644
--- a/src/api/salesManagement/indicatorStats.js
+++ b/src/api/salesManagement/indicatorStats.js
@@ -18,3 +18,21 @@
params: query,
});
}
+
+// 瀹㈡埛寰�鏉ュ垪琛�
+export function customewTransactions(query) {
+ return request({
+ url: "/metricStatistics/customewTransactions",
+ method: "get",
+ params: query,
+ });
+}
+
+// 瀹㈡埛寰�鏉ユ槑缁�
+export function customewTransactionsDetails(query) {
+ return request({
+ url: "/metricStatistics/customewTransactionsDetails",
+ method: "get",
+ params: query,
+ });
+}
diff --git a/src/api/salesManagement/invoiceLedger.js b/src/api/salesManagement/invoiceLedger.js
index 6a54493..9545ec0 100644
--- a/src/api/salesManagement/invoiceLedger.js
+++ b/src/api/salesManagement/invoiceLedger.js
@@ -1,92 +1,10 @@
-// 寮�绁ㄥ彴璐﹂〉闈㈡帴鍙�
import request from '@/utils/request'
-// 鍒嗛〉鏌ヨ
-export function invoiceLedgerList(query) {
- return request({
- url: '/invoiceLedger/page',
- method: 'get',
- params: query
- })
-}
-
-// 鏂板
-export function invoiceLedgerSaveOrUpdate(query) {
- return request({
- url: '/invoiceLedger/saveOrUpdate',
- method: 'post',
- data: query
- })
-}
-
-// 寮�绁ㄥ彴璐﹀垹闄�
-export function invoiceLedgerDel(query) {
- return request({
- url: '/invoiceLedger/del',
- method: 'delete',
- data: query
- })
-}
-
-// 璇︽儏鏌ヨ
-export function invoiceLedgerDetail(query) {
- return request({
- url: '/invoiceLedger/info',
- method: 'get',
- params: query
- })
-}
-
-// 闄勪欢鎻愪氦
-export function commitFile(query) {
- return request({
- url: '/invoiceLedger/commitFile',
- method: 'post',
- data: query
- })
-}
-
-// 寮�绁ㄥ彴璐﹂儴鍒嗕篃鏌ヨ
-export function invoiceLedgerListNoPage(query) {
- return request({
- url: '/invoiceLedger/list',
- method: 'get',
- data: query
- })
-}
-
-// 鍒嗛〉鏌ヨ
+/** 鍥炴鍙拌处 - 瀹㈡埛閿�鍞处鎴峰垎椤� */
export function invoiceLedgerSalesAccount(query) {
- return request({
- url: '/invoiceLedger/salesAccount',
- method: 'get',
- params: query
- })
+ return request({
+ url: '/invoiceLedger/salesAccount',
+ method: 'get',
+ params: query
+ })
}
-
-// 浜у搧寮�绁ㄨ褰曞垎椤垫煡璇�
-export function registrationProductPage(query) {
- return request({
- url: '/invoiceLedger/registrationProductPage',
- method: 'get',
- params: query
- })
-}
-
-// 浜у搧寮�绁ㄨ鎯呮煡璇�
-export function invoiceLedgerProductInfo(query) {
- return request({
- url: '/invoiceLedger/invoiceLedgerProductInfo',
- method: 'get',
- params: query
- })
-}
-
-export function delInvoiceLedgerByRegProductId(invoiceRegistrationProductId) {
- return request({
- url: '/invoiceLedger/delInvoiceLedger/'+ invoiceRegistrationProductId,
- method: 'delete'
- })
-}
-
-
diff --git a/src/api/salesManagement/invoiceRegistration.js b/src/api/salesManagement/invoiceRegistration.js
deleted file mode 100644
index 4bc33ce..0000000
--- a/src/api/salesManagement/invoiceRegistration.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// 閿�鍞彴璐﹂〉闈㈡帴鍙�
-import request from '@/utils/request'
-
-// 鍒嗛〉鏌ヨ
-export function invoiceRegistrationList(query) {
- return request({
- url: '/invoiceRegistration/listPage',
- method: 'get',
- params: query
- })
-}
-// 寮�绁ㄧ櫥璁版柊澧�
-export function invoiceRegistrationSave(query) {
- return request({
- url: '/invoiceRegistration/save',
- method: 'post',
- data: query
- })
-}
-// 寮�绁ㄧ櫥璁板垹闄�
-export function invoiceRegistrationDel(query) {
- return request({
- url: '/invoiceRegistration/del',
- method: 'delete',
- data: query
- })
-}
-// 瀛愯〃鏍兼煡璇�
-export function productList(query) {
- return request({
- url: '/invoiceRegistration/productList',
- method: 'get',
- params: query
- })
-}
-
-// 寮�绁ㄧ櫥璁拌鎯�
-export function invoiceRegistrationDetail(query) {
- return request({
- url: '/invoiceRegistration/detail',
- method: 'get',
- params: query
- })
-}
-
-// 瀵煎嚭寮�绁ㄧ櫥璁�
-export function invoiceRegistrationExport(query) {
- return request({
- url: '/invoiceRegistration/export',
- method: 'get',
- params: query,
- responseType: 'blob'
- })
-}
diff --git a/src/api/salesManagement/receiptPayment.js b/src/api/salesManagement/receiptPayment.js
index 0f0529d..7fdb9a7 100644
--- a/src/api/salesManagement/receiptPayment.js
+++ b/src/api/salesManagement/receiptPayment.js
@@ -1,84 +1,10 @@
-// 寮�绁ㄧ櫥璁伴〉闈㈡帴鍙�
import request from '@/utils/request'
-// 鏂板/淇敼
-export function receiptPaymentSaveOrUpdate(query) {
- return request({
- url: '/receiptPayment/saveOrUpdate',
- method: 'post',
- data: query
- })
-}
-
-// 瀹㈡埛寰�鏉ヨ褰曟煡璇�
+/** 鍥炴鍙拌处 - 瀹㈡埛寰�鏉ヨ褰� */
export function customerInteractions(query) {
- return request({
- url: '/receiptPayment/customerInteractions',
- method: 'get',
- params: query
- })
-}
-
-// 璇︽儏
-export function receiptPaymentInfo(query) {
- return request({
- url: '/receiptPayment/info',
- method: 'get',
- params: query
- })
-}
-
-// 鍒犻櫎
-export function receiptPaymentDel(query) {
- return request({
- url: '/receiptPayment/del',
- method: 'delete',
- data: query
- })
-}
-
-// 鏌ヨ宸茬粡缁戝畾鍙戠エ鐨勫紑绁ㄥ彴璐�
-export function bindInvoiceNoRegPage(query) {
- return request({
- url: '/sales/product/listPageSalesLedger',
- method: 'get',
- params: query
- })
-}
-
-// 寮�绁ㄥ彴璐﹁鎯�
-export function invoiceInfo(query) {
- return request({
- url: '/receiptPayment/invoiceInfo',
- method: 'get',
- params: query
- })
-}
-
-// 璇㈠洖娆捐褰�
-export function receiptPaymentHistoryList(query) {
- return request({
- url: '/receiptPayment/receiptPaymentHistoryList',
- method: 'get',
- params: query
- })
-}
-
-/**
- * 鏌ヨ鍥炴璁板綍鍒嗛〉鏌ヨ
- */
-export function receiptPaymentHistoryListPage(query) {
- return request({
- url: '/receiptPayment/receiptPaymentHistoryListPage',
- method: 'get',
- params: query
- })
-}
-
-export function receiptPaymentHistoryListNoPage(query) {
- return request({
- url: '/receiptPayment/receiptPaymentHistoryListNoPage',
- method: 'get',
- params: query
- })
+ return request({
+ url: '/receiptPayment/customerInteractions',
+ method: 'get',
+ params: query
+ })
}
diff --git a/src/api/viewIndex.js b/src/api/viewIndex.js
index dafe6e8..9cae219 100644
--- a/src/api/viewIndex.js
+++ b/src/api/viewIndex.js
@@ -347,30 +347,18 @@
});
};
-const HOME_PROGRESS_STATUS_LIST = ["all", "waiting", "inProgress", "completed", "paused", "1", "2", "3", "4"];
-const HOME_PROGRESS_TAB_LIST = ["all", "inProgress", "completed", "paused"];
-const HOME_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
-
-const normalizeDateParam = (value) => {
- const dateText = typeof value === "string" ? value.trim() : "";
- return HOME_DATE_PATTERN.test(dateText) ? dateText : undefined;
-};
-
export const productionOrderProgress = (params = {}) => {
const safePageNum = Math.max(1, Number(params.pageNum || 1));
const safePageSize = Math.min(50, Math.max(1, Number(params.pageSize || 10)));
- const rawStatus = String(params.status ?? "").trim();
- const safeStatus = HOME_PROGRESS_STATUS_LIST.includes(rawStatus) ? rawStatus : undefined;
- const safeTab = HOME_PROGRESS_TAB_LIST.includes(params.tab) ? params.tab : "all";
- const normalizedTab = safeStatus && HOME_PROGRESS_TAB_LIST.includes(safeStatus) ? safeStatus : safeTab;
+ const safeTab = ["all", "inProgress", "completed", "paused"].includes(params.tab)
+ ? params.tab
+ : "all";
return request({
url: "/home/productionOrderProgress",
method: "get",
params: {
...params,
- status: safeStatus,
- tab: normalizedTab,
- bizDate: normalizeDateParam(params.bizDate),
+ tab: safeTab,
pageNum: safePageNum,
pageSize: safePageSize,
},
@@ -388,7 +376,6 @@
params: {
...params,
limit: safeLimit,
- planDate: normalizeDateParam(params.planDate),
},
headers: {
handleAuthError: false,
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index b7714f6..0d2e61e 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -52,13 +52,13 @@
getInfo() {
return new Promise((resolve, reject) => {
getInfo().then(res => {
- res = res.data
- const user = res.user || {}
+ const data = res?.data ?? res
+ const user = data.user || {}
let avatar = user.avatar || ""
avatar = import.meta.env.VITE_APP_BASE_API + '/profile/' + avatar
- if (res.roles && res.roles.length > 0) { // 楠岃瘉杩斿洖鐨剅oles鏄惁鏄竴涓潪绌烘暟缁�
- this.roles = res.roles
- this.permissions = res.permissions
+ if (data.roles && data.roles.length > 0) { // 楠岃瘉杩斿洖鐨剅oles鏄惁鏄竴涓潪绌烘暟缁�
+ this.roles = data.roles
+ this.permissions = data.permissions
} else {
this.roles = ['ROLE_DEFAULT']
}
@@ -70,8 +70,8 @@
this.roleName = Array.isArray(user.roles) && user.roles.length > 0 ? (user.roles[0].roleName || '') : ''
this.currentDeptId = user.tenantId || ''
this.currentLoginTime = this.getCurrentTime()
- this.aiEnabled = Number(res.aiEnabled) === 1 ? 1 : 0
- resolve(res)
+ this.aiEnabled = Number(data.aiEnabled) === 1 ? 1 : 0
+ resolve(data)
}).catch(error => {
reject(error)
})
diff --git a/src/views/financialManagement/expenseManagement/Modal.vue b/src/views/financialManagement/expenseManagement/Modal.vue
deleted file mode 100644
index 4d743c1..0000000
--- a/src/views/financialManagement/expenseManagement/Modal.vue
+++ /dev/null
@@ -1,177 +0,0 @@
-<template>
- <FormDialog
- v-model="dialogVisible"
- :title="dialogTitle"
- :operationType="operationType"
- width="50%"
- @confirm="sendForm"
- @close="close"
- @cancel="close"
- >
- <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef">
- <el-form-item label="鏀嚭鏃ユ湡" prop="expenseDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.expenseDate"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- clearable
- />
- </el-form-item>
- <el-form-item label="鏀嚭绫诲瀷" prop="expenseType">
- <el-select
- v-model="form.expenseType"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option :label="item.label" :value="item.value" v-for="(item,index) in expense_types" :key="index" />
- </el-select>
- </el-form-item>
- <el-form-item label="渚涘簲鍟嗗悕绉�" prop="supplierName">
- <el-input v-model="form.supplierName" placeholder="璇疯緭鍏�" />
- </el-form-item>
- <el-form-item label="鏀嚭閲戦" prop="expenseMoney">
- <el-input-number :step="0.01" :min="0" style="width: 100%"
- v-model="form.expenseMoney"
- placeholder="璇疯緭鍏�"
- />
- </el-form-item>
- <el-form-item label="鏀嚭鎻忚堪" prop="expenseDescribed">
- <el-input v-model="form.expenseDescribed" placeholder="璇疯緭鍏�" />
- </el-form-item>
- <el-form-item label="浠樻鏂瑰紡" prop="expenseMethod">
- <el-select
- v-model="form.expenseMethod"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option :label="item.label" :value="item.value" v-for="(item,index) in checkout_payment" :key="index" />
- </el-select>
- </el-form-item>
- <el-form-item label="鍙戠エ鍙风爜" prop="invoiceNumber">
- <el-input v-model="form.invoiceNumber" placeholder="璇疯緭鍏�" />
- </el-form-item>
- <el-form-item label="澶囨敞" prop="note">
- <el-input
- v-model="form.note"
- placeholder="澶囨敞"
- />
- </el-form-item>
- </el-form>
- </FormDialog>
-</template>
-
-<script setup>
-import { add, update, getAccountExpense } from "@/api/financialManagement/expenseManagement";
-import { ElMessage } from "element-plus";
-import useFormData from "@/hooks/useFormData";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import { ref } from "vue";
-
-const { proxy } = getCurrentInstance()
-
-defineOptions({
- name: "鏀嚭鏂板缂栬緫",
-});
-
-const emits = defineEmits(["success"]);
-
-const formRef = ref(null);
-const dialogVisible = ref(false);
-const operationType = ref("add"); // add | edit
-const id = ref(undefined);
-const submitting = ref(false);
-
-const dialogTitle = (type) => {
- if (type === "edit") return "缂栬緫鏀嚭";
- return "鏂板鏀嚭";
-};
-
-const { expense_types } = proxy.useDict("expense_types");
-const { checkout_payment } = proxy.useDict("checkout_payment");
-
-const formRules = {
- supplierName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
- expenseMoney: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
- expenseDescribed: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
- expenseDate: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
- expenseType: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
- expenseMethod: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
-}
-
-const { form, resetForm } = useFormData({
- expenseDate: undefined, // 鏀嚭鏃ユ湡
- expenseType: undefined, // 鏀嚭绫诲瀷
- supplierName: undefined, // 渚涘簲鍟嗗悕绉�
- expenseMoney: undefined, // 鏀嚭閲戦
- expenseDescribed: undefined, // 鏀嚭鎻忚堪
- expenseMethod: undefined, // 浠樻鏂瑰紡
- invoiceNumber: undefined, // 鍙戠エ鍙风爜
- note: undefined, // 澶囨敞
-});
-
-const sendForm = () => {
- if (submitting.value) return;
- formRef.value?.validate(async (valid) => {
- if (valid) {
- submitting.value = true;
- try {
- const { code } = id.value
- ? await update({ id: id.value, ...form })
- : await add(form);
- if (code == 200) {
- emits("success");
- ElMessage({ message: "鎿嶄綔鎴愬姛", type: "success" });
- close();
- }
- } finally {
- submitting.value = false;
- }
- }
- })
-};
-
-const close = () => {
- resetForm();
- formRef.value?.clearValidate();
- id.value = undefined;
- dialogVisible.value = false;
-};
-
-const loadForm = async (rowId) => {
- operationType.value = "edit";
- id.value = rowId;
- dialogVisible.value = true;
- if (rowId) {
- const { code, data } = await getAccountExpense(rowId);
- if (code == 200) {
- form.expenseDate = data.expenseDate;
- form.expenseType = data.expenseType;
- form.supplierName = data.supplierName;
- form.expenseMoney = data.expenseMoney;
- form.expenseDescribed = data.expenseDescribed;
- form.expenseMethod = data.expenseMethod;
- form.invoiceNumber = data.invoiceNumber;
- form.note = data.note;
- }
- } else {
- resetForm();
- formRef.value?.clearValidate();
- }
-};
-
-const openModal = () => {
- operationType.value = "add";
- id.value = undefined;
- resetForm();
- formRef.value?.clearValidate();
- dialogVisible.value = true;
-};
-
-defineExpose({
- openModal,
- loadForm,
-});
-</script>
diff --git a/src/views/financialManagement/expenseManagement/index.vue b/src/views/financialManagement/expenseManagement/index.vue
deleted file mode 100644
index 173f8e1..0000000
--- a/src/views/financialManagement/expenseManagement/index.vue
+++ /dev/null
@@ -1,332 +0,0 @@
-<template>
- <div class="app-container">
- <el-form :model="filters" :inline="true">
- <el-form-item label="鏀嚭鏃ユ湡:">
- <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
- placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
- </el-form-item>
- <el-form-item label="浠樻鏂瑰紡:">
- <el-select
- v-model="filters.expenseMethod"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 200px;"
- >
- <el-option
- v-for="item in checkout_payment"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
- <el-button @click="resetFilters">閲嶇疆</el-button>
- </el-form-item>
- </el-form>
- <div class="table_list">
- <div class="actions">
- <div></div>
- <div>
- <el-button type="primary" @click="add" icon="Plus"> 鏂板 </el-button>
- <el-button @click="handleOut" icon="download">瀵煎嚭</el-button>
- <el-button
- type="danger"
- icon="Delete"
- :disabled="multipleList.length <= 0 || hasBusinessIdInSelection"
- @click="handleBatchDelete"
- >
- 鎵归噺鍒犻櫎
- </el-button>
- </div>
- </div>
- <PIMTable
- rowKey="id"
- isSelection
- :column="columns"
- :tableData="dataList"
- :page="{
- current: pagination.currentPage,
- size: pagination.pageSize,
- total: pagination.total,
- }"
- :isShowSummary="true"
- :summaryMethod="summarizeMainTable"
- @selection-change="handleSelectionChange"
- @pagination="changePage"
- >
- <template #operation="{ row }">
- <el-button
- type="primary"
- link
- :disabled="!!row.businessId"
- @click="edit(row.id)"
- >
- 缂栬緫
- </el-button>
- <el-button
- type="primary"
- link
- @click="openFilesFormDia(row)"
- >
- 闄勪欢
- </el-button>
- </template>
- </PIMTable>
- </div>
- <Modal ref="modalRef" @success="getTableData"></Modal>
- <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="account_expense" :record-id="recordId" />
- </div>
-</template>
-
-<script setup>
-import { usePaginationApi } from "@/hooks/usePaginationApi";
-import { listPage, delAccountExpense } from "@/api/financialManagement/expenseManagement";
-import {onMounted, getCurrentInstance, ref, computed, defineAsyncComponent} from "vue";
-import Modal from "./Modal.vue";
-import { ElMessageBox, ElMessage } from "element-plus";
-import dayjs from "dayjs";
-const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
-
-defineOptions({
- name: "鏀嚭绠$悊",
-});
-
-// 琛ㄦ牸澶氶�夋閫変腑椤�
-const multipleList = ref([]);
-const { proxy } = getCurrentInstance();
-const modalRef = ref();
-const { checkout_payment } = proxy.useDict("checkout_payment");
-const { expense_types } = proxy.useDict("expense_types");
-const accountType = ref('鏀嚭');
-
-const {
- filters,
- columns,
- dataList,
- pagination,
- getTableData,
- resetFilters,
- onCurrentChange,
-} = usePaginationApi(
- listPage,
- {
- expenseMethod: undefined,
- entryDate: undefined,
- },
- [
- {
- label: "鏀嚭鏃ユ湡",
- prop: "expenseDate",
- },
- {
- label: "鏀嚭绫诲瀷",
- align: "center",
- prop: "expenseType",
- dataType: "tag",
- formatData: (params) => {
- if (expense_types.value.find((m) => m.value == params)) {
- return expense_types.value.find((m) => m.value == params).label;
- } else {
- return null
- }
- },
- },
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
-
- },
- {
- label: "鏀嚭閲戦",
- prop: "expenseMoney",
-
- },
- {
- label: "鏀嚭鎻忚堪",
- prop: "expenseDescribed",
-
- },
- {
- label: "浠樻鏂瑰紡",
- align: "center",
- prop: "expenseMethod",
- width: '120',
- dataType: "tag",
- formatData: (params) => {
- if (checkout_payment.value.find((m) => m.value == params)) {
- return checkout_payment.value.find((m) => m.value == params).label;
- } else {
- return null
- }
- },
- },
- {
- label: "鍙戠エ鍙风爜",
- prop: "invoiceNumber",
-
- },
- {
- label: "澶囨敞",
- prop: "note",
-
- },
- {
- label: "褰曞叆浜�",
- prop: "inputUser",
- },
- {
- label: "褰曞叆鏃ユ湡",
- prop: "inputTime",
-
- },
- {
- fixed: "right",
- label: "鎿嶄綔",
- dataType: "slot",
- slot: "operation",
- align: "center",
- width: "160px",
- },
- ]
-);
-
-// 琛ㄦ牸鍚堣锛氭敮鍑洪噾棰�
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, ["expenseMoney"]);
-};
-
-// 澶氶�夊悗鍋氫粈涔�
-const handleSelectionChange = (selectionList) => {
- multipleList.value = selectionList;
-};
-
-// 鍒ゆ柇閫変腑鐨勯」涓槸鍚︽湁 businessId
-const hasBusinessIdInSelection = computed(() => {
- return multipleList.value.some(item => item.businessId);
-});
-
-const add = () => {
- modalRef.value.openModal();
-};
-const edit = (id) => {
- // 妫�鏌ュ綋鍓嶈鏄惁鏈� businessId
- const row = dataList.value.find(item => item.id === id);
- if (row && row.businessId) {
- proxy.$modal.msgWarning("璇ヨ褰曞凡鍏宠仈涓氬姟锛屼笉鑳界紪杈�");
- return;
- }
- modalRef.value.loadForm(id);
-};
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- onCurrentChange(page);
-};
-const deleteRow = (id) => {
- // 濡傛灉鏄暟缁勶紝妫�鏌ユ槸鍚︽湁 businessId
- if (Array.isArray(id)) {
- const hasBusinessId = id.some(itemId => {
- const row = dataList.value.find(item => item.id === itemId);
- return row && row.businessId;
- });
- if (hasBusinessId) {
- proxy.$modal.msgWarning("閫変腑鐨勮褰曚腑鍖呭惈宸插叧鑱斾笟鍔$殑璁板綍锛屼笉鑳藉垹闄�");
- return;
- }
- } else {
- // 鍗曚釜鍒犻櫎锛屾鏌ユ槸鍚︽湁 businessId
- const row = dataList.value.find(item => item.id === id);
- if (row && row.businessId) {
- proxy.$modal.msgWarning("璇ヨ褰曞凡鍏宠仈涓氬姟锛屼笉鑳藉垹闄�");
- return;
- }
- }
-
- ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }).then(async () => {
- const { code } = await delAccountExpense(id);
- if (code == 200) {
- ElMessage({
- type: "success",
- message: "鍒犻櫎鎴愬姛",
- });
- getTableData();
- }
- });
-};
-
-// 鎵归噺鍒犻櫎
-const handleBatchDelete = () => {
- if (multipleList.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁 businessId
- if (hasBusinessIdInSelection.value) {
- proxy.$modal.msgWarning("閫変腑鐨勮褰曚腑鍖呭惈宸插叧鑱斾笟鍔$殑璁板綍锛屼笉鑳藉垹闄�");
- return;
- }
-
- const ids = multipleList.value.map((item) => item.id);
- deleteRow(ids);
-};
-
-const changeDaterange = (value) => {
- if (value) {
- filters.entryDate = value;
- filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- filters.entryDate = null;
- filters.entryDateStart = undefined;
- filters.entryDateEnd = undefined;
- }
- getTableData();
-};
-
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(`/account/accountExpense/export`, {}, "鏀嚭鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 鎵撳紑闄勪欢寮圭獥
-const recordId =ref(0)
-const fileDialogVisible = ref(false)
-
-// 鎵撳紑闄勪欢寮规
-const openFilesFormDia = async (row) => {
- recordId.value = row.id
- fileDialogVisible.value = true
-}
-
-onMounted(() => {
- getTableData();
-});
-</script>
-
-<style lang="scss" scoped>
-.table_list {
- margin-top: unset;
-}
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-</style>
-
diff --git a/src/views/financialManagement/loanManagement/Modal.vue b/src/views/financialManagement/loanManagement/Modal.vue
deleted file mode 100644
index 73b2cc3..0000000
--- a/src/views/financialManagement/loanManagement/Modal.vue
+++ /dev/null
@@ -1,222 +0,0 @@
-<template>
- <FormDialog
- v-model="dialogVisible"
- :title="dialogTitle"
- :operationType="operationType"
- width="60%"
- @confirm="sendForm"
- @close="close"
- @cancel="close"
- >
- <el-form
- ref="formRef"
- :model="form"
- :rules="formRules"
- label-width="120px"
- >
- <el-form-item label="鍊熸浜哄鍚�" prop="borrowerName">
- <el-input v-model="form.borrowerName" placeholder="璇疯緭鍏ュ�熸浜哄鍚�" />
- </el-form-item>
- <el-form-item label="鍊熸閲戦锛堝厓锛�" prop="borrowAmount">
- <el-input-number
- :step="0.01"
- :min="0"
- :precision="2"
- style="width: 100%"
- v-model="form.borrowAmount"
- placeholder="璇疯緭鍏ュ�熸閲戦"
- />
- </el-form-item>
- <el-form-item label="鍊熸鍒╃巼锛�%锛�" prop="interestRate">
- <el-input-number
- :step="0.01"
- :min="0"
- :precision="2"
- style="width: 100%"
- v-model="form.interestRate"
- placeholder="璇疯緭鍏ュ�熸鍒╃巼锛屽锛�5.85"
- />
- </el-form-item>
- <el-form-item label="鍊熸鏃ユ湡" prop="borrowDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.borrowDate"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨鍊熸鏃ユ湡"
- clearable
- />
- </el-form-item>
- <!-- 瀹為檯杩樻鏃ユ湡锛氫粎鈥滆繕娆锯�濇椂鍙~ -->
- <el-form-item
- v-if="operationType === 'repay'"
- label="瀹為檯杩樻鏃ユ湡"
- prop="repayDate"
- >
- <el-date-picker
- style="width: 100%"
- v-model="form.repayDate"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨瀹為檯杩樻鏃ユ湡锛堣繕娆惧悗濉啓锛�"
- clearable
- />
- </el-form-item>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input
- v-model="form.remark"
- type="textarea"
- :rows="3"
- placeholder="璇疯緭鍏ュ娉紙鍊熸璇存槑锛�"
- />
- </el-form-item>
- </el-form>
- </FormDialog>
-</template>
-
-<script setup>
-import { add, update } from "@/api/financialManagement/loanManagement";
-import useFormData from "@/hooks/useFormData";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import { ElMessage } from "element-plus";
-import { ref } from "vue";
-
-defineOptions({
- name: "鍊熸鏂板缂栬緫",
-});
-
-const emits = defineEmits(["success"]);
-
-const formRef = ref(null);
-const dialogVisible = ref(false);
-const operationType = ref("add"); // add | edit
-const id = ref(undefined);
-const submitting = ref(false);
-
-const dialogTitle = (type) => {
- if (type === "edit") return "缂栬緫鍊熸";
- if (type === "repay") return "杩樻";
- return "鏂板鍊熸";
-};
-
-const formRules = {
- borrowerName: [{ required: true, trigger: "blur", message: "璇疯緭鍏ュ�熸浜哄鍚�" }],
- borrowAmount: [{ required: true, trigger: "blur", message: "璇疯緭鍏ュ�熸閲戦" }],
- interestRate: [{ required: true, trigger: "blur", message: "璇疯緭鍏ュ�熸鍒╃巼" }],
- borrowDate: [{ required: true, trigger: "change", message: "璇烽�夋嫨鍊熸鏃ユ湡" }],
- repayDate: [
- {
- validator: (_rule, value, callback) => {
- if (operationType.value === "repay" && !value) {
- callback(new Error("璇烽�夋嫨瀹為檯杩樻鏃ユ湡"));
- return;
- }
- callback();
- },
- trigger: "change",
- },
- ],
-};
-
-const { form, resetForm } = useFormData({
- borrowerName: undefined, // 鍊熸浜哄鍚�
- borrowAmount: undefined, // 鍊熸閲戦锛堝厓锛�
- interestRate: undefined, // 鍊熸鍒╃巼锛堝锛�5.85 浠h〃5.85%锛�
- borrowDate: undefined, // 鍊熸鏃ユ湡
- repayDate: undefined, // 瀹為檯杩樻鏃ユ湡锛堣繕娆惧悗濉厖锛�
- remark: undefined, // 澶囨敞锛堝�熸璇存槑锛�
-});
-
-const sendForm = () => {
- if (submitting.value) return;
- formRef.value?.validate(async (valid) => {
- if (valid) {
- submitting.value = true;
- try {
- const isRepay = operationType.value === "repay";
- // 杩樻锛氫笉灞曠ず status锛屼絾鎻愪氦鏃跺己鍒朵紶 status=2锛岃蛋鏇存柊鎺ュ彛
- const payload = isRepay
- ? { id: id.value, ...form, status: 2 }
- : id.value
- ? { id: id.value, ...form }
- : form;
-
- const { code } = isRepay
- ? await update(payload)
- : id.value
- ? await update(payload)
- : await add(payload);
- if (code == 200) {
- emits("success");
- ElMessage({ message: "鎿嶄綔鎴愬姛", type: "success" });
- close();
- }
- } finally {
- submitting.value = false;
- }
- }
- });
-};
-
-const close = () => {
- resetForm();
- formRef.value?.clearValidate();
- id.value = undefined;
- dialogVisible.value = false;
-};
-
-// 缂栬緫锛氱洿鎺ョ敤鍒楄〃琛屾暟鎹洖濉紙閬垮厤渚濊禆璇︽儏鎺ュ彛锛�
-const loadForm = async (row) => {
- const rowId = row?.id;
- operationType.value = "edit";
- id.value = rowId;
- dialogVisible.value = true;
- if (rowId) {
- form.borrowerName = row.borrowerName;
- form.borrowAmount = row.borrowAmount;
- form.interestRate = row.interestRate;
- form.borrowDate = row.borrowDate;
- form.repayDate = row.repayDate;
- form.remark = row.remark;
- } else {
- resetForm();
- formRef.value?.clearValidate();
- }
-};
-
-// 杩樻锛氭墦寮�寮圭獥锛屼粎濉啓瀹為檯杩樻鏃ユ湡锛屾彁浜ゆ椂寮哄埗 status=2
-const repay = async (row) => {
- const rowId = row?.id;
- operationType.value = "repay";
- id.value = rowId;
- dialogVisible.value = true;
- if (rowId) {
- // 涓轰簡璧� update 鎺ュ彛鏇寸ǔ濡ワ紝甯︿笂鍘熸湁鏁版嵁锛涘彧璁╃敤鎴烽�� repayDate
- form.borrowerName = row.borrowerName;
- form.borrowAmount = row.borrowAmount;
- form.interestRate = row.interestRate;
- form.borrowDate = row.borrowDate;
- form.remark = row.remark;
- form.repayDate = undefined;
- } else {
- resetForm();
- formRef.value?.clearValidate();
- }
-};
-
-const openModal = () => {
- operationType.value = "add";
- id.value = undefined;
- resetForm();
- formRef.value?.clearValidate();
- dialogVisible.value = true;
-};
-
-defineExpose({
- openModal,
- loadForm,
- repay,
-});
-</script>
diff --git a/src/views/financialManagement/loanManagement/index.vue b/src/views/financialManagement/loanManagement/index.vue
deleted file mode 100644
index cb52ff1..0000000
--- a/src/views/financialManagement/loanManagement/index.vue
+++ /dev/null
@@ -1,278 +0,0 @@
-<template>
- <div class="app-container">
- <el-form :model="filters" :inline="true">
- <el-form-item label="鍊熸浜哄鍚�:">
- <el-input
- v-model="filters.borrowerName"
- placeholder="璇疯緭鍏ュ�熸浜哄鍚�"
- clearable
- style="width: 200px;"
- />
- </el-form-item>
- <el-form-item label="鍊熸鏃ユ湡:">
- <el-date-picker
- v-model="filters.borrowDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- clearable
- @change="changeDaterange"
- />
- </el-form-item>
- <el-form-item label="鍊熸鐘舵��:">
- <el-select
- v-model="filters.status"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 200px;"
- >
- <el-option label="寰呰繕娆�" :value="1" />
- <el-option label="宸茶繕娆�" :value="2" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
- <el-button @click="resetFilters">閲嶇疆</el-button>
- </el-form-item>
- </el-form>
- <div class="table_list">
- <div class="actions">
- <div></div>
- <div>
- <el-button type="primary" @click="add" icon="Plus"> 鏂板 </el-button>
- <el-button @click="handleOut" icon="download">瀵煎嚭</el-button>
- <el-button
- type="danger"
- icon="Delete"
- :disabled="multipleList.length <= 0"
- @click="deleteRow(multipleList.map((item) => item.id))"
- >
- 鎵归噺鍒犻櫎
- </el-button>
- </div>
- </div>
- <PIMTable
- rowKey="id"
- isSelection
- :column="columns"
- :tableData="dataList"
- :page="{
- current: pagination.currentPage,
- size: pagination.pageSize,
- total: pagination.total,
- }"
- :isShowSummary="true"
- :summaryMethod="summarizeMainTable"
- @selection-change="handleSelectionChange"
- @pagination="changePage"
- >
- <template #operation="{ row }">
- <el-button type="primary" link @click="edit(row)">
- 缂栬緫
- </el-button>
- <el-button
- :disabled="row.status !== 1"
- type="primary"
- link
- @click="repay(row)"
- >
- 杩樻
- </el-button>
- </template>
- </PIMTable>
- </div>
- <Modal ref="modalRef" @success="getTableData"></Modal>
- </div>
-</template>
-
-<script setup>
-import { usePaginationApi } from "@/hooks/usePaginationApi";
-import { listPage, delAccountLoan } from "@/api/financialManagement/loanManagement";
-import { onMounted, getCurrentInstance, ref, nextTick } from "vue";
-import Modal from "./Modal.vue";
-import { ElMessageBox, ElMessage } from "element-plus";
-import dayjs from "dayjs";
-
-defineOptions({
- name: "鍊熸绠$悊",
-});
-
-// 琛ㄦ牸澶氶�夋閫変腑椤�
-const multipleList = ref([]);
-const { proxy } = getCurrentInstance();
-const modalRef = ref();
-
-const {
- filters,
- columns,
- dataList,
- pagination,
- getTableData,
- resetFilters,
- onCurrentChange,
-} = usePaginationApi(
- listPage,
- {
- borrowerName: undefined,
- borrowDate: undefined,
- status: undefined,
- },
- [
- {
- label: "鍊熸浜哄鍚�",
- prop: "borrowerName",
- },
- {
- label: "鍊熸閲戦锛堝厓锛�",
- prop: "borrowAmount",
- formatData: (val) => {
- return val ? `楼${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '楼0.00';
- },
- },
- {
- label: "鍊熸鍒╃巼锛�%锛�",
- prop: "interestRate",
- formatData: (val) => {
- return val ? `${parseFloat(val).toFixed(2)}%` : '-';
- },
- },
- {
- label: "鍊熸鏃ユ湡",
- prop: "borrowDate",
- },
- {
- label: "瀹為檯杩樻鏃ユ湡",
- prop: "repayDate",
- },
- {
- label: "鍊熸鐘舵��",
- prop: "status",
- dataType: "tag",
- align: 'center',
- formatData: (params) => {
- if (params == 1) {
- return "寰呰繕娆�";
- } else if (params == 2) {
- return "宸茶繕娆�";
- }
- return null;
- },
- formatType: (params) => {
- if (params == 1) {
- return "error";
- } else if (params == 2) {
- return "success";
- }
- return null;
- },
- },
- {
- fixed: "right",
- label: "鎿嶄綔",
- dataType: "slot",
- slot: "operation",
- align: "center",
- width: "120px",
- },
- ],
- null,
- {
- // 灏嗗墠绔�熸鏃ユ湡鑼冨洿杞崲涓哄悗绔渶瑕佺殑 entryDateStart / entryDateEnd锛屽苟涓斾笉浼� borrowDate
- borrowDate: (val) => {
- if (val && val.length === 2) {
- return {
- entryDateStart: dayjs(val[0]).format("YYYY-MM-DD"),
- entryDateEnd: dayjs(val[1]).format("YYYY-MM-DD"),
- };
- }
- return {};
- },
- }
-);
-
-// 琛ㄦ牸鍚堣锛氬�熸閲戦
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, ["borrowAmount"]);
-};
-
-// 澶氶�夊悗鍋氫粈涔�
-const handleSelectionChange = (selectionList) => {
- multipleList.value = selectionList;
-};
-
-const add = () => {
- modalRef.value.openModal();
-};
-
-const edit = (row) => {
- modalRef.value.loadForm(row);
-};
-
-const repay = (row) => {
- modalRef.value.repay(row);
-};
-
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- onCurrentChange(page);
-};
-
-const deleteRow = (id) => {
- ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }).then(async () => {
- const { code } = await delAccountLoan(id);
- if (code == 200) {
- ElMessage({
- type: "success",
- message: "鍒犻櫎鎴愬姛",
- });
- getTableData();
- }
- });
-};
-
-const changeDaterange = (value) => {
- if (value) {
- filters.borrowDate = value;
- } else {
- filters.borrowDate = null;
- }
- getTableData();
-};
-
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(`/borrowInfo/export`, {}, "鍊熸鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-onMounted(() => {
- getTableData();
-});
-</script>
-
-<style lang="scss" scoped>
-.table_list {
- margin-top: unset;
-}
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-</style>
diff --git a/src/views/financialManagement/payable/input-invoice.vue b/src/views/financialManagement/payable/input-invoice.vue
index 660d0dd..86ebd09 100644
--- a/src/views/financialManagement/payable/input-invoice.vue
+++ b/src/views/financialManagement/payable/input-invoice.vue
@@ -1,50 +1,61 @@
<template>
<div class="app-container">
<el-form :model="filters" :inline="true">
- <el-form-item label="鍙戠エ浠g爜:">
- <el-input v-model="filters.invoiceCode" placeholder="璇疯緭鍏ュ彂绁ㄤ唬鐮�" clearable style="width: 200px;" />
- </el-form-item>
<el-form-item label="鍙戠エ鍙风爜:">
- <el-input v-model="filters.invoiceNo" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" clearable style="width: 200px;" />
+ <el-input v-model="filters.invoiceNumber" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" clearable style="width: 200px;" />
</el-form-item>
<el-form-item label="渚涘簲鍟�:">
- <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px;">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable filterable style="width: 200px;">
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
- <el-form-item label="璁よ瘉鐘舵��:">
- <el-select v-model="filters.certifyStatus" placeholder="璇烽�夋嫨璁よ瘉鐘舵��" clearable style="width: 150px;">
- <el-option label="鏈璇�" value="uncertified" />
- <el-option label="宸茶璇�" value="certified" />
- <el-option label="璁よ瘉澶辫触" value="failed" />
+ <el-form-item label="寮�绁ㄦ棩鏈�:">
+ <el-date-picker
+ v-model="filters.dateRange"
+ type="daterange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable
+ style="width: 240px;"
+ />
+ </el-form-item>
+ <el-form-item label="鐘舵��:">
+ <el-select v-model="filters.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px;">
+ <el-option label="姝e父" :value="0" />
+ <el-option label="浣滃簾" :value="1" />
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary" @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
<div class="table_list">
<div class="actions">
- <div>
- <el-button type="success" @click="handleBatchCertify" icon="Check" :disabled="selectedRows.length === 0">鎵归噺璁よ瘉</el-button>
- </div>
+ <div></div>
<div>
<el-button type="primary" @click="add" icon="Plus">褰曞叆鍙戠エ</el-button>
- <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+ <el-button @click="handleExport" icon="Download">瀵煎嚭</el-button>
</div>
</div>
<PIMTable
rowKey="id"
- isSelection
:column="columns"
:tableData="dataList"
+ :tableLoading="tableLoading"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @selection-change="handleSelectionChange"
@pagination="changePage"
>
<template #amount="{ row }">
@@ -56,54 +67,123 @@
<template #totalAmount="{ row }">
<span class="text-success">楼{{ formatMoney(row.totalAmount) }}</span>
</template>
- <template #certifyStatus="{ row }">
- <el-tag :type="getCertifyStatusType(row.certifyStatus)">{{ getCertifyStatusLabel(row.certifyStatus) }}</el-tag>
+ <template #status="{ row }">
+ <el-tag :type="getStatusType(row.status)" effect="light" round>
+ {{ getStatusLabel(row.status) }}
+ </el-tag>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="edit(row)">缂栬緫</el-button>
- <el-button type="success" link @click="handleCertify(row)" v-if="row.certifyStatus === 'uncertified'">璁よ瘉</el-button>
+ <el-button type="warning" link @click="handleCancel(row)" v-if="isNormalStatus(row.status)">浣滃簾</el-button>
+ <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
- <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
+ <FormDialog
+ :title="dialogTitle"
+ v-model="dialogVisible"
+ width="800px"
+ :operation-type="isView ? 'detail' : ''"
+ @confirm="submitForm"
+ @cancel="closeDialog"
+ >
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
- <el-row :gutter="20">
+ <el-row v-if="isView" :gutter="20">
<el-col :span="12">
- <el-form-item label="鍙戠エ浠g爜" prop="invoiceCode">
- <el-input v-model="form.invoiceCode" placeholder="璇疯緭鍏ュ彂绁ㄤ唬鐮�" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍙戠エ鍙风爜" prop="invoiceNo">
- <el-input v-model="form.invoiceNo" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" />
+ <el-form-item label="鐘舵��">
+ <el-tag :type="getStatusType(form.status)" effect="light" round>
+ {{ getStatusLabel(form.status) }}
+ </el-tag>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
+ <el-form-item label="鍙戠エ鍙风爜" prop="invoiceNo">
+ <el-input v-model="form.invoiceNo" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" :disabled="isView" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
<el-form-item label="渚涘簲鍟�" prop="supplierId">
- <el-select v-model="form.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%;">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select
+ v-model="form.supplierId"
+ placeholder="璇烽�夋嫨渚涘簲鍟�"
+ style="width: 100%;"
+ filterable
+ :disabled="isView"
+ @change="handleSupplierChange"
+ >
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍏宠仈鍏ュ簱鍗�" prop="stockInRecordIds">
+ <el-input
+ :model-value="inboundBatchDisplayText"
+ placeholder="璇峰厛閫夋嫨渚涘簲鍟�"
+ readonly
+ :disabled="!form.supplierId || isView"
+ class="inbound-batch-input"
+ @click="handleInboundInputClick"
+ >
+ <template v-if="!isView" #append>
+ <el-button
+ :disabled="!form.supplierId"
+ :loading="inboundBatchLoading"
+ @click.stop="openInboundSelectDialog"
+ >
+ 閫夋嫨
+ </el-button>
+ </template>
+ </el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="寮�绁ㄦ棩鏈�" prop="invoiceDate">
- <el-date-picker v-model="form.invoiceDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
+ <el-date-picker
+ v-model="form.invoiceDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="閲戦(涓嶅惈绋�)" prop="amount">
- <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" @change="calculateTax" />
+ <el-col :span="12">
+ <el-form-item label="鍙戠エ绫诲瀷" prop="invoiceType">
+ <el-select
+ v-model="form.invoiceType"
+ placeholder="璇烽�夋嫨鍙戠エ绫诲瀷"
+ style="width: 100%;"
+ :disabled="isView"
+ >
+ <el-option label="澧炲�肩◣涓撶敤鍙戠エ" value="澧炲�肩◣涓撶敤鍙戠エ" />
+ <el-option label="澧炲�肩◣鏅�氬彂绁�" value="澧炲�肩◣鏅�氬彂绁�" />
+ <el-option label="鐢靛瓙鍙戠エ" value="鐢靛瓙鍙戠エ" />
+ </el-select>
</el-form-item>
</el-col>
- <el-col :span="8">
+ <el-col :span="12">
<el-form-item label="绋庣巼" prop="taxRate">
- <el-select v-model="form.taxRate" placeholder="璇烽�夋嫨绋庣巼" style="width: 100%;" @change="calculateTax">
+ <el-select
+ v-model="form.taxRate"
+ placeholder="璇烽�夋嫨绋庣巼"
+ style="width: 100%;"
+ :disabled="isView"
+ @change="handleTaxRateChange"
+ >
<el-option
v-for="dict in tax_rate"
:key="dict.value"
@@ -113,47 +193,109 @@
</el-select>
</el-form-item>
</el-col>
- <el-col :span="8">
- <el-form-item label="绋庨">
- <el-input v-model="form.taxAmount" disabled />
- </el-form-item>
- </el-col>
</el-row>
<el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="璁よ瘉鐘舵��" prop="certifyStatus">
- <el-select v-model="form.certifyStatus" placeholder="璇烽�夋嫨璁よ瘉鐘舵��" style="width: 100%;" disabled>
- <el-option label="鏈璇�" value="uncertified" />
- <el-option label="宸茶璇�" value="certified" />
- <el-option label="璁よ瘉澶辫触" value="failed" />
- </el-select>
+ <el-col :span="8">
+ <el-form-item label="閲戦(涓嶅惈绋�)" prop="amount">
+ <el-input-number
+ v-model="form.amount"
+ :min="0"
+ :precision="2"
+ style="width: 100%;"
+ :disabled="isView"
+ placeholder="鏍规嵁鍏ュ簱鍗曞惈绋庨噾棰濊嚜鍔ㄦ崲绠楋紝鍙慨鏀�"
+ @change="calculateTaxFromExclusive"
+ />
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="璁よ瘉鏃ユ湡" prop="certifyDate">
- <el-date-picker v-model="form.certifyDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" disabled />
+ <el-col :span="8">
+ <el-form-item label="绋庨">
+ <el-input-number
+ v-model="form.taxAmount"
+ :min="0"
+ :precision="2"
+ :controls="false"
+ style="width: 100%;"
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="浠风◣鍚堣">
+ <el-input-number
+ v-model="form.totalAmount"
+ :min="0"
+ :precision="2"
+ :controls="false"
+ style="width: 100%;"
+ disabled
+ />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="鍙戠エ鍐呭" prop="content">
- <el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" />
+ <el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" :disabled="isView" />
</el-form-item>
<el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" />
+ <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" :disabled="isView" />
</el-form-item>
</el-form>
- <template #footer>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <template v-if="!isView" #footer>
+ <el-button type="primary" :loading="submitLoading" @click="submitForm">纭畾</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
</template>
</FormDialog>
+
+ <el-dialog
+ v-model="inboundSelectVisible"
+ title="閫夋嫨鍏ュ簱鍗曞彿"
+ width="1100px"
+ append-to-body
+ destroy-on-close
+ :close-on-click-modal="false"
+ @closed="handleInboundDialogClosed"
+ >
+ <el-table
+ ref="inboundTableRef"
+ v-loading="inboundBatchLoading"
+ :data="inboundBatchList"
+ row-key="id"
+ border
+ stripe
+ max-height="480"
+ @selection-change="handleInboundDialogSelectionChange"
+ >
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column prop="inboundBatches" label="鍏ュ簱鍗曞彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="supplierName" label="渚涘簲鍟�" min-width="120" show-overflow-tooltip />
+ <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="120" show-overflow-tooltip />
+ <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="purchaseContractNumber" label="閲囪喘璁㈠崟鍙�" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="inboundDate" label="鍏ュ簱鏃ユ湡" width="110" align="center" />
+ <el-table-column prop="inboundAmount" label="鍏ュ簱閲戦(鍚◣)" width="120" align="right">
+ <template #default="{ row }">楼{{ formatMoney(getInboundRowTaxInclusiveAmount(row)) }}</template>
+ </el-table-column>
+ </el-table>
+ <template #footer>
+ <el-button type="primary" @click="confirmInboundSelection">纭畾</el-button>
+ <el-button @click="inboundSelectVisible = false">鍙栨秷</el-button>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
+import {
+ getInboundBatchesBySupplier,
+ addAccountPurchaseInvoice,
+ listPageAccountPurchaseInvoice,
+ cancelAccountPurchaseInvoice,
+ deleteAccountPurchaseInvoice,
+} from "@/api/financialManagement/accountPurchaseInvoice.js";
defineOptions({
name: "杩涢」鍙戠エ",
@@ -163,10 +305,10 @@
const { tax_rate } = proxy.useDict("tax_rate");
const filters = reactive({
- invoiceCode: "",
- invoiceNo: "",
+ invoiceNumber: "",
supplierId: "",
- certifyStatus: "",
+ dateRange: [],
+ status: "",
});
const pagination = reactive({
@@ -176,211 +318,601 @@
});
const columns = [
- { label: "鍙戠エ浠g爜", prop: "invoiceCode", width: "130" },
- { label: "鍙戠エ鍙风爜", prop: "invoiceNo", width: "120" },
+ { label: "鍙戠エ鍙风爜", prop: "invoiceNo", width: "140" },
{ label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
{ label: "寮�绁ㄦ棩鏈�", prop: "invoiceDate", width: "120" },
- { label: "閲戦", prop: "amount", slot: "amount" },
- { label: "绋庨", prop: "taxAmount", slot: "taxAmount" },
- { label: "浠风◣鍚堣", prop: "totalAmount", slot: "totalAmount" },
- { label: "璁よ瘉鐘舵��", prop: "certifyStatus", slot: "certifyStatus" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "180", fixed: "right" },
+ { label: "閲戦", prop: "amount", dataType: "slot", slot: "amount" },
+ { label: "绋庨", prop: "taxAmount", dataType: "slot", slot: "taxAmount" },
+ { label: "浠风◣鍚堣", prop: "totalAmount", dataType: "slot", slot: "totalAmount" },
+ { label: "鍙戠エ绫诲瀷", prop: "invoiceType", width: "130" },
+ { label: "鐘舵��", prop: "status", dataType: "slot", slot: "status", width: "90", align: "center" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "200", fixed: "right" },
];
const dataList = ref([]);
-const selectedRows = ref([]);
+const tableLoading = ref(false);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
+const isView = ref(false);
+const submitLoading = ref(false);
+const supplierList = ref([]);
-const supplierList = [
- { id: 1, name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
- { id: 2, name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
- { id: 3, name: "骞垮窞鍖呰鏉愭枡鍘�" },
- { id: 4, name: "娣卞湷浜旈噾閰嶄欢鍏徃" },
-];
+const inboundBatchList = ref([]);
+const inboundBatchOptions = ref([]);
+const inboundBatchLoading = ref(false);
+const inboundSelectVisible = ref(false);
+const inboundTableRef = ref(null);
+const dialogInboundSelection = ref([]);
+
+const STATUS_LABEL_MAP = { 0: "姝e父", 1: "浣滃簾" };
+const STATUS_TYPE_MAP = { 0: "success", 1: "info" };
const form = reactive({
- invoiceCode: "",
invoiceNo: "",
supplierId: "",
invoiceDate: "",
- amount: 0,
+ invoiceType: "澧炲�肩◣涓撶敤鍙戠エ",
taxRate: 13,
+ amount: 0,
taxAmount: 0,
totalAmount: 0,
- certifyStatus: "uncertified",
- certifyDate: "",
content: "",
remark: "",
+ stockInRecordIds: [],
+ inboundBatches: "",
+ storageAttachmentId: undefined,
+ status: 0,
});
const rules = {
- invoiceCode: [{ required: true, message: "璇疯緭鍏ュ彂绁ㄤ唬鐮�", trigger: "blur" }],
invoiceNo: [{ required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿鐮�", trigger: "blur" }],
supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
+ stockInRecordIds: [{ required: true, type: "array", min: 1, message: "璇烽�夋嫨鍏宠仈鍏ュ簱鍗�", trigger: "change" }],
invoiceDate: [{ required: true, message: "璇烽�夋嫨寮�绁ㄦ棩鏈�", trigger: "change" }],
- amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨鍙戠エ绫诲瀷", trigger: "change" }],
taxRate: [{ required: true, message: "璇烽�夋嫨绋庣巼", trigger: "change" }],
+ amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
};
-
-const mockData = [
- { id: 1, invoiceCode: "0440021001", invoiceNo: "12345678", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", invoiceDate: "2024-01-08", amount: 8000, taxRate: 13, taxAmount: 1040, totalAmount: 9040, certifyStatus: "certified", certifyDate: "2024-01-15", content: "鍘熸潗鏂欓噰璐�", remark: "" },
- { id: 2, invoiceCode: "0440021002", invoiceNo: "87654321", supplierId: 2, supplierName: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�", invoiceDate: "2024-01-10", amount: 12000, taxRate: 13, taxAmount: 1560, totalAmount: 13560, certifyStatus: "uncertified", certifyDate: "", content: "鐢靛瓙鍏冨櫒浠�", remark: "" },
- { id: 3, invoiceCode: "0440021003", invoiceNo: "11112222", supplierId: 3, supplierName: "骞垮窞鍖呰鏉愭枡鍘�", invoiceDate: "2024-01-12", amount: 3500, taxRate: 13, taxAmount: 455, totalAmount: 3955, certifyStatus: "certified", certifyDate: "2024-01-18", content: "鍖呰鏉愭枡", remark: "" },
-];
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
-const calculateTax = () => {
+const normalizeStatus = (status) => {
+ if (status === undefined || status === null || status === "") return 0;
+ const num = Number(status);
+ return Number.isNaN(num) ? 0 : num;
+};
+
+const isNormalStatus = (status) => normalizeStatus(status) === 0;
+
+const getStatusLabel = (status) => STATUS_LABEL_MAP[normalizeStatus(status)] ?? "姝e父";
+
+const getStatusType = (status) => STATUS_TYPE_MAP[normalizeStatus(status)] ?? "success";
+
+const parseStockInRecordIds = (value) => {
+ if (!value) return [];
+ if (Array.isArray(value)) return value;
+ return String(value)
+ .split(/[,锛宂/)
+ .map((s) => s.trim())
+ .filter(Boolean)
+ .map((s) => (/^\d+$/.test(s) ? Number(s) : s));
+};
+
+const formatInboundBatches = (value) => {
+ if (value === undefined || value === null || value === "") return "";
+ if (Array.isArray(value)) return value.filter(Boolean).join("銆�");
+ return String(value)
+ .split(/[,锛宂/)
+ .map((s) => s.trim())
+ .filter(Boolean)
+ .join("銆�");
+};
+
+const isSameInboundId = (a, b) => String(a) === String(b);
+
+const getInboundRowId = (row) => row?.id ?? row?.stockInRecordId;
+
+/** 鍏ュ簱鍗曢噾棰濅负鍚◣浠� */
+const getInboundRowTaxInclusiveAmount = (row) =>
+ Number(row?.inboundAmount ?? row?.taxInclusivePrice ?? row?.totalAmount ?? 0);
+
+const normalizeInboundBatchOptions = (data) => {
+ const list = Array.isArray(data) ? data : [];
+ return list.map((item, index) => {
+ if (typeof item === "string" || typeof item === "number") {
+ const text = String(item);
+ return { label: text, value: text, inboundAmount: 0 };
+ }
+ const label =
+ item.inboundBatches ?? item.batchNo ?? item.inboundNo ?? item.label ?? `鍏ュ簱鍗�${index + 1}`;
+ const value = item.id ?? item.stockInRecordId ?? label;
+ return {
+ label: String(label),
+ value,
+ inboundAmount: getInboundRowTaxInclusiveAmount(item),
+ };
+ });
+};
+
+/** 涓嶅惈绋庨噾棰濆彉鏇达細绋庨銆佷环绋庡悎璁℃鍚戣绠� */
+const calculateTaxFromExclusive = () => {
form.taxAmount = Number((form.amount * form.taxRate / 100).toFixed(2));
form.totalAmount = Number((form.amount + form.taxAmount).toFixed(2));
};
-const getCertifyStatusLabel = (status) => {
- const map = { uncertified: "鏈璇�", certified: "宸茶璇�", failed: "璁よ瘉澶辫触" };
- return map[status] || status;
+/** 浠风◣鍚堣鍙樻洿锛氭寜绋庣巼鍙嶇畻涓嶅惈绋庨噾棰濄�佺◣棰� */
+const calculateTaxFromInclusive = (inclusiveTotal) => {
+ const total = Number(inclusiveTotal ?? form.totalAmount ?? 0);
+ if (total <= 0) {
+ form.amount = 0;
+ form.taxAmount = 0;
+ form.totalAmount = 0;
+ return;
+ }
+ const rate = Number(form.taxRate) / 100;
+ form.totalAmount = Number(total.toFixed(2));
+ form.amount = Number((form.totalAmount / (1 + rate)).toFixed(2));
+ form.taxAmount = Number((form.totalAmount - form.amount).toFixed(2));
};
-const getCertifyStatusType = (status) => {
- const map = { uncertified: "info", certified: "success", failed: "danger" };
- return map[status] || "";
+const handleTaxRateChange = () => {
+ if (form.totalAmount > 0) {
+ calculateTaxFromInclusive(form.totalAmount);
+ } else {
+ calculateTaxFromExclusive();
+ }
+};
+
+/** 鏍规嵁宸查�夊叆搴撳崟姹囨�诲惈绋庨噾棰濓紝鍙嶇畻涓嶅惈绋庨噾棰濅笌绋庨 */
+const syncInvoiceAmount = () => {
+ const selected = form.stockInRecordIds || [];
+ const sumFromOptions = inboundBatchOptions.value
+ .filter((opt) => selected.some((id) => isSameInboundId(id, opt.value)))
+ .reduce((acc, opt) => acc + (Number(opt.inboundAmount) || 0), 0);
+
+ let taxInclusiveSum = sumFromOptions;
+ if (taxInclusiveSum <= 0 && selected.length) {
+ taxInclusiveSum = inboundBatchList.value
+ .filter((row) => selected.some((id) => isSameInboundId(id, getInboundRowId(row))))
+ .reduce((acc, row) => acc + getInboundRowTaxInclusiveAmount(row), 0);
+ }
+
+ calculateTaxFromInclusive(taxInclusiveSum > 0 ? Number(taxInclusiveSum.toFixed(2)) : 0);
+};
+
+const inboundBatchDisplayText = computed(() => {
+ if (form.inboundBatches) return form.inboundBatches;
+ const ids = form.stockInRecordIds || [];
+ if (!ids.length) return "";
+ const labels = inboundBatchOptions.value
+ .filter((opt) => ids.some((id) => isSameInboundId(id, opt.value)))
+ .map((opt) => opt.label);
+ if (labels.length) return labels.join("銆�");
+ return ids.join("銆�");
+});
+
+const normalizeTableRow = (row) => ({
+ ...row,
+ invoiceNo: row.invoiceNumber ?? row.invoiceNo,
+ invoiceDate: row.issueDate ?? row.invoiceDate,
+ amount: row.taxExclusivelPrice ?? row.amount,
+ taxAmount: row.taxPrice ?? row.taxAmount,
+ totalAmount: row.taxInclusivePrice ?? row.totalAmount,
+ content: row.invoiceContent ?? row.content,
+ status: normalizeStatus(row.status),
+ stockInRecordIds: row.stockInRecordIds ?? "",
+ inboundBatches: formatInboundBatches(row.inboundBatches),
+});
+
+const toFormNumber = (val) => {
+ const n = Number(val);
+ return Number.isFinite(n) ? n : 0;
+};
+
+const resolveFormAmounts = (row) => {
+ let amount = toFormNumber(row.taxExclusivelPrice ?? row.amount);
+ let taxAmount = toFormNumber(row.taxPrice ?? row.taxAmount);
+ let totalAmount = toFormNumber(row.taxInclusivePrice ?? row.totalAmount);
+ const taxRate = toFormNumber(row.taxRate) || 13;
+
+ if (totalAmount > 0 && amount === 0 && taxAmount === 0) {
+ amount = Number((totalAmount / (1 + taxRate / 100)).toFixed(2));
+ taxAmount = Number((totalAmount - amount).toFixed(2));
+ } else if (totalAmount > 0 && amount > 0 && taxAmount === 0) {
+ taxAmount = Number((totalAmount - amount).toFixed(2));
+ } else if (amount > 0 && taxAmount === 0 && totalAmount === 0) {
+ taxAmount = Number((amount * taxRate / 100).toFixed(2));
+ totalAmount = Number((amount + taxAmount).toFixed(2));
+ } else if (amount > 0 && taxAmount > 0 && totalAmount === 0) {
+ totalAmount = Number((amount + taxAmount).toFixed(2));
+ }
+
+ return { amount, taxAmount, totalAmount };
+};
+
+const fillFormFromRow = (row) => {
+ const stockInRecordIds = parseStockInRecordIds(row.stockInRecordIds);
+ const { amount, taxAmount, totalAmount } = resolveFormAmounts(row);
+ Object.assign(form, {
+ invoiceNo: row.invoiceNo ?? row.invoiceNumber ?? "",
+ supplierId: row.supplierId,
+ invoiceDate: row.invoiceDate ?? row.issueDate ?? "",
+ invoiceType: row.invoiceType ?? "澧炲�肩◣涓撶敤鍙戠エ",
+ taxRate: row.taxRate ?? 13,
+ amount,
+ taxAmount,
+ totalAmount,
+ content: row.content ?? row.invoiceContent ?? "",
+ remark: row.remark ?? "",
+ stockInRecordIds,
+ inboundBatches: formatInboundBatches(row.inboundBatches),
+ storageAttachmentId: row.storageAttachmentId,
+ status: normalizeStatus(row.status),
+ });
+};
+
+const buildCancelPayload = (row) => ({
+ id: row.id,
+ invoiceNumber: row.invoiceNumber ?? row.invoiceNo,
+ taxRate: row.taxRate,
+ invoiceType: row.invoiceType,
+ issueDate: row.issueDate ?? row.invoiceDate,
+ taxExclusivelPrice: row.taxExclusivelPrice ?? row.amount,
+ taxPrice: row.taxPrice ?? row.taxAmount,
+ taxInclusivePrice: row.taxInclusivePrice ?? row.totalAmount,
+ remark: row.remark ?? "",
+ invoiceContent: row.invoiceContent ?? row.content,
+ supplierId: row.supplierId,
+ storageAttachmentId: row.storageAttachmentId,
+ stockInRecordIds: row.stockInRecordIds ?? "",
+ status: 1,
+});
+
+const buildSubmitPayload = () => ({
+ invoiceNumber: form.invoiceNo,
+ supplierId: form.supplierId,
+ issueDate: form.invoiceDate,
+ invoiceType: form.invoiceType,
+ taxRate: form.taxRate,
+ taxExclusivelPrice: form.amount,
+ taxPrice: form.taxAmount,
+ taxInclusivePrice: form.totalAmount,
+ invoiceContent: form.content,
+ remark: form.remark || "",
+ stockInRecordIds: (form.stockInRecordIds || []).join(","),
+ status: 0,
+ storageAttachmentId: form.storageAttachmentId,
+});
+
+const getSupplierList = () => {
+ getOptions().then((res) => {
+ if (res.code === 200) {
+ supplierList.value = res.data ?? [];
+ }
+ });
+};
+
+const appendFilterParams = (params) => {
+ if (filters.invoiceNumber) {
+ params.invoiceNumber = filters.invoiceNumber;
+ }
+ if (filters.supplierId) {
+ params.supplierId = filters.supplierId;
+ }
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ if (filters.status !== "" && filters.status != null) {
+ params.status = filters.status;
+ }
+ return params;
+};
+
+const buildListParams = () =>
+ appendFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+const buildExportParams = () => appendFilterParams({});
+
+const handleExport = () => {
+ proxy.download(
+ "/accountPurchaseInvoice/exportAccountPurchaseInvoice",
+ buildExportParams(),
+ `杩涢」鍙戠エ_${Date.now()}.xlsx`
+ );
};
const getTableData = () => {
- let result = [...mockData];
- if (filters.invoiceCode) {
- result = result.filter(item => item.invoiceCode.includes(filters.invoiceCode));
- }
- if (filters.invoiceNo) {
- result = result.filter(item => item.invoiceNo.includes(filters.invoiceNo));
- }
- if (filters.supplierId) {
- result = result.filter(item => item.supplierId === filters.supplierId);
- }
- if (filters.certifyStatus) {
- result = result.filter(item => item.certifyStatus === filters.certifyStatus);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ tableLoading.value = true;
+ listPageAccountPurchaseInvoice(buildListParams())
+ .then((res) => {
+ if (res.code === 200) {
+ const records = res.data?.records ?? [];
+ dataList.value = records.map(normalizeTableRow);
+ pagination.total = res.data?.total ?? 0;
+ } else {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
};
-const resetFilters = () => {
- filters.invoiceCode = "";
- filters.invoiceNo = "";
- filters.supplierId = "";
- filters.certifyStatus = "";
+const onSearch = () => {
pagination.currentPage = 1;
getTableData();
};
-const changePage = ({ current, size }) => {
- pagination.currentPage = current;
- pagination.pageSize = size;
+const resetFilters = () => {
+ filters.invoiceNumber = "";
+ filters.supplierId = "";
+ filters.dateRange = [];
+ filters.status = "";
+ pagination.currentPage = 1;
getTableData();
};
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
+const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
+ getTableData();
+};
+
+const closeDialog = () => {
+ dialogVisible.value = false;
+ isView.value = false;
+ inboundSelectVisible.value = false;
+};
+
+const resetForm = () => {
+ Object.assign(form, {
+ invoiceNo: "",
+ supplierId: "",
+ invoiceDate: new Date().toISOString().split("T")[0],
+ invoiceType: "澧炲�肩◣涓撶敤鍙戠エ",
+ taxRate: 13,
+ amount: 0,
+ taxAmount: 0,
+ totalAmount: 0,
+ content: "",
+ remark: "",
+ stockInRecordIds: [],
+ inboundBatches: "",
+ storageAttachmentId: undefined,
+ status: 0,
+ });
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
};
const add = () => {
- isEdit.value = false;
+ isView.value = false;
dialogTitle.value = "褰曞叆鍙戠エ";
- Object.assign(form, {
- invoiceCode: "",
- invoiceNo: "",
- supplierId: "",
- invoiceDate: new Date().toISOString().split('T')[0],
- amount: 0,
- taxRate: 13,
- taxAmount: 0,
- totalAmount: 0,
- certifyStatus: "uncertified",
- certifyDate: "",
- content: "",
- remark: "",
- });
- dialogVisible.value = true;
-};
-
-const edit = (row) => {
- isEdit.value = true;
- currentId.value = row.id;
- dialogTitle.value = "缂栬緫鍙戠エ";
- Object.assign(form, row);
+ resetForm();
dialogVisible.value = true;
};
const view = (row) => {
- ElMessage.info(`鏌ョ湅鍙戠エ: ${row.invoiceCode}-${row.invoiceNo}`);
+ isView.value = true;
+ dialogTitle.value = "鏌ョ湅鍙戠エ";
+ fillFormFromRow(row);
+ if (row.supplierId) {
+ loadInboundBatches(row.supplierId, true, false);
+ }
+ dialogVisible.value = true;
};
-const handleCertify = (row) => {
- ElMessageBox.confirm("纭璁よ瘉璇ュ彂绁ㄥ悧锛�", "鎻愮ず", {
- confirmButtonText: "纭",
+const handleCancel = (row) => {
+ ElMessageBox.confirm(`纭浣滃簾鍙戠エ銆�${row.invoiceNo ?? row.invoiceNumber}銆嶅悧锛焋, "浣滃簾纭", {
+ confirmButtonText: "纭畾",
cancelButtonText: "鍙栨秷",
- type: "info",
+ type: "warning",
}).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].certifyStatus = "certified";
- mockData[index].certifyDate = new Date().toISOString().split('T')[0];
- }
- ElMessage.success("璁よ瘉鎴愬姛");
- getTableData();
+ cancelAccountPurchaseInvoice(buildCancelPayload(row))
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("浣滃簾鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "浣滃簾澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("浣滃簾澶辫触");
+ });
});
};
-const handleBatchCertify = () => {
- ElMessageBox.confirm(`纭鎵归噺璁よ瘉閫変腑鐨� ${selectedRows.value.length} 寮犲彂绁ㄥ悧锛焋, "鎻愮ず", {
- confirmButtonText: "纭",
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎鍙戠エ銆�${row.invoiceNo ?? row.invoiceNumber}銆嶅悧锛焋, "鍒犻櫎纭", {
+ confirmButtonText: "纭畾",
cancelButtonText: "鍙栨秷",
- type: "info",
+ type: "warning",
}).then(() => {
- selectedRows.value.forEach(row => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1 && mockData[index].certifyStatus === "uncertified") {
- mockData[index].certifyStatus = "certified";
- mockData[index].certifyDate = new Date().toISOString().split('T')[0];
- }
- });
- ElMessage.success("鎵归噺璁よ瘉鎴愬姛");
- getTableData();
+ deleteAccountPurchaseInvoice([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
});
-};
-
-const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
};
const submitForm = () => {
- formRef.value.validate((valid) => {
- if (valid) {
- const supplier = supplierList.find(item => item.id === form.supplierId);
- if (isEdit.value) {
- const index = mockData.findIndex(item => item.id === currentId.value);
- if (index !== -1) {
- mockData[index] = { ...mockData[index], ...form, supplierName: supplier?.name };
+ formRef.value?.validate((valid) => {
+ if (!valid) return;
+ submitLoading.value = true;
+ addAccountPurchaseInvoice(buildSubmitPayload())
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("褰曞叆鎴愬姛");
+ closeDialog();
+ pagination.currentPage = 1;
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "褰曞叆澶辫触");
}
- ElMessage.success("缂栬緫鎴愬姛");
- } else {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- mockData.push({ id: newId, ...form, supplierName: supplier?.name });
- ElMessage.success("褰曞叆鎴愬姛");
- }
- dialogVisible.value = false;
- getTableData();
- }
+ })
+ .catch(() => {
+ ElMessage.error("褰曞叆澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
});
};
+const ensureInboundOptionsForSelected = () => {
+ const ids = form.stockInRecordIds || [];
+ ids.forEach((id) => {
+ const exists = inboundBatchOptions.value.some((opt) => isSameInboundId(opt.value, id));
+ if (exists) return;
+ const fromList = inboundBatchList.value.find((row) => isSameInboundId(getInboundRowId(row), id));
+ if (fromList) {
+ const [option] = normalizeInboundBatchOptions([fromList]);
+ if (option) inboundBatchOptions.value.push(option);
+ return;
+ }
+ inboundBatchOptions.value.push({
+ label: String(id),
+ value: id,
+ inboundAmount: 0,
+ });
+ });
+};
+
+const restoreInboundTableSelection = () => {
+ nextTick(() => {
+ const table = inboundTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ const selectedIds = new Set((form.stockInRecordIds || []).map((id) => String(id)));
+ inboundBatchList.value.forEach((row) => {
+ const rowId = getInboundRowId(row);
+ if (rowId !== undefined && rowId !== null && selectedIds.has(String(rowId))) {
+ table.toggleRowSelection(row, true);
+ }
+ });
+ });
+};
+
+const loadInboundBatches = (supplierId, keepSelected = false, syncAmount = true) => {
+ if (!supplierId) {
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
+ if (!keepSelected) {
+ form.stockInRecordIds = [];
+ form.inboundBatches = "";
+ form.amount = 0;
+ form.taxAmount = 0;
+ form.totalAmount = 0;
+ }
+ return Promise.resolve();
+ }
+ inboundBatchLoading.value = true;
+ return getInboundBatchesBySupplier({ supplierId })
+ .then((res) => {
+ if (res.code === 200) {
+ const list = res.data?.records ?? res.data ?? [];
+ inboundBatchList.value = Array.isArray(list) ? list : [];
+ inboundBatchOptions.value = normalizeInboundBatchOptions(list);
+ } else {
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
+ }
+ })
+ .catch(() => {
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
+ })
+ .finally(() => {
+ inboundBatchLoading.value = false;
+ if (keepSelected) {
+ ensureInboundOptionsForSelected();
+ restoreInboundTableSelection();
+ if (syncAmount && !isView.value) {
+ syncInvoiceAmount();
+ }
+ }
+ });
+};
+
+const handleSupplierChange = (supplierId) => {
+ form.stockInRecordIds = [];
+ form.inboundBatches = "";
+ form.amount = 0;
+ form.taxAmount = 0;
+ form.totalAmount = 0;
+ loadInboundBatches(supplierId);
+};
+
+const handleInboundInputClick = () => {
+ if (isView.value) return;
+ openInboundSelectDialog();
+};
+
+const openInboundSelectDialog = () => {
+ if (!form.supplierId || isView.value) return;
+ inboundSelectVisible.value = true;
+ loadInboundBatches(form.supplierId, true).then(() => {
+ restoreInboundTableSelection();
+ });
+};
+
+const handleInboundDialogSelectionChange = (selection) => {
+ dialogInboundSelection.value = selection;
+};
+
+const confirmInboundSelection = () => {
+ if (dialogInboundSelection.value.length === 0) {
+ ElMessage.warning("璇疯嚦灏戦�夋嫨涓�鏉″叆搴撳崟");
+ return;
+ }
+ form.stockInRecordIds = dialogInboundSelection.value
+ .map((row) => getInboundRowId(row))
+ .filter((id) => id !== undefined && id !== null);
+ form.inboundBatches = dialogInboundSelection.value
+ .map((row) => row.inboundBatches ?? row.batchNo ?? "")
+ .filter(Boolean)
+ .join("銆�");
+ dialogInboundSelection.value.forEach((row) => {
+ const [option] = normalizeInboundBatchOptions([row]);
+ if (option && !inboundBatchOptions.value.some((opt) => isSameInboundId(opt.value, option.value))) {
+ inboundBatchOptions.value.push(option);
+ }
+ });
+ inboundSelectVisible.value = false;
+ syncInvoiceAmount();
+ formRef.value?.validateField("stockInRecordIds");
+};
+
+const handleInboundDialogClosed = () => {
+ dialogInboundSelection.value = [];
+};
+
onMounted(() => {
+ getSupplierList();
getTableData();
});
</script>
@@ -406,4 +938,8 @@
color: #67c23a;
font-weight: bold;
}
+
+.inbound-batch-input :deep(.el-input__wrapper) {
+ cursor: pointer;
+}
</style>
diff --git a/src/views/financialManagement/payable/payment.vue b/src/views/financialManagement/payable/payment.vue
index d4774fe..18e7941 100644
--- a/src/views/financialManagement/payable/payment.vue
+++ b/src/views/financialManagement/payable/payment.vue
@@ -1,377 +1,299 @@
<template>
<div class="app-container">
- <el-form :model="filters" :inline="true">
+ <el-form :model="filters"
+ :inline="true">
<el-form-item label="浠樻鍗曞彿:">
- <el-input v-model="filters.paymentCode" placeholder="璇疯緭鍏ヤ粯娆惧崟鍙�" clearable style="width: 200px;" />
+ <el-input v-model="filters.paymentNumber"
+ placeholder="璇疯緭鍏ヤ粯娆惧崟鍙�"
+ clearable
+ style="width: 200px;" />
</el-form-item>
<el-form-item label="渚涘簲鍟�:">
- <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px;">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.supplierId"
+ placeholder="璇烽�夋嫨渚涘簲鍟�"
+ clearable
+ filterable
+ style="width: 200px;">
+ <el-option v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="浠樻鏂瑰紡:">
- <el-select v-model="filters.paymentMethod" placeholder="璇烽�夋嫨浠樻鏂瑰紡" clearable style="width: 150px;">
- <el-option label="閾惰杞处" value="bank_transfer" />
- <el-option label="鐜伴噾" value="cash" />
- <el-option label="鏀エ" value="check" />
- <el-option label="姹囩エ" value="draft" />
+ <el-select v-model="filters.paymentMethod"
+ placeholder="璇烽�夋嫨浠樻鏂瑰紡"
+ clearable
+ style="width: 150px;">
+ <el-option v-for="item in checkout_payment"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
</el-select>
</el-form-item>
- <el-form-item label="鐘舵��:">
- <el-select v-model="filters.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px;">
- <el-option label="寰呬粯娆�" value="pending" />
- <el-option label="宸插畬鎴�" value="completed" />
- <el-option label="宸插彇娑�" value="cancelled" />
- </el-select>
+ <el-form-item label="浠樻鏃ユ湡:">
+ <el-date-picker v-model="filters.dateRange"
+ type="daterange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable
+ style="width: 240px;" />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary"
+ @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
<div class="table_list">
<div class="actions">
<div>
- <el-statistic title="鏈湡浠樻鍚堣" :value="totalPaymentAmount" precision="2" prefix="楼" />
+ <el-statistic title="鏈〉浠樻鍚堣"
+ :value="totalPaymentAmount"
+ :precision="2"
+ prefix="楼" />
</div>
<div>
- <el-button type="primary" @click="add" icon="Plus">鏂板浠樻</el-button>
- <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+ <el-button @click="handleExport"
+ icon="Download">瀵煎嚭</el-button>
</div>
</div>
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableData="dataList"
- :page="{
+ <PIMTable rowKey="id"
+ :column="columns"
+ :tableData="dataList"
+ :tableLoading="tableLoading"
+ :page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @pagination="changePage"
- >
+ @pagination="changePage">
<template #amount="{ row }">
<span class="text-danger">楼{{ formatMoney(row.amount) }}</span>
</template>
<template #paymentMethod="{ row }">
<el-tag>{{ getPaymentMethodLabel(row.paymentMethod) }}</el-tag>
</template>
- <template #status="{ row }">
- <el-tag :type="row.status === 'completed' ? 'success' : row.status === 'pending' ? 'warning' : 'info'">
- {{ row.status === 'completed' ? '宸插畬鎴�' : row.status === 'pending' ? '寰呬粯娆�' : '宸插彇娑�' }}
- </el-tag>
- </template>
<template #operation="{ row }">
- <el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
- <el-button type="success" link @click="handleComplete(row)" v-if="row.status === 'pending'">瀹屾垚</el-button>
- <el-button type="danger" link @click="handleCancel(row)" v-if="row.status === 'pending'">鍙栨秷</el-button>
+ <el-button :disabled="row.accountStatemen"
+ type="danger"
+ link
+ @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
-
- <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
- <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="浠樻鍗曞彿" prop="paymentCode">
- <el-input v-model="form.paymentCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍏宠仈鐢宠鍗�" prop="applyCode">
- <el-select v-model="form.applyCode" placeholder="璇烽�夋嫨鍏宠仈鐢宠鍗�" style="width: 100%;" :disabled="isEdit">
- <el-option v-for="item in applyList" :key="item.applyCode" :label="item.applyCode" :value="item.applyCode" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="渚涘簲鍟�" prop="supplierId">
- <el-select v-model="form.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%;" :disabled="isEdit">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="浠樻鏃ユ湡" prop="paymentDate">
- <el-date-picker v-model="form.paymentDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="浠樻閲戦" prop="amount">
- <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
- <el-select v-model="form.paymentMethod" placeholder="璇烽�夋嫨浠樻鏂瑰紡" style="width: 100%;">
- <el-option label="閾惰杞处" value="bank_transfer" />
- <el-option label="鐜伴噾" value="cash" />
- <el-option label="鏀エ" value="check" />
- <el-option label="姹囩エ" value="draft" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="閾惰璐﹀彿" prop="bankAccount" v-if="form.paymentMethod === 'bank_transfer'">
- <el-input v-model="form.bankAccount" placeholder="璇疯緭鍏ラ摱琛岃处鍙�" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="寮�鎴疯" prop="bankName" v-if="form.paymentMethod === 'bank_transfer'">
- <el-input v-model="form.bankName" placeholder="璇疯緭鍏ュ紑鎴疯" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
- </el-form-item>
- </el-form>
- <template #footer>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
- </template>
- </FormDialog>
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, computed } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import { ref, reactive, computed, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
+ import {
+ listPageAccountPurchasePayment,
+ deleteAccountPurchasePayment,
+ } from "@/api/financialManagement/accountPurchasePayment.js";
-defineOptions({
- name: "浠樻鍗�",
-});
+ defineOptions({
+ name: "浠樻鍗�",
+ });
-const filters = reactive({
- paymentCode: "",
- supplierId: "",
- paymentMethod: "",
- status: "",
-});
+ const { proxy } = getCurrentInstance();
+ const { checkout_payment } = proxy.useDict("checkout_payment");
-const pagination = reactive({
- currentPage: 1,
- pageSize: 10,
- total: 0,
-});
-
-const columns = [
- { label: "浠樻鍗曞彿", prop: "paymentCode", width: "150" },
- { label: "鍏宠仈鐢宠鍗�", prop: "applyCode", width: "150" },
- { label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
- { label: "浠樻鏃ユ湡", prop: "paymentDate", width: "120" },
- { label: "浠樻閲戦", prop: "amount", slot: "amount" },
- { label: "浠樻鏂瑰紡", prop: "paymentMethod", slot: "paymentMethod" },
- { label: "鐘舵��", prop: "status", slot: "status" },
- { label: "澶囨敞", prop: "remark", showOverflowTooltip: true },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "220", fixed: "right" },
-];
-
-const dataList = ref([]);
-const dialogVisible = ref(false);
-const dialogTitle = ref("");
-const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
-
-const supplierList = [
- { id: 1, name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
- { id: 2, name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
- { id: 3, name: "骞垮窞鍖呰鏉愭枡鍘�" },
- { id: 4, name: "娣卞湷浜旈噾閰嶄欢鍏徃" },
-];
-
-const applyList = [
- { applyCode: "FK2024001", supplierId: 1, amount: 5000 },
- { applyCode: "FK2024002", supplierId: 2, amount: 8000 },
- { applyCode: "FK2024003", supplierId: 3, amount: 3000 },
-];
-
-const form = reactive({
- paymentCode: "",
- applyCode: "",
- supplierId: "",
- paymentDate: "",
- amount: 0,
- paymentMethod: "bank_transfer",
- bankAccount: "",
- bankName: "",
- remark: "",
-});
-
-const rules = {
- applyCode: [{ required: true, message: "璇烽�夋嫨鍏宠仈鐢宠鍗�", trigger: "change" }],
- supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
- paymentDate: [{ required: true, message: "璇烽�夋嫨浠樻鏃ユ湡", trigger: "change" }],
- amount: [{ required: true, message: "璇疯緭鍏ヤ粯娆鹃噾棰�", trigger: "blur" }],
- paymentMethod: [{ required: true, message: "璇烽�夋嫨浠樻鏂瑰紡", trigger: "change" }],
-};
-
-const mockData = [
- { id: 1, paymentCode: "FKD2024001", applyCode: "FK2024001", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", paymentDate: "2024-01-15", amount: 5000, paymentMethod: "bank_transfer", status: "completed", bankAccount: "6222021234567890123", bankName: "宸ュ晢閾惰", remark: "" },
- { id: 2, paymentCode: "FKD2024002", applyCode: "FK2024002", supplierId: 2, supplierName: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�", paymentDate: "2024-01-18", amount: 8000, paymentMethod: "bank_transfer", status: "pending", bankAccount: "6222029876543210987", bankName: "寤鸿閾惰", remark: "" },
- { id: 3, paymentCode: "FKD2024003", applyCode: "FK2024003", supplierId: 3, supplierName: "骞垮窞鍖呰鏉愭枡鍘�", paymentDate: "2024-01-20", amount: 3000, paymentMethod: "cash", status: "completed", remark: "" },
-];
-
-const totalPaymentAmount = computed(() => {
- return dataList.value.reduce((sum, item) => sum + Number(item.amount), 0);
-});
-
-const formatMoney = (value) => {
- if (value === undefined || value === null) return "0.00";
- return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
-};
-
-const getPaymentMethodLabel = (method) => {
- const map = {
- bank_transfer: "閾惰杞处",
- cash: "鐜伴噾",
- check: "鏀エ",
- draft: "姹囩エ",
- };
- return map[method] || method;
-};
-
-const getTableData = () => {
- let result = [...mockData];
- if (filters.paymentCode) {
- result = result.filter(item => item.paymentCode.includes(filters.paymentCode));
- }
- if (filters.supplierId) {
- result = result.filter(item => item.supplierId === filters.supplierId);
- }
- if (filters.paymentMethod) {
- result = result.filter(item => item.paymentMethod === filters.paymentMethod);
- }
- if (filters.status) {
- result = result.filter(item => item.status === filters.status);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
-};
-
-const resetFilters = () => {
- filters.paymentCode = "";
- filters.supplierId = "";
- filters.paymentMethod = "";
- filters.status = "";
- pagination.currentPage = 1;
- getTableData();
-};
-
-const changePage = ({ current, size }) => {
- pagination.currentPage = current;
- pagination.pageSize = size;
- getTableData();
-};
-
-const add = () => {
- isEdit.value = false;
- dialogTitle.value = "鏂板浠樻";
- Object.assign(form, {
- paymentCode: "FKD" + Date.now().toString().slice(-8),
- applyCode: "",
+ const filters = reactive({
+ paymentNumber: "",
supplierId: "",
- paymentDate: new Date().toISOString().split('T')[0],
- amount: 0,
- paymentMethod: "bank_transfer",
- bankAccount: "",
- bankName: "",
- remark: "",
+ paymentMethod: "",
+ dateRange: [],
});
- dialogVisible.value = true;
-};
-const edit = (row) => {
- isEdit.value = true;
- currentId.value = row.id;
- dialogTitle.value = "缂栬緫浠樻";
- Object.assign(form, row);
- dialogVisible.value = true;
-};
-
-const view = (row) => {
- ElMessage.info(`鏌ョ湅浠樻鍗�: ${row.paymentCode}`);
-};
-
-const handleComplete = (row) => {
- ElMessageBox.confirm("纭璇ヤ粯娆惧崟宸插畬鎴愬悧锛�", "鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "info",
- }).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "completed";
- }
- ElMessage.success("浠樻瀹屾垚");
- getTableData();
+ const pagination = reactive({
+ currentPage: 1,
+ pageSize: 10,
+ total: 0,
});
-};
-const handleCancel = (row) => {
- ElMessageBox.confirm("纭鍙栨秷璇ヤ粯娆惧崟鍚楋紵", "鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "cancelled";
- }
- ElMessage.success("宸插彇娑�");
- getTableData();
+ const columns = [
+ { label: "浠樻鍗曞彿", prop: "paymentNumber", width: "150" },
+ { label: "鍏宠仈鐢宠鍗�", prop: "invoiceApplicationNo", width: "150" },
+ { label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
+ { label: "浠樻鏃ユ湡", prop: "paymentDate", width: "120" },
+ { label: "浠樻閲戦", prop: "amount", dataType: "slot", slot: "amount" },
+ {
+ label: "浠樻鏂瑰紡",
+ prop: "paymentMethod",
+ dataType: "slot",
+ slot: "paymentMethod",
+ width: "120",
+ },
+ { label: "澶囨敞", prop: "remark", showOverflowTooltip: true },
+ {
+ label: "鎿嶄綔",
+ prop: "operation",
+ dataType: "slot",
+ slot: "operation",
+ width: "80",
+ fixed: "right",
+ },
+ ];
+
+ const dataList = ref([]);
+ const tableLoading = ref(false);
+ const supplierList = ref([]);
+
+ const totalPaymentAmount = computed(() =>
+ dataList.value.reduce((sum, item) => sum + Number(item.amount ?? 0), 0)
+ );
+
+ const formatMoney = value => {
+ if (value === undefined || value === null) return "0.00";
+ return Number(value)
+ .toFixed(2)
+ .replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+ };
+
+ const getPaymentMethodLabel = value => {
+ if (value === undefined || value === null || value === "") return "-";
+ const item = checkout_payment.value?.find(
+ m => String(m.value) === String(value)
+ );
+ return item?.label ?? value;
+ };
+
+ const normalizeTableRow = row => ({
+ ...row,
+ paymentNumber: row.paymentNumber ?? row.paymentCode,
+ invoiceApplicationNo: row.invoiceApplicationNo ?? row.applyCode ?? "",
+ amount: row.paymentAmount ?? row.amount,
+ bankAccountNum: row.bankAccountNum ?? row.bankAccount ?? "",
+ bankAccountName: row.bankAccountName ?? row.bankName ?? "",
});
-};
-const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
-};
-
-const submitForm = () => {
- formRef.value.validate((valid) => {
- if (valid) {
- const supplier = supplierList.find(item => item.id === form.supplierId);
- if (isEdit.value) {
- const index = mockData.findIndex(item => item.id === currentId.value);
- if (index !== -1) {
- mockData[index] = { ...mockData[index], ...form, supplierName: supplier?.name };
- }
- ElMessage.success("缂栬緫鎴愬姛");
- } else {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- mockData.push({ id: newId, ...form, supplierName: supplier?.name, status: "pending" });
- ElMessage.success("鏂板鎴愬姛");
+ const getSupplierList = () => {
+ getOptions().then(res => {
+ if (res.code === 200) {
+ supplierList.value = res.data ?? [];
}
- dialogVisible.value = false;
- getTableData();
- }
- });
-};
+ });
+ };
-onMounted(() => {
- getTableData();
-});
+ const appendFilterParams = params => {
+ if (filters.paymentNumber) {
+ params.paymentNumber = filters.paymentNumber;
+ }
+ if (filters.supplierId) {
+ params.supplierId = filters.supplierId;
+ }
+ if (filters.paymentMethod) {
+ params.paymentMethod = filters.paymentMethod;
+ }
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ return params;
+ };
+
+ const buildListParams = () =>
+ appendFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+ const buildExportParams = () => appendFilterParams({});
+
+ const handleExport = () => {
+ proxy.download(
+ "/accountPurchasePayment/exportAccountPurchasePayment",
+ buildExportParams(),
+ `浠樻鍗昣${Date.now()}.xlsx`
+ );
+ };
+
+ const getTableData = () => {
+ tableLoading.value = true;
+ listPageAccountPurchasePayment(buildListParams())
+ .then(res => {
+ if (res.code === 200) {
+ dataList.value = (res.data?.records ?? []).map(normalizeTableRow);
+ pagination.total = res.data?.total ?? 0;
+ } else {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
+ };
+
+ const resetFilters = () => {
+ filters.paymentNumber = "";
+ filters.supplierId = "";
+ filters.paymentMethod = "";
+ filters.dateRange = [];
+ pagination.currentPage = 1;
+ getTableData();
+ };
+
+ const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
+ getTableData();
+ };
+
+ const handleDelete = row => {
+ ElMessageBox.confirm(`纭鍒犻櫎浠樻鍗曘��${row.paymentNumber}銆嶅悧锛焋, "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountPurchasePayment([row.id])
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+ };
+
+ onMounted(() => {
+ getSupplierList();
+ getTableData();
+ });
</script>
<style lang="scss" scoped>
-.actions {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 15px;
-}
+ .actions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ }
-.text-danger {
- color: #f56c6c;
- font-weight: bold;
-}
+ .text-danger {
+ color: #f56c6c;
+ font-weight: bold;
+ }
</style>
diff --git a/src/views/financialManagement/payable/paymentApply.vue b/src/views/financialManagement/payable/paymentApply.vue
index fb23db3..3937e96 100644
--- a/src/views/financialManagement/payable/paymentApply.vue
+++ b/src/views/financialManagement/payable/paymentApply.vue
@@ -2,23 +2,40 @@
<div class="app-container">
<el-form :model="filters" :inline="true">
<el-form-item label="鐢宠鍗曞彿:">
- <el-input v-model="filters.applyCode" placeholder="璇疯緭鍏ョ敵璇峰崟鍙�" clearable style="width: 200px;" />
+ <el-input v-model="filters.invoiceApplicationNo" placeholder="璇疯緭鍏ョ敵璇峰崟鍙�" clearable style="width: 200px;" />
</el-form-item>
<el-form-item label="渚涘簲鍟�:">
- <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px;">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable filterable style="width: 200px;">
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
- <el-form-item label="鐘舵��:">
+ <el-form-item label="瀹℃牳鐘舵��:">
<el-select v-model="filters.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px;">
- <el-option label="寰呭鎵�" value="pending" />
- <el-option label="宸插鎵�" value="approved" />
- <el-option label="宸查┏鍥�" value="rejected" />
- <el-option label="宸蹭粯娆�" value="paid" />
+ <el-option label="寰呭鏍�" :value="0" />
+ <el-option label="瀹℃牳閫氳繃" :value="1" />
+ <el-option label="瀹℃牳涓嶉�氳繃" :value="2" />
</el-select>
+ </el-form-item>
+ <el-form-item label="鐢宠鏃ユ湡:">
+ <el-date-picker
+ v-model="filters.dateRange"
+ type="daterange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable
+ style="width: 240px;"
+ />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary" @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -27,20 +44,19 @@
<div></div>
<div>
<el-button type="primary" @click="add" icon="Plus">鏂板鐢宠</el-button>
- <el-button @click="handleBatchApply" icon="Document" :disabled="selectedRows.length === 0">鎵归噺鐢宠</el-button>
+ <el-button @click="handleExport" icon="Download">瀵煎嚭</el-button>
</div>
</div>
<PIMTable
rowKey="id"
- isSelection
:column="columns"
:tableData="dataList"
+ :tableLoading="tableLoading"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @selection-change="handleSelectionChange"
@pagination="changePage"
>
<template #amount="{ row }">
@@ -54,90 +70,291 @@
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
- <el-button type="success" link @click="handleAudit(row)" v-if="row.status === 'pending'">瀹℃壒</el-button>
+ <el-button type="primary" link @click="edit(row)" v-if="isPendingStatus(row.status)">缂栬緫</el-button>
+ <el-button type="success" link @click="handleAudit(row)" v-if="isPendingStatus(row.status)">瀹℃牳</el-button>
+ <el-button type="warning" link @click="openPaymentDialog(row)" v-if="isApprovedStatus(row.status)">浠樻</el-button>
+ <el-button type="danger" link @click="handleDelete(row)" v-if="isPendingStatus(row.status)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
- <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
+ <FormDialog
+ :title="dialogTitle"
+ v-model="dialogVisible"
+ width="800px"
+ :operation-type="isView ? 'detail' : ''"
+ @confirm="submitForm"
+ @cancel="closeDialog"
+ >
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+ <el-row v-if="isView" :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="瀹℃牳鐘舵��">
+ <el-tag :type="getStatusType(form.status)">{{ getStatusLabel(form.status) }}</el-tag>
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鐢宠鍗曞彿" prop="applyCode">
- <el-input v-model="form.applyCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-form-item label="鐢宠鍗曞彿" prop="invoiceApplicationNo">
+ <el-input v-model="form.invoiceApplicationNo" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="渚涘簲鍟�" prop="supplierId">
- <el-select v-model="form.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%;" :disabled="isEdit">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select
+ v-model="form.supplierId"
+ placeholder="璇烽�夋嫨渚涘簲鍟�"
+ style="width: 100%;"
+ filterable
+ :disabled="isEdit || isView"
+ @change="handleSupplierChange"
+ >
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="浠樻閲戦" prop="amount">
- <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
+ <el-form-item label="鍏宠仈鍏ュ簱鍗�" prop="stockInRecordIds">
+ <el-input
+ :model-value="inboundBatchDisplayText"
+ placeholder="璇峰厛閫夋嫨渚涘簲鍟�"
+ readonly
+ :disabled="!form.supplierId || isEdit || isView"
+ class="inbound-batch-input"
+ @click="handleInboundInputClick"
+ >
+ <template v-if="!isEdit && !isView" #append>
+ <el-button
+ :disabled="!form.supplierId"
+ :loading="inboundBatchLoading"
+ @click.stop="openInboundSelectDialog"
+ >
+ 閫夋嫨
+ </el-button>
+ </template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐢宠鏃ユ湡" prop="applyDate">
+ <el-date-picker
+ v-model="form.applyDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浠樻閲戦" prop="paymentAmount">
+ <el-input-number
+ v-model="form.paymentAmount"
+ :min="0"
+ :precision="2"
+ style="width: 100%;"
+ :disabled="isView"
+ placeholder="鏍规嵁鍏ュ簱鍗曡嚜鍔ㄦ眹鎬伙紝鍙慨鏀�"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
- <el-select v-model="form.paymentMethod" placeholder="璇烽�夋嫨浠樻鏂瑰紡" style="width: 100%;">
- <el-option label="閾惰杞处" value="bank_transfer" />
- <el-option label="鐜伴噾" value="cash" />
- <el-option label="鏀エ" value="check" />
- <el-option label="姹囩エ" value="draft" />
+ <el-select
+ v-model="form.paymentMethod"
+ placeholder="璇烽�夋嫨浠樻鏂瑰紡"
+ style="width: 100%;"
+ :disabled="isView"
+ >
+ <el-option
+ v-for="item in checkout_payment"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
</el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="浠樻浜嬬敱" prop="paymentContent">
+ <el-input
+ v-model="form.paymentContent"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヤ粯娆句簨鐢�"
+ :disabled="isView"
+ />
+ </el-form-item>
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" :disabled="isView" />
+ </el-form-item>
+ </el-form>
+ <template v-if="!isView" #footer>
+ <el-button type="primary" :loading="submitLoading" @click="submitForm">纭畾</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
+ </template>
+ </FormDialog>
+
+ <FormDialog
+ title="浠樻"
+ v-model="paymentDialogVisible"
+ width="800px"
+ @confirm="submitPayment"
+ @cancel="paymentDialogVisible = false"
+ >
+ <el-form :model="paymentForm" :rules="paymentRules" ref="paymentFormRef" label-width="120px">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浠樻鍗曞彿" prop="paymentNumber">
+ <el-input v-model="paymentForm.paymentNumber" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏宠仈鐢宠鍗�" prop="invoiceApplicationNo">
+ <el-input v-model="paymentForm.invoiceApplicationNo" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鐢宠鏃ユ湡" prop="applyDate">
- <el-date-picker v-model="form.applyDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
+ <el-form-item label="渚涘簲鍟�">
+ <el-input v-model="paymentForm.supplierName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏈熸湜浠樻鏃ユ湡" prop="expectedDate">
- <el-date-picker v-model="form.expectedDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
+ <el-form-item label="浠樻鏃ユ湡" prop="paymentDate">
+ <el-date-picker
+ v-model="paymentForm.paymentDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ />
</el-form-item>
</el-col>
</el-row>
- <el-form-item label="鍏宠仈鍏ュ簱鍗�" prop="relatedDocs">
- <el-select v-model="form.relatedDocs" multiple placeholder="璇烽�夋嫨鍏宠仈鍏ュ簱鍗�" style="width: 100%;">
- <el-option v-for="item in inList" :key="item.inCode" :label="item.inCode" :value="item.inCode" />
- </el-select>
- </el-form-item>
- <el-form-item label="浠樻浜嬬敱" prop="reason">
- <el-input v-model="form.reason" type="textarea" :rows="3" placeholder="璇疯緭鍏ヤ粯娆句簨鐢�" />
- </el-form-item>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浠樻閲戦" prop="paymentAmount">
+ <el-input-number
+ v-model="paymentForm.paymentAmount"
+ :min="0"
+ :precision="2"
+ style="width: 100%;"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
+ <el-select v-model="paymentForm.paymentMethod" placeholder="璇烽�夋嫨浠樻鏂瑰紡" style="width: 100%;">
+ <el-option
+ v-for="item in checkout_payment"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row v-if="isBankTransferPayment(paymentForm.paymentMethod)" :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="閾惰璐﹀彿" prop="bankAccount">
+ <el-input v-model="paymentForm.bankAccount" placeholder="閾惰璐﹀彿" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="寮�鎴疯" prop="bankName">
+ <el-input v-model="paymentForm.bankName" placeholder="寮�鎴疯" />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" />
+ <el-input v-model="paymentForm.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
</el-form-item>
</el-form>
<template #footer>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" :loading="paymentSubmitLoading" @click="submitPayment">纭畾</el-button>
+ <el-button @click="paymentDialogVisible = false">鍙栨秷</el-button>
</template>
</FormDialog>
+
+ <el-dialog
+ v-model="inboundSelectVisible"
+ title="閫夋嫨鍏ュ簱鍗曞彿"
+ width="1100px"
+ append-to-body
+ destroy-on-close
+ :close-on-click-modal="false"
+ @closed="handleInboundDialogClosed"
+ >
+ <el-table
+ ref="inboundTableRef"
+ v-loading="inboundBatchLoading"
+ :data="inboundBatchList"
+ row-key="id"
+ border
+ stripe
+ max-height="480"
+ @selection-change="handleInboundDialogSelectionChange"
+ >
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column prop="inboundBatches" label="鍏ュ簱鍗曞彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="supplierName" label="渚涘簲鍟�" min-width="120" show-overflow-tooltip />
+ <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="120" show-overflow-tooltip />
+ <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="purchaseContractNumber" label="閲囪喘璁㈠崟鍙�" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="inboundDate" label="鍏ュ簱鏃ユ湡" width="110" align="center" />
+ <el-table-column prop="inboundAmount" label="鍏ュ簱閲戦(鍚◣)" width="120" align="right">
+ <template #default="{ row }">楼{{ formatMoney(getInboundRowTaxInclusiveAmount(row)) }}</template>
+ </el-table-column>
+ </el-table>
+ <template #footer>
+ <el-button type="primary" @click="confirmInboundSelection">纭畾</el-button>
+ <el-button @click="inboundSelectVisible = false">鍙栨秷</el-button>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
-import { ref, reactive, onMounted } from "vue";
+import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
+import {
+ getInboundBatchesBySupplier,
+ addAccountPaymentApplication,
+ listPageAccountPaymentApplication,
+ updateAccountPaymentApplication,
+ auditAccountPaymentApplication,
+ deleteAccountPaymentApplication,
+} from "@/api/financialManagement/accountPaymentApplication.js";
+import { addAccountPurchasePayment } from "@/api/financialManagement/accountPurchasePayment.js";
defineOptions({
name: "浠樻鐢宠",
});
+const { proxy } = getCurrentInstance();
+const { checkout_payment } = proxy.useDict("checkout_payment");
+
const filters = reactive({
- applyCode: "",
+ invoiceApplicationNo: "",
supplierId: "",
status: "",
+ dateRange: [],
});
const pagination = reactive({
@@ -149,199 +366,634 @@
const columns = [
{ label: "鐢宠鍗曞彿", prop: "applyCode", width: "150" },
{ label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
- { label: "浠樻閲戦", prop: "amount", slot: "amount" },
- { label: "浠樻鏂瑰紡", prop: "paymentMethod", slot: "paymentMethod" },
+ { label: "浠樻閲戦", prop: "amount", dataType: "slot", slot: "amount" },
+ { label: "浠樻鏂瑰紡", prop: "paymentMethod", dataType: "slot", slot: "paymentMethod", width: "120" },
{ label: "鐢宠鏃ユ湡", prop: "applyDate", width: "120" },
- { label: "鏈熸湜浠樻鏃�", prop: "expectedDate", width: "120" },
- { label: "鐘舵��", prop: "status", slot: "status" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "200", fixed: "right" },
+ { label: "鐘舵��", prop: "status", dataType: "slot", slot: "status", width: "100" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "260", fixed: "right" },
];
const dataList = ref([]);
-const selectedRows = ref([]);
+const tableLoading = ref(false);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
+const isView = ref(false);
+const submitLoading = ref(false);
const currentId = ref(null);
+const supplierList = ref([]);
-const supplierList = [
- { id: 1, name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
- { id: 2, name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
- { id: 3, name: "骞垮窞鍖呰鏉愭枡鍘�" },
- { id: 4, name: "娣卞湷浜旈噾閰嶄欢鍏徃" },
-];
+const inboundBatchList = ref([]);
+const inboundBatchOptions = ref([]);
+const inboundBatchLoading = ref(false);
+const inboundSelectVisible = ref(false);
+const inboundTableRef = ref(null);
+const dialogInboundSelection = ref([]);
-const inList = [
- { inCode: "RK2024001", supplierId: 1 },
- { inCode: "RK2024002", supplierId: 2 },
- { inCode: "RK2024003", supplierId: 3 },
-];
+const paymentDialogVisible = ref(false);
+const paymentFormRef = ref(null);
+const paymentSubmitLoading = ref(false);
+
+const paymentForm = reactive({
+ paymentNumber: "",
+ invoiceApplicationNo: "",
+ supplierName: "",
+ supplierId: "",
+ accountPaymentApplicationId: null,
+ paymentDate: "",
+ paymentAmount: 0,
+ paymentMethod: "",
+ bankAccount: "",
+ bankName: "",
+ remark: "",
+});
+
+const paymentRules = {
+ paymentDate: [{ required: true, message: "璇烽�夋嫨浠樻鏃ユ湡", trigger: "change" }],
+ paymentAmount: [{ required: true, message: "璇疯緭鍏ヤ粯娆鹃噾棰�", trigger: "blur" }],
+ paymentMethod: [{ required: true, message: "璇烽�夋嫨浠樻鏂瑰紡", trigger: "change" }],
+};
+
+const STATUS_LABEL_MAP = { 0: "寰呭鏍�", 1: "瀹℃牳閫氳繃", 2: "瀹℃牳涓嶉�氳繃" };
+const STATUS_TYPE_MAP = { 0: "warning", 1: "success", 2: "danger" };
const form = reactive({
- applyCode: "",
+ invoiceApplicationNo: "",
supplierId: "",
- amount: 0,
- paymentMethod: "bank_transfer",
+ paymentAmount: 0,
+ paymentMethod: "",
applyDate: "",
- expectedDate: "",
- relatedDocs: [],
- reason: "",
+ paymentContent: "",
remark: "",
+ stockInRecordIds: [],
+ inboundBatches: "",
+ status: 0,
});
const rules = {
supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
- amount: [{ required: true, message: "璇疯緭鍏ヤ粯娆鹃噾棰�", trigger: "blur" }],
+ stockInRecordIds: [{ required: true, type: "array", min: 1, message: "璇烽�夋嫨鍏宠仈鍏ュ簱鍗�", trigger: "change" }],
+ paymentAmount: [{ required: true, message: "璇疯緭鍏ヤ粯娆鹃噾棰�", trigger: "blur" }],
paymentMethod: [{ required: true, message: "璇烽�夋嫨浠樻鏂瑰紡", trigger: "change" }],
applyDate: [{ required: true, message: "璇烽�夋嫨鐢宠鏃ユ湡", trigger: "change" }],
- expectedDate: [{ required: true, message: "璇烽�夋嫨鏈熸湜浠樻鏃ユ湡", trigger: "change" }],
};
-
-const mockData = [
- { id: 1, applyCode: "FK2024001", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", amount: 5000, paymentMethod: "bank_transfer", applyDate: "2024-01-12", expectedDate: "2024-01-15", status: "pending", relatedDocs: ["RK2024001"], reason: "鏀粯鍘熸潗鏂欒揣娆�", remark: "" },
- { id: 2, applyCode: "FK2024002", supplierId: 2, supplierName: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�", amount: 8000, paymentMethod: "bank_transfer", applyDate: "2024-01-14", expectedDate: "2024-01-18", status: "approved", relatedDocs: ["RK2024002"], reason: "鏀粯鐢靛瓙鍏冨櫒浠惰揣娆�", remark: "" },
- { id: 3, applyCode: "FK2024003", supplierId: 3, supplierName: "骞垮窞鍖呰鏉愭枡鍘�", amount: 3000, paymentMethod: "cash", applyDate: "2024-01-16", expectedDate: "2024-01-20", status: "paid", relatedDocs: ["RK2024003"], reason: "鏀粯鍖呰鏉愭枡璐ф", remark: "" },
-];
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
-const getPaymentMethodLabel = (method) => {
- const map = {
- bank_transfer: "閾惰杞处",
- cash: "鐜伴噾",
- check: "鏀エ",
- draft: "姹囩エ",
+const normalizeStatus = (status) => {
+ if (status === undefined || status === null || status === "") return 0;
+ const num = Number(status);
+ return Number.isNaN(num) ? 0 : num;
+};
+
+const isPendingStatus = (status) => normalizeStatus(status) === 0;
+
+const isApprovedStatus = (status) => normalizeStatus(status) === 1;
+
+const isBankTransferPayment = (method) => {
+ if (method === undefined || method === null || method === "") return false;
+ const item = checkout_payment.value?.find((m) => String(m.value) === String(method));
+ if (item?.label?.includes("閾惰")) return true;
+ return String(method) === "bank_transfer" || String(method).toLowerCase().includes("bank");
+};
+
+const getStatusLabel = (status) => STATUS_LABEL_MAP[normalizeStatus(status)] ?? "寰呭鏍�";
+
+const getStatusType = (status) => STATUS_TYPE_MAP[normalizeStatus(status)] ?? "warning";
+
+const getPaymentMethodLabel = (value) => {
+ if (value === undefined || value === null || value === "") return "-";
+ const item = checkout_payment.value?.find((m) => String(m.value) === String(value));
+ return item?.label ?? value;
+};
+
+const getDefaultPaymentMethod = () => checkout_payment.value?.[0]?.value ?? "";
+
+const parseStockInRecordIds = (value) => {
+ if (!value) return [];
+ if (Array.isArray(value)) return value;
+ return String(value)
+ .split(/[,锛宂/)
+ .map((s) => s.trim())
+ .filter(Boolean)
+ .map((s) => (/^\d+$/.test(s) ? Number(s) : s));
+};
+
+const formatInboundBatches = (value) => {
+ if (value === undefined || value === null || value === "") return "";
+ if (Array.isArray(value)) return value.filter(Boolean).join("銆�");
+ return String(value)
+ .split(/[,锛宂/)
+ .map((s) => s.trim())
+ .filter(Boolean)
+ .join("銆�");
+};
+
+const isSameInboundId = (a, b) => String(a) === String(b);
+
+const getInboundRowId = (row) => row?.id ?? row?.stockInRecordId;
+
+const getInboundRowTaxInclusiveAmount = (row) =>
+ Number(row?.inboundAmount ?? row?.taxInclusivePrice ?? row?.totalAmount ?? row?.amount ?? 0);
+
+const normalizeInboundBatchOptions = (data) => {
+ const list = Array.isArray(data) ? data : [];
+ return list.map((item, index) => {
+ const label =
+ item.inboundBatches ?? item.batchNo ?? item.inboundNo ?? `鍏ュ簱鍗�${index + 1}`;
+ const value = item.id ?? item.stockInRecordId ?? label;
+ return {
+ label: String(label),
+ value,
+ inboundAmount: getInboundRowTaxInclusiveAmount(item),
+ };
+ });
+};
+
+const syncPaymentAmount = () => {
+ const selected = form.stockInRecordIds || [];
+ let sum = inboundBatchOptions.value
+ .filter((opt) => selected.some((id) => isSameInboundId(id, opt.value)))
+ .reduce((acc, opt) => acc + (Number(opt.inboundAmount) || 0), 0);
+
+ if (sum <= 0 && selected.length) {
+ sum = inboundBatchList.value
+ .filter((row) => selected.some((id) => isSameInboundId(id, getInboundRowId(row))))
+ .reduce((acc, row) => acc + getInboundRowTaxInclusiveAmount(row), 0);
+ }
+
+ form.paymentAmount = sum > 0 ? Number(sum.toFixed(2)) : 0;
+};
+
+const inboundBatchDisplayText = computed(() => {
+ if (form.inboundBatches) return form.inboundBatches;
+ const ids = form.stockInRecordIds || [];
+ if (!ids.length) return "";
+ const labels = inboundBatchOptions.value
+ .filter((opt) => ids.some((id) => isSameInboundId(id, opt.value)))
+ .map((opt) => opt.label);
+ if (labels.length) return labels.join("銆�");
+ return ids.join("銆�");
+});
+
+const normalizeTableRow = (row) => ({
+ ...row,
+ applyCode: row.invoiceApplicationNo ?? row.applyCode,
+ amount: row.paymentAmount ?? row.amount,
+ reason: row.paymentContent ?? row.reason,
+ status: normalizeStatus(row.status),
+ stockInRecordIds: row.stockInRecordIds ?? "",
+ inboundBatches: formatInboundBatches(row.inboundBatches),
+});
+
+const fillFormFromRow = (row) => {
+ const stockInRecordIds = parseStockInRecordIds(row.stockInRecordIds);
+ Object.assign(form, {
+ invoiceApplicationNo: row.invoiceApplicationNo ?? row.applyCode ?? "",
+ supplierId: row.supplierId,
+ paymentAmount: Number(row.paymentAmount ?? row.amount ?? 0),
+ paymentMethod: row.paymentMethod ?? getDefaultPaymentMethod(),
+ applyDate: row.applyDate ?? "",
+ paymentContent: row.paymentContent ?? row.reason ?? "",
+ remark: row.remark ?? "",
+ stockInRecordIds,
+ inboundBatches: formatInboundBatches(row.inboundBatches),
+ status: normalizeStatus(row.status),
+ });
+};
+
+const buildPayloadFromRow = (row, statusOverride) => ({
+ id: row.id,
+ supplierId: row.supplierId,
+ stockInRecordIds:
+ typeof row.stockInRecordIds === "string"
+ ? row.stockInRecordIds
+ : (row.stockInRecordIds || []).join(","),
+ invoiceApplicationNo: row.invoiceApplicationNo ?? row.applyCode ?? "",
+ paymentMethod: row.paymentMethod,
+ paymentContent: row.paymentContent ?? row.reason ?? "",
+ applyDate: row.applyDate,
+ remark: row.remark ?? "",
+ status: statusOverride !== undefined ? statusOverride : normalizeStatus(row.status),
+ paymentAmount: Number(row.paymentAmount ?? row.amount ?? 0),
+});
+
+const buildSubmitPayload = (forUpdate = false) => {
+ const payload = {
+ supplierId: form.supplierId,
+ stockInRecordIds: (form.stockInRecordIds || []).join(","),
+ invoiceApplicationNo: form.invoiceApplicationNo || "",
+ paymentMethod: form.paymentMethod,
+ paymentContent: form.paymentContent || "",
+ applyDate: form.applyDate,
+ remark: form.remark || "",
+ status: 0,
+ paymentAmount: form.paymentAmount,
};
- return map[method] || method;
+ if (forUpdate) {
+ payload.id = currentId.value;
+ }
+ return payload;
};
-const getStatusLabel = (status) => {
- const map = { pending: "寰呭鎵�", approved: "宸插鎵�", rejected: "宸查┏鍥�", paid: "宸蹭粯娆�" };
- return map[status] || status;
+const getSupplierList = () => {
+ getOptions().then((res) => {
+ if (res.code === 200) {
+ supplierList.value = res.data ?? [];
+ }
+ });
};
-const getStatusType = (status) => {
- const map = { pending: "warning", approved: "success", rejected: "danger", paid: "primary" };
- return map[status] || "";
+const appendFilterParams = (params) => {
+ if (filters.invoiceApplicationNo) {
+ params.invoiceApplicationNo = filters.invoiceApplicationNo;
+ }
+ if (filters.supplierId) {
+ params.supplierId = filters.supplierId;
+ }
+ if (filters.status !== "" && filters.status != null) {
+ params.status = filters.status;
+ }
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ return params;
+};
+
+const buildListParams = () =>
+ appendFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+const buildExportParams = () => appendFilterParams({});
+
+const handleExport = () => {
+ proxy.download(
+ "/accountPaymentApplication/exportAccountPaymentApplication",
+ buildExportParams(),
+ `浠樻鐢宠_${Date.now()}.xlsx`
+ );
};
const getTableData = () => {
- let result = [...mockData];
- if (filters.applyCode) {
- result = result.filter(item => item.applyCode.includes(filters.applyCode));
- }
- if (filters.supplierId) {
- result = result.filter(item => item.supplierId === filters.supplierId);
- }
- if (filters.status) {
- result = result.filter(item => item.status === filters.status);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ tableLoading.value = true;
+ listPageAccountPaymentApplication(buildListParams())
+ .then((res) => {
+ if (res.code === 200) {
+ dataList.value = (res.data?.records ?? []).map(normalizeTableRow);
+ pagination.total = res.data?.total ?? 0;
+ } else {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
};
-const resetFilters = () => {
- filters.applyCode = "";
- filters.supplierId = "";
- filters.status = "";
+const onSearch = () => {
pagination.currentPage = 1;
getTableData();
};
-const changePage = ({ current, size }) => {
- pagination.currentPage = current;
- pagination.pageSize = size;
+const resetFilters = () => {
+ filters.invoiceApplicationNo = "";
+ filters.supplierId = "";
+ filters.status = "";
+ filters.dateRange = [];
+ pagination.currentPage = 1;
getTableData();
};
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
+const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
+ getTableData();
+};
+
+const closeDialog = () => {
+ dialogVisible.value = false;
+ isView.value = false;
+ isEdit.value = false;
+ inboundSelectVisible.value = false;
+};
+
+const resetForm = () => {
+ Object.assign(form, {
+ invoiceApplicationNo: "",
+ supplierId: "",
+ paymentAmount: 0,
+ paymentMethod: getDefaultPaymentMethod(),
+ applyDate: new Date().toISOString().split("T")[0],
+ paymentContent: "",
+ remark: "",
+ stockInRecordIds: [],
+ inboundBatches: "",
+ status: 0,
+ });
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
};
const add = () => {
isEdit.value = false;
+ isView.value = false;
dialogTitle.value = "鏂板浠樻鐢宠";
- Object.assign(form, {
- applyCode: "FK" + Date.now().toString().slice(-8),
- supplierId: "",
- amount: 0,
- paymentMethod: "bank_transfer",
- applyDate: new Date().toISOString().split('T')[0],
- expectedDate: "",
- relatedDocs: [],
- reason: "",
- remark: "",
- });
+ resetForm();
dialogVisible.value = true;
};
const edit = (row) => {
isEdit.value = true;
+ isView.value = false;
currentId.value = row.id;
dialogTitle.value = "缂栬緫浠樻鐢宠";
- Object.assign(form, row);
+ fillFormFromRow(row);
dialogVisible.value = true;
};
const view = (row) => {
- ElMessage.info(`鏌ョ湅鐢宠鍗�: ${row.applyCode}`);
+ isView.value = true;
+ isEdit.value = false;
+ dialogTitle.value = "鏌ョ湅浠樻鐢宠";
+ fillFormFromRow(row);
+ if (row.supplierId) {
+ loadInboundBatches(row.supplierId, true, false);
+ }
+ dialogVisible.value = true;
+};
+
+const submitAudit = (row, status) => {
+ auditAccountPaymentApplication(buildPayloadFromRow(row, status))
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success(status === 1 ? "瀹℃牳閫氳繃" : "瀹℃牳涓嶉�氳繃");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "瀹℃牳澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("瀹℃牳澶辫触");
+ });
};
const handleAudit = (row) => {
- ElMessageBox.confirm("纭瀹℃壒閫氳繃璇ヤ粯娆剧敵璇峰悧锛�", "鎻愮ず", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃牳缁撴灉", "浠樻鐢宠瀹℃牳", {
+ confirmButtonText: "瀹℃牳閫氳繃",
+ cancelButtonText: "瀹℃牳涓嶉�氳繃",
distinguishCancelAndClose: true,
type: "warning",
- }).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "approved";
- }
- ElMessage.success("瀹℃壒閫氳繃");
- getTableData();
- }).catch((action) => {
- if (action === "cancel") {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "rejected";
+ })
+ .then(() => {
+ submitAudit(row, 1);
+ })
+ .catch((action) => {
+ if (action === "cancel") {
+ submitAudit(row, 2);
}
- ElMessage.warning("宸查┏鍥�");
- getTableData();
- }
+ });
+};
+
+const openPaymentDialog = (row) => {
+ Object.assign(paymentForm, {
+ paymentNumber: "",
+ invoiceApplicationNo: row.invoiceApplicationNo ?? row.applyCode ?? "",
+ supplierName: row.supplierName ?? "",
+ supplierId: row.supplierId,
+ accountPaymentApplicationId: row.id,
+ paymentDate: new Date().toISOString().split("T")[0],
+ paymentAmount: Number(row.paymentAmount ?? row.amount ?? 0),
+ paymentMethod: row.paymentMethod ?? getDefaultPaymentMethod(),
+ bankAccount: row.bankAccountNum ?? row.bankAccount ?? "",
+ bankName: row.bankAccountName ?? row.bankName ?? "",
+ remark: "",
+ });
+ paymentDialogVisible.value = true;
+ nextTick(() => {
+ paymentFormRef.value?.clearValidate();
});
};
-const handleBatchApply = () => {
- ElMessage.success(`鎵归噺鐢宠 ${selectedRows.value.length} 鏉¤褰昤);
+const submitPayment = () => {
+ paymentFormRef.value?.validate((valid) => {
+ if (!valid) return;
+ paymentSubmitLoading.value = true;
+ addAccountPurchasePayment({
+ accountPaymentApplicationId: paymentForm.accountPaymentApplicationId,
+ supplierId: paymentForm.supplierId,
+ paymentDate: paymentForm.paymentDate,
+ paymentMethod: paymentForm.paymentMethod,
+ paymentAmount: paymentForm.paymentAmount,
+ paymentNumber: paymentForm.paymentNumber || "",
+ remark: paymentForm.remark || "",
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("浠樻鎴愬姛");
+ paymentDialogVisible.value = false;
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "浠樻澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("浠樻澶辫触");
+ })
+ .finally(() => {
+ paymentSubmitLoading.value = false;
+ });
+ });
+};
+
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎鐢宠鍗曘��${row.applyCode ?? row.invoiceApplicationNo}銆嶅悧锛焋, "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountPaymentApplication([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
};
const submitForm = () => {
- formRef.value.validate((valid) => {
- if (valid) {
- const supplier = supplierList.find(item => item.id === form.supplierId);
- if (isEdit.value) {
- const index = mockData.findIndex(item => item.id === currentId.value);
- if (index !== -1) {
- mockData[index] = { ...mockData[index], ...form, supplierName: supplier?.name };
+ formRef.value?.validate((valid) => {
+ if (!valid) return;
+ submitLoading.value = true;
+ const request = isEdit.value
+ ? updateAccountPaymentApplication(buildSubmitPayload(true))
+ : addAccountPaymentApplication(buildSubmitPayload(false));
+
+ request
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ closeDialog();
+ pagination.currentPage = 1;
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "淇濆瓨澶辫触");
}
- ElMessage.success("缂栬緫鎴愬姛");
- } else {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- mockData.push({ id: newId, ...form, supplierName: supplier?.name, status: "pending" });
- ElMessage.success("鏂板鎴愬姛");
- }
- dialogVisible.value = false;
- getTableData();
- }
+ })
+ .catch(() => {
+ ElMessage.error("淇濆瓨澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
});
};
+const ensureInboundOptionsForSelected = () => {
+ const ids = form.stockInRecordIds || [];
+ ids.forEach((id) => {
+ const exists = inboundBatchOptions.value.some((opt) => isSameInboundId(opt.value, id));
+ if (exists) return;
+ const fromList = inboundBatchList.value.find((row) => isSameInboundId(getInboundRowId(row), id));
+ if (fromList) {
+ const [option] = normalizeInboundBatchOptions([fromList]);
+ if (option) inboundBatchOptions.value.push(option);
+ return;
+ }
+ inboundBatchOptions.value.push({
+ label: String(id),
+ value: id,
+ inboundAmount: 0,
+ });
+ });
+};
+
+const restoreInboundTableSelection = () => {
+ nextTick(() => {
+ const table = inboundTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ const selectedIds = new Set((form.stockInRecordIds || []).map((id) => String(id)));
+ inboundBatchList.value.forEach((row) => {
+ const rowId = getInboundRowId(row);
+ if (rowId !== undefined && rowId !== null && selectedIds.has(String(rowId))) {
+ table.toggleRowSelection(row, true);
+ }
+ });
+ });
+};
+
+const loadInboundBatches = (supplierId, keepSelected = false, syncAmount = true) => {
+ if (!supplierId) {
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
+ if (!keepSelected) {
+ form.stockInRecordIds = [];
+ form.inboundBatches = "";
+ form.paymentAmount = 0;
+ }
+ return Promise.resolve();
+ }
+ inboundBatchLoading.value = true;
+ return getInboundBatchesBySupplier({ supplierId })
+ .then((res) => {
+ if (res.code === 200) {
+ const list = res.data?.records ?? res.data ?? [];
+ inboundBatchList.value = Array.isArray(list) ? list : [];
+ inboundBatchOptions.value = normalizeInboundBatchOptions(list);
+ } else {
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
+ }
+ })
+ .catch(() => {
+ inboundBatchList.value = [];
+ inboundBatchOptions.value = [];
+ })
+ .finally(() => {
+ inboundBatchLoading.value = false;
+ if (keepSelected) {
+ ensureInboundOptionsForSelected();
+ restoreInboundTableSelection();
+ if (syncAmount && !isView.value) {
+ syncPaymentAmount();
+ }
+ }
+ });
+};
+
+const handleSupplierChange = (supplierId) => {
+ form.stockInRecordIds = [];
+ form.inboundBatches = "";
+ form.paymentAmount = 0;
+ loadInboundBatches(supplierId);
+};
+
+const handleInboundInputClick = () => {
+ if (isEdit.value || isView.value) return;
+ openInboundSelectDialog();
+};
+
+const openInboundSelectDialog = () => {
+ if (!form.supplierId || isEdit.value || isView.value) return;
+ inboundSelectVisible.value = true;
+ loadInboundBatches(form.supplierId, true, false).then(() => {
+ restoreInboundTableSelection();
+ });
+};
+
+const handleInboundDialogSelectionChange = (selection) => {
+ dialogInboundSelection.value = selection;
+};
+
+const confirmInboundSelection = () => {
+ if (dialogInboundSelection.value.length === 0) {
+ ElMessage.warning("璇疯嚦灏戦�夋嫨涓�鏉″叆搴撳崟");
+ return;
+ }
+ form.stockInRecordIds = dialogInboundSelection.value
+ .map((row) => getInboundRowId(row))
+ .filter((id) => id !== undefined && id !== null);
+ form.inboundBatches = dialogInboundSelection.value
+ .map((row) => row.inboundBatches ?? row.batchNo ?? "")
+ .filter(Boolean)
+ .join("銆�");
+ dialogInboundSelection.value.forEach((row) => {
+ const [option] = normalizeInboundBatchOptions([row]);
+ if (option && !inboundBatchOptions.value.some((opt) => isSameInboundId(opt.value, option.value))) {
+ inboundBatchOptions.value.push(option);
+ }
+ });
+ inboundSelectVisible.value = false;
+ syncPaymentAmount();
+ formRef.value?.validateField("stockInRecordIds");
+};
+
+const handleInboundDialogClosed = () => {
+ dialogInboundSelection.value = [];
+};
+
onMounted(() => {
+ getSupplierList();
getTableData();
});
</script>
@@ -357,4 +1009,8 @@
color: #f56c6c;
font-weight: bold;
}
+
+.inbound-batch-input :deep(.el-input__wrapper) {
+ cursor: pointer;
+}
</style>
diff --git a/src/views/financialManagement/payable/purchaseIn.vue b/src/views/financialManagement/payable/purchaseIn.vue
index 4fadcbb..fcb768f 100644
--- a/src/views/financialManagement/payable/purchaseIn.vue
+++ b/src/views/financialManagement/payable/purchaseIn.vue
@@ -1,27 +1,39 @@
<template>
<!-- 閲囪喘鍏ュ簱 -->
<div class="app-container">
- <el-form :model="filters" :inline="true">
+ <el-form :model="filters"
+ :inline="true">
<el-form-item label="鍏ュ簱鍗曞彿:">
- <el-input v-model="filters.inboundBatches" placeholder="璇疯緭鍏ュ叆搴撳崟鍙�" clearable style="width: 200px;" />
+ <el-input v-model="filters.inboundBatches"
+ placeholder="璇疯緭鍏ュ叆搴撳崟鍙�"
+ clearable
+ style="width: 200px;" />
</el-form-item>
<el-form-item label="渚涘簲鍟�:">
- <el-input v-model="filters.supplierName" placeholder="璇疯緭鍏ヤ緵搴斿晢" clearable style="width: 200px;" />
+ <el-select v-model="filters.supplierId"
+ placeholder="璇烽�夋嫨渚涘簲鍟�"
+ clearable
+ filterable
+ style="width: 200px;">
+ <el-option v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id" />
+ </el-select>
</el-form-item>
<el-form-item label="鍏ュ簱鏃ユ湡:">
- <el-date-picker
- v-model="filters.dateRange"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- clearable
- />
+ <el-date-picker v-model="filters.dateRange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="onSearch">鎼滅储</el-button>
+ <el-button type="primary"
+ @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -29,23 +41,22 @@
<div class="actions">
<div></div>
<div>
- <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+ <el-button @click="handleOut"
+ icon="Download">瀵煎嚭</el-button>
</div>
</div>
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableData="dataList"
- :tableLoading="tableLoading"
- :page="{
+ <PIMTable rowKey="id"
+ :column="columns"
+ :tableData="dataList"
+ :tableLoading="tableLoading"
+ :page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @pagination="changePage"
- >
+ @pagination="changePage">
<template #inboundDate="{ row }">
- {{ row.InboundDate || row.inboundDate || "" }}
+ {{ row.inboundDate ?? row.InboundDate ?? "" }}
</template>
</PIMTable>
</div>
@@ -53,119 +64,149 @@
</template>
<script setup>
-import { ref, reactive, onMounted, getCurrentInstance } from "vue";
-import { ElMessage } from "element-plus";
-import { listPageAccountPurchase } from "@/api/financialManagement/accountPurchase";
+ import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage } from "element-plus";
+ import { listPageAccountPurchase } from "@/api/financialManagement/accountPurchase";
+ import { listSupplier } from "@/api/basicData/supplierManageFile.js";
-defineOptions({
- name: "閲囪喘鍏ュ簱",
-});
+ defineOptions({
+ name: "閲囪喘鍏ュ簱",
+ });
-const { proxy } = getCurrentInstance();
+ const { proxy } = getCurrentInstance();
-const filters = reactive({
- inboundBatches: "",
- supplierName: "",
- dateRange: [],
-});
+ const filters = reactive({
+ inboundBatches: "",
+ supplierId: "",
+ dateRange: [],
+ });
-const pagination = reactive({
- currentPage: 1,
- pageSize: 10,
- total: 0,
-});
+ const pagination = reactive({
+ currentPage: 1,
+ pageSize: 10,
+ total: 0,
+ });
-const columns = [
- { label: "鍏ュ簱鍗曞彿", prop: "inboundBatches", minWidth: "150" },
- { label: "渚涘簲鍟�", prop: "supplierName", minWidth: "180" },
- {
- label: "鍏ュ簱鏃ユ湡",
- prop: "InboundDate",
- minWidth: "170",
- dataType: "slot",
- slot: "inboundDate",
- },
- { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
- { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
- { label: "閲囪喘璁㈠崟鍙�", prop: "purchaseContractNumber", minWidth: "150" },
-];
+ const columns = [
+ { label: "鍏ュ簱鍗曞彿", prop: "inboundBatches", minWidth: "150" },
+ { label: "渚涘簲鍟�", prop: "supplierName", minWidth: "180" },
+ {
+ label: "鍏ュ簱鏃ユ湡",
+ prop: "inboundDate",
+ minWidth: "170",
+ dataType: "slot",
+ slot: "inboundDate",
+ },
+ { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
+ { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
+ {
+ label: "閲戦",
+ prop: "inboundAmount",
+ minWidth: "120",
+ align: "right",
+ formatData: val =>
+ val === null || val === undefined || val === ""
+ ? ""
+ : Number(val).toLocaleString("zh-CN", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ }),
+ },
+ { label: "閲囪喘璁㈠崟鍙�", prop: "purchaseContractNumber", minWidth: "150" },
+ ];
-const dataList = ref([]);
-const tableLoading = ref(false);
+ const dataList = ref([]);
+ const tableLoading = ref(false);
+ const supplierList = ref([]);
-function buildFilterParams() {
- const params = {
- inboundBatches: filters.inboundBatches || undefined,
- supplierName: filters.supplierName || undefined,
+ const buildFilterParams = () => {
+ const params = {};
+ if (filters.inboundBatches) {
+ params.inboundBatches = filters.inboundBatches;
+ }
+ if (filters.supplierId) {
+ params.supplierId = filters.supplierId;
+ }
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ return params;
};
- if (filters.dateRange && filters.dateRange.length === 2) {
- params.startDate = filters.dateRange[0];
- params.endDate = filters.dateRange[1];
- }
- return params;
-}
-const onSearch = () => {
- pagination.currentPage = 1;
- getTableData();
-};
-
-const getTableData = () => {
- tableLoading.value = true;
- listPageAccountPurchase({
- ...buildFilterParams(),
- current: pagination.currentPage,
- size: pagination.pageSize,
- })
- .then((res) => {
- const ok = res.code === 200 || res.code === 0;
- if (ok && res.data) {
- pagination.total = res.data.total ?? 0;
- dataList.value = res.data.records ?? [];
- } else {
- ElMessage.error(res.msg || "鏌ヨ澶辫触");
- dataList.value = [];
+ const getSupplierList = () => {
+ listSupplier({ current: -1, size: -1, isWhite: 0 }).then(res => {
+ if (res.code === 200) {
+ supplierList.value = res.data?.records ?? [];
}
- })
- .catch(() => {
- dataList.value = [];
- })
- .finally(() => {
- tableLoading.value = false;
});
-};
+ };
-const resetFilters = () => {
- filters.inboundBatches = "";
- filters.supplierName = "";
- filters.dateRange = [];
- pagination.currentPage = 1;
- getTableData();
-};
+ const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
+ };
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- getTableData();
-};
+ const getTableData = () => {
+ tableLoading.value = true;
+ listPageAccountPurchase({
+ ...buildFilterParams(),
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ })
+ .then(res => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = res.data.records ?? [];
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ pagination.total = 0;
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
-const handleOut = () => {
- proxy.download(
- "/accountPurchase/exportAccountPurchaseInbound",
- buildFilterParams(),
- `閲囪喘鍏ュ簱_${new Date().getTime()}.xlsx`
- );
-};
+ const resetFilters = () => {
+ filters.inboundBatches = "";
+ filters.supplierId = "";
+ filters.dateRange = [];
+ pagination.currentPage = 1;
+ getTableData();
+ };
-onMounted(() => {
- getTableData();
-});
+ const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
+ getTableData();
+ };
+
+ const handleOut = () => {
+ proxy.download(
+ "/accountPurchase/exportAccountPurchaseInbound",
+ buildFilterParams(),
+ `閲囪喘鍏ュ簱_${Date.now()}.xlsx`
+ );
+ };
+
+ onMounted(() => {
+ getSupplierList();
+ getTableData();
+ });
</script>
<style lang="scss" scoped>
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 15px;
-}
+ .actions {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 15px;
+ }
</style>
diff --git a/src/views/financialManagement/payable/purchaseReturn.vue b/src/views/financialManagement/payable/purchaseReturn.vue
index e7ca665..eeec383 100644
--- a/src/views/financialManagement/payable/purchaseReturn.vue
+++ b/src/views/financialManagement/payable/purchaseReturn.vue
@@ -1,26 +1,20 @@
<template>
<!-- 閲囪喘閫�璐� -->
-
<div class="app-container">
<el-form :model="filters" :inline="true">
<el-form-item label="閫�璐у崟鍙�:">
- <el-input
- v-model="filters.returnNo"
- placeholder="璇疯緭鍏ラ��璐у崟鍙�"
- clearable
- style="width: 200px"
- />
+ <el-input v-model="filters.returnNo" placeholder="璇疯緭鍏ラ��璐у崟鍙�" clearable style="width: 200px;" />
</el-form-item>
-
<el-form-item label="渚涘簲鍟�:">
- <el-input
- v-model="filters.supplierName"
- placeholder="璇疯緭鍏ヤ緵搴斿晢"
- clearable
- style="width: 200px"
- />
+ <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable filterable style="width: 200px;">
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
+ </el-select>
</el-form-item>
-
<el-form-item label="閫�璐ф棩鏈�:">
<el-date-picker
v-model="filters.dateRange"
@@ -33,23 +27,18 @@
clearable
/>
</el-form-item>
-
<el-form-item>
<el-button type="primary" @click="onSearch">鎼滅储</el-button>
-
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
-
<div class="table_list">
<div class="actions">
<div></div>
-
<div>
<el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
</div>
</div>
-
<PIMTable
rowKey="id"
:column="columns"
@@ -57,9 +46,7 @@
:tableLoading="tableLoading"
:page="{
current: pagination.currentPage,
-
size: pagination.pageSize,
-
total: pagination.total,
}"
@pagination="changePage"
@@ -68,14 +55,11 @@
</div>
</template>
-
-
<script setup>
import { ref, reactive, onMounted, getCurrentInstance } from "vue";
-
import { ElMessage } from "element-plus";
-
import { listPageAccountPurchaseReturn } from "@/api/financialManagement/accountPurchase";
+import { listSupplier } from "@/api/basicData/supplierManageFile.js";
defineOptions({
name: "閲囪喘閫�璐�",
@@ -85,38 +69,26 @@
const filters = reactive({
returnNo: "",
-
- supplierName: "",
-
+ supplierId: "",
dateRange: [],
});
const pagination = reactive({
currentPage: 1,
-
pageSize: 10,
-
total: 0,
});
const columns = [
{ label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: "150" },
-
{ label: "渚涘簲鍟�", prop: "supplierName", minWidth: "180" },
-
{ label: "鍏宠仈鍏ュ簱鍗曞彿", prop: "inboundBatches", minWidth: "150" },
-
{ label: "閫�璐ф棩鏈�", prop: "preparedAt", minWidth: "170" },
-
{
label: "閫�娆炬�婚",
-
prop: "totalAmount",
-
minWidth: "150",
-
align: "right",
-
formatData: (val) =>
val === null || val === undefined || val === ""
? ""
@@ -125,66 +97,65 @@
maximumFractionDigits: 2,
}),
},
-
{ label: "閫�璐ф柟寮�", prop: "returnType", minWidth: "150" },
-
{ label: "閲囪喘璁㈠崟鍙�", prop: "purchaseContractNumber", minWidth: "150" },
];
const dataList = ref([]);
-
const tableLoading = ref(false);
+const supplierList = ref([]);
-function buildFilterParams() {
- const params = {
- returnNo: filters.returnNo || undefined,
-
- supplierName: filters.supplierName || undefined,
- };
-
- if (filters.dateRange && filters.dateRange.length === 2) {
+const buildFilterParams = () => {
+ const params = {};
+ if (filters.returnNo) {
+ params.returnNo = filters.returnNo;
+ }
+ if (filters.supplierId) {
+ params.supplierId = filters.supplierId;
+ }
+ if (filters.dateRange?.length === 2) {
params.startDate = filters.dateRange[0];
-
params.endDate = filters.dateRange[1];
}
-
return params;
-}
+};
+
+const getSupplierList = () => {
+ listSupplier({ current: -1, size: -1, isWhite: 0 }).then((res) => {
+ if (res.code === 200) {
+ supplierList.value = res.data?.records ?? [];
+ }
+ });
+};
const onSearch = () => {
pagination.currentPage = 1;
-
getTableData();
};
const getTableData = () => {
tableLoading.value = true;
-
listPageAccountPurchaseReturn({
...buildFilterParams(),
-
current: pagination.currentPage,
-
size: pagination.pageSize,
})
.then((res) => {
const ok = res.code === 200 || res.code === 0;
-
if (ok && res.data) {
pagination.total = res.data.total ?? 0;
-
dataList.value = res.data.records ?? [];
} else {
ElMessage.error(res.msg || "鏌ヨ澶辫触");
-
dataList.value = [];
+ pagination.total = 0;
}
})
-
.catch(() => {
dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
})
-
.finally(() => {
tableLoading.value = false;
});
@@ -192,48 +163,36 @@
const resetFilters = () => {
filters.returnNo = "";
-
- filters.supplierName = "";
-
+ filters.supplierId = "";
filters.dateRange = [];
-
pagination.currentPage = 1;
-
getTableData();
};
const changePage = ({ page, limit }) => {
pagination.currentPage = page;
-
pagination.pageSize = limit;
-
getTableData();
};
const handleOut = () => {
proxy.download(
"/accountPurchase/exportAccountPurchaseReturn",
-
buildFilterParams(),
-
- `閲囪喘閫�璐${new Date().getTime()}.xlsx`
+ `閲囪喘閫�璐${Date.now()}.xlsx`
);
};
onMounted(() => {
+ getSupplierList();
getTableData();
});
</script>
-
-
<style lang="scss" scoped>
.actions {
display: flex;
-
justify-content: space-between;
-
margin-bottom: 15px;
}
</style>
-
diff --git a/src/views/financialManagement/payable/reconciliation.vue b/src/views/financialManagement/payable/reconciliation.vue
index 3aa23cd..e749e56 100644
--- a/src/views/financialManagement/payable/reconciliation.vue
+++ b/src/views/financialManagement/payable/reconciliation.vue
@@ -2,8 +2,13 @@
<div class="app-container">
<el-form :model="filters" :inline="true">
<el-form-item label="渚涘簲鍟�:">
- <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px;">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable filterable style="width: 200px;">
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
<el-form-item label="瀵硅处鏈熼棿:">
@@ -12,7 +17,7 @@
<el-date-picker v-model="filters.endMonth" type="month" placeholder="缁撴潫鏈堜唤" value-format="YYYY-MM" style="width: 140px;" />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary" @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -29,6 +34,7 @@
rowKey="id"
:column="columns"
:tableData="dataList"
+ :tableLoading="tableLoading"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -36,21 +42,21 @@
}"
@pagination="changePage"
>
- <template #beginBalance="{ row }">
- <span :class="row.beginBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.beginBalance) }}</span>
+ <template #openingBalance="{ row }">
+ <span :class="row.openingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.openingBalance) }}</span>
</template>
- <template #currentPayable="{ row }">
- <span class="text-danger">楼{{ formatMoney(row.currentPayable) }}</span>
+ <template #currentPlan="{ row }">
+ <span class="text-danger">楼{{ formatMoney(row.currentPlan) }}</span>
</template>
- <template #currentPayment="{ row }">
- <span class="text-success">楼{{ formatMoney(row.currentPayment) }}</span>
+ <template #currentActually="{ row }">
+ <span class="text-success">楼{{ formatMoney(row.currentActually) }}</span>
</template>
- <template #endBalance="{ row }">
- <span :class="row.endBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.endBalance) }}</span>
+ <template #closingBalance="{ row }">
+ <span :class="row.closingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.closingBalance) }}</span>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="viewDetail(row)">鏌ョ湅鏄庣粏</el-button>
- <el-button type="primary" link @click="printStatement(row)">鎵撳嵃</el-button>
+ <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
@@ -60,7 +66,7 @@
<h3>{{ currentSupplier }} 搴斾粯瀵硅处鍗�</h3>
<p>瀵硅处鏈熼棿: {{ currentPeriod }}</p>
</div>
- <el-table :data="detailData" border style="width: 100%">
+ <el-table :data="detailData" border style="width: 100%" v-loading="detailLoading">
<el-table-column prop="date" label="鏃ユ湡" width="120" />
<el-table-column prop="type" label="绫诲瀷" width="100">
<template #default="{ row }">
@@ -77,6 +83,7 @@
<el-table-column prop="credit" label="璐锋柟(搴斾粯)" width="120">
<template #default="{ row }">
<span v-if="row.credit > 0" class="text-danger">楼{{ formatMoney(row.credit) }}</span>
+ <span v-else-if="row.credit < 0" class="text-success">楼{{ formatMoney(Math.abs(row.credit)) }}</span>
<span v-else>-</span>
</template>
</el-table-column>
@@ -98,52 +105,80 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="閫夋嫨渚涘簲鍟�" prop="supplierId">
- <el-select v-model="generateForm.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%;" @change="onSupplierChange">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select
+ v-model="generateForm.supplierId"
+ placeholder="璇烽�夋嫨渚涘簲鍟�"
+ style="width: 100%;"
+ filterable
+ @change="onSupplierChange"
+ >
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="瀵硅处鏈堜唤" prop="period">
- <el-date-picker v-model="generateForm.period" type="month" placeholder="閫夋嫨鏈堜唤" value-format="YYYY-MM" style="width: 100%;" @change="onPeriodChange" />
+ <el-form-item label="瀵硅处鏈堜唤" prop="statementMonth">
+ <el-date-picker
+ v-model="generateForm.statementMonth"
+ type="month"
+ placeholder="閫夋嫨鏈堜唤"
+ value-format="YYYY-MM"
+ style="width: 100%;"
+ @change="onStatementMonthChange"
+ />
</el-form-item>
</el-col>
</el-row>
</el-form>
- <div v-if="purchaseData.length > 0" class="purchase-section">
- <div class="section-title">鏈湀閲囪喘鏁版嵁</div>
- <el-table :data="purchaseData" border style="width: 100%; margin-bottom: 15px;" v-loading="purchaseLoading" @selection-change="handlePurchaseSelectionChange">
+ <div v-if="statementDetailLoaded" class="purchase-section">
+ <div v-if="purchaseData.length > 0" class="section-title">鏈湀閲囪喘鏁版嵁</div>
+ <el-table
+ v-if="purchaseData.length > 0"
+ ref="purchaseTableRef"
+ :data="purchaseData"
+ border
+ row-key="id"
+ style="width: 100%; margin-bottom: 15px;"
+ v-loading="purchaseLoading"
+ @selection-change="handlePurchaseSelectionChange"
+ >
<el-table-column type="selection" width="55" align="center" />
- <el-table-column prop="date" label="鏃ユ湡" width="120" />
- <el-table-column prop="code" label="鍗曟嵁缂栧彿" width="150" />
+ <el-table-column prop="occurrenceDate" label="鏃ユ湡" width="120" />
+ <el-table-column prop="receiptNumber" label="鍗曟嵁缂栧彿" width="150" />
<el-table-column prop="type" label="绫诲瀷" width="100">
<template #default="{ row }">
- <el-tag :type="row.type === '鍏ュ簱' ? 'success' : 'danger'">{{ row.type }}</el-tag>
+ <el-tag :type="getDetailTypeTagType(row.type)">{{ row.typeLabel }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="amount" label="閲戦" width="120">
<template #default="{ row }">
- <span :class="row.type === '鍏ュ簱' ? 'text-danger' : 'text-success'">楼{{ formatMoney(row.amount) }}</span>
+ <span :class="getDetailAmountClass(row.type)">楼{{ formatMoney(row.amount) }}</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="澶囨敞" />
</el-table>
+ <el-empty v-else description="璇ヤ緵搴斿晢鏈湀鏆傛棤鏄庣粏鏁版嵁" :image-size="80" />
<div class="summary-row">
- <span>鏈熷垵浣欓: <strong class="text-primary">楼{{ formatMoney(generateForm.beginBalance) }}</strong></span>
- <span>鏈湡搴斾粯: <strong class="text-danger">楼{{ formatMoney(generateForm.currentPayable) }}</strong></span>
- <span>鏈湡浠樻: <strong class="text-success">楼{{ formatMoney(generateForm.currentPayment) }}</strong></span>
- <span>鏈熸湯浣欓: <strong class="text-primary">楼{{ formatMoney(calculateEndBalance(generateForm.beginBalance, generateForm.currentPayable, generateForm.currentPayment)) }}</strong></span>
+ <span>鏈熷垵浣欓: <strong class="text-primary">楼{{ formatMoney(generateForm.openingBalance) }}</strong></span>
+ <span>鏈湡搴斾粯: <strong class="text-danger">楼{{ formatMoney(generateForm.currentPlan) }}</strong></span>
+ <span>鏈湡浠樻: <strong class="text-success">楼{{ formatMoney(generateForm.currentActually) }}</strong></span>
+ <span>鏈熸湯浣欓: <strong :class="displayClosingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(displayClosingBalance) }}</strong></span>
</div>
</div>
- <div v-else-if="generateForm.supplierId && !purchaseLoading" class="empty-tip">
+ <div v-else-if="generateForm.supplierId && generateForm.statementMonth && !purchaseLoading" class="empty-tip">
<el-empty description="璇ヤ緵搴斿晢鏈湀鏆傛棤閲囪喘鏁版嵁" />
</div>
<template #footer>
- <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate">纭鐢熸垚</el-button>
+ <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate" :loading="submitLoading">纭鐢熸垚</el-button>
<el-button @click="generateDialogVisible = false">鍙栨秷</el-button>
</template>
</FormDialog>
@@ -151,9 +186,20 @@
</template>
<script setup>
-import { ref, reactive, onMounted, computed } from "vue";
-import { ElMessage } from "element-plus";
+import { ref, reactive, onMounted, computed, nextTick, getCurrentInstance } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
+import {
+ getAccountStatementDetailsByMonth,
+ addAccountStatement,
+ listPageAccountStatement,
+ deleteAccountStatement,
+} from "@/api/financialManagement/accountStatement.js";
+
+const ACCOUNT_TYPE_PAYABLE = 2;
+
+const { proxy } = getCurrentInstance();
defineOptions({
name: "搴斾粯瀵硅处",
@@ -172,56 +218,192 @@
});
const columns = [
- { label: "瀵硅处鍗曞彿", prop: "statementCode", width: "150" },
+ { label: "瀵硅处鍗曞彿", prop: "statementNumber", width: "150" },
{ label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
- { label: "瀵硅处鏈熼棿", prop: "period", width: "150" },
- { label: "鏈熷垵浣欓", prop: "beginBalance", slot: "beginBalance" },
- { label: "鏈湡搴斾粯", prop: "currentPayable", slot: "currentPayable" },
- { label: "鏈湡浠樻", prop: "currentPayment", slot: "currentPayment" },
- { label: "鏈熸湯浣欓", prop: "endBalance", slot: "endBalance" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "150", fixed: "right" },
+ { label: "瀵硅处鏈熼棿", prop: "statementMonth", width: "150" },
+ { label: "鏈熷垵浣欓", prop: "openingBalance", dataType: "slot", slot: "openingBalance" },
+ { label: "鏈湡搴斾粯", prop: "currentPlan", dataType: "slot", slot: "currentPlan" },
+ { label: "鏈湡浠樻", prop: "currentActually", dataType: "slot", slot: "currentActually" },
+ { label: "鏈熸湯浣欓", prop: "closingBalance", dataType: "slot", slot: "closingBalance" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "200", fixed: "right" },
];
const dataList = ref([]);
+const tableLoading = ref(false);
+const submitLoading = ref(false);
const detailDialogVisible = ref(false);
const currentSupplier = ref("");
const currentPeriod = ref("");
const detailData = ref([]);
+const detailLoading = ref(false);
const generateDialogVisible = ref(false);
const purchaseLoading = ref(false);
+const statementDetailLoaded = ref(false);
const purchaseData = ref([]);
const selectedPurchases = ref([]);
+const purchaseTableRef = ref(null);
+const supplierList = ref([]);
+
+/** 鏄庣粏 type锛�1鍑哄簱 2鍏ュ簱 3鏀舵 4浠樻 5閫�璐� */
+const STATEMENT_DETAIL_TYPE_MAP = {
+ 1: "鍑哄簱",
+ 2: "鍏ュ簱",
+ 3: "鏀舵",
+ 4: "浠樻",
+ 5: "閫�璐�",
+};
+
+const calculateEndBalance = (openingBalance, currentPlan, currentActually) => {
+ return openingBalance + currentPlan - currentActually;
+};
+
+const getDetailTypeLabel = (type) => STATEMENT_DETAIL_TYPE_MAP[Number(type)] ?? "";
+
+const getDetailTypeTagType = (type) => {
+ const t = Number(type);
+ if (t === 2) return "success";
+ if (t === 4) return "primary";
+ if (t === 5) return "danger";
+ return "info";
+};
+
+const getDetailAmountClass = (type) => {
+ const t = Number(type);
+ if (t === 2) return "text-danger";
+ if (t === 4) return "text-success";
+ return "text-danger";
+};
const generateForm = reactive({
supplierId: "",
supplierName: "",
- period: "",
- beginBalance: 0,
- currentPayable: 0,
- currentPayment: 0,
+ statementMonth: "",
+ openingBalance: 0,
+ currentPlan: 0,
+ currentActually: 0,
+ closingBalance: 0,
});
-const canGenerate = computed(() => {
- return generateForm.supplierId && generateForm.period && selectedPurchases.value.length > 0;
-});
+const displayClosingBalance = computed(() =>
+ calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ )
+);
-const supplierList = [
- { id: 1, name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
- { id: 2, name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
- { id: 3, name: "骞垮窞鍖呰鏉愭枡鍘�" },
- { id: 4, name: "娣卞湷浜旈噾閰嶄欢鍏徃" },
-];
+const canGenerate = computed(
+ () => generateForm.supplierId && generateForm.statementMonth && selectedPurchases.value.length > 0
+);
-const mockData = [
- { id: 1, statementCode: "DZ202401001", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", period: "2024-01", beginBalance: 20000, currentPayable: 15000, currentPayment: 10000, endBalance: 25000 },
- { id: 2, statementCode: "DZ202401002", supplierId: 2, supplierName: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�", period: "2024-01", beginBalance: 10000, currentPayable: 20000, currentPayment: 15000, endBalance: 15000 },
- { id: 3, statementCode: "DZ202402001", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", period: "2024-02", beginBalance: 25000, currentPayable: 18000, currentPayment: 20000, endBalance: 23000 },
-];
-
-const calculateEndBalance = (beginBalance, currentPayable, currentPayment) => {
- return beginBalance + currentPayable - currentPayment;
+const applyStatementSummary = (data) => {
+ generateForm.openingBalance = Number(data.openingBalance ?? 0);
+ generateForm.currentPlan = Number(data.currentPlan ?? 0);
+ generateForm.currentActually = Number(data.currentActually ?? 0);
+ generateForm.closingBalance = Number(
+ data.closingBalance ??
+ calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ )
+ );
};
+
+const getSupplierList = () => {
+ getOptions().then((res) => {
+ if (res.code === 200) {
+ supplierList.value = res.data ?? [];
+ }
+ });
+};
+
+const normalizePurchaseRows = (list) => {
+ const rows = Array.isArray(list) ? list : [];
+ return rows.map((item, index) => {
+ const type = Number(item.type);
+ return {
+ id: item.id ?? `detail-${index}`,
+ accountStatementId: item.accountStatementId,
+ occurrenceDate: item.occurrenceDate ?? "",
+ receiptNumber: item.receiptNumber ?? "",
+ type,
+ typeLabel: getDetailTypeLabel(type),
+ amount: Math.abs(Number(item.amount ?? 0)),
+ remark: item.remark ?? "",
+ };
+ });
+};
+
+const selectAllPurchaseRows = (keepApiSummary = false) => {
+ nextTick(() => {
+ const table = purchaseTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ purchaseData.value.forEach((row) => table.toggleRowSelection(row, true));
+ selectedPurchases.value = [...purchaseData.value];
+ if (!keepApiSummary) {
+ calculateSummary();
+ }
+ });
+};
+
+const isNumericId = (id) => id !== undefined && id !== null && id !== "" && /^\d+$/.test(String(id));
+
+const buildFilterParams = (params = {}) => {
+ const result = { ...params, accountType: ACCOUNT_TYPE_PAYABLE };
+ if (filters.supplierId) {
+ result.customerId = filters.supplierId;
+ }
+ if (filters.startMonth && filters.endMonth && filters.startMonth === filters.endMonth) {
+ result.statementMonth = filters.startMonth;
+ } else if (filters.startMonth) {
+ result.startMonth = filters.startMonth;
+ }
+ if (filters.endMonth && filters.startMonth !== filters.endMonth) {
+ result.endMonth = filters.endMonth;
+ }
+ return result;
+};
+
+const buildListParams = () =>
+ buildFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+const buildExportParams = () => buildFilterParams({});
+
+const buildDetailSubmitItem = (row) => {
+ const item = {
+ occurrenceDate: row.occurrenceDate,
+ receiptNumber: row.receiptNumber,
+ type: row.type,
+ amount: row.amount,
+ remark: row.remark ?? "",
+ };
+ if (isNumericId(row.id)) {
+ item.id = Number(row.id);
+ }
+ if (row.accountStatementId) {
+ item.accountStatementId = row.accountStatementId;
+ }
+ return item;
+};
+
+const buildAddPayload = () => ({
+ customerId: generateForm.supplierId,
+ customerName: generateForm.supplierName,
+ statementMonth: generateForm.statementMonth,
+ accountType: ACCOUNT_TYPE_PAYABLE,
+ statementNumber: "",
+ openingBalance: generateForm.openingBalance,
+ currentPlan: generateForm.currentPlan,
+ currentActually: generateForm.currentActually,
+ closingBalance: generateForm.closingBalance,
+ accountStatementDetails: selectedPurchases.value.map(buildDetailSubmitItem),
+});
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
@@ -229,15 +411,35 @@
};
const getTableData = () => {
- let result = [...mockData];
- if (filters.supplierId) {
- result = result.filter(item => item.supplierId === filters.supplierId);
- }
- if (filters.startMonth && filters.endMonth) {
- result = result.filter(item => item.period >= filters.startMonth && item.period <= filters.endMonth);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ tableLoading.value = true;
+ listPageAccountStatement(buildListParams())
+ .then((res) => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = (res.data.records ?? []).map((row) => ({
+ ...row,
+ supplierName: row.supplierName ?? row.customerName,
+ }));
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ pagination.total = 0;
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+};
+
+const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
};
const resetFilters = () => {
@@ -248,92 +450,106 @@
getTableData();
};
-const changePage = ({ current, size }) => {
- pagination.currentPage = current;
- pagination.pageSize = size;
+const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
getTableData();
};
const generateStatement = () => {
generateForm.supplierId = "";
generateForm.supplierName = "";
- generateForm.period = "";
- generateForm.beginBalance = 0;
- generateForm.currentPayable = 0;
- generateForm.currentPayment = 0;
+ generateForm.statementMonth = "";
+ generateForm.openingBalance = 0;
+ generateForm.currentPlan = 0;
+ generateForm.currentActually = 0;
+ generateForm.closingBalance = 0;
+ statementDetailLoaded.value = false;
purchaseData.value = [];
selectedPurchases.value = [];
generateDialogVisible.value = true;
};
const onSupplierChange = (supplierId) => {
- const supplier = supplierList.find(item => item.id === supplierId);
- if (supplier) {
- generateForm.supplierName = supplier.name;
- }
+ const supplier = supplierList.value.find((item) => item.id === supplierId);
+ generateForm.supplierName = supplier?.supplierName ?? "";
loadPurchaseData();
};
-const onPeriodChange = () => {
+const onStatementMonthChange = () => {
loadPurchaseData();
};
const loadPurchaseData = () => {
- if (!generateForm.supplierId || !generateForm.period) {
+ if (!generateForm.supplierId || !generateForm.statementMonth) {
purchaseData.value = [];
+ selectedPurchases.value = [];
+ statementDetailLoaded.value = false;
+ generateForm.openingBalance = 0;
+ generateForm.currentPlan = 0;
+ generateForm.currentActually = 0;
+ generateForm.closingBalance = 0;
return;
}
purchaseLoading.value = true;
+ selectedPurchases.value = [];
+ statementDetailLoaded.value = false;
- setTimeout(() => {
- const mockPurchaseData = [
- { id: 1, date: generateForm.period + "-05", code: "RK2024001", type: "鍏ュ簱", amount: 8000, remark: "鍘熸潗鏂欓噰璐�" },
- { id: 2, date: generateForm.period + "-10", code: "FK2024001", type: "浠樻", amount: 5000, remark: "鏀粯璐ф" },
- { id: 3, date: generateForm.period + "-15", code: "RK2024002", type: "鍏ュ簱", amount: 12000, remark: "鐢靛瓙鍏冨櫒浠�" },
- { id: 4, date: generateForm.period + "-18", code: "TH2024001", type: "閫�璐�", amount: 2000, remark: "璐ㄩ噺闂閫�璐�" },
- { id: 5, date: generateForm.period + "-22", code: "RK2024003", type: "鍏ュ簱", amount: 6000, remark: "鍖呰鏉愭枡" },
- { id: 6, date: generateForm.period + "-25", code: "FK2024002", type: "浠樻", amount: 8000, remark: "鏀粯璐ф" },
- ];
+ getAccountStatementDetailsByMonth({
+ accountType: ACCOUNT_TYPE_PAYABLE,
+ customerId: generateForm.supplierId,
+ statementMonth: generateForm.statementMonth,
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ const data = res.data ?? {};
+ const details = data.accountStatementDetails;
+ const list = Array.isArray(details) ? details : [];
+ purchaseData.value = normalizePurchaseRows(list);
+ applyStatementSummary(data);
+ statementDetailLoaded.value = true;
- purchaseData.value = mockPurchaseData;
-
- const lastPeriod = getLastPeriod(generateForm.period);
- const lastStatement = mockData.find(item =>
- item.supplierId === generateForm.supplierId && item.period === lastPeriod
- );
- generateForm.beginBalance = lastStatement ? lastStatement.endBalance : 0;
-
- calculateSummary();
-
- purchaseLoading.value = false;
- }, 500);
-};
-
-const getLastPeriod = (period) => {
- const [year, month] = period.split("-").map(Number);
- if (month === 1) {
- return `${year - 1}-12`;
- }
- return `${year}-${String(month - 1).padStart(2, "0")}`;
+ if (purchaseData.value.length > 0) {
+ selectAllPurchaseRows(true);
+ }
+ } else {
+ purchaseData.value = [];
+ statementDetailLoaded.value = false;
+ ElMessage.error(res.msg || "鏌ヨ瀵硅处鏄庣粏澶辫触");
+ }
+ })
+ .catch(() => {
+ purchaseData.value = [];
+ statementDetailLoaded.value = false;
+ ElMessage.error("鏌ヨ瀵硅处鏄庣粏澶辫触");
+ })
+ .finally(() => {
+ purchaseLoading.value = false;
+ });
};
const calculateSummary = () => {
let payable = 0;
let payment = 0;
- selectedPurchases.value.forEach(item => {
- if (item.type === "鍏ュ簱") {
+ selectedPurchases.value.forEach((item) => {
+ if (item.type === 2) {
payable += item.amount;
- } else if (item.type === "閫�璐�") {
+ } else if (item.type === 5) {
payable -= item.amount;
- } else if (item.type === "浠樻") {
+ } else if (item.type === 4) {
payment += item.amount;
}
});
- generateForm.currentPayable = payable;
- generateForm.currentPayment = payment;
+ generateForm.currentPlan = payable;
+ generateForm.currentActually = payment;
+ generateForm.closingBalance = calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ );
};
const handlePurchaseSelectionChange = (selection) => {
@@ -342,51 +558,127 @@
};
const confirmGenerate = () => {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- const endBalance = calculateEndBalance(generateForm.beginBalance, generateForm.currentPayable, generateForm.currentPayment);
+ if (!canGenerate.value) return;
+ submitLoading.value = true;
+ addAccountStatement(buildAddPayload())
+ .then((res) => {
+ if (res.code === 200) {
+ generateDialogVisible.value = false;
+ ElMessage.success("瀵硅处鍗曠敓鎴愭垚鍔�");
+ pagination.currentPage = 1;
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鐢熸垚澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鐢熸垚澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
+};
- mockData.unshift({
- id: newId,
- statementCode: "DZ" + Date.now(),
- supplierId: generateForm.supplierId,
- supplierName: generateForm.supplierName,
- period: generateForm.period,
- beginBalance: generateForm.beginBalance,
- currentPayable: generateForm.currentPayable,
- currentPayment: generateForm.currentPayment,
- endBalance,
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎瀵硅处鍗曘��${row.statementNumber || row.id}銆嶅悧锛焋, "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountStatement([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+};
+
+const buildDetailTableFromApi = (data, statementMonth) => {
+ const details = Array.isArray(data.accountStatementDetails) ? data.accountStatementDetails : [];
+ let runningBalance = Number(data.openingBalance ?? 0);
+ const rows = [
+ {
+ date: statementMonth ?? "",
+ type: "鏈熷垵",
+ code: "-",
+ debit: 0,
+ credit: 0,
+ balance: runningBalance,
+ remark: "鏈熷垵浣欓",
+ },
+ ];
+
+ details.forEach((item) => {
+ const amount = Math.abs(Number(item.amount ?? 0));
+ const type = Number(item.type);
+ let debit = 0;
+ let credit = 0;
+
+ if (type === 2) {
+ credit = amount;
+ runningBalance += amount;
+ } else if (type === 4) {
+ debit = amount;
+ runningBalance -= amount;
+ } else if (type === 5) {
+ credit = -amount;
+ runningBalance -= amount;
+ }
+
+ rows.push({
+ date: item.occurrenceDate ?? "",
+ type: getDetailTypeLabel(type),
+ code: item.receiptNumber ?? "",
+ debit,
+ credit,
+ balance: runningBalance,
+ remark: item.remark ?? "",
+ });
});
- generateDialogVisible.value = false;
- ElMessage.success("瀵硅处鍗曠敓鎴愭垚鍔�");
- getTableData();
+ return rows;
};
const viewDetail = (row) => {
- currentSupplier.value = row.supplierName;
- currentPeriod.value = row.period;
+ const partnerId = row.customerId ?? row.supplierId;
+ if (!partnerId || !row.statementMonth) {
+ ElMessage.warning("缂哄皯渚涘簲鍟嗘垨瀵硅处鏈堜唤锛屾棤娉曟煡璇㈡槑缁�");
+ return;
+ }
- const purchaseInAmount = Math.floor(row.currentPayable * 0.7);
- const returnAmount = Math.floor(row.currentPayable * 0.1);
- const firstPayment = Math.floor(row.currentPayment * 0.5);
- const secondPayment = row.currentPayment - firstPayment;
-
- let runningBalance = row.beginBalance;
-
- detailData.value = [
- { date: row.period + "-01", type: "鏈熷垵", code: "-", debit: 0, credit: 0, balance: runningBalance, remark: "鏈熷垵浣欓" },
- { date: row.period + "-05", type: "鍏ュ簱", code: "RK2024001", debit: 0, credit: purchaseInAmount, balance: runningBalance += purchaseInAmount, remark: "閲囪喘鍏ュ簱" },
- { date: row.period + "-10", type: "浠樻", code: "FK2024001", debit: firstPayment, credit: 0, balance: runningBalance -= firstPayment, remark: "鏀粯璐ф" },
- { date: row.period + "-15", type: "鍏ュ簱", code: "RK2024002", debit: 0, credit: row.currentPayable - purchaseInAmount - returnAmount, balance: runningBalance += (row.currentPayable - purchaseInAmount - returnAmount), remark: "閲囪喘鍏ュ簱" },
- { date: row.period + "-20", type: "閫�璐�", code: "TH2024001", debit: 0, credit: -returnAmount, balance: runningBalance -= returnAmount, remark: "閲囪喘閫�璐�" },
- { date: row.period + "-25", type: "浠樻", code: "FK2024002", debit: secondPayment, credit: 0, balance: runningBalance -= secondPayment, remark: "鏀粯璐ф" },
- ];
-
+ currentSupplier.value = row.supplierName ?? row.customerName ?? "";
+ currentPeriod.value = row.statementMonth ?? "";
+ detailData.value = [];
detailDialogVisible.value = true;
-};
+ detailLoading.value = true;
-const printStatement = (row) => {
- ElMessage.info(`鎵撳嵃瀵硅处鍗�: ${row.statementCode}`);
+ getAccountStatementDetailsByMonth({
+ accountType: ACCOUNT_TYPE_PAYABLE,
+ customerId: partnerId,
+ statementMonth: row.statementMonth,
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ detailData.value = buildDetailTableFromApi(res.data ?? {}, row.statementMonth);
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ鏄庣粏澶辫触");
+ detailDialogVisible.value = false;
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鏌ヨ鏄庣粏澶辫触");
+ detailDialogVisible.value = false;
+ })
+ .finally(() => {
+ detailLoading.value = false;
+ });
};
const printDetail = () => {
@@ -394,10 +686,15 @@
};
const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
+ proxy.download(
+ "/accountStatement/exportAccountStatement",
+ buildExportParams(),
+ `搴斾粯瀵硅处鍗昣${Date.now()}.xlsx`
+ );
};
onMounted(() => {
+ getSupplierList();
getTableData();
});
</script>
@@ -415,6 +712,10 @@
.text-danger {
color: #f56c6c;
+}
+
+.text-primary {
+ color: #409eff;
}
.statement-header {
@@ -461,9 +762,5 @@
.empty-tip {
margin-top: 30px;
-}
-
-.text-primary {
- color: #409eff;
}
</style>
diff --git a/src/views/financialManagement/receivable/invoiceApply.vue b/src/views/financialManagement/receivable/invoiceApply.vue
index 2a4bd81..14fdd67 100644
--- a/src/views/financialManagement/receivable/invoiceApply.vue
+++ b/src/views/financialManagement/receivable/invoiceApply.vue
@@ -6,19 +6,31 @@
</el-form-item>
<el-form-item label="瀹㈡埛:">
<el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable style="width: 200px;">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-option v-for="item in customerList" :key="item.id" :label="item.customerName" :value="item.id" />
</el-select>
</el-form-item>
- <el-form-item label="鐘舵��:">
- <el-select v-model="filters.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px;">
- <el-option label="寰呭鏍�" value="pending" />
- <el-option label="宸插鏍�" value="approved" />
- <el-option label="宸查┏鍥�" value="rejected" />
- <el-option label="宸插紑绁�" value="invoiced" />
+ <el-form-item label="瀹℃牳鐘舵��:">
+ <el-select v-model="filters.status" placeholder="璇烽�夋嫨瀹℃牳鐘舵��" clearable style="width: 150px;">
+ <el-option label="寰呭鏍�" :value="0" />
+ <el-option label="瀹℃牳閫氳繃" :value="1" />
+ <el-option label="瀹℃牳涓嶉�氳繃" :value="2" />
</el-select>
+ </el-form-item>
+ <el-form-item label="鐢宠鏃ユ湡:">
+ <el-date-picker
+ v-model="filters.dateRange"
+ type="daterange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable
+ style="width: 240px;"
+ />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary" @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -27,12 +39,13 @@
<div></div>
<div>
<el-button type="primary" @click="add" icon="Plus">鏂板鐢宠</el-button>
- <el-button @click="handleBatchApply" icon="Document" :disabled="selectedRows.length === 0">鎵归噺鐢宠</el-button>
+ <el-button type="success" @click="handleExport" icon="Download">瀵煎嚭寮�绁ㄧ敵璇�</el-button>
</div>
</div>
<PIMTable
rowKey="id"
isSelection
+ v-loading="tableLoading"
:column="columns"
:tableData="dataList"
:page="{
@@ -50,42 +63,99 @@
<span>{{ row.taxRate }}%</span>
</template>
<template #status="{ row }">
- <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
+ <el-tag :type="getStatusType(row.status)" effect="light" round>
+ {{ getStatusLabel(row.status) }}
+ </el-tag>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
- <el-button type="success" link @click="handleAudit(row)" v-if="row.status === 'pending'">瀹℃牳</el-button>
- <el-button type="warning" link @click="handleInvoice(row)" v-if="row.status === 'approved'">寮�绁�</el-button>
+ <el-button type="primary" link @click="edit(row)" v-if="isPendingStatus(row.status)">缂栬緫</el-button>
+ <el-button type="danger" link @click="handleDelete(row)" v-if="isPendingStatus(row.status)">鍒犻櫎</el-button>
+ <el-button type="success" link @click="handleAudit(row)" v-if="isPendingStatus(row.status)">瀹℃牳</el-button>
+ <el-button type="primary" link @click="openFileDialog(row)" v-if="isApprovedStatus(row.status)">闄勪欢</el-button>
</template>
</PIMTable>
</div>
- <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
+ <FormDialog
+ :title="dialogTitle"
+ v-model="dialogVisible"
+ width="800px"
+ :operation-type="isView ? 'detail' : ''"
+ @confirm="submitForm"
+ @cancel="closeDialog"
+ >
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
- <el-row :gutter="20">
+ <el-row v-if="isView" :gutter="20">
<el-col :span="12">
+ <el-form-item label="瀹℃牳鐘舵��">
+ <el-tag :type="getStatusType(form.status)" effect="light" round>
+ {{ getStatusLabel(form.status) }}
+ </el-tag>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="24">
<el-form-item label="鐢宠鍗曞彿" prop="applyCode">
<el-input v-model="form.applyCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
+ </el-row>
+ <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="瀹㈡埛" prop="customerId">
- <el-select v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" :disabled="isEdit">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select
+ v-model="form.customerId"
+ placeholder="璇烽�夋嫨瀹㈡埛"
+ style="width: 100%;"
+ :disabled="isEdit || isView"
+ filterable
+ @change="handleCustomerChange"
+ >
+ <el-option v-for="item in customerList" :key="item.id" :label="item.customerName" :value="item.id" />
</el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍑哄簱鍗曞彿" prop="outboundBatchNos">
+ <el-input
+ :model-value="outboundBatchDisplayText"
+ placeholder="璇峰厛閫夋嫨瀹㈡埛"
+ readonly
+ :disabled="!form.customerId || isEdit || isView"
+ class="outbound-batch-input"
+ @click="handleOutboundInputClick"
+ >
+ <template v-if="!isEdit && !isView" #append>
+ <el-button
+ :disabled="!form.customerId"
+ :loading="outboundBatchLoading"
+ @click.stop="openOutboundSelectDialog"
+ >
+ 閫夋嫨
+ </el-button>
+ </template>
+ </el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="寮�绁ㄩ噾棰�" prop="amount">
- <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
+ <el-input-number
+ v-model="form.amount"
+ :min="0"
+ :precision="2"
+ :disabled="isView"
+ style="width: 100%;"
+ placeholder="鏍规嵁鎵�閫夊嚭搴撳崟鑷姩姹囨�伙紝鍙慨鏀�"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="绋庣巼" prop="taxRate">
- <el-select v-model="form.taxRate" placeholder="璇烽�夋嫨绋庣巼" style="width: 100%;">
+ <el-select v-model="form.taxRate" placeholder="璇烽�夋嫨绋庣巼" style="width: 100%;" :disabled="isView">
<el-option
v-for="dict in tax_rate"
:key="dict.value"
@@ -99,38 +169,103 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="鍙戠エ绫诲瀷" prop="invoiceType">
- <el-select v-model="form.invoiceType" placeholder="璇烽�夋嫨鍙戠エ绫诲瀷" style="width: 100%;">
- <el-option label="澧炲�肩◣涓撶敤鍙戠エ" value="special" />
- <el-option label="澧炲�肩◣鏅�氬彂绁�" value="normal" />
- <el-option label="鐢靛瓙鍙戠エ" value="electronic" />
+ <el-select v-model="form.invoiceType" placeholder="璇烽�夋嫨鍙戠エ绫诲瀷" style="width: 100%;" :disabled="isView">
+ <el-option label="澧炲�肩◣涓撶敤鍙戠エ" value="澧炲�肩◣涓撶敤鍙戠エ" />
+ <el-option label="澧炲�肩◣鏅�氬彂绁�" value="澧炲�肩◣鏅�氬彂绁�" />
+ <el-option label="鐢靛瓙鍙戠エ" value="鐢靛瓙鍙戠エ" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="鐢宠鏃ユ湡" prop="applyDate">
- <el-date-picker v-model="form.applyDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
+ <el-date-picker
+ v-model="form.applyDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView"
+ />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="鍙戠エ鍐呭" prop="content">
- <el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" />
+ <el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" :disabled="isView" />
</el-form-item>
<el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" />
+ <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" :disabled="isView" />
</el-form-item>
</el-form>
- <template #footer>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <template v-if="!isView" #footer>
+ <el-button type="primary" :loading="submitLoading" @click="submitForm">纭畾</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
</template>
</FormDialog>
+
+ <el-dialog
+ v-model="outboundSelectVisible"
+ title="閫夋嫨鍑哄簱鍗�"
+ width="1200px"
+ append-to-body
+ destroy-on-close
+ :close-on-click-modal="false"
+ @closed="handleOutboundDialogClosed"
+ >
+ <el-table
+ ref="outboundTableRef"
+ v-loading="outboundBatchLoading"
+ :data="outboundBatchList"
+ row-key="id"
+ border
+ stripe
+ max-height="480"
+ @selection-change="handleOutboundDialogSelectionChange"
+ >
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column prop="outboundBatches" label="鍑哄簱鍗曞彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="customerName" label="瀹㈡埛鍚嶇О" min-width="120" show-overflow-tooltip />
+ <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="120" show-overflow-tooltip />
+ <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="salesContractNo" label="閿�鍞悎鍚屽彿" min-width="140" show-overflow-tooltip />
+ <el-table-column prop="shippingNo" label="鍙戣揣鍗曞彿" min-width="130" show-overflow-tooltip />
+ <el-table-column prop="shippingDate" label="鍙戣揣鏃ユ湡" width="110" align="center" />
+ <el-table-column prop="outboundAmount" label="鍑哄簱閲戦" width="110" align="right">
+ <template #default="{ row }">楼{{ formatMoney(row.outboundAmount) }}</template>
+ </el-table-column>
+ <el-table-column prop="taxRate" label="绋庣巼" width="80" align="center">
+ <template #default="{ row }">{{ row.taxRate }}%</template>
+ </el-table-column>
+ </el-table>
+ <template #footer>
+ <el-button type="primary" @click="confirmOutboundSelection">纭畾</el-button>
+ <el-button @click="outboundSelectVisible = false">鍙栨秷</el-button>
+ </template>
+ </el-dialog>
+
+ <FileList
+ v-if="fileDialogVisible"
+ v-model:visible="fileDialogVisible"
+ record-type="account_invoice_application"
+ :record-id="currentRecordId"
+ />
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance, defineAsyncComponent } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { listCustomer } from "@/api/basicData/customer.js";
+import {
+ getOutboundBatchesByCustomer,
+ addAccountInvoiceApplication,
+ listPageAccountInvoiceApplication,
+ auditAccountInvoiceApplication,
+ updateAccountInvoiceApplication,
+ deleteAccountInvoiceApplication,
+} from "@/api/financialManagement/invoiceApply.js";
+
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
defineOptions({
name: "寮�绁ㄧ敵璇�",
@@ -143,6 +278,7 @@
applyCode: "",
customerId: "",
status: "",
+ dateRange: [],
});
const pagination = reactive({
@@ -154,35 +290,237 @@
const columns = [
{ label: "鐢宠鍗曞彿", prop: "applyCode", width: "150" },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
- { label: "寮�绁ㄩ噾棰�", prop: "amount", slot: "amount" },
- { label: "绋庣巼", prop: "taxRate", slot: "taxRate" },
- { label: "鍙戠エ绫诲瀷", prop: "invoiceTypeLabel", width: "130" },
+ { label: "寮�绁ㄩ噾棰�", prop: "amount", dataType: "slot", slot: "amount" },
+ { label: "绋庣巼", prop: "taxRate", dataType: "slot", slot: "taxRate" },
+ { label: "鍙戠エ绫诲瀷", prop: "invoiceType", width: "130" },
{ label: "鐢宠鏃ユ湡", prop: "applyDate", width: "120" },
- { label: "鐘舵��", prop: "status", slot: "status" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "200", fixed: "right" },
+ { label: "瀹℃牳鐘舵��", prop: "status", dataType: "slot", slot: "status", width: "110", align: "center" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "300", fixed: "right" },
];
const dataList = ref([]);
+const tableLoading = ref(false);
const selectedRows = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
+const isView = ref(false);
const currentId = ref(null);
-const customerList = [
- { id: 1, name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
- { id: 2, name: "涓婃捣璐告槗鍏徃" },
- { id: 3, name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
- { id: 4, name: "娣卞湷鐢靛瓙鍏徃" },
-];
+const closeDialog = () => {
+ dialogVisible.value = false;
+ outboundSelectVisible.value = false;
+ isView.value = false;
+ isEdit.value = false;
+};
+
+const customerList = ref([]);
+const outboundBatchList = ref([]);
+const outboundBatchOptions = ref([]);
+const outboundBatchLoading = ref(false);
+const outboundSelectVisible = ref(false);
+const outboundTableRef = ref(null);
+const dialogOutboundSelection = ref([]);
+
+const getCustomerList = () => {
+ listCustomer({ current: -1, size: -1, type: 0 }).then((res) => {
+ if (res.code === 200) {
+ customerList.value = res.data?.records || [];
+ }
+ });
+};
+
+const normalizeOutboundBatchOptions = (data) => {
+ const list = Array.isArray(data) ? data : [];
+ return list.map((item, index) => {
+ if (typeof item === "string" || typeof item === "number") {
+ const text = String(item);
+ return { label: text, value: text, outboundAmount: 0 };
+ }
+ const label =
+ item.outboundBatches ??
+ item.batchNo ??
+ item.shippingNo ??
+ item.outboundNo ??
+ item.label ??
+ `鍑哄簱鍗�${index + 1}`;
+ const value = item.id ?? item.stockOutRecordId ?? item.stockOutRecordIds ?? label;
+ const outboundAmount = Number(item.outboundAmount) || 0;
+ const taxRate =
+ item.taxRate !== undefined && item.taxRate !== null && item.taxRate !== ""
+ ? Number(item.taxRate)
+ : undefined;
+ return { label: String(label), value, outboundAmount, taxRate };
+ });
+};
+
+const isSameOutboundId = (a, b) => String(a) === String(b);
+
+const getSelectedOutboundOptions = () => {
+ const selected = form.outboundBatchNos || [];
+ return outboundBatchOptions.value.filter((opt) =>
+ selected.some((id) => isSameOutboundId(id, opt.value))
+ );
+};
+
+/** 鏍¢獙鎵�閫夊嚭搴撳崟绋庣巼鏄惁涓�鑷达紝涓�鑷村垯鍥炲~ form.taxRate */
+const checkTaxRateConsistency = (showMessage = true) => {
+ const selected = getSelectedOutboundOptions();
+ if (selected.length === 0) return true;
+
+ const withTaxRate = selected.filter(
+ (opt) => opt.taxRate !== undefined && opt.taxRate !== null && !Number.isNaN(opt.taxRate)
+ );
+ if (withTaxRate.length === 0) return true;
+
+ const uniqueRates = [...new Set(withTaxRate.map((opt) => Number(opt.taxRate)))];
+ if (uniqueRates.length > 1) {
+ if (showMessage) {
+ const detail = withTaxRate.map((opt) => `${opt.label}(${opt.taxRate}%)`).join("銆�");
+ ElMessage.error(`鎵�閫夊嚭搴撳崟绋庣巼涓嶄竴鑷达紝鏃犳硶寮�绁細${detail}`);
+ }
+ return false;
+ }
+
+ form.taxRate = uniqueRates[0];
+ return true;
+};
+
+/** 鏍规嵁鎵�閫夊嚭搴撳崟姹囨�� outboundAmount 浣滀负寮�绁ㄩ噾棰� */
+const syncInvoiceAmount = () => {
+ const selected = form.outboundBatchNos || [];
+ const sum = outboundBatchOptions.value
+ .filter((opt) => selected.some((id) => isSameOutboundId(id, opt.value)))
+ .reduce((acc, opt) => acc + (Number(opt.outboundAmount) || 0), 0);
+ form.amount = sum > 0 ? Number(sum.toFixed(2)) : 0;
+};
+
+const getOutboundRowId = (row) => row?.id ?? row?.stockOutRecordId;
+
+const outboundBatchDisplayText = computed(() => {
+ if (isEdit.value || isView.value) {
+ return form.outboundBatches || "";
+ }
+ if (form.outboundBatches) return form.outboundBatches;
+ const ids = form.outboundBatchNos || [];
+ if (!ids.length) return "";
+ return outboundBatchOptions.value
+ .filter((opt) => ids.some((id) => isSameOutboundId(id, opt.value)))
+ .map((opt) => opt.label)
+ .join("銆�");
+});
+
+const handleOutboundInputClick = () => {
+ if (isEdit.value || isView.value) return;
+ openOutboundSelectDialog();
+};
+
+const restoreOutboundTableSelection = () => {
+ nextTick(() => {
+ const table = outboundTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ const selectedIds = new Set((form.outboundBatchNos || []).map((id) => String(id)));
+ outboundBatchList.value.forEach((row) => {
+ const rowId = getOutboundRowId(row);
+ if (rowId !== undefined && rowId !== null && selectedIds.has(String(rowId))) {
+ table.toggleRowSelection(row, true);
+ }
+ });
+ });
+};
+
+const openOutboundSelectDialog = () => {
+ if (!form.customerId || isEdit.value || isView.value) return;
+ outboundSelectVisible.value = true;
+ loadOutboundBatches(form.customerId, true).then(() => {
+ restoreOutboundTableSelection();
+ });
+};
+
+const handleOutboundDialogSelectionChange = (selection) => {
+ dialogOutboundSelection.value = selection;
+};
+
+const confirmOutboundSelection = () => {
+ if (dialogOutboundSelection.value.length === 0) {
+ ElMessage.warning("璇疯嚦灏戦�夋嫨涓�鏉″嚭搴撳崟");
+ return;
+ }
+ const prevIds = [...(form.outboundBatchNos || [])];
+ const prevBatches = form.outboundBatches;
+ form.outboundBatchNos = dialogOutboundSelection.value
+ .map((row) => getOutboundRowId(row))
+ .filter((id) => id !== undefined && id !== null);
+ form.outboundBatches = dialogOutboundSelection.value
+ .map((row) => row.outboundBatches ?? row.batchNo ?? row.shippingNo ?? "")
+ .filter(Boolean)
+ .join("銆�");
+ if (!checkTaxRateConsistency()) {
+ form.outboundBatchNos = prevIds;
+ form.outboundBatches = prevBatches;
+ return;
+ }
+ outboundSelectVisible.value = false;
+ syncInvoiceAmount();
+ formRef.value?.validateField("outboundBatchNos");
+};
+
+const handleOutboundDialogClosed = () => {
+ dialogOutboundSelection.value = [];
+};
+
+const loadOutboundBatches = (customerId, keepSelected = false) => {
+ if (!customerId) {
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ if (!keepSelected) {
+ form.outboundBatchNos = [];
+ form.amount = 0;
+ }
+ return Promise.resolve();
+ }
+ outboundBatchLoading.value = true;
+ return getOutboundBatchesByCustomer({ customerId })
+ .then((res) => {
+ if (res.code === 200) {
+ const list = res.data?.records ?? res.data ?? [];
+ outboundBatchList.value = Array.isArray(list) ? list : [];
+ outboundBatchOptions.value = normalizeOutboundBatchOptions(list);
+ } else {
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ }
+ })
+ .catch(() => {
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ })
+ .finally(() => {
+ outboundBatchLoading.value = false;
+ if (keepSelected) {
+ syncInvoiceAmount();
+ checkTaxRateConsistency(false);
+ }
+ });
+};
+
+const handleCustomerChange = (customerId) => {
+ form.outboundBatchNos = [];
+ form.outboundBatches = "";
+ form.amount = 0;
+ loadOutboundBatches(customerId);
+};
const form = reactive({
applyCode: "",
customerId: "",
+ outboundBatchNos: [],
+ outboundBatches: "",
amount: 0,
taxRate: 13,
- invoiceType: "special",
+ invoiceType: "澧炲�肩◣涓撶敤鍙戠エ",
applyDate: "",
content: "",
remark: "",
@@ -190,17 +528,103 @@
const rules = {
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
+ outboundBatchNos: [{ required: true, type: "array", min: 1, message: "璇烽�夋嫨鍑哄簱鍗曞彿", trigger: "change" }],
amount: [{ required: true, message: "璇疯緭鍏ュ紑绁ㄩ噾棰�", trigger: "blur" }],
taxRate: [{ required: true, message: "璇烽�夋嫨绋庣巼", trigger: "change" }],
invoiceType: [{ required: true, message: "璇烽�夋嫨鍙戠エ绫诲瀷", trigger: "change" }],
applyDate: [{ required: true, message: "璇烽�夋嫨鐢宠鏃ユ湡", trigger: "change" }],
};
-const mockData = [
- { id: 1, applyCode: "KP2024001", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", amount: 5000, taxRate: 13, invoiceType: "special", invoiceTypeLabel: "澧炲�肩◣涓撶敤鍙戠エ", applyDate: "2024-01-15", status: "pending", content: "杞欢鏈嶅姟璐�", remark: "" },
- { id: 2, applyCode: "KP2024002", customerId: 2, customerName: "涓婃捣璐告槗鍏徃", amount: 8000, taxRate: 13, invoiceType: "normal", invoiceTypeLabel: "澧炲�肩◣鏅�氬彂绁�", applyDate: "2024-01-16", status: "approved", content: "鍟嗗搧閿�鍞�", remark: "" },
- { id: 3, applyCode: "KP2024003", customerId: 3, customerName: "骞垮窞瀹炰笟鏈夐檺鍏徃", amount: 12000, taxRate: 6, invoiceType: "electronic", invoiceTypeLabel: "鐢靛瓙鍙戠エ", applyDate: "2024-01-18", status: "invoiced", content: "鎶�鏈湇鍔¤垂", remark: "" },
-];
+/** 瀹℃牳鐘舵�侊細0寰呭鏍� 1瀹℃牳閫氳繃 2瀹℃牳涓嶉�氳繃 */
+const STATUS_LABEL_MAP = {
+ 0: "寰呭鏍�",
+ 1: "瀹℃牳閫氳繃",
+ 2: "瀹℃牳涓嶉�氳繃",
+};
+
+const STATUS_TYPE_MAP = {
+ 0: "warning",
+ 1: "success",
+ 2: "danger",
+};
+
+const normalizeStatus = (status) => {
+ if (status === undefined || status === null || status === "") return status;
+ const num = Number(status);
+ return Number.isNaN(num) ? status : num;
+};
+
+const isPendingStatus = (status) => normalizeStatus(status) === 0;
+const isApprovedStatus = (status) => normalizeStatus(status) === 1;
+
+const fileDialogVisible = ref(false);
+const currentRecordId = ref(0);
+
+const openFileDialog = (row) => {
+ currentRecordId.value = row.id;
+ fileDialogVisible.value = true;
+};
+
+const formatOutboundBatches = (value) => {
+ if (value === undefined || value === null || value === "") return "";
+ if (Array.isArray(value)) return value.filter(Boolean).join("銆�");
+ return String(value)
+ .split(/[,锛宂/)
+ .map((s) => s.trim())
+ .filter(Boolean)
+ .join("銆�");
+};
+
+const normalizeTableRow = (row) => ({
+ ...row,
+ applyCode: row.invoiceApplicationNo ?? row.applyCode,
+ amount: row.invoiceAmount ?? row.amount,
+ content: row.invoiceContent ?? row.content,
+ status: normalizeStatus(row.status ?? row.auditStatus),
+ stockOutRecordIds: row.stockOutRecordIds ?? row.stockOutRecordId ?? "",
+ outboundBatches: formatOutboundBatches(row.outboundBatches),
+});
+
+const appendFilterParams = (params) => {
+ if (filters.applyCode) {
+ params.invoiceApplicationNo = filters.applyCode;
+ }
+ if (filters.customerId) {
+ params.customerId = filters.customerId;
+ }
+ if (filters.status !== "" && filters.status != null) {
+ params.status = filters.status;
+ }
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ return params;
+};
+
+const buildListParams = () => {
+ return appendFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+};
+
+const buildExportParams = () => {
+ const params = appendFilterParams({});
+ if (selectedRows.value.length > 0) {
+ params.ids = selectedRows.value.map((row) => row.id).join(",");
+ }
+ return params;
+};
+
+const handleExport = () => {
+ const params = buildExportParams();
+ const filename =
+ selectedRows.value.length > 0
+ ? `寮�绁ㄧ敵璇穇宸查��${selectedRows.value.length}鏉${Date.now()}.xlsx`
+ : `寮�绁ㄧ敵璇穇${Date.now()}.xlsx`;
+ proxy.download("/accountInvoiceApplication/exportAccountInvoiceApplication", params, filename);
+};
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
@@ -208,34 +632,54 @@
};
const getStatusLabel = (status) => {
- const map = { pending: "寰呭鏍�", approved: "宸插鏍�", rejected: "宸查┏鍥�", invoiced: "宸插紑绁�" };
- return map[status] || status;
+ const num = normalizeStatus(status);
+ if (num === 0 || num === 1 || num === 2) {
+ return STATUS_LABEL_MAP[num];
+ }
+ return "-";
};
const getStatusType = (status) => {
- const map = { pending: "warning", approved: "success", rejected: "danger", invoiced: "primary" };
- return map[status] || "";
+ const num = normalizeStatus(status);
+ if (num === 0 || num === 1 || num === 2) {
+ return STATUS_TYPE_MAP[num];
+ }
+ return "info";
+};
+
+const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
};
const getTableData = () => {
- let result = [...mockData];
- if (filters.applyCode) {
- result = result.filter(item => item.applyCode.includes(filters.applyCode));
- }
- if (filters.customerId) {
- result = result.filter(item => item.customerId === filters.customerId);
- }
- if (filters.status) {
- result = result.filter(item => item.status === filters.status);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ tableLoading.value = true;
+ listPageAccountInvoiceApplication(buildListParams())
+ .then((res) => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = (res.data.records ?? []).map(normalizeTableRow);
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ pagination.total = 0;
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
};
const resetFilters = () => {
filters.applyCode = "";
filters.customerId = "";
filters.status = "";
+ filters.dateRange = [];
pagination.currentPage = 1;
getTableData();
};
@@ -250,57 +694,139 @@
selectedRows.value = selection;
};
+const fillFormFromRow = (row) => {
+ const outboundBatchNos = Array.isArray(row.outboundBatchNos)
+ ? row.outboundBatchNos
+ : parseStockOutRecordIds(row.stockOutRecordIds ?? row.stockOutRecordId);
+ Object.assign(form, {
+ ...row,
+ applyCode: row.applyCode ?? row.invoiceApplicationNo ?? "",
+ amount: Number(row.amount ?? row.invoiceAmount ?? 0),
+ content: row.content ?? row.invoiceContent,
+ status: normalizeStatus(row.status ?? row.auditStatus),
+ outboundBatchNos,
+ outboundBatches: formatOutboundBatches(row.outboundBatches),
+ });
+};
+
const add = () => {
isEdit.value = false;
+ isView.value = false;
dialogTitle.value = "鏂板寮�绁ㄧ敵璇�";
Object.assign(form, {
applyCode: "KP" + Date.now().toString().slice(-8),
customerId: "",
+ outboundBatchNos: [],
+ outboundBatches: "",
amount: 0,
taxRate: 13,
- invoiceType: "special",
- applyDate: new Date().toISOString().split('T')[0],
+ invoiceType: "澧炲�肩◣涓撶敤鍙戠エ",
+ applyDate: new Date().toISOString().split("T")[0],
content: "",
remark: "",
});
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
dialogVisible.value = true;
+};
+
+const parseStockOutRecordIds = (value) => {
+ if (!value) return [];
+ if (Array.isArray(value)) return value;
+ return String(value)
+ .split(/[,锛宂/)
+ .map((s) => s.trim())
+ .filter(Boolean)
+ .map((s) => (/^\d+$/.test(s) ? Number(s) : s));
+};
+
+const buildSubmitPayload = (forUpdate = false) => {
+ const payload = {
+ customerId: form.customerId,
+ stockOutRecordIds: (form.outboundBatchNos || []).join(","),
+ invoiceApplicationNo: form.applyCode || "",
+ invoiceType: form.invoiceType,
+ applyDate: form.applyDate,
+ invoiceContent: form.content,
+ remark: form.remark || "",
+ invoiceAmount: form.amount,
+ taxRate: form.taxRate,
+ status: 0,
+ };
+ if (forUpdate) {
+ payload.id = currentId.value;
+ }
+ return payload;
};
const edit = (row) => {
isEdit.value = true;
+ isView.value = false;
currentId.value = row.id;
dialogTitle.value = "缂栬緫寮�绁ㄧ敵璇�";
- Object.assign(form, row);
+ fillFormFromRow(row);
dialogVisible.value = true;
};
const view = (row) => {
- ElMessage.info(`鏌ョ湅鐢宠鍗�: ${row.applyCode}`);
+ isView.value = true;
+ isEdit.value = false;
+ dialogTitle.value = "鏌ョ湅寮�绁ㄧ敵璇�";
+ fillFormFromRow(row);
+ dialogVisible.value = true;
+};
+
+const submitAudit = (row, status) => {
+ auditAccountInvoiceApplication({ id: row.id, status })
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success(status === 1 ? "瀹℃牳閫氳繃" : "瀹℃牳涓嶉�氳繃");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "瀹℃壒澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("瀹℃壒澶辫触");
+ });
+};
+
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎鐢宠鍗曘��${row.applyCode ?? row.invoiceApplicationNo}銆嶅悧锛焋, "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountInvoiceApplication([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
};
const handleAudit = (row) => {
- ElMessageBox.confirm("纭瀹℃牳閫氳繃璇ュ紑绁ㄧ敵璇峰悧锛�", "鎻愮ず", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "寮�绁ㄧ敵璇峰鏍�", {
+ confirmButtonText: "瀹℃牳閫氳繃",
+ cancelButtonText: "瀹℃牳涓嶉�氳繃",
distinguishCancelAndClose: true,
type: "warning",
- }).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "approved";
- }
- ElMessage.success("瀹℃牳閫氳繃");
- getTableData();
- }).catch((action) => {
- if (action === "cancel") {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "rejected";
+ })
+ .then(() => {
+ submitAudit(row, 1);
+ })
+ .catch((action) => {
+ if (action === "cancel") {
+ submitAudit(row, 2);
}
- ElMessage.warning("宸查┏鍥�");
- getTableData();
- }
- });
+ });
};
const handleInvoice = (row) => {
@@ -309,10 +835,6 @@
cancelButtonText: "鍙栨秷",
type: "info",
}).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "invoiced";
- }
ElMessage.success("寮�绁ㄥ畬鎴�");
getTableData();
});
@@ -322,29 +844,39 @@
ElMessage.success(`鎵归噺鐢宠 ${selectedRows.value.length} 鏉¤褰昤);
};
+const submitLoading = ref(false);
+
const submitForm = () => {
formRef.value.validate((valid) => {
- if (valid) {
- const customer = customerList.find(item => item.id === form.customerId);
- const invoiceTypeMap = { special: "澧炲�肩◣涓撶敤鍙戠エ", normal: "澧炲�肩◣鏅�氬彂绁�", electronic: "鐢靛瓙鍙戠エ" };
- if (isEdit.value) {
- const index = mockData.findIndex(item => item.id === currentId.value);
- if (index !== -1) {
- mockData[index] = { ...mockData[index], ...form, customerName: customer?.name, invoiceTypeLabel: invoiceTypeMap[form.invoiceType] };
+ if (!valid) return;
+ if (!checkTaxRateConsistency()) return;
+
+ submitLoading.value = true;
+ const request = isEdit.value
+ ? updateAccountInvoiceApplication(buildSubmitPayload(true))
+ : addAccountInvoiceApplication(buildSubmitPayload());
+
+ request
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success(isEdit.value ? "淇敼鎴愬姛" : "鏂板鎴愬姛");
+ closeDialog();
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || (isEdit.value ? "淇敼澶辫触" : "鏂板澶辫触"));
}
- ElMessage.success("缂栬緫鎴愬姛");
- } else {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- mockData.push({ id: newId, ...form, customerName: customer?.name, invoiceTypeLabel: invoiceTypeMap[form.invoiceType], status: "pending" });
- ElMessage.success("鏂板鎴愬姛");
- }
- dialogVisible.value = false;
- getTableData();
- }
+ })
+ .catch(() => {
+ ElMessage.error(isEdit.value ? "淇敼澶辫触" : "鏂板澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
});
};
onMounted(() => {
+ getCustomerList();
getTableData();
});
</script>
@@ -360,4 +892,10 @@
color: #409eff;
font-weight: bold;
}
+
+.outbound-batch-input:not(.is-disabled) {
+ :deep(.el-input__wrapper) {
+ cursor: pointer;
+ }
+}
</style>
diff --git a/src/views/financialManagement/receivable/outputInvoice.vue b/src/views/financialManagement/receivable/outputInvoice.vue
index 3e597db..d746aea 100644
--- a/src/views/financialManagement/receivable/outputInvoice.vue
+++ b/src/views/financialManagement/receivable/outputInvoice.vue
@@ -1,19 +1,35 @@
<template>
<div class="app-container">
<el-form :model="filters" :inline="true">
- <el-form-item label="鍙戠エ浠g爜:">
- <el-input v-model="filters.invoiceCode" placeholder="璇疯緭鍏ュ彂绁ㄤ唬鐮�" clearable style="width: 200px;" />
- </el-form-item>
<el-form-item label="鍙戠エ鍙风爜:">
- <el-input v-model="filters.invoiceNo" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" clearable style="width: 200px;" />
+ <el-input v-model="filters.invoiceNumber" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" clearable style="width: 200px;" />
</el-form-item>
<el-form-item label="瀹㈡埛:">
<el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable style="width: 200px;">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-option v-for="item in customerList" :key="item.id" :label="item.customerName" :value="item.id" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="寮�绁ㄦ棩鏈�:">
+ <el-date-picker
+ v-model="filters.dateRange"
+ type="daterange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable
+ style="width: 240px;"
+ />
+ </el-form-item>
+ <el-form-item label="鐘舵��:">
+ <el-select v-model="filters.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px;">
+ <el-option label="姝e父" :value="0" />
+ <el-option label="浣滃簾" :value="1" />
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary" @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -21,13 +37,13 @@
<div class="actions">
<div></div>
<div>
- <el-button type="primary" @click="add" icon="Plus">褰曞叆鍙戠エ</el-button>
- <el-button @click="handleImport" icon="Upload">瀵煎叆</el-button>
- <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+ <!-- <el-button type="primary" @click="add" icon="Plus">褰曞叆鍙戠エ</el-button> -->
+ <el-button type="success" @click="handleExport" icon="Download">瀵煎嚭</el-button>
</div>
</div>
<PIMTable
rowKey="id"
+ v-loading="tableLoading"
:column="columns"
:tableData="dataList"
:page="{
@@ -46,58 +62,98 @@
<template #totalAmount="{ row }">
<span class="text-success">楼{{ formatMoney(row.totalAmount) }}</span>
</template>
- <template #invoiceType="{ row }">
- <el-tag :type="row.invoiceType === 'special' ? 'danger' : 'primary'">{{ row.invoiceTypeLabel }}</el-tag>
+ <template #status="{ row }">
+ <el-tag :type="getStatusType(row.status)" effect="light" round>
+ {{ getStatusLabel(row.status) }}
+ </el-tag>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="edit(row)">缂栬緫</el-button>
- <el-button type="danger" link @click="handleDelete(row)">浣滃簾</el-button>
+ <el-button
+ type="primary"
+ link
+ @click="openFileDialog(row)"
+ v-if="row.accountInvoiceApplicationId"
+ >
+ 闄勪欢
+ </el-button>
+ <el-button type="warning" link @click="handleCancel(row)" v-if="isNormalStatus(row.status)">浣滃簾</el-button>
+ <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
- <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
+ <FormDialog
+ :title="dialogTitle"
+ v-model="dialogVisible"
+ width="800px"
+ :operation-type="isView ? 'detail' : ''"
+ @confirm="submitForm"
+ @cancel="closeDialog"
+ >
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
- <el-row :gutter="20">
+ <el-row v-if="isView" :gutter="20">
<el-col :span="12">
- <el-form-item label="鍙戠エ浠g爜" prop="invoiceCode">
- <el-input v-model="form.invoiceCode" placeholder="璇疯緭鍏ュ彂绁ㄤ唬鐮�" />
+ <el-form-item label="鐘舵��">
+ <el-tag :type="getStatusType(form.status)" effect="light" round>
+ {{ getStatusLabel(form.status) }}
+ </el-tag>
</el-form-item>
</el-col>
+ </el-row>
+ <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="鍙戠エ鍙风爜" prop="invoiceNo">
- <el-input v-model="form.invoiceNo" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" />
+ <el-input v-model="form.invoiceNo" placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" :disabled="isView" />
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="瀹㈡埛" prop="customerId">
- <el-select v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" :disabled="isView">
+ <el-option v-for="item in customerList" :key="item.id" :label="item.customerName" :value="item.id" />
</el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="寮�绁ㄦ棩鏈�" prop="invoiceDate">
- <el-date-picker v-model="form.invoiceDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷" prop="invoiceType">
- <el-select v-model="form.invoiceType" placeholder="璇烽�夋嫨鍙戠エ绫诲瀷" style="width: 100%;" @change="handleInvoiceTypeChange">
- <el-option label="澧炲�肩◣涓撶敤鍙戠エ" value="special" />
- <el-option label="澧炲�肩◣鏅�氬彂绁�" value="normal" />
- <el-option label="鐢靛瓙鍙戠エ" value="electronic" />
- </el-select>
+ <el-form-item label="寮�绁ㄦ棩鏈�" prop="invoiceDate">
+ <el-date-picker
+ v-model="form.invoiceDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
+ <el-form-item label="鍙戠エ绫诲瀷" prop="invoiceType">
+ <el-select
+ v-model="form.invoiceType"
+ placeholder="璇烽�夋嫨鍙戠エ绫诲瀷"
+ style="width: 100%;"
+ :disabled="isView"
+ @change="handleInvoiceTypeChange"
+ >
+ <el-option label="澧炲�肩◣涓撶敤鍙戠エ" value="澧炲�肩◣涓撶敤鍙戠エ" />
+ <el-option label="澧炲�肩◣鏅�氬彂绁�" value="澧炲�肩◣鏅�氬彂绁�" />
+ <el-option label="鐢靛瓙鍙戠エ" value="鐢靛瓙鍙戠エ" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
<el-form-item label="绋庣巼" prop="taxRate">
- <el-select v-model="form.taxRate" placeholder="璇烽�夋嫨绋庣巼" style="width: 100%;" @change="calculateTax">
+ <el-select
+ v-model="form.taxRate"
+ placeholder="璇烽�夋嫨绋庣巼"
+ style="width: 100%;"
+ :disabled="isView"
+ @change="calculateTax"
+ >
<el-option
v-for="dict in tax_rate"
:key="dict.value"
@@ -111,7 +167,14 @@
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="閲戦(涓嶅惈绋�)" prop="amount">
- <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" @change="calculateTax" />
+ <el-input-number
+ v-model="form.amount"
+ :min="0"
+ :precision="2"
+ style="width: 100%;"
+ :disabled="isView"
+ @change="calculateTax"
+ />
</el-form-item>
</el-col>
<el-col :span="8">
@@ -126,24 +189,41 @@
</el-col>
</el-row>
<el-form-item label="鍙戠エ鍐呭" prop="content">
- <el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" />
+ <el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" :disabled="isView" />
</el-form-item>
<el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" />
+ <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ娉�" :disabled="isView" />
</el-form-item>
</el-form>
- <template #footer>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <template v-if="!isView" #footer>
+ <el-button type="primary" :loading="submitLoading" @click="submitForm">纭畾</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
</template>
</FormDialog>
+
+ <FileList
+ v-if="fileDialogVisible"
+ v-model:visible="fileDialogVisible"
+ record-type="account_invoice_application"
+ :record-id="currentRecordId"
+ :editable="false"
+ />
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, computed, getCurrentInstance } from "vue";
+import { ref, reactive, onMounted, getCurrentInstance, defineAsyncComponent } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { listCustomer } from "@/api/basicData/customer.js";
+import {
+ addAccountSalesInvoice,
+ listPageAccountSalesInvoice,
+ cancelAccountSalesInvoice,
+ deleteAccountSalesInvoice,
+} from "@/api/financialManagement/accountSalesInvoice.js";
+
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
defineOptions({
name: "閿�椤瑰彂绁�",
@@ -153,9 +233,10 @@
const { tax_rate } = proxy.useDict("tax_rate");
const filters = reactive({
- invoiceCode: "",
- invoiceNo: "",
+ invoiceNumber: "",
customerId: "",
+ dateRange: [],
+ status: "",
});
const pagination = reactive({
@@ -165,47 +246,76 @@
});
const columns = [
- { label: "鍙戠エ浠g爜", prop: "invoiceCode", width: "130" },
- { label: "鍙戠エ鍙风爜", prop: "invoiceNo", width: "120" },
+ { label: "鍙戠エ鍙风爜", prop: "invoiceNo", width: "140" },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
{ label: "寮�绁ㄦ棩鏈�", prop: "invoiceDate", width: "120" },
- { label: "閲戦", prop: "amount", slot: "amount" },
- { label: "绋庨", prop: "taxAmount", slot: "taxAmount" },
- { label: "浠风◣鍚堣", prop: "totalAmount", slot: "totalAmount" },
- { label: "鍙戠エ绫诲瀷", prop: "invoiceType", slot: "invoiceType" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "180", fixed: "right" },
+ { label: "閲戦", prop: "amount", dataType: "slot", slot: "amount" },
+ { label: "绋庨", prop: "taxAmount", dataType: "slot", slot: "taxAmount" },
+ { label: "浠风◣鍚堣", prop: "totalAmount", dataType: "slot", slot: "totalAmount" },
+ { label: "鍙戠エ绫诲瀷", prop: "invoiceType", width: "130" },
+ { label: "鐘舵��", prop: "status", dataType: "slot", slot: "status", width: "90", align: "center" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "260", fixed: "right" },
];
const dataList = ref([]);
+const tableLoading = ref(false);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
+const isView = ref(false);
+const submitLoading = ref(false);
-const customerList = [
- { id: 1, name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
- { id: 2, name: "涓婃捣璐告槗鍏徃" },
- { id: 3, name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
- { id: 4, name: "娣卞湷鐢靛瓙鍏徃" },
-];
+const customerList = ref([]);
+const fileDialogVisible = ref(false);
+const currentRecordId = ref(0);
+
+const openFileDialog = (row) => {
+ if (!row.accountInvoiceApplicationId) {
+ ElMessage.warning("鏈叧鑱斿紑绁ㄧ敵璇凤紝鏃犳硶鏌ョ湅闄勪欢");
+ return;
+ }
+ currentRecordId.value = row.accountInvoiceApplicationId;
+ fileDialogVisible.value = true;
+};
+
+/** 鐘舵�侊細0姝e父 1浣滃簾 */
+const STATUS_LABEL_MAP = { 0: "姝e父", 1: "浣滃簾" };
+const STATUS_TYPE_MAP = { 0: "success", 1: "info" };
+
+const normalizeStatus = (status) => {
+ if (status === undefined || status === null || status === "") return 0;
+ const num = Number(status);
+ return Number.isNaN(num) ? 0 : num;
+};
+
+const isNormalStatus = (status) => normalizeStatus(status) === 0;
+
+const getStatusLabel = (status) => {
+ const num = normalizeStatus(status);
+ return STATUS_LABEL_MAP[num] ?? "姝e父";
+};
+
+const getStatusType = (status) => {
+ const num = normalizeStatus(status);
+ return STATUS_TYPE_MAP[num] ?? "success";
+};
const form = reactive({
- invoiceCode: "",
invoiceNo: "",
customerId: "",
invoiceDate: "",
- invoiceType: "special",
+ invoiceType: "澧炲�肩◣涓撶敤鍙戠エ",
taxRate: 13,
amount: 0,
taxAmount: 0,
totalAmount: 0,
content: "",
remark: "",
+ accountInvoiceApplicationId: undefined,
+ storageAttachmentId: undefined,
});
const rules = {
- invoiceCode: [{ required: true, message: "璇疯緭鍏ュ彂绁ㄤ唬鐮�", trigger: "blur" }],
invoiceNo: [{ required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿鐮�", trigger: "blur" }],
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
invoiceDate: [{ required: true, message: "璇烽�夋嫨寮�绁ㄦ棩鏈�", trigger: "change" }],
@@ -213,12 +323,6 @@
taxRate: [{ required: true, message: "璇烽�夋嫨绋庣巼", trigger: "change" }],
amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
};
-
-const mockData = [
- { id: 1, invoiceCode: "0440021001", invoiceNo: "12345678", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", invoiceDate: "2024-01-15", amount: 5000, taxRate: 13, taxAmount: 650, totalAmount: 5650, invoiceType: "special", invoiceTypeLabel: "澧炲�肩◣涓撶敤鍙戠エ", content: "杞欢鏈嶅姟璐�", remark: "" },
- { id: 2, invoiceCode: "0440021002", invoiceNo: "87654321", customerId: 2, customerName: "涓婃捣璐告槗鍏徃", invoiceDate: "2024-01-16", amount: 8000, taxRate: 13, taxAmount: 1040, totalAmount: 9040, invoiceType: "normal", invoiceTypeLabel: "澧炲�肩◣鏅�氬彂绁�", content: "鍟嗗搧閿�鍞�", remark: "" },
- { id: 3, invoiceCode: "0440021003", invoiceNo: "11112222", customerId: 3, customerName: "骞垮窞瀹炰笟鏈夐檺鍏徃", invoiceDate: "2024-01-18", amount: 12000, taxRate: 6, taxAmount: 720, totalAmount: 12720, invoiceType: "electronic", invoiceTypeLabel: "鐢靛瓙鍙戠エ", content: "鎶�鏈湇鍔¤垂", remark: "" },
-];
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
@@ -231,33 +335,142 @@
};
const handleInvoiceTypeChange = () => {
- if (form.invoiceType === "special") {
- form.taxRate = 13;
- } else {
- form.taxRate = 13;
- }
calculateTax();
};
-const getTableData = () => {
- let result = [...mockData];
- if (filters.invoiceCode) {
- result = result.filter(item => item.invoiceCode.includes(filters.invoiceCode));
- }
- if (filters.invoiceNo) {
- result = result.filter(item => item.invoiceNo.includes(filters.invoiceNo));
+const normalizeTableRow = (row) => ({
+ ...row,
+ invoiceNo: row.invoiceNumber ?? row.invoiceNo,
+ invoiceDate: row.issueDate ?? row.invoiceDate,
+ amount: row.taxExclusivelPrice ?? row.amount,
+ taxAmount: row.taxPrice ?? row.taxAmount,
+ totalAmount: row.taxInclusivePrice ?? row.totalAmount,
+ content: row.invoiceContent ?? row.content,
+ status: normalizeStatus(row.status),
+});
+
+const fillFormFromRow = (row) => {
+ Object.assign(form, {
+ invoiceNo: row.invoiceNo ?? row.invoiceNumber ?? "",
+ customerId: row.customerId,
+ invoiceDate: row.invoiceDate ?? row.issueDate ?? "",
+ invoiceType: row.invoiceType ?? "澧炲�肩◣涓撶敤鍙戠エ",
+ taxRate: row.taxRate ?? 13,
+ amount: row.amount ?? row.taxExclusivelPrice ?? 0,
+ taxAmount: row.taxAmount ?? row.taxPrice ?? 0,
+ totalAmount: row.totalAmount ?? row.taxInclusivePrice ?? 0,
+ content: row.content ?? row.invoiceContent ?? "",
+ remark: row.remark ?? "",
+ accountInvoiceApplicationId: row.accountInvoiceApplicationId,
+ storageAttachmentId: row.storageAttachmentId,
+ status: normalizeStatus(row.status),
+ });
+};
+
+const buildCancelPayload = (row) => ({
+ id: row.id,
+ accountInvoiceApplicationId: row.accountInvoiceApplicationId,
+ invoiceNumber: row.invoiceNumber ?? row.invoiceNo,
+ taxRate: row.taxRate,
+ invoiceType: row.invoiceType,
+ issueDate: row.issueDate ?? row.invoiceDate,
+ taxExclusivelPrice: row.taxExclusivelPrice ?? row.amount,
+ taxPrice: row.taxPrice ?? row.taxAmount,
+ taxInclusivePrice: row.taxInclusivePrice ?? row.totalAmount,
+ remark: row.remark ?? "",
+ invoiceContent: row.invoiceContent ?? row.content,
+ customerId: row.customerId,
+ storageAttachmentId: row.storageAttachmentId,
+ status: 1,
+});
+
+const buildSubmitPayload = () => ({
+ invoiceNumber: form.invoiceNo,
+ customerId: form.customerId,
+ issueDate: form.invoiceDate,
+ invoiceType: form.invoiceType,
+ taxRate: form.taxRate,
+ taxExclusivelPrice: form.amount,
+ taxPrice: form.taxAmount,
+ taxInclusivePrice: form.totalAmount,
+ invoiceContent: form.content,
+ remark: form.remark || "",
+ accountInvoiceApplicationId: form.accountInvoiceApplicationId,
+ storageAttachmentId: form.storageAttachmentId,
+});
+
+const getCustomerList = () => {
+ listCustomer({ current: -1, size: -1, type: 0 }).then((res) => {
+ if (res.code === 200) {
+ customerList.value = res.data?.records || [];
+ }
+ });
+};
+
+const appendFilterParams = (params) => {
+ if (filters.invoiceNumber) {
+ params.invoiceNumber = filters.invoiceNumber;
}
if (filters.customerId) {
- result = result.filter(item => item.customerId === filters.customerId);
+ params.customerId = filters.customerId;
}
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ if (filters.status !== "" && filters.status != null) {
+ params.status = filters.status;
+ }
+ return params;
+};
+
+const buildListParams = () =>
+ appendFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+const buildExportParams = () => appendFilterParams({});
+
+const handleExport = () => {
+ const params = buildExportParams();
+ proxy.download("/accountSalesInvoice/exportAccountSalesInvoice", params, `閿�椤瑰彂绁╛${Date.now()}.xlsx`);
+};
+
+const getTableData = () => {
+ tableLoading.value = true;
+ listPageAccountSalesInvoice(buildListParams())
+ .then((res) => {
+ if (res.code === 200) {
+ const records = res.data?.records ?? [];
+ dataList.value = records.map(normalizeTableRow);
+ pagination.total = res.data?.total ?? 0;
+ } else {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+};
+
+const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
};
const resetFilters = () => {
- filters.invoiceCode = "";
- filters.invoiceNo = "";
+ filters.invoiceNumber = "";
filters.customerId = "";
+ filters.dateRange = [];
+ filters.status = "";
pagination.currentPage = 1;
getTableData();
};
@@ -268,83 +481,105 @@
getTableData();
};
+const closeDialog = () => {
+ dialogVisible.value = false;
+ isView.value = false;
+};
+
const add = () => {
- isEdit.value = false;
+ isView.value = false;
dialogTitle.value = "褰曞叆鍙戠エ";
Object.assign(form, {
- invoiceCode: "",
invoiceNo: "",
customerId: "",
- invoiceDate: new Date().toISOString().split('T')[0],
- invoiceType: "special",
+ invoiceDate: new Date().toISOString().split("T")[0],
+ invoiceType: "澧炲�肩◣涓撶敤鍙戠エ",
taxRate: 13,
amount: 0,
taxAmount: 0,
totalAmount: 0,
content: "",
remark: "",
+ accountInvoiceApplicationId: undefined,
+ storageAttachmentId: undefined,
});
- dialogVisible.value = true;
-};
-
-const edit = (row) => {
- isEdit.value = true;
- currentId.value = row.id;
- dialogTitle.value = "缂栬緫鍙戠エ";
- Object.assign(form, row);
dialogVisible.value = true;
};
const view = (row) => {
- ElMessage.info(`鏌ョ湅鍙戠エ: ${row.invoiceCode}-${row.invoiceNo}`);
+ isView.value = true;
+ dialogTitle.value = "鏌ョ湅鍙戠エ";
+ fillFormFromRow(row);
+ dialogVisible.value = true;
};
-const handleDelete = (row) => {
- ElMessageBox.confirm("纭浣滃簾璇ュ彂绁ㄥ悧锛�", "鎻愮ず", {
+const handleCancel = (row) => {
+ ElMessageBox.confirm(`纭浣滃簾鍙戠エ銆�${row.invoiceNo ?? row.invoiceNumber}銆嶅悧锛焋, "浣滃簾纭", {
confirmButtonText: "纭畾",
cancelButtonText: "鍙栨秷",
type: "warning",
}).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData.splice(index, 1);
- }
- ElMessage.success("浣滃簾鎴愬姛");
- getTableData();
+ cancelAccountSalesInvoice(buildCancelPayload(row))
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("浣滃簾鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "浣滃簾澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("浣滃簾澶辫触");
+ });
});
};
-const handleImport = () => {
- ElMessage.info("瀵煎叆鍔熻兘");
-};
-
-const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎鍙戠エ銆�${row.invoiceNo ?? row.invoiceNumber}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙, "鍒犻櫎纭", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountSalesInvoice([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
};
const submitForm = () => {
formRef.value.validate((valid) => {
- if (valid) {
- const customer = customerList.find(item => item.id === form.customerId);
- const invoiceTypeMap = { special: "澧炲�肩◣涓撶敤鍙戠エ", normal: "澧炲�肩◣鏅�氬彂绁�", electronic: "鐢靛瓙鍙戠エ" };
- if (isEdit.value) {
- const index = mockData.findIndex(item => item.id === currentId.value);
- if (index !== -1) {
- mockData[index] = { ...mockData[index], ...form, customerName: customer?.name, invoiceTypeLabel: invoiceTypeMap[form.invoiceType] };
+ if (!valid) return;
+ submitLoading.value = true;
+ addAccountSalesInvoice(buildSubmitPayload())
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("褰曞叆鎴愬姛");
+ closeDialog();
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "褰曞叆澶辫触");
}
- ElMessage.success("缂栬緫鎴愬姛");
- } else {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- mockData.push({ id: newId, ...form, customerName: customer?.name, invoiceTypeLabel: invoiceTypeMap[form.invoiceType] });
- ElMessage.success("褰曞叆鎴愬姛");
- }
- dialogVisible.value = false;
- getTableData();
- }
+ })
+ .catch(() => {
+ ElMessage.error("褰曞叆澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
});
};
onMounted(() => {
+ getCustomerList();
getTableData();
});
</script>
diff --git a/src/views/financialManagement/receivable/receipt.vue b/src/views/financialManagement/receivable/receipt.vue
index 2bbbb96..6ddb3fe 100644
--- a/src/views/financialManagement/receivable/receipt.vue
+++ b/src/views/financialManagement/receivable/receipt.vue
@@ -1,356 +1,855 @@
<template>
<div class="app-container">
- <el-form :model="filters" :inline="true">
+ <el-form :model="filters"
+ :inline="true">
<el-form-item label="鏀舵鍗曞彿:">
- <el-input v-model="filters.receiptCode" placeholder="璇疯緭鍏ユ敹娆惧崟鍙�" clearable style="width: 200px;" />
+ <el-input v-model="filters.collectionNumber"
+ placeholder="璇疯緭鍏ユ敹娆惧崟鍙�"
+ clearable
+ style="width: 200px;" />
</el-form-item>
<el-form-item label="瀹㈡埛:">
- <el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable style="width: 200px;">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.customerId"
+ placeholder="璇烽�夋嫨瀹㈡埛"
+ clearable
+ filterable
+ style="width: 200px;">
+ <el-option v-for="item in customerList"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="鏀舵鏂瑰紡:">
- <el-select v-model="filters.receiptMethod" placeholder="璇烽�夋嫨鏀舵鏂瑰紡" clearable style="width: 150px;">
- <el-option label="閾惰杞处" value="bank_transfer" />
- <el-option label="鐜伴噾" value="cash" />
- <el-option label="鏀エ" value="check" />
- <el-option label="姹囩エ" value="draft" />
- <el-option label="鏀粯瀹�" value="alipay" />
- <el-option label="寰俊" value="wechat" />
+ <el-select v-model="filters.collectionMethod"
+ placeholder="璇烽�夋嫨鏀舵鏂瑰紡"
+ clearable
+ style="width: 150px;">
+ <el-option v-for="item in payment_methods"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
</el-select>
</el-form-item>
+ <el-form-item label="鏀舵鏃ユ湡:">
+ <el-date-picker v-model="filters.dateRange"
+ type="daterange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable
+ style="width: 240px;" />
+ </el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary"
+ @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
<div class="table_list">
<div class="actions">
<div>
- <el-statistic title="鏈湡鏀舵鍚堣" :value="totalReceiptAmount" precision="2" prefix="楼" />
+ <el-statistic title="鏈〉鏀舵鍚堣"
+ :value="totalReceiptAmount"
+ :precision="2"
+ prefix="楼" />
</div>
<div>
- <el-button type="primary" @click="add" icon="Plus">鏂板鏀舵</el-button>
- <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+ <el-button type="primary"
+ @click="add"
+ icon="Plus">鏂板鏀舵</el-button>
+ <el-button type="success"
+ @click="handleExport"
+ icon="Download">瀵煎嚭</el-button>
</div>
</div>
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableData="dataList"
- :page="{
+ <PIMTable rowKey="id"
+ v-loading="tableLoading"
+ :column="columns"
+ :tableData="dataList"
+ :page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @pagination="changePage"
- >
+ @pagination="changePage">
<template #amount="{ row }">
<span class="text-success">楼{{ formatMoney(row.amount) }}</span>
</template>
<template #receiptMethod="{ row }">
- <el-tag>{{ getReceiptMethodLabel(row.receiptMethod) }}</el-tag>
- </template>
- <template #status="{ row }">
- <el-tag :type="row.status === 'confirmed' ? 'success' : 'warning'">{{ row.status === 'confirmed' ? '宸茬‘璁�' : '寰呯‘璁�' }}</el-tag>
+ <span>{{ getReceiptMethodLabel(row.receiptMethod) }}</span>
</template>
<template #operation="{ row }">
- <el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
- <el-button type="success" link @click="handleConfirm(row)" v-if="row.status === 'pending'">纭</el-button>
- <el-button type="danger" link @click="handleDelete(row)" v-if="row.status === 'pending'">鍒犻櫎</el-button>
+ <el-button type="primary"
+ link
+ @click="view(row)">鏌ョ湅</el-button>
+ <el-button :disabled="row.accountStatemen"
+ type="primary"
+ link
+ @click="edit(row)">缂栬緫</el-button>
+ <el-button :disabled="row.accountStatemen"
+ type="danger"
+ link
+ @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
-
- <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
- <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+ <FormDialog :title="dialogTitle"
+ v-model="dialogVisible"
+ width="800px"
+ :operation-type="isView ? 'detail' : ''"
+ @confirm="submitForm"
+ @cancel="closeDialog">
+ <el-form :model="form"
+ :rules="rules"
+ ref="formRef"
+ label-width="120px">
<el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鏀舵鍗曞彿" prop="receiptCode">
- <el-input v-model="form.receiptCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="瀹㈡埛" prop="customerId">
- <el-select v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" :disabled="isEdit">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
- </el-select>
+ <el-col :span="24">
+ <el-form-item label="鏀舵鍗曞彿"
+ prop="receiptCode">
+ <el-input v-model="form.receiptCode"
+ placeholder="绯荤粺鑷姩鐢熸垚"
+ disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鏀舵鏃ユ湡" prop="receiptDate">
- <el-date-picker v-model="form.receiptDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏀舵閲戦" prop="amount">
- <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鏀舵鏂瑰紡" prop="receiptMethod">
- <el-select v-model="form.receiptMethod" placeholder="璇烽�夋嫨鏀舵鏂瑰紡" style="width: 100%;">
- <el-option label="閾惰杞处" value="bank_transfer" />
- <el-option label="鐜伴噾" value="cash" />
- <el-option label="鏀エ" value="check" />
- <el-option label="姹囩エ" value="draft" />
- <el-option label="鏀粯瀹�" value="alipay" />
- <el-option label="寰俊" value="wechat" />
+ <el-form-item label="瀹㈡埛"
+ prop="customerId">
+ <el-select v-model="form.customerId"
+ placeholder="璇烽�夋嫨瀹㈡埛"
+ style="width: 100%;"
+ :disabled="isEdit || isView"
+ filterable
+ @change="handleCustomerChange">
+ <el-option v-for="item in customerList"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="閾惰璐﹀彿" prop="bankAccount" v-if="form.receiptMethod === 'bank_transfer'">
- <el-input v-model="form.bankAccount" placeholder="璇疯緭鍏ラ摱琛岃处鍙�" />
+ <el-form-item label="鍏宠仈鍗曟嵁"
+ prop="stockOutRecordIds">
+ <el-input :model-value="outboundBatchDisplayText"
+ placeholder="璇峰厛閫夋嫨瀹㈡埛"
+ readonly
+ :disabled="!form.customerId || isEdit || isView"
+ class="outbound-batch-input"
+ @click="handleOutboundInputClick">
+ <template v-if="!isEdit && !isView"
+ #append>
+ <el-button :disabled="!form.customerId"
+ :loading="outboundBatchLoading"
+ @click.stop="openOutboundSelectDialog">
+ 閫夋嫨
+ </el-button>
+ </template>
+ </el-input>
</el-form-item>
</el-col>
</el-row>
- <el-form-item label="鍏宠仈鍗曟嵁" prop="relatedDocs">
- <el-select v-model="form.relatedDocs" multiple placeholder="璇烽�夋嫨鍏宠仈鍗曟嵁" style="width: 100%;">
- <el-option v-for="item in outList" :key="item.outCode" :label="item.outCode" :value="item.outCode" />
- </el-select>
- </el-form-item>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鏀舵鏃ユ湡"
+ prop="receiptDate">
+ <el-date-picker v-model="form.receiptDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏀舵閲戦"
+ prop="amount">
+ <el-input-number v-model="form.amount"
+ :min="0"
+ :precision="2"
+ style="width: 100%;"
+ :disabled="isView"
+ placeholder="鏍规嵁鍏宠仈鍗曟嵁鑷姩姹囨�伙紝鍙慨鏀�" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鏀舵鏂瑰紡"
+ prop="receiptMethod">
+ <el-select v-model="form.receiptMethod"
+ placeholder="璇烽�夋嫨鏀舵鏂瑰紡"
+ style="width: 100%;"
+ :disabled="isView">
+ <el-option v-for="item in payment_methods"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ娉�"
+ :disabled="isView" />
</el-form-item>
</el-form>
- <template #footer>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <template v-if="!isView"
+ #footer>
+ <el-button type="primary"
+ :loading="submitLoading"
+ @click="submitForm">纭畾</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
</template>
</FormDialog>
+ <el-dialog v-model="outboundSelectVisible"
+ title="閫夋嫨鍏宠仈鍗曟嵁"
+ width="1200px"
+ append-to-body
+ destroy-on-close
+ :close-on-click-modal="false"
+ @closed="handleOutboundDialogClosed">
+ <el-table ref="outboundTableRef"
+ v-loading="outboundBatchLoading"
+ :data="outboundBatchList"
+ row-key="id"
+ border
+ stripe
+ max-height="480"
+ @selection-change="handleOutboundDialogSelectionChange">
+ <el-table-column type="selection"
+ width="55"
+ align="center" />
+ <el-table-column prop="outboundBatches"
+ label="鍑哄簱鍗曞彿"
+ min-width="140"
+ show-overflow-tooltip />
+ <el-table-column prop="customerName"
+ label="瀹㈡埛鍚嶇О"
+ min-width="120"
+ show-overflow-tooltip />
+ <el-table-column prop="productName"
+ label="浜у搧鍚嶇О"
+ min-width="120"
+ show-overflow-tooltip />
+ <el-table-column prop="specificationModel"
+ label="瑙勬牸鍨嬪彿"
+ min-width="140"
+ show-overflow-tooltip />
+ <el-table-column prop="salesContractNo"
+ label="閿�鍞悎鍚屽彿"
+ min-width="140"
+ show-overflow-tooltip />
+ <el-table-column prop="shippingNo"
+ label="鍙戣揣鍗曞彿"
+ min-width="130"
+ show-overflow-tooltip />
+ <el-table-column prop="shippingDate"
+ label="鍙戣揣鏃ユ湡"
+ width="110"
+ align="center" />
+ <el-table-column prop="outboundAmount"
+ label="鍑哄簱閲戦"
+ width="110"
+ align="right">
+ <template #default="{ row }">楼{{ formatMoney(row.outboundAmount) }}</template>
+ </el-table-column>
+ <el-table-column prop="taxRate"
+ label="绋庣巼"
+ width="80"
+ align="center">
+ <template #default="{ row }">{{ row.taxRate }}%</template>
+ </el-table-column>
+ </el-table>
+ <template #footer>
+ <el-button type="primary"
+ @click="confirmOutboundSelection">纭畾</el-button>
+ <el-button @click="outboundSelectVisible = false">鍙栨秷</el-button>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, computed } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import {
+ ref,
+ reactive,
+ computed,
+ onMounted,
+ nextTick,
+ getCurrentInstance,
+ } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import { listCustomer } from "@/api/basicData/customer.js";
+ import {
+ getOutboundBatchesByCustomer,
+ addAccountSalesCollection,
+ listPageAccountSalesCollection,
+ updateAccountSalesCollection,
+ deleteAccountSalesCollection,
+ } from "@/api/financialManagement/accountSalesCollection.js";
-defineOptions({
- name: "鏀舵鍗�",
-});
+ defineOptions({
+ name: "鏀舵鍗�",
+ });
-const filters = reactive({
- receiptCode: "",
- customerId: "",
- receiptMethod: "",
-});
+ const { proxy } = getCurrentInstance();
+ const { payment_methods } = proxy.useDict("payment_methods");
-const pagination = reactive({
- currentPage: 1,
- pageSize: 10,
- total: 0,
-});
-
-const columns = [
- { label: "鏀舵鍗曞彿", prop: "receiptCode", width: "150" },
- { label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
- { label: "鏀舵鏃ユ湡", prop: "receiptDate", width: "120" },
- { label: "鏀舵閲戦", prop: "amount", slot: "amount" },
- { label: "鏀舵鏂瑰紡", prop: "receiptMethod", slot: "receiptMethod" },
- { label: "鐘舵��", prop: "status", slot: "status" },
- { label: "澶囨敞", prop: "remark", showOverflowTooltip: true },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "220", fixed: "right" },
-];
-
-const dataList = ref([]);
-const dialogVisible = ref(false);
-const dialogTitle = ref("");
-const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
-
-const customerList = [
- { id: 1, name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
- { id: 2, name: "涓婃捣璐告槗鍏徃" },
- { id: 3, name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
- { id: 4, name: "娣卞湷鐢靛瓙鍏徃" },
-];
-
-const outList = [
- { outCode: "CK2024001", customerId: 1 },
- { outCode: "CK2024002", customerId: 2 },
- { outCode: "CK2024003", customerId: 3 },
-];
-
-const form = reactive({
- receiptCode: "",
- customerId: "",
- receiptDate: "",
- amount: 0,
- receiptMethod: "bank_transfer",
- bankAccount: "",
- relatedDocs: [],
- remark: "",
-});
-
-const rules = {
- customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
- receiptDate: [{ required: true, message: "璇烽�夋嫨鏀舵鏃ユ湡", trigger: "change" }],
- amount: [{ required: true, message: "璇疯緭鍏ユ敹娆鹃噾棰�", trigger: "blur" }],
- receiptMethod: [{ required: true, message: "璇烽�夋嫨鏀舵鏂瑰紡", trigger: "change" }],
-};
-
-const mockData = [
- { id: 1, receiptCode: "SK2024001", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", receiptDate: "2024-01-16", amount: 3000, receiptMethod: "bank_transfer", status: "confirmed", relatedDocs: ["CK2024001"], remark: "" },
- { id: 2, receiptCode: "SK2024002", customerId: 2, customerName: "涓婃捣璐告槗鍏徃", receiptDate: "2024-01-18", amount: 5000, receiptMethod: "cash", status: "pending", relatedDocs: ["CK2024002"], remark: "" },
- { id: 3, receiptCode: "SK2024003", customerId: 3, customerName: "骞垮窞瀹炰笟鏈夐檺鍏徃", receiptDate: "2024-01-20", amount: 8000, receiptMethod: "alipay", status: "confirmed", relatedDocs: ["CK2024003"], remark: "" },
-];
-
-const totalReceiptAmount = computed(() => {
- return dataList.value.reduce((sum, item) => sum + Number(item.amount), 0);
-});
-
-const formatMoney = (value) => {
- if (value === undefined || value === null) return "0.00";
- return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
-};
-
-const getReceiptMethodLabel = (method) => {
- const map = {
- bank_transfer: "閾惰杞处",
- cash: "鐜伴噾",
- check: "鏀エ",
- draft: "姹囩エ",
- alipay: "鏀粯瀹�",
- wechat: "寰俊",
- };
- return map[method] || method;
-};
-
-const getTableData = () => {
- let result = [...mockData];
- if (filters.receiptCode) {
- result = result.filter(item => item.receiptCode.includes(filters.receiptCode));
- }
- if (filters.customerId) {
- result = result.filter(item => item.customerId === filters.customerId);
- }
- if (filters.receiptMethod) {
- result = result.filter(item => item.receiptMethod === filters.receiptMethod);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
-};
-
-const resetFilters = () => {
- filters.receiptCode = "";
- filters.customerId = "";
- filters.receiptMethod = "";
- pagination.currentPage = 1;
- getTableData();
-};
-
-const changePage = ({ current, size }) => {
- pagination.currentPage = current;
- pagination.pageSize = size;
- getTableData();
-};
-
-const add = () => {
- isEdit.value = false;
- dialogTitle.value = "鏂板鏀舵";
- Object.assign(form, {
- receiptCode: "SK" + Date.now().toString().slice(-8),
+ const filters = reactive({
+ collectionNumber: "",
customerId: "",
- receiptDate: new Date().toISOString().split('T')[0],
+ collectionMethod: "",
+ dateRange: [],
+ });
+
+ const pagination = reactive({
+ currentPage: 1,
+ pageSize: 10,
+ total: 0,
+ });
+
+ const columns = [
+ { label: "鏀舵鍗曞彿", prop: "receiptCode", width: "150" },
+ { label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
+ { label: "鏀舵鏃ユ湡", prop: "receiptDate", width: "120" },
+ { label: "鏀舵閲戦", prop: "amount", dataType: "slot", slot: "amount" },
+ {
+ label: "鏀舵鏂瑰紡",
+ prop: "receiptMethod",
+ dataType: "slot",
+ slot: "receiptMethod",
+ width: "120",
+ },
+ { label: "澶囨敞", prop: "remark", showOverflowTooltip: true },
+ {
+ label: "鎿嶄綔",
+ prop: "operation",
+ dataType: "slot",
+ slot: "operation",
+ width: "200",
+ fixed: "right",
+ },
+ ];
+
+ const dataList = ref([]);
+ const tableLoading = ref(false);
+ const dialogVisible = ref(false);
+ const dialogTitle = ref("");
+ const formRef = ref(null);
+ const isEdit = ref(false);
+ const isView = ref(false);
+ const currentId = ref(null);
+ const submitLoading = ref(false);
+
+ const customerList = ref([]);
+ const outboundBatchList = ref([]);
+ const outboundBatchOptions = ref([]);
+ const outboundBatchLoading = ref(false);
+ const outboundSelectVisible = ref(false);
+ const outboundTableRef = ref(null);
+ const dialogOutboundSelection = ref([]);
+
+ const getReceiptMethodLabel = value => {
+ if (value === undefined || value === null || value === "") return "-";
+ const item = payment_methods.value?.find(
+ m => String(m.value) === String(value)
+ );
+ return item?.label ?? value;
+ };
+
+ const getDefaultReceiptMethod = () => payment_methods.value?.[0]?.value ?? "";
+
+ const form = reactive({
+ receiptCode: "",
+ customerId: "",
+ receiptDate: "",
amount: 0,
- receiptMethod: "bank_transfer",
- bankAccount: "",
- relatedDocs: [],
+ receiptMethod: "",
+ stockOutRecordIds: [],
+ outboundBatches: "",
remark: "",
});
- dialogVisible.value = true;
-};
-const edit = (row) => {
- isEdit.value = true;
- currentId.value = row.id;
- dialogTitle.value = "缂栬緫鏀舵";
- Object.assign(form, row);
- dialogVisible.value = true;
-};
+ const rules = {
+ customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
+ stockOutRecordIds: [
+ {
+ required: true,
+ type: "array",
+ min: 1,
+ message: "璇烽�夋嫨鍏宠仈鍗曟嵁",
+ trigger: "change",
+ },
+ ],
+ receiptDate: [
+ { required: true, message: "璇烽�夋嫨鏀舵鏃ユ湡", trigger: "change" },
+ ],
+ amount: [{ required: true, message: "璇疯緭鍏ユ敹娆鹃噾棰�", trigger: "blur" }],
+ receiptMethod: [
+ { required: true, message: "璇烽�夋嫨鏀舵鏂瑰紡", trigger: "change" },
+ ],
+ };
-const view = (row) => {
- ElMessage.info(`鏌ョ湅鏀舵鍗�: ${row.receiptCode}`);
-};
+ const totalReceiptAmount = computed(() =>
+ dataList.value.reduce((sum, item) => sum + Number(item.amount || 0), 0)
+ );
-const handleConfirm = (row) => {
- ElMessageBox.confirm("纭璇ユ敹娆惧崟鍚楋紵", "鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "info",
- }).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData[index].status = "confirmed";
- }
- ElMessage.success("纭鎴愬姛");
- getTableData();
+ const formatMoney = value => {
+ if (value === undefined || value === null) return "0.00";
+ return Number(value)
+ .toFixed(2)
+ .replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+ };
+
+ const parseStockOutRecordIds = value => {
+ if (!value) return [];
+ if (Array.isArray(value)) return value;
+ return String(value)
+ .split(/[,锛宂/)
+ .map(s => s.trim())
+ .filter(Boolean)
+ .map(s => (/^\d+$/.test(s) ? Number(s) : s));
+ };
+
+ const formatOutboundBatches = value => {
+ if (value === undefined || value === null || value === "") return "";
+ if (Array.isArray(value)) return value.filter(Boolean).join("銆�");
+ return String(value)
+ .split(/[,锛宂/)
+ .map(s => s.trim())
+ .filter(Boolean)
+ .join("銆�");
+ };
+
+ const normalizeTableRow = row => ({
+ ...row,
+ receiptCode: row.collectionNumber ?? row.receiptCode,
+ receiptDate: row.collectionDate ?? row.receiptDate,
+ amount: row.collectionAmount ?? row.amount,
+ receiptMethod: row.collectionMethod ?? row.receiptMethod ?? "",
+ stockOutRecordIds: row.stockOutRecordIds ?? row.stockOutRecordId ?? "",
+ outboundBatches: formatOutboundBatches(row.outboundBatches),
});
-};
-const handleDelete = (row) => {
- ElMessageBox.confirm("纭鍒犻櫎璇ユ敹娆惧崟鍚楋紵", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }).then(() => {
- const index = mockData.findIndex(item => item.id === row.id);
- if (index !== -1) {
- mockData.splice(index, 1);
- }
- ElMessage.success("鍒犻櫎鎴愬姛");
- getTableData();
- });
-};
-
-const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
-};
-
-const submitForm = () => {
- formRef.value.validate((valid) => {
- if (valid) {
- const customer = customerList.find(item => item.id === form.customerId);
- if (isEdit.value) {
- const index = mockData.findIndex(item => item.id === currentId.value);
- if (index !== -1) {
- mockData[index] = { ...mockData[index], ...form, customerName: customer?.name };
- }
- ElMessage.success("缂栬緫鎴愬姛");
- } else {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- mockData.push({ id: newId, ...form, customerName: customer?.name, status: "pending" });
- ElMessage.success("鏂板鎴愬姛");
+ const getCustomerList = () => {
+ listCustomer({ current: -1, size: -1, type: 0 }).then(res => {
+ if (res.code === 200) {
+ customerList.value = res.data?.records || [];
}
- dialogVisible.value = false;
- getTableData();
- }
- });
-};
+ });
+ };
-onMounted(() => {
- getTableData();
-});
+ const normalizeOutboundBatchOptions = data => {
+ const list = Array.isArray(data) ? data : [];
+ return list.map((item, index) => {
+ if (typeof item === "string" || typeof item === "number") {
+ const text = String(item);
+ return { label: text, value: text, outboundAmount: 0 };
+ }
+ const label =
+ item.outboundBatches ??
+ item.batchNo ??
+ item.shippingNo ??
+ item.outboundNo ??
+ item.label ??
+ `鍑哄簱鍗�${index + 1}`;
+ const value = item.id ?? item.stockOutRecordId ?? label;
+ return {
+ label: String(label),
+ value,
+ outboundAmount: Number(item.outboundAmount) || 0,
+ };
+ });
+ };
+
+ const isSameOutboundId = (a, b) => String(a) === String(b);
+
+ const getOutboundRowId = row => row?.id ?? row?.stockOutRecordId;
+
+ const outboundBatchDisplayText = computed(() => {
+ if (isEdit.value || isView.value) {
+ return form.outboundBatches || "";
+ }
+ if (form.outboundBatches) return form.outboundBatches;
+ const ids = form.stockOutRecordIds || [];
+ if (!ids.length) return "";
+ const labels = outboundBatchOptions.value
+ .filter(opt => ids.some(id => isSameOutboundId(id, opt.value)))
+ .map(opt => opt.label);
+ if (labels.length) return labels.join("銆�");
+ return ids.join("銆�");
+ });
+
+ const handleOutboundInputClick = () => {
+ if (isEdit.value || isView.value) return;
+ openOutboundSelectDialog();
+ };
+
+ /** 涓哄凡閫� ID 琛ュ叏閫夐」锛堢紪杈�/鏌ョ湅鍥炴樉锛� */
+ const ensureOutboundOptionsForSelected = () => {
+ const ids = form.stockOutRecordIds || [];
+ ids.forEach(id => {
+ const exists = outboundBatchOptions.value.some(opt =>
+ isSameOutboundId(opt.value, id)
+ );
+ if (exists) return;
+ const fromList = outboundBatchList.value.find(row =>
+ isSameOutboundId(getOutboundRowId(row), id)
+ );
+ if (fromList) {
+ const [option] = normalizeOutboundBatchOptions([fromList]);
+ if (option) outboundBatchOptions.value.push(option);
+ return;
+ }
+ outboundBatchOptions.value.push({
+ label: String(id),
+ value: id,
+ outboundAmount: 0,
+ });
+ });
+ };
+
+ const syncCollectionAmount = () => {
+ const selected = form.stockOutRecordIds || [];
+ const sum = outboundBatchOptions.value
+ .filter(opt => selected.some(id => isSameOutboundId(id, opt.value)))
+ .reduce((acc, opt) => acc + (Number(opt.outboundAmount) || 0), 0);
+ form.amount = sum > 0 ? Number(sum.toFixed(2)) : 0;
+ };
+
+ const restoreOutboundTableSelection = () => {
+ nextTick(() => {
+ const table = outboundTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ const selectedIds = new Set(
+ (form.stockOutRecordIds || []).map(id => String(id))
+ );
+ outboundBatchList.value.forEach(row => {
+ const rowId = getOutboundRowId(row);
+ if (
+ rowId !== undefined &&
+ rowId !== null &&
+ selectedIds.has(String(rowId))
+ ) {
+ table.toggleRowSelection(row, true);
+ }
+ });
+ });
+ };
+
+ const loadOutboundBatches = (customerId, keepSelected = false) => {
+ if (!customerId) {
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ if (!keepSelected) {
+ form.stockOutRecordIds = [];
+ form.amount = 0;
+ }
+ return Promise.resolve();
+ }
+ outboundBatchLoading.value = true;
+ return getOutboundBatchesByCustomer({ customerId })
+ .then(res => {
+ if (res.code === 200) {
+ const list = res.data?.records ?? res.data ?? [];
+ outboundBatchList.value = Array.isArray(list) ? list : [];
+ outboundBatchOptions.value = normalizeOutboundBatchOptions(list);
+ } else {
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ }
+ })
+ .catch(() => {
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ })
+ .finally(() => {
+ outboundBatchLoading.value = false;
+ if (keepSelected) {
+ ensureOutboundOptionsForSelected();
+ restoreOutboundTableSelection();
+ }
+ });
+ };
+
+ const handleCustomerChange = customerId => {
+ form.stockOutRecordIds = [];
+ form.outboundBatches = "";
+ form.amount = 0;
+ loadOutboundBatches(customerId);
+ };
+
+ const openOutboundSelectDialog = () => {
+ if (!form.customerId || isEdit.value || isView.value) return;
+ outboundSelectVisible.value = true;
+ loadOutboundBatches(form.customerId, true).then(() => {
+ restoreOutboundTableSelection();
+ });
+ };
+
+ const handleOutboundDialogSelectionChange = selection => {
+ dialogOutboundSelection.value = selection;
+ };
+
+ const confirmOutboundSelection = () => {
+ if (dialogOutboundSelection.value.length === 0) {
+ ElMessage.warning("璇疯嚦灏戦�夋嫨涓�鏉″叧鑱斿崟鎹�");
+ return;
+ }
+ form.stockOutRecordIds = dialogOutboundSelection.value
+ .map(row => getOutboundRowId(row))
+ .filter(id => id !== undefined && id !== null);
+ form.outboundBatches = dialogOutboundSelection.value
+ .map(row => row.outboundBatches ?? row.batchNo ?? row.shippingNo ?? "")
+ .filter(Boolean)
+ .join("銆�");
+ outboundSelectVisible.value = false;
+ syncCollectionAmount();
+ formRef.value?.validateField("stockOutRecordIds");
+ };
+
+ const handleOutboundDialogClosed = () => {
+ dialogOutboundSelection.value = [];
+ };
+
+ const appendFilterParams = params => {
+ if (filters.collectionNumber) {
+ params.collectionNumber = filters.collectionNumber;
+ }
+ if (filters.customerId) {
+ params.customerId = filters.customerId;
+ }
+ if (filters.collectionMethod) {
+ params.collectionMethod = filters.collectionMethod;
+ }
+ if (filters.dateRange?.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ return params;
+ };
+
+ const buildListParams = () =>
+ appendFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+ const buildExportParams = () => appendFilterParams({});
+
+ const buildSubmitPayload = (forUpdate = false) => {
+ const payload = {
+ customerId: form.customerId,
+ collectionDate: form.receiptDate,
+ collectionAmount: form.amount,
+ collectionMethod: form.receiptMethod,
+ collectionNumber: form.receiptCode || "",
+ remark: form.remark || "",
+ stockOutRecordIds: (form.stockOutRecordIds || []).join(","),
+ };
+ if (forUpdate) {
+ payload.id = currentId.value;
+ }
+ return payload;
+ };
+
+ const fillFormFromRow = row => {
+ const stockOutRecordIds = parseStockOutRecordIds(
+ row.stockOutRecordIds ?? row.stockOutRecordId
+ );
+ Object.assign(form, {
+ receiptCode: row.receiptCode ?? row.collectionNumber ?? "",
+ customerId: row.customerId,
+ receiptDate: row.receiptDate ?? row.collectionDate ?? "",
+ amount: Number(row.amount ?? row.collectionAmount ?? 0),
+ receiptMethod: row.receiptMethod ?? row.collectionMethod ?? "",
+ stockOutRecordIds,
+ outboundBatches: formatOutboundBatches(row.outboundBatches),
+ remark: row.remark ?? "",
+ });
+ };
+
+ const closeDialog = () => {
+ dialogVisible.value = false;
+ outboundSelectVisible.value = false;
+ isView.value = false;
+ isEdit.value = false;
+ };
+
+ const handleExport = () => {
+ const params = buildExportParams();
+ proxy.download(
+ "/accountSalesCollection/exportAccountSalesCollection",
+ params,
+ `鏀舵鍗昣${Date.now()}.xlsx`
+ );
+ };
+
+ const getTableData = () => {
+ tableLoading.value = true;
+ listPageAccountSalesCollection(buildListParams())
+ .then(res => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = (res.data.records ?? []).map(normalizeTableRow);
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ pagination.total = 0;
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
+ };
+
+ const resetFilters = () => {
+ filters.collectionNumber = "";
+ filters.customerId = "";
+ filters.collectionMethod = "";
+ filters.dateRange = [];
+ pagination.currentPage = 1;
+ getTableData();
+ };
+
+ const changePage = ({ current, size }) => {
+ pagination.currentPage = current;
+ pagination.pageSize = size;
+ getTableData();
+ };
+
+ const add = () => {
+ isEdit.value = false;
+ isView.value = false;
+ dialogTitle.value = "鏂板鏀舵";
+ Object.assign(form, {
+ receiptCode: "SK" + Date.now().toString().slice(-8),
+ customerId: "",
+ receiptDate: new Date().toISOString().split("T")[0],
+ amount: 0,
+ receiptMethod: getDefaultReceiptMethod(),
+ stockOutRecordIds: [],
+ outboundBatches: "",
+ remark: "",
+ });
+ outboundBatchList.value = [];
+ outboundBatchOptions.value = [];
+ dialogVisible.value = true;
+ };
+
+ const edit = row => {
+ isEdit.value = true;
+ isView.value = false;
+ currentId.value = row.id;
+ dialogTitle.value = "缂栬緫鏀舵";
+ fillFormFromRow(row);
+ dialogVisible.value = true;
+ };
+
+ const view = row => {
+ isView.value = true;
+ isEdit.value = false;
+ dialogTitle.value = "鏌ョ湅鏀舵";
+ fillFormFromRow(row);
+ dialogVisible.value = true;
+ };
+
+ const handleDelete = row => {
+ ElMessageBox.confirm(
+ `纭鍒犻櫎鏀舵鍗曘��${row.receiptCode ?? row.collectionNumber}銆嶅悧锛焋,
+ "鎻愮ず",
+ {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }
+ ).then(() => {
+ deleteAccountSalesCollection([row.id])
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+ };
+
+ const submitForm = () => {
+ formRef.value.validate(valid => {
+ if (!valid) return;
+ submitLoading.value = true;
+ const request = isEdit.value
+ ? updateAccountSalesCollection(buildSubmitPayload(true))
+ : addAccountSalesCollection(buildSubmitPayload());
+ request
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success(isEdit.value ? "淇敼鎴愬姛" : "鏂板鎴愬姛");
+ closeDialog();
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || (isEdit.value ? "淇敼澶辫触" : "鏂板澶辫触"));
+ }
+ })
+ .catch(() => {
+ ElMessage.error(isEdit.value ? "淇敼澶辫触" : "鏂板澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
+ });
+ };
+
+ onMounted(() => {
+ getCustomerList();
+ getTableData();
+ });
</script>
<style lang="scss" scoped>
-.actions {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 15px;
-}
+ .actions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ }
-.text-success {
- color: #67c23a;
- font-weight: bold;
-}
+ .text-success {
+ color: #67c23a;
+ font-weight: bold;
+ }
+
+ .outbound-batch-input:not(.is-disabled) {
+ :deep(.el-input__wrapper) {
+ cursor: pointer;
+ }
+ }
</style>
diff --git a/src/views/financialManagement/receivable/reconciliation.vue b/src/views/financialManagement/receivable/reconciliation.vue
index 883e12e..b1bff0e 100644
--- a/src/views/financialManagement/receivable/reconciliation.vue
+++ b/src/views/financialManagement/receivable/reconciliation.vue
@@ -2,8 +2,8 @@
<div class="app-container">
<el-form :model="filters" :inline="true">
<el-form-item label="瀹㈡埛:">
- <el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable style="width: 200px;">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable filterable style="width: 200px;">
+ <el-option v-for="item in customerList" :key="item.id" :label="item.customerName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="瀵硅处鏈熼棿:">
@@ -29,6 +29,7 @@
rowKey="id"
:column="columns"
:tableData="dataList"
+ :tableLoading="tableLoading"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -36,21 +37,22 @@
}"
@pagination="changePage"
>
- <template #beginBalance="{ row }">
- <span :class="row.beginBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.beginBalance) }}</span>
+ <template #openingBalance="{ row }">
+ <span :class="row.openingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.openingBalance) }}</span>
</template>
- <template #currentReceivable="{ row }">
- <span class="text-primary">楼{{ formatMoney(row.currentReceivable) }}</span>
+ <template #currentPlan="{ row }">
+ <span class="text-primary">楼{{ formatMoney(row.currentPlan) }}</span>
</template>
- <template #currentReceipt="{ row }">
- <span class="text-success">楼{{ formatMoney(row.currentReceipt) }}</span>
+ <template #currentActually="{ row }">
+ <span class="text-success">楼{{ formatMoney(row.currentActually) }}</span>
</template>
- <template #endBalance="{ row }">
- <span :class="row.endBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.endBalance) }}</span>
+ <template #closingBalance="{ row }">
+ <span :class="row.closingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.closingBalance) }}</span>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="viewDetail(row)">鏌ョ湅鏄庣粏</el-button>
- <el-button type="primary" link @click="printStatement(row)">鎵撳嵃</el-button>
+ <!-- <el-button type="primary" link @click="printStatement(row)">鎵撳嵃</el-button> -->
+ <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
@@ -60,7 +62,7 @@
<h3>{{ currentCustomer }} 搴旀敹瀵硅处鍗�</h3>
<p>瀵硅处鏈熼棿: {{ currentPeriod }}</p>
</div>
- <el-table :data="detailData" border style="width: 100%">
+ <el-table :data="detailData" border style="width: 100%" v-loading="detailLoading">
<el-table-column prop="date" label="鏃ユ湡" width="120" />
<el-table-column prop="type" label="绫诲瀷" width="100">
<template #default="{ row }">
@@ -98,52 +100,68 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="閫夋嫨瀹㈡埛" prop="customerId">
- <el-select v-model="generateForm.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" @change="onCustomerChange">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select
+ v-model="generateForm.customerId"
+ placeholder="璇烽�夋嫨瀹㈡埛"
+ style="width: 100%;"
+ filterable
+ @change="onCustomerChange"
+ >
+ <el-option v-for="item in customerList" :key="item.id" :label="item.customerName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="瀵硅处鏈堜唤" prop="period">
- <el-date-picker v-model="generateForm.period" type="month" placeholder="閫夋嫨鏈堜唤" value-format="YYYY-MM" style="width: 100%;" @change="onPeriodChange" />
+ <el-form-item label="瀵硅处鏈堜唤" prop="statementMonth">
+ <el-date-picker v-model="generateForm.statementMonth" type="month" placeholder="閫夋嫨鏈堜唤" value-format="YYYY-MM" style="width: 100%;" @change="onStatementMonthChange" />
</el-form-item>
</el-col>
</el-row>
</el-form>
- <div v-if="salesData.length > 0" class="sales-section">
- <div class="section-title">鏈湀閿�鍞暟鎹�</div>
- <el-table :data="salesData" border style="width: 100%; margin-bottom: 15px;" v-loading="salesLoading" @selection-change="handleSalesSelectionChange">
+ <div v-if="statementDetailLoaded" class="sales-section">
+ <div v-if="salesData.length > 0" class="section-title">鏈湀閿�鍞暟鎹�</div>
+ <el-table
+ v-if="salesData.length > 0"
+ ref="salesTableRef"
+ :data="salesData"
+ border
+ row-key="id"
+ style="width: 100%; margin-bottom: 15px;"
+ v-loading="salesLoading"
+ @selection-change="handleSalesSelectionChange"
+ >
<el-table-column type="selection" width="55" align="center" />
- <el-table-column prop="date" label="鏃ユ湡" width="120" />
- <el-table-column prop="code" label="鍗曟嵁缂栧彿" width="150" />
+ <el-table-column prop="occurrenceDate" label="鏃ユ湡" width="120" />
+ <el-table-column prop="receiptNumber" label="鍗曟嵁缂栧彿" width="150" />
<el-table-column prop="type" label="绫诲瀷" width="100">
<template #default="{ row }">
- <el-tag :type="row.type === '鍑哄簱' ? 'success' : row.type === '鏀舵' ? 'primary' : 'danger'">{{ row.type }}</el-tag>
+ <el-tag :type="getDetailTypeTagType(row.type)">{{ row.typeLabel }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="amount" label="閲戦" width="120">
<template #default="{ row }">
- <span :class="row.type === '鍑哄簱' ? 'text-primary' : row.type === '鏀舵' ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.amount) }}</span>
+ <span :class="getDetailAmountClass(row.type)">楼{{ formatMoney(row.amount) }}</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="澶囨敞" />
</el-table>
+ <el-empty v-else description="璇ュ鎴锋湰鏈堟殏鏃犳槑缁嗘暟鎹�" :image-size="80" />
<div class="summary-row">
- <span>鏈熷垵浣欓: <strong class="text-primary">楼{{ formatMoney(generateForm.beginBalance) }}</strong></span>
- <span>鏈湡搴旀敹: <strong class="text-primary">楼{{ formatMoney(generateForm.currentReceivable) }}</strong></span>
- <span>鏈湡鏀舵: <strong class="text-success">楼{{ formatMoney(generateForm.currentReceipt) }}</strong></span>
- <span>鏈熸湯浣欓: <strong :class="calculateEndBalance(generateForm.beginBalance, generateForm.currentReceivable, generateForm.currentReceipt) >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(calculateEndBalance(generateForm.beginBalance, generateForm.currentReceivable, generateForm.currentReceipt)) }}</strong></span>
+ <span>鏈熷垵浣欓: <strong class="text-primary">楼{{ formatMoney(generateForm.openingBalance) }}</strong></span>
+ <span>鏈湡搴旀敹: <strong class="text-primary">楼{{ formatMoney(generateForm.currentPlan) }}</strong></span>
+ <span>鏈湡鏀舵: <strong class="text-success">楼{{ formatMoney(generateForm.currentActually) }}</strong></span>
+ <span>鏈熸湯浣欓: <strong :class="displayClosingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(displayClosingBalance) }}</strong></span>
</div>
</div>
- <div v-else-if="generateForm.customerId && !salesLoading" class="empty-tip">
+ <div v-else-if="generateForm.customerId && generateForm.statementMonth && !salesLoading" class="empty-tip">
<el-empty description="璇ュ鎴锋湰鏈堟殏鏃犻攢鍞暟鎹�" />
</div>
<template #footer>
- <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate">纭鐢熸垚</el-button>
+ <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate" :loading="submitLoading">纭鐢熸垚</el-button>
<el-button @click="generateDialogVisible = false">鍙栨秷</el-button>
</template>
</FormDialog>
@@ -151,9 +169,20 @@
</template>
<script setup>
-import { ref, reactive, onMounted, computed } from "vue";
-import { ElMessage } from "element-plus";
+import { ref, reactive, onMounted, computed, nextTick, getCurrentInstance } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { listCustomer } from "@/api/basicData/customer.js";
+import {
+ getAccountStatementDetailsByMonth,
+ addAccountStatement,
+ listPageAccountStatement,
+ deleteAccountStatement,
+} from "@/api/financialManagement/accountStatement.js";
+
+const ACCOUNT_TYPE_RECEIVABLE = 1;
+
+const { proxy } = getCurrentInstance();
defineOptions({
name: "搴旀敹瀵硅处",
@@ -172,56 +201,192 @@
});
const columns = [
- { label: "瀵硅处鍗曞彿", prop: "statementCode", width: "150" },
+ { label: "瀵硅处鍗曞彿", prop: "statementNumber", width: "150" },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
- { label: "瀵硅处鏈熼棿", prop: "period", width: "150" },
- { label: "鏈熷垵浣欓", prop: "beginBalance", slot: "beginBalance" },
- { label: "鏈湡搴旀敹", prop: "currentReceivable", slot: "currentReceivable" },
- { label: "鏈湡鏀舵", prop: "currentReceipt", slot: "currentReceipt" },
- { label: "鏈熸湯浣欓", prop: "endBalance", slot: "endBalance" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "150", fixed: "right" },
+ { label: "瀵硅处鏈熼棿", prop: "statementMonth", width: "150" },
+ { label: "鏈熷垵浣欓", prop: "openingBalance", dataType: "slot", slot: "openingBalance" },
+ { label: "鏈湡搴旀敹", prop: "currentPlan", dataType: "slot", slot: "currentPlan" },
+ { label: "鏈湡鏀舵", prop: "currentActually", dataType: "slot", slot: "currentActually" },
+ { label: "鏈熸湯浣欓", prop: "closingBalance", dataType: "slot", slot: "closingBalance" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "200", fixed: "right" },
];
const dataList = ref([]);
+const tableLoading = ref(false);
+const submitLoading = ref(false);
const detailDialogVisible = ref(false);
const currentCustomer = ref("");
const currentPeriod = ref("");
const detailData = ref([]);
+const detailLoading = ref(false);
const generateDialogVisible = ref(false);
const salesLoading = ref(false);
+const statementDetailLoaded = ref(false);
const salesData = ref([]);
const selectedSales = ref([]);
+const salesTableRef = ref(null);
+const customerList = ref([]);
+
+/** 鏄庣粏 type锛�1鍑哄簱 2鍏ュ簱 3鏀舵 4浠樻 5閫�璐� */
+const STATEMENT_DETAIL_TYPE_MAP = {
+ 1: "鍑哄簱",
+ 2: "鍏ュ簱",
+ 3: "鏀舵",
+ 4: "浠樻",
+ 5: "閫�璐�",
+};
+
+const calculateEndBalance = (openingBalance, currentPlan, currentActually) => {
+ return openingBalance + currentPlan - currentActually;
+};
+
+const getDetailTypeLabel = (type) => STATEMENT_DETAIL_TYPE_MAP[Number(type)] ?? "";
+
+const getDetailTypeTagType = (type) => {
+ const t = Number(type);
+ if (t === 1) return "success";
+ if (t === 3) return "primary";
+ if (t === 5) return "danger";
+ return "info";
+};
+
+const getDetailAmountClass = (type) => {
+ const t = Number(type);
+ if (t === 1) return "text-primary";
+ if (t === 3) return "text-success";
+ return "text-danger";
+};
const generateForm = reactive({
customerId: "",
customerName: "",
- period: "",
- beginBalance: 0,
- currentReceivable: 0,
- currentReceipt: 0,
+ statementMonth: "",
+ openingBalance: 0,
+ currentPlan: 0,
+ currentActually: 0,
+ closingBalance: 0,
+});
+
+const displayClosingBalance = computed(() => {
+ return calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ );
});
const canGenerate = computed(() => {
- return generateForm.customerId && generateForm.period && selectedSales.value.length > 0;
+ return generateForm.customerId && generateForm.statementMonth && selectedSales.value.length > 0;
});
-const customerList = [
- { id: 1, name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
- { id: 2, name: "涓婃捣璐告槗鍏徃" },
- { id: 3, name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
- { id: 4, name: "娣卞湷鐢靛瓙鍏徃" },
-];
-
-const mockData = [
- { id: 1, statementCode: "DZ202401001", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", period: "2024-01", beginBalance: 10000, currentReceivable: 15000, currentReceipt: 8000, endBalance: 17000 },
- { id: 2, statementCode: "DZ202401002", customerId: 2, customerName: "涓婃捣璐告槗鍏徃", period: "2024-01", beginBalance: 5000, currentReceivable: 12000, currentReceipt: 10000, endBalance: 7000 },
- { id: 3, statementCode: "DZ202402001", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", period: "2024-02", beginBalance: 17000, currentReceivable: 20000, currentReceipt: 15000, endBalance: 22000 },
-];
-
-const calculateEndBalance = (beginBalance, currentReceivable, currentReceipt) => {
- return beginBalance + currentReceivable - currentReceipt;
+const applyStatementSummary = (data) => {
+ generateForm.openingBalance = Number(data.openingBalance ?? 0);
+ generateForm.currentPlan = Number(data.currentPlan ?? 0);
+ generateForm.currentActually = Number(data.currentActually ?? 0);
+ generateForm.closingBalance = Number(
+ data.closingBalance ??
+ calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ )
+ );
};
+
+const getCustomerList = () => {
+ listCustomer({ current: -1, size: -1, type: 0 }).then((res) => {
+ if (res.code === 200) {
+ customerList.value = res.data?.records || [];
+ }
+ });
+};
+
+const normalizeSalesRows = (list) => {
+ const rows = Array.isArray(list) ? list : [];
+ return rows.map((item, index) => {
+ const type = Number(item.type);
+ return {
+ id: item.id ?? `detail-${index}`,
+ accountStatementId: item.accountStatementId,
+ occurrenceDate: item.occurrenceDate ?? "",
+ receiptNumber: item.receiptNumber ?? "",
+ type,
+ typeLabel: getDetailTypeLabel(type),
+ amount: Math.abs(Number(item.amount ?? 0)),
+ remark: item.remark ?? "",
+ };
+ });
+};
+
+const selectAllSalesRows = (keepApiSummary = false) => {
+ nextTick(() => {
+ const table = salesTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ salesData.value.forEach((row) => table.toggleRowSelection(row, true));
+ selectedSales.value = [...salesData.value];
+ if (!keepApiSummary) {
+ calculateSummary();
+ }
+ });
+};
+
+const isNumericId = (id) => id !== undefined && id !== null && id !== "" && /^\d+$/.test(String(id));
+
+const buildFilterParams = (params = {}) => {
+ const result = { ...params, accountType: ACCOUNT_TYPE_RECEIVABLE };
+ if (filters.customerId) {
+ result.customerId = filters.customerId;
+ }
+ if (filters.startMonth && filters.endMonth && filters.startMonth === filters.endMonth) {
+ result.statementMonth = filters.startMonth;
+ } else if (filters.startMonth) {
+ result.startMonth = filters.startMonth;
+ }
+ if (filters.endMonth && filters.startMonth !== filters.endMonth) {
+ result.endMonth = filters.endMonth;
+ }
+ return result;
+};
+
+const buildListParams = () =>
+ buildFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+const buildExportParams = () => buildFilterParams({});
+
+const buildDetailSubmitItem = (row) => {
+ const item = {
+ occurrenceDate: row.occurrenceDate,
+ receiptNumber: row.receiptNumber,
+ type: row.type,
+ amount: row.amount,
+ remark: row.remark ?? "",
+ };
+ if (isNumericId(row.id)) {
+ item.id = Number(row.id);
+ }
+ if (row.accountStatementId) {
+ item.accountStatementId = row.accountStatementId;
+ }
+ return item;
+};
+
+const buildAddPayload = () => ({
+ customerId: generateForm.customerId,
+ customerName: generateForm.customerName,
+ statementMonth: generateForm.statementMonth,
+ accountType: ACCOUNT_TYPE_RECEIVABLE,
+ statementNumber: "",
+ openingBalance: generateForm.openingBalance,
+ currentPlan: generateForm.currentPlan,
+ currentActually: generateForm.currentActually,
+ closingBalance: generateForm.closingBalance,
+ accountStatementDetails: selectedSales.value.map(buildDetailSubmitItem),
+});
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
@@ -229,15 +394,27 @@
};
const getTableData = () => {
- let result = [...mockData];
- if (filters.customerId) {
- result = result.filter(item => item.customerId === filters.customerId);
- }
- if (filters.startMonth && filters.endMonth) {
- result = result.filter(item => item.period >= filters.startMonth && item.period <= filters.endMonth);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ tableLoading.value = true;
+ listPageAccountStatement(buildListParams())
+ .then((res) => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = res.data.records ?? [];
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ pagination.total = 0;
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
};
const resetFilters = () => {
@@ -257,83 +434,97 @@
const generateStatement = () => {
generateForm.customerId = "";
generateForm.customerName = "";
- generateForm.period = "";
- generateForm.beginBalance = 0;
- generateForm.currentReceivable = 0;
- generateForm.currentReceipt = 0;
+ generateForm.statementMonth = "";
+ generateForm.openingBalance = 0;
+ generateForm.currentPlan = 0;
+ generateForm.currentActually = 0;
+ generateForm.closingBalance = 0;
+ statementDetailLoaded.value = false;
salesData.value = [];
selectedSales.value = [];
generateDialogVisible.value = true;
};
const onCustomerChange = (customerId) => {
- const customer = customerList.find(item => item.id === customerId);
- if (customer) {
- generateForm.customerName = customer.name;
- }
+ const customer = customerList.value.find((item) => item.id === customerId);
+ generateForm.customerName = customer?.customerName ?? "";
loadSalesData();
};
-const onPeriodChange = () => {
+const onStatementMonthChange = () => {
loadSalesData();
};
const loadSalesData = () => {
- if (!generateForm.customerId || !generateForm.period) {
+ if (!generateForm.customerId || !generateForm.statementMonth) {
salesData.value = [];
+ selectedSales.value = [];
+ statementDetailLoaded.value = false;
+ generateForm.openingBalance = 0;
+ generateForm.currentPlan = 0;
+ generateForm.currentActually = 0;
+ generateForm.closingBalance = 0;
return;
}
salesLoading.value = true;
+ selectedSales.value = [];
+ statementDetailLoaded.value = false;
- setTimeout(() => {
- const mockSalesData = [
- { id: 1, date: generateForm.period + "-03", code: "CK2024001", type: "鍑哄簱", amount: 8000, remark: "浜у搧A閿�鍞�" },
- { id: 2, date: generateForm.period + "-08", code: "SK2024001", type: "鏀舵", amount: 5000, remark: "瀹㈡埛鍥炴" },
- { id: 3, date: generateForm.period + "-12", code: "CK2024002", type: "鍑哄簱", amount: 12000, remark: "浜у搧B閿�鍞�" },
- { id: 4, date: generateForm.period + "-15", code: "TH2024001", type: "閫�璐�", amount: 2000, remark: "璐ㄩ噺闂閫�璐�" },
- { id: 5, date: generateForm.period + "-20", code: "CK2024003", type: "鍑哄簱", amount: 5000, remark: "浜у搧C閿�鍞�" },
- { id: 6, date: generateForm.period + "-25", code: "SK2024002", type: "鏀舵", amount: 8000, remark: "瀹㈡埛鍥炴" },
- ];
+ getAccountStatementDetailsByMonth({
+ accountType: ACCOUNT_TYPE_RECEIVABLE,
+ customerId: generateForm.customerId,
+ statementMonth: generateForm.statementMonth,
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ const data = res.data ?? {};
+ const details = data.accountStatementDetails;
+ const list = Array.isArray(details) ? details : [];
+ salesData.value = normalizeSalesRows(list);
+ applyStatementSummary(data);
+ statementDetailLoaded.value = true;
- salesData.value = mockSalesData;
-
- const lastPeriod = getLastPeriod(generateForm.period);
- const lastStatement = mockData.find(item =>
- item.customerId === generateForm.customerId && item.period === lastPeriod
- );
- generateForm.beginBalance = lastStatement ? lastStatement.endBalance : 0;
-
- calculateSummary();
-
- salesLoading.value = false;
- }, 500);
-};
-
-const getLastPeriod = (period) => {
- const [year, month] = period.split("-").map(Number);
- if (month === 1) {
- return `${year - 1}-12`;
- }
- return `${year}-${String(month - 1).padStart(2, "0")}`;
+ if (salesData.value.length > 0) {
+ selectAllSalesRows(true);
+ }
+ } else {
+ salesData.value = [];
+ statementDetailLoaded.value = false;
+ ElMessage.error(res.msg || "鏌ヨ瀵硅处鏄庣粏澶辫触");
+ }
+ })
+ .catch(() => {
+ salesData.value = [];
+ statementDetailLoaded.value = false;
+ ElMessage.error("鏌ヨ瀵硅处鏄庣粏澶辫触");
+ })
+ .finally(() => {
+ salesLoading.value = false;
+ });
};
const calculateSummary = () => {
let receivable = 0;
let receipt = 0;
- selectedSales.value.forEach(item => {
- if (item.type === "鍑哄簱") {
+ selectedSales.value.forEach((item) => {
+ if (item.type === 1) {
receivable += item.amount;
- } else if (item.type === "閫�璐�") {
+ } else if (item.type === 5) {
receivable -= item.amount;
- } else if (item.type === "鏀舵") {
+ } else if (item.type === 3) {
receipt += item.amount;
}
});
- generateForm.currentReceivable = receivable;
- generateForm.currentReceipt = receipt;
+ generateForm.currentPlan = receivable;
+ generateForm.currentActually = receipt;
+ generateForm.closingBalance = calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ );
};
const handleSalesSelectionChange = (selection) => {
@@ -342,51 +533,127 @@
};
const confirmGenerate = () => {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- const endBalance = calculateEndBalance(generateForm.beginBalance, generateForm.currentReceivable, generateForm.currentReceipt);
+ if (!canGenerate.value) return;
+ submitLoading.value = true;
+ addAccountStatement(buildAddPayload())
+ .then((res) => {
+ if (res.code === 200) {
+ generateDialogVisible.value = false;
+ ElMessage.success("瀵硅处鍗曠敓鎴愭垚鍔�");
+ pagination.currentPage = 1;
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鐢熸垚澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鐢熸垚澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
+};
- mockData.unshift({
- id: newId,
- statementCode: "DZ" + Date.now(),
- customerId: generateForm.customerId,
- customerName: generateForm.customerName,
- period: generateForm.period,
- beginBalance: generateForm.beginBalance,
- currentReceivable: generateForm.currentReceivable,
- currentReceipt: generateForm.currentReceipt,
- endBalance,
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎瀵硅处鍗曘��${row.statementNumber || row.id}銆嶅悧锛焋, "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountStatement([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+};
+
+const buildDetailTableFromApi = (data, statementMonth) => {
+ const details = Array.isArray(data.accountStatementDetails) ? data.accountStatementDetails : [];
+ let runningBalance = Number(data.openingBalance ?? 0);
+ const rows = [
+ {
+ date: statementMonth ?? "",
+ type: "鏈熷垵",
+ code: "-",
+ debit: 0,
+ credit: 0,
+ balance: runningBalance,
+ remark: "鏈熷垵浣欓",
+ },
+ ];
+
+ details.forEach((item) => {
+ const amount = Math.abs(Number(item.amount ?? 0));
+ const type = Number(item.type);
+ let debit = 0;
+ let credit = 0;
+
+ if (type === 1) {
+ debit = amount;
+ runningBalance += amount;
+ } else if (type === 3 || type === 5) {
+ credit = amount;
+ runningBalance -= amount;
+ }
+
+ rows.push({
+ date: item.occurrenceDate ?? "",
+ type: getDetailTypeLabel(type),
+ code: item.receiptNumber ?? "",
+ debit,
+ credit,
+ balance: runningBalance,
+ remark: item.remark ?? "",
+ });
});
- generateDialogVisible.value = false;
- ElMessage.success("瀵硅处鍗曠敓鎴愭垚鍔�");
- getTableData();
+ return rows;
};
const viewDetail = (row) => {
- currentCustomer.value = row.customerName;
- currentPeriod.value = row.period;
+ if (!row.customerId || !row.statementMonth) {
+ ElMessage.warning("缂哄皯瀹㈡埛鎴栧璐︽湀浠斤紝鏃犳硶鏌ヨ鏄庣粏");
+ return;
+ }
- const saleOutAmount = Math.floor(row.currentReceivable * 0.6);
- const returnAmount = Math.floor(row.currentReceivable * 0.1);
- const firstReceipt = Math.floor(row.currentReceipt * 0.4);
- const secondReceipt = row.currentReceipt - firstReceipt;
-
- let runningBalance = row.beginBalance;
-
- detailData.value = [
- { date: row.period + "-01", type: "鏈熷垵", code: "-", debit: 0, credit: 0, balance: runningBalance, remark: "鏈熷垵浣欓" },
- { date: row.period + "-05", type: "鍑哄簱", code: "CK2024001", debit: saleOutAmount, credit: 0, balance: runningBalance += saleOutAmount, remark: "閿�鍞嚭搴�" },
- { date: row.period + "-10", type: "鏀舵", code: "SK2024001", debit: 0, credit: firstReceipt, balance: runningBalance -= firstReceipt, remark: "瀹㈡埛鍥炴" },
- { date: row.period + "-15", type: "鍑哄簱", code: "CK2024002", debit: row.currentReceivable - saleOutAmount - returnAmount, credit: 0, balance: runningBalance += (row.currentReceivable - saleOutAmount - returnAmount), remark: "閿�鍞嚭搴�" },
- { date: row.period + "-20", type: "閫�璐�", code: "TH2024001", debit: 0, credit: returnAmount, balance: runningBalance -= returnAmount, remark: "閿�鍞��璐�" },
- { date: row.period + "-25", type: "鏀舵", code: "SK2024002", debit: 0, credit: secondReceipt, balance: runningBalance -= secondReceipt, remark: "瀹㈡埛鍥炴" },
- ];
-
+ currentCustomer.value = row.customerName ?? "";
+ currentPeriod.value = row.statementMonth ?? "";
+ detailData.value = [];
detailDialogVisible.value = true;
+ detailLoading.value = true;
+
+ getAccountStatementDetailsByMonth({
+ accountType: ACCOUNT_TYPE_RECEIVABLE,
+ customerId: row.customerId,
+ statementMonth: row.statementMonth,
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ detailData.value = buildDetailTableFromApi(res.data ?? {}, row.statementMonth);
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ鏄庣粏澶辫触");
+ detailDialogVisible.value = false;
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鏌ヨ鏄庣粏澶辫触");
+ detailDialogVisible.value = false;
+ })
+ .finally(() => {
+ detailLoading.value = false;
+ });
};
const printStatement = (row) => {
- ElMessage.info(`鎵撳嵃瀵硅处鍗�: ${row.statementCode}`);
+ ElMessage.info(`鎵撳嵃瀵硅处鍗�: ${row.statementNumber}`);
};
const printDetail = () => {
@@ -394,10 +661,12 @@
};
const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
+ const params = buildExportParams();
+ proxy.download("/accountStatement/exportAccountStatement", params, `搴旀敹瀵硅处鍗昣${Date.now()}.xlsx`);
};
onMounted(() => {
+ getCustomerList();
getTableData();
});
</script>
diff --git a/src/views/financialManagement/revenueManagement/Modal.vue b/src/views/financialManagement/revenueManagement/Modal.vue
deleted file mode 100644
index 7dd6865..0000000
--- a/src/views/financialManagement/revenueManagement/Modal.vue
+++ /dev/null
@@ -1,177 +0,0 @@
-<template>
- <FormDialog
- v-model="dialogVisible"
- :title="dialogTitle"
- :operationType="operationType"
- width="30%"
- @confirm="sendForm"
- @close="close"
- @cancel="close"
- >
- <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef">
- <el-form-item label="鏀跺叆鏃ユ湡" prop="incomeDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.incomeDate"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- clearable
- />
- </el-form-item>
- <el-form-item label="鏀跺叆绫诲瀷" prop="incomeType">
- <el-select
- v-model="form.incomeType"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option :label="item.label" :value="item.value" v-for="(item,index) in income_types.filter(item => item.value != 3)" :key="index" />
- </el-select>
- </el-form-item>
- <el-form-item label="瀹㈡埛鍚嶇О" prop="customerName">
- <el-input v-model="form.customerName" placeholder="璇疯緭鍏�" />
- </el-form-item>
- <el-form-item label="鏀跺叆閲戦" prop="incomeMoney">
- <el-input-number :step="0.01" :min="0" style="width: 100%"
- v-model="form.incomeMoney"
- placeholder="璇疯緭鍏�"
- />
- </el-form-item>
- <el-form-item label="鏀跺叆鎻忚堪" prop="incomeDescribed">
- <el-input v-model="form.incomeDescribed" placeholder="璇疯緭鍏�" />
- </el-form-item>
- <el-form-item label="鏀舵鏂瑰紡" prop="incomeMethod">
- <el-select
- v-model="form.incomeMethod"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option :label="item.label" :value="item.value" v-for="(item,index) in payment_methods" :key="index" />
- </el-select>
- </el-form-item>
- <el-form-item label="鍙戠エ鍙风爜" prop="invoiceNumber">
- <el-input v-model="form.invoiceNumber" placeholder="璇疯緭鍏�" />
- </el-form-item>
- <el-form-item label="澶囨敞" prop="note">
- <el-input
- v-model="form.note"
- placeholder="澶囨敞"
- />
- </el-form-item>
- </el-form>
- </FormDialog>
-</template>
-
-<script setup>
-import { add, update, getAccountIncome } from "@/api/financialManagement/revenueManagement";
-import { ElMessage } from "element-plus";
-import useFormData from "@/hooks/useFormData";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import { ref } from "vue";
-
-const { proxy } = getCurrentInstance()
-
-defineOptions({
- name: "鏀跺叆鏂板缂栬緫",
-});
-
-const emits = defineEmits(["success"]);
-
-const formRef = ref(null);
-const dialogVisible = ref(false);
-const operationType = ref("add"); // add | edit
-const id = ref(undefined);
-const submitting = ref(false);
-
-const dialogTitle = (type) => {
- if (type === "edit") return "缂栬緫鏀跺叆";
- return "鏂板鏀跺叆";
-};
-
-const { income_types } = proxy.useDict("income_types");
-const { payment_methods } = proxy.useDict("payment_methods");
-
-const formRules = {
- customerName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
- incomeMoney: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
- incomeDescribed: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
- incomeDate: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
- incomeType: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
- incomeMethod: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
-}
-
-const { form, resetForm } = useFormData({
- incomeDate: undefined, // 鏀跺叆鏃ユ湡
- incomeType: undefined, // 鏀跺叆绫诲瀷
- customerName: undefined, // 瀹㈡埛鍚嶇О
- incomeMoney: undefined, // 鏀跺叆閲戦
- incomeDescribed: undefined, // 鏀跺叆鎻忚堪
- incomeMethod: undefined, // 鏀舵鏂瑰紡
- invoiceNumber: undefined, // 鍙戠エ鍙风爜
- note: undefined, // 澶囨敞
-});
-
-const sendForm = () => {
- if (submitting.value) return;
- formRef.value?.validate(async (valid) => {
- if (valid) {
- submitting.value = true;
- try {
- const { code } = id.value
- ? await update({ id: id.value, ...form })
- : await add(form);
- if (code == 200) {
- emits("success");
- ElMessage({ message: "鎿嶄綔鎴愬姛", type: "success" });
- close();
- }
- } finally {
- submitting.value = false;
- }
- }
- })
-};
-
-const close = () => {
- resetForm();
- formRef.value?.clearValidate();
- id.value = undefined;
- dialogVisible.value = false;
-};
-
-const loadForm = async (rowId) => {
- operationType.value = "edit";
- id.value = rowId;
- dialogVisible.value = true;
- if (rowId) {
- const { code, data } = await getAccountIncome(rowId);
- if (code == 200) {
- form.incomeDate = data.incomeDate;
- form.incomeType = data.incomeType;
- form.customerName = data.customerName;
- form.incomeMoney = data.incomeMoney;
- form.incomeDescribed = data.incomeDescribed;
- form.incomeMethod = data.incomeMethod;
- form.invoiceNumber = data.invoiceNumber;
- form.note = data.note;
- }
- } else {
- resetForm();
- formRef.value?.clearValidate();
- }
-};
-
-const openModal = () => {
- operationType.value = "add";
- id.value = undefined;
- resetForm();
- formRef.value?.clearValidate();
- dialogVisible.value = true;
-};
-
-defineExpose({
- openModal,
- loadForm,
-});
-</script>
diff --git a/src/views/financialManagement/revenueManagement/index.vue b/src/views/financialManagement/revenueManagement/index.vue
deleted file mode 100644
index bcef5b6..0000000
--- a/src/views/financialManagement/revenueManagement/index.vue
+++ /dev/null
@@ -1,355 +0,0 @@
-<template>
- <div class="app-container">
- <el-form :model="filters" :inline="true">
- <el-form-item label="鏀跺叆鏃ユ湡:">
- <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
- placeholder="璇烽�夋嫨" clearable @change="changeDaterange"/>
- </el-form-item>
- <el-form-item label="鏀舵鏂瑰紡:">
- <el-select
- v-model="filters.incomeMethodLabel"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 200px;"
- >
- <el-option
- v-for="item in incomeMethodOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
- <el-button @click="resetFilters">閲嶇疆</el-button>
- </el-form-item>
- </el-form>
- <div class="table_list">
- <div class="actions">
- <div></div>
- <div>
- <el-button type="primary" @click="add" icon="Plus"> 鏂板</el-button>
- <el-button @click="handleOut" icon="download">瀵煎嚭</el-button>
- <el-button
- type="danger"
- icon="Delete"
- :disabled="multipleList.length <= 0 || hasBusinessIdInSelection"
- @click="handleBatchDelete"
- >
- 鎵归噺鍒犻櫎
- </el-button>
- </div>
- </div>
- <PIMTable
- rowKey="id"
- isSelection
- :column="columns"
- :tableData="dataList"
- :page="{
- current: pagination.currentPage,
- size: pagination.pageSize,
- total: pagination.total,
- }"
- :isShowSummary="true"
- :summaryMethod="summarizeMainTable"
- @selection-change="handleSelectionChange"
- @pagination="changePage"
- >
- <template #incomeMethodSlot="{ row }">
- <el-tag>
- {{ getIncomeMethodLabel(row) }}
- </el-tag>
- </template>
- <template #operation="{ row }">
- <el-button
- type="primary"
- link
- :disabled="!!row.businessId"
- @click="edit(row.id)"
- >
- 缂栬緫
- </el-button>
- <el-button
- type="primary"
- link
- @click="openFilesFormDia(row)"
- >
- 闄勪欢
- </el-button>
- </template>
- </PIMTable>
- </div>
- <Modal ref="modalRef" @success="getTableData"></Modal>
- <FileListDialog v-if="fileListDialogVisible" :record-id="currentRecordId" record-type="account_income" v-model:visible="fileListDialogVisible"/>
- </div>
-</template>
-
-<script setup>
-import {usePaginationApi} from "@/hooks/usePaginationApi";
-import {listPage, delAccountIncome} from "@/api/financialManagement/revenueManagement";
-import {onMounted, getCurrentInstance, ref, computed} from "vue";
-import {ElMessageBox, ElMessage} from "element-plus";
-import dayjs from "dayjs";
-
-defineOptions({
- name: "鏀跺叆绠$悊",
-});
-
-// 琛ㄦ牸澶氶�夋閫変腑椤�
-const multipleList = ref([]);
-const {proxy} = getCurrentInstance();
-const modalRef = ref();
-const {payment_methods} = proxy.useDict("payment_methods");
-const {receipt_payment_type} = proxy.useDict("receipt_payment_type");
-const {income_types} = proxy.useDict("income_types");
-const fileListRef = ref(null);
-const fileListDialogVisible = ref(false);
-const currentRecordId = ref(0);
-
-const incomeMethodOptions = computed(() => {
- const merged = [...(payment_methods.value || []), ...(receipt_payment_type.value || [])];
- const uniqueMap = new Map();
- merged.forEach((item) => {
- const label = item?.label;
- if (!label) return;
- if (!uniqueMap.has(label)) {
- uniqueMap.set(label, {label, value: label});
- }
- });
- return Array.from(uniqueMap.values());
-});
-
-const {
- filters,
- columns,
- dataList,
- pagination,
- getTableData,
- resetFilters,
- onCurrentChange,
-} = usePaginationApi(
- listPage,
- {
- incomeMethodLabel: undefined,
- entryDate: undefined,
- },
- [
- {
- label: "鏀跺叆鏃ユ湡",
- prop: "incomeDate",
- },
- {
- label: "鏀跺叆绫诲瀷",
- prop: "incomeType",
- dataType: "tag",
- formatData: (params) => {
- if (income_types.value.find((m) => m.value == params)) {
- return income_types.value.find((m) => m.value == params).label;
- } else {
- return null
- }
- },
- },
- {
- label: "瀹㈡埛鍚嶇О",
- prop: "customerName",
- width: '200'
-
- },
- {
- label: "鏀跺叆閲戦",
- prop: "incomeMoney",
-
- },
- {
- label: "鏀跺叆鎻忚堪",
- prop: "incomeDescribed",
-
- },
- {
- label: "鏀舵鏂瑰紡",
- prop: "incomeMethodLabel",
- align: 'center',
- width: '100',
- dataType: "slot",
- slot: "incomeMethodSlot",
- },
- {
- label: "鍙戠エ鍙风爜",
- prop: "invoiceNumber",
-
- },
- {
- label: "澶囨敞",
- prop: "note",
-
- },
- {
- label: "褰曞叆浜�",
- prop: "inputUser",
- },
- {
- label: "褰曞叆鏃ユ湡",
- prop: "inputTime",
-
- },
- {
- fixed: "right",
- label: "鎿嶄綔",
- dataType: "slot",
- slot: "operation",
- align: "center",
- width: "160px",
- },
- ],
- undefined,
- {
- incomeMethodLabel: (value) => ({
- incomeMethodLabel: value || undefined,
- }),
- }
-);
-
-// 琛ㄦ牸鍚堣锛氭敹鍏ラ噾棰�
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, ["incomeMoney"]);
-};
-
-const getIncomeMethodLabel = (row) => {
- const methodValue = row?.incomeMethod;
- const dictList = String(row?.businessType) === "1"
- ? receipt_payment_type.value
- : payment_methods.value;
- return dictList.find((item) => item.value == methodValue)?.label || "--";
-};
-
-// 澶氶�夊悗鍋氫粈涔�
-const handleSelectionChange = (selectionList) => {
- multipleList.value = selectionList;
-};
-
-// 鍒ゆ柇閫変腑鐨勯」涓槸鍚︽湁 businessId
-const hasBusinessIdInSelection = computed(() => {
- return multipleList.value.some(item => item.businessId);
-});
-
-const add = () => {
- modalRef.value.openModal();
-};
-const edit = (id) => {
- // 妫�鏌ュ綋鍓嶈鏄惁鏈� businessId
- const row = dataList.value.find(item => item.id === id);
- if (row && row.businessId) {
- proxy.$modal.msgWarning("璇ヨ褰曞凡鍏宠仈涓氬姟锛屼笉鑳界紪杈�");
- return;
- }
- modalRef.value.loadForm(id);
-};
-const changePage = ({page, limit}) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- onCurrentChange(page);
-};
-const deleteRow = (id) => {
- // 濡傛灉鏄暟缁勶紝妫�鏌ユ槸鍚︽湁 businessId
- if (Array.isArray(id)) {
- const hasBusinessId = id.some(itemId => {
- const row = dataList.value.find(item => item.id === itemId);
- return row && row.businessId;
- });
- if (hasBusinessId) {
- proxy.$modal.msgWarning("閫変腑鐨勮褰曚腑鍖呭惈宸插叧鑱斾笟鍔$殑璁板綍锛屼笉鑳藉垹闄�");
- return;
- }
- } else {
- // 鍗曚釜鍒犻櫎锛屾鏌ユ槸鍚︽湁 businessId
- const row = dataList.value.find(item => item.id === id);
- if (row && row.businessId) {
- proxy.$modal.msgWarning("璇ヨ褰曞凡鍏宠仈涓氬姟锛屼笉鑳藉垹闄�");
- return;
- }
- }
-
- ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }).then(async () => {
- const {code} = await delAccountIncome(id);
- if (code == 200) {
- ElMessage({
- type: "success",
- message: "鍒犻櫎鎴愬姛",
- });
- getTableData();
- }
- });
-};
-
-// 鎵归噺鍒犻櫎
-const handleBatchDelete = () => {
- if (multipleList.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁 businessId
- if (hasBusinessIdInSelection.value) {
- proxy.$modal.msgWarning("閫変腑鐨勮褰曚腑鍖呭惈宸插叧鑱斾笟鍔$殑璁板綍锛屼笉鑳藉垹闄�");
- return;
- }
-
- const ids = multipleList.value.map((item) => item.id);
- deleteRow(ids);
-};
-
-const changeDaterange = (value) => {
- if (value) {
- filters.entryDate = value;
- filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- filters.entryDate = null;
- filters.entryDateStart = undefined;
- filters.entryDateEnd = undefined;
- }
- getTableData();
-};
-
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(`/account/accountIncome/export`, {}, "鏀跺叆鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-// 鎵撳紑闄勪欢寮规
-const openFilesFormDia = async (row) => {
- currentRecordId.value = row.id;
- fileListDialogVisible.value = true;
-};
-
-onMounted(() => {
- getTableData();
-});
-</script>
-
-<style lang="scss" scoped>
-.table_list {
- margin-top: unset;
-}
-
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-</style>
-
diff --git a/src/views/financialManagement/salesRefund/components/ReceiptandRefundPopupWindow.vue b/src/views/financialManagement/salesRefund/components/ReceiptandRefundPopupWindow.vue
deleted file mode 100644
index 35215a5..0000000
--- a/src/views/financialManagement/salesRefund/components/ReceiptandRefundPopupWindow.vue
+++ /dev/null
@@ -1,227 +0,0 @@
-<template>
- <FormDialog v-model="visible" title="鏀舵/閫�娆�" width="90%" @confirm="submit" @cancel="visible=false">
- <div class="section">
- <div class="section-title descriptions">鍩虹璧勬枡</div>
- <el-form :model="form" label-width="100px">
- <el-row :gutter="20">
- <el-col :span="6">
- <el-form-item label="鍗曟嵁缂栧彿">
- <el-input v-model="form.billNo" placeholder="浣跨敤绯荤粺缂栧彿" />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="瀹㈡埛">
- <el-select v-model="form.customerId" placeholder="璇烽�夋嫨">
- <el-option v-for="c in customerOptions" :key="c.value" :label="c.label" :value="c.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="鍒跺崟浜�">
- <el-select v-model="form.makerId" placeholder="璇烽�夋嫨">
- <el-option v-for="u in userOptions" :key="u.value" :label="u.label" :value="u.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="鍒跺崟鏃ユ湡">
- <el-date-picker v-model="form.makeDate" type="date" value-format="YYYY-MM-DD" />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="鐢宠閮ㄩ棬">
- <el-select v-model="form.applyDeptId" placeholder="璇烽�夋嫨">
- <el-option v-for="d in deptOptions" :key="d.value" :label="d.label" :value="d.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="澶囨敞">
- <el-input v-model="form.remark" maxlength="100" show-word-limit placeholder="璇疯緭鍏�" />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="闄勪欢">
- <el-upload :action="uploadUrl" :headers="uploadHeaders" name="files" :on-success="onUploadSuccess">
- <el-button>涓婁紶鏂囦欢</el-button>
- </el-upload>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </div>
-
- <div class="section">
- <div class="toolbar">
- <div class="section-title descriptions">浠樻鍒楄〃</div>
- <el-input v-model="form.discountAmount" placeholder="浼樻儬閲戦" style="width:240px" />
- </div>
- <el-table :data="form.paymentList" border>
- <el-table-column label="浠樻璐﹀彿" minWidth="160">
- <template #default="scope">
- <el-input v-model="scope.row.accountNo" placeholder="璇疯緭鍏�" />
- </template>
- </el-table-column>
- <el-table-column label="浠樻璐﹀彿鍚嶇О" minWidth="180">
- <template #default="scope">
- <el-select v-model="scope.row.accountName" placeholder="璇烽�夋嫨">
- <el-option v-for="a in accountOptions" :key="a.value" :label="a.label" :value="a.label" />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="浠樻鏂瑰紡" minWidth="140">
- <template #default="scope">
- <el-select v-model="scope.row.payMethod" placeholder="璇烽�夋嫨">
- <el-option v-for="m in payMethodOptions" :key="m.value" :label="m.label" :value="m.value" />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="瀹為檯浠樻閲戦" minWidth="160">
- <template #default="scope">
- <el-input v-model="scope.row.amount" placeholder="璇疯緭鍏�" />
- </template>
- </el-table-column>
- <el-table-column label="鎵嬬画璐�" minWidth="140">
- <template #default="scope">
- <el-input v-model="scope.row.fee" placeholder="璇疯緭鍏�" />
- </template>
- </el-table-column>
- <el-table-column label="浜ゆ槗鍙�/绁ㄦ嵁鍙�" minWidth="180">
- <template #default="scope">
- <el-input v-model="scope.row.txNo" placeholder="璇疯緭鍏�" />
- </template>
- </el-table-column>
- <el-table-column label="澶囨敞" minWidth="200">
- <template #default="scope">
- <el-input v-model="scope.row.remark" maxlength="30" show-word-limit placeholder="璇疯緭鍏�" />
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" minWidth="120" fixed="right">
- <template #default="scope">
- <el-button link type="primary" @click="addPayment">鏂板涓�琛�</el-button>
- <el-button link type="danger" @click="removePayment(scope.$index)">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
- <div class="summary">鍚堣</div>
- </div>
-
- <div class="section">
- <div class="section-container">
- <div class="section-title descriptions">婧愬崟淇℃伅</div>
- <div class="source-toolbar">
- <el-button @click="clearSource">娓呯┖</el-button>
- <el-button @click="selectSource">閫夋嫨婧愬崟</el-button>
- <el-button type="primary" @click="autoWriteOff">鑷姩鏍搁攢</el-button>
- </div>
- </div>
- <el-table :data="form.sourceList" border>
- <el-table-column label="鍗曟嵁鏃ユ湡" minWidth="160" prop="billDate" />
- <el-table-column label="鍗曟嵁绫诲瀷" minWidth="160" prop="billType" />
- <el-table-column label="鍗曟嵁缂栧彿" minWidth="200" prop="billNo" />
- <el-table-column label="鍗曟嵁閲戦" minWidth="120" prop="billAmount" />
- <el-table-column label="宸叉牳閿�閲戦" minWidth="120" prop="wroteAmount" />
- <el-table-column label="鏈牳閿�閲戦" minWidth="120" prop="unWroteAmount" />
- <el-table-column label="鏈鏍搁攢閲戦" minWidth="160">
- <template #default="scope">
- <el-input v-model="scope.row.thisWriteOffAmount" />
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" width="100" fixed="right">
- <template #default="scope">
- <el-button link type="danger" @click="removeSource(scope.$index)">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
- <div class="summary">鍚堣</div>
- </div>
-
- <template #footer>
- <el-button type="primary" @click="submit">纭</el-button>
- <el-button @click="visible=false">鍙栨秷</el-button>
- </template>
- </FormDialog>
-</template>
-
-<script setup>
-import { ref } from 'vue';
-import { getToken } from '@/utils/auth';
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-
-const visible = ref(false);
-const form = ref({
- billNo: '',
- customerId: undefined,
- makerId: undefined,
- makeDate: '',
- applyDeptId: undefined,
- remark: '',
- discountAmount: '',
- paymentList: [{ accountNo: '', accountName: '', payMethod: '', amount: '', fee: '', txNo: '', remark: '' }],
- sourceList: [{ billDate: '', billType: '', billNo: '', billAmount: 0, wroteAmount: 0, unWroteAmount: 0, thisWriteOffAmount: '' }]
-});
-
-const customerOptions = ref([]);
-const userOptions = ref([]);
-const deptOptions = ref([]);
-const accountOptions = ref([]);
-const payMethodOptions = ref([]);
-
-const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/basic/customer-follow/upload';
-const uploadHeaders = { Authorization: 'Bearer ' + getToken() };
-
-function addPayment() {
- form.value.paymentList.push({ accountNo: '', accountName: '', payMethod: '', amount: '', fee: '', txNo: '', remark: '' });
-}
-function removePayment(i) {
- form.value.paymentList.splice(i, 1);
-}
-function removeSource(i) {
- form.value.sourceList.splice(i, 1);
-}
-function clearSource() {
- form.value.sourceList = [];
-}
-function selectSource() {}
-function autoWriteOff() {}
-function onUploadSuccess() {}
-
-function open(payload) {
- visible.value = true;
-}
-function submit() {
- visible.value = false;
- emit('submitted');
-}
-
-defineExpose({ open });
-</script>
-
-<style scoped>
-.section { background: #fff; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05); padding: 16px; margin-bottom: 16px; }
-.section-title { font-weight: 600; margin-bottom: 12px; }
-.descriptions {
- margin-bottom: 20px;
- display: inline-block;
- font-size: 1rem;
- font-weight: 600;
- padding-left: 12px;
- position: relative;
-}
-.descriptions::before {
- content: "";
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 4px;
- height: 1rem;
- background-color: #002FA7;
- border-radius: 2px;
-}
-.toolbar { margin-bottom: 10px; display: flex; justify-content: space-between;
- align-items: center; }
-.source-toolbar { margin-bottom: 10px; display: flex; gap: 8px; }
-.summary { padding: 8px 12px; background: #fff7e6; color: #ad6800; }
-.section-container{display: flex;align-items: center;justify-content: space-between; }
-</style>
diff --git a/src/views/financialManagement/salesRefund/index.vue b/src/views/financialManagement/salesRefund/index.vue
deleted file mode 100644
index ccb775f..0000000
--- a/src/views/financialManagement/salesRefund/index.vue
+++ /dev/null
@@ -1,134 +0,0 @@
-<template>
- <div class="app-container">
- <!-- 浣跨敤鍏叡鎼滅储缁勪欢 -->
- <SearchPanel
- v-model="queryParams"
- :schema="searchSchema"
- @search="handleQuery"
- @reset="resetQuery"
- />
-
- <!-- 琛ㄦ牸鍖哄煙 -->
- <el-card class="table-card">
- <el-table :data="refundList" v-loading="loading" border>
- <el-table-column label="閫�璐у崟鍙�" prop="returnManagementNo" align="center" />
- <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" align="center" />
- <el-table-column label="閿�鍞崟鍙�" prop="salesContractNo" align="center" />
- <el-table-column label="搴旈��娆鹃噾棰�" prop="refundAmount" align="center" />
- <el-table-column label="宸查��娆鹃噾棰�" prop="refundedAmount" align="center" />
- <el-table-column label="鏈��娆鹃噾棰�" prop="notRefundedAmount" align="center" />
- <el-table-column label="鐘舵��" prop="status" align="center">
- <template #default="scope">
- <dict-tag :options="dictRef.sales_refund_status.value" :value="scope.row.status" />
- </template>
- </el-table-column>
- <el-table-column label="鍒涘缓浜�" prop="createUserName" align="center" />
- <el-table-column label="鍒涘缓鏃堕棿" prop="createTime" align="center" />
- <el-table-column label="鎿嶄綔" align="center" width="150">
- <template #default="scope">
- <el-button link type="primary" @click="openDetail(scope.row)" style="color: #67C23A">璇︽儏</el-button>
- <el-button link type="primary" @click="openConfirm(scope.row)">纭</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <pagination
- v-show="total > 0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- @pagination="getList"
- />
- </el-card>
-<ReceiptandRefundPopupWindow ref="popupRef" @submitted="getList" />
- </div>
-</template>
-
-<script setup name="SalesRefund">
-import { ref, reactive, onMounted, computed, getCurrentInstance } from 'vue';
-const { proxy } = getCurrentInstance();
-import { listPage, add, update, del } from '@/api/financialManagement/salesRefund';
-import SearchPanel from '@/components/SearchPanel/index.vue';
-import ReceiptandRefundPopupWindow from './components/ReceiptandRefundPopupWindow.vue';
-
-// 鏌ヨ鍙傛暟
-const queryParams = reactive({
- pageNum: 1,
- pageSize: 10,
- returnManagementNo: undefined,
- customerName: undefined,
- salesContractNo: undefined,
- createUserName: undefined,
- status: undefined
-});
-
-const dictRef = proxy.useDict('sales_refund_status');
-const salesRefundStatusOptions = computed(() => dictRef.sales_refund_status.value || []);
-
-// 鎼滅储鏍忛厤缃�
-const searchSchema = [
- { type: 'input', prop: 'returnManagementNo', placeholder: '閫�璐у崟鍙�' },
- { type: 'input', prop: 'customerName', placeholder: '瀹㈡埛鍚嶇О' },
- { type: 'input', prop: 'salesContractNo', placeholder: '閿�鍞崟鍙�' },
- { type: 'input', prop: 'createUserName', placeholder: '鍒涘缓浜哄悕绉�' },
- { type: 'select', prop: 'status', placeholder: '鐘舵��', options: salesRefundStatusOptions }
-];
-
-const loading = ref(false);
-const total = ref(0);
-const refundList = ref([]);
-const popupRef = ref(null);
-
-/** 鏌ヨ鍒楄〃 */
-function getList() {
- loading.value = true;
- const { pageNum, pageSize, ...filters } = queryParams;
- listPage({
- current: pageNum,
- size: pageSize,
- ...filters
- })
- .then(res => {
- refundList.value = res?.data?.records || res?.rows || [];
- total.value = res?.data?.total || res?.total || 0;
- })
- .finally(() => {
- loading.value = false;
- });
-}
-
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-function handleQuery() {
- queryParams.pageNum = 1;
- getList();
-}
-
-/** 閲嶇疆鎸夐挳鎿嶄綔 */
-function resetQuery() {
- handleQuery();
-}
-
-function openDetail(row) {
- if (popupRef.value) {
- popupRef.value.open({ mode: 'detail', row });
- }
-}
-function openConfirm(row) {
- if (popupRef.value) {
- popupRef.value.open({ mode: 'confirm', row });
- }
-}
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table-card {
- border-radius: 8px;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
-}
-</style>
-
-<!-- keep-alive child -->
diff --git a/src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue b/src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue
deleted file mode 100644
index d329768..0000000
--- a/src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue
+++ /dev/null
@@ -1,144 +0,0 @@
-<template>
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableData="dataList"
- :tableLoading="loading"
- :summaryMethod="summarizeChildrenTable"
- :isShowSummary="true"
- :isShowPagination="false"
- height="auto"
- >
- </PIMTable>
-</template>
-
-<script setup>
-import { usePaginationApi } from "@/hooks/usePaginationApi";
-import { productList } from "@/api/procurementManagement/procurementLedger.js";
-import { nextTick } from "vue";
-const { proxy } = getCurrentInstance();
-
-defineOptions({
- name: "鏉ョエ鐧昏鎶樺彔琛�",
-});
-
-const {
- loading,
- filters,
- columns,
- dataList,
- pagination,
- getTableData,
- resetFilters,
-} = usePaginationApi(
- productList,
- {
- salesLedgerId: undefined,
- type: 2,
- },
- [
- {
- label: "浜у搧澶х被",
- prop: "productCategory",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "specificationModel",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鏁伴噺",
- prop: "quantity",
- },
- {
- label: "绋庣巼(%)",
- prop: "taxRate",
- },
- {
- label: "鍚◣鍗曚环(鍏�)",
- prop: "taxInclusiveUnitPrice",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : "-";
- },
- },
- {
- label: "鍚◣鎬讳环(鍏�)",
- prop: "taxInclusiveTotalPrice",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : "-";
- },
- },
- {
- label: "涓嶅惈绋庢�讳环(鍏�)",
- prop: "taxExclusiveTotalPrice",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : "-";
- },
- },
- {
- label: "鏈鏉ョエ閲戦(鍏�)",
- prop: "ticketsAmount",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : "-";
- },
- },
- {
- label: "鏈潵绁ㄦ暟",
- prop: "futureTickets",
- },
- {
- label: "鏈潵绁ㄩ噾棰�(鍏�)",
- prop: "futureTicketsAmount",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : "-";
- },
- },
- ],
- {},
- {},
- (data) => {
- dataList.value = data;
- }
-);
-
-const getList = async (id) => {
- await nextTick();
- filters.salesLedgerId = id;
- // 璁剧疆涓�涓緢澶х殑 pageSize 浠ヨ幏鍙栨墍鏈夋暟鎹�
- pagination.pageSize = 10000;
- pagination.currentPage = 1;
- getTableData();
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
- return proxy.summarizeTable(
- param,
- [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- "ticketsNum",
- "ticketsAmount",
- "futureTickets",
- "futureTicketsAmount",
- ],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
-};
-defineExpose({
- getList,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/procurementManagement/invoiceEntry/components/Modal.vue b/src/views/procurementManagement/invoiceEntry/components/Modal.vue
deleted file mode 100644
index 33d5144..0000000
--- a/src/views/procurementManagement/invoiceEntry/components/Modal.vue
+++ /dev/null
@@ -1,718 +0,0 @@
-<template>
- <el-dialog :title="modalOptions.title" v-model="visible" width="70%" draggable>
- <el-form
- ref="formRef"
- :model="form"
- :rules="rules"
- label-width="120px"
- label-position="top"
- >
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="閲囪喘鍚堝悓鍙凤細" prop="purchaseLedgerNo">
- <el-input v-model="form.purchaseLedgerNo" disabled placeholder="澶氬悎鍚屾壒閲忓鐞嗭紙鍏蜂綋鍚堝悓鍙疯浜у搧鍒楄〃锛�" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
- <el-input
- v-model="form.salesContractNo"
- placeholder="鑷姩濉厖"
- clearable
- disabled
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierName">
- <el-input
- v-model="form.supplierName"
- placeholder="鑷姩濉厖"
- clearable
- disabled
- />
- </el-form-item>
- </el-col>
-<!-- <el-col :span="12">-->
-<!-- <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">-->
-<!-- <el-input-->
-<!-- v-model="form.projectName"-->
-<!-- placeholder="鑷姩濉厖"-->
-<!-- clearable-->
-<!-- disabled-->
-<!-- />-->
-<!-- </el-form-item>-->
-<!-- </el-col>-->
- <el-col :span="12">
- <el-form-item label="鍙戠エ鍙凤細" prop="invoiceNumber">
- <el-input
- v-model="form.invoiceNumber"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍙戠エ閲戦(鍏�)锛�" prop="invoiceAmount">
- <el-input-number :step="0.01" :min="0" style="width: 100%"
- v-model="form.invoiceAmount"
- placeholder="璇疯緭鍏ュ彂绁ㄩ噾棰�"
- clearable
- disabled
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="褰曞叆浜猴細" prop="issUer">
- <el-input
- v-model="form.issUer"
- placeholder="璇疯緭鍏�"
- clearable
- disabled
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="寮�绁ㄦ棩鏈燂細" prop="entryDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.entryDate"
- type="date"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="褰曞叆鏃ユ湡锛�" prop="enterDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.enterDate"
- type="date"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- />
- </el-form-item>
- </el-col>
-
- </el-row>
- <el-form-item label="浜у搧淇℃伅锛�"> </el-form-item>
- <el-table
- :data="form.productData"
- border
- show-summary
- :summary-method="summarizeChildrenTable"
- >
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="鎵�灞炲悎鍚�" prop="purchaseLedgerNo" width="200">
- <template #default="{ row }">
- <el-tag type="primary">{{ row.purchaseLedgerNo }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="150" />
- <el-table-column label="鍗曚綅" prop="unit" width="70" />
- <el-table-column label="鏁伴噺" prop="quantity" width="70" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
- <el-table-column
- label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber"
- />
- <el-table-column label="鏈寮�绁ㄦ暟" prop="ticketsNum" width="180">
- <template #default="scope">
- <el-input-number
- :step="0.1"
- :min="0"
- :max="scope.row.tempFutureTickets || 0"
- style="width: 100%"
- :precision="2"
- v-model="scope.row.ticketsNum"
- :disabled="isProductDisabled(scope.row)"
- @change="invoiceNumBlur(scope.row)"
- />
- </template>
- </el-table-column>
- <el-table-column
- label="鏈寮�绁ㄩ噾棰�(鍏�)"
- prop="ticketsAmount"
- width="180"
- >
- <template #default="scope">
- <el-input-number
- :step="0.01"
- :min="0"
- style="width: 100%"
- :precision="2"
- v-model="scope.row.ticketsAmount"
- :disabled="isProductDisabled(scope.row)"
- @change="invoiceAmountBlur(scope.row)"
- />
- </template>
- </el-table-column>
- <el-table-column
- label="鏈潵绁ㄦ暟"
- prop="futureTickets"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鏈鏉ョエ閲戦(鍏�)"
- prop="ticketsAmount"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鏈潵绁ㄦ暟"
- prop="futureTickets"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鏈潵绁ㄩ噾棰�(鍏�)"
- prop="futureTicketsAmount"
- :formatter="formattedNumber"
- />
- </el-table>
- </el-form>
- <template #footer>
- <el-button type="primary" :loading="modalLoading" @click="submitForm">
- 纭
- </el-button>
- <el-button @click="closeModal">鍙栨秷</el-button>
- </template>
- </el-dialog>
-</template>
-
-<script setup>
-import { ref, getCurrentInstance } from "vue";
-import { defineEmits } from 'vue';
-import { useModal } from "@/hooks/useModal";
-import useFormData from "@/hooks/useFormData";
-import {
- getPurchaseNoById,
- getInfo,
- addOrUpdateRegistration,
-} from "@/api/procurementManagement/invoiceEntry.js";
-import { getPurchaseById } from "@/api/procurementManagement/procurementLedger.js";
-import useUserStore from "@/store/modules/user";
-import dayjs from "dayjs";
-
-defineOptions({
- name: "鏉ョエ鐧昏妯℃�佹",
-});
-
-const userStore = useUserStore();
-const formRef = ref();
-const { proxy } = getCurrentInstance();
-const { form } = useFormData({
- purchaseLedgerNo: undefined, // 閲囪喘鍚堝悓鍙�
- salesContractNo: undefined, // 閿�鍞悎鍚屽彿
- supplierName: undefined, // 渚涘簲鍟嗗悕绉�
- projectName: undefined, // 椤圭洰鍚嶇О
- invoiceNumber: undefined, // 鍙戠エ鍙�
- invoiceAmount: undefined, // 鍙戠エ閲戦(鍏�)
- issUerId: userStore.id, // 褰曞叆浜�
- issUer: userStore.nickName, // 褰曞叆浜�
- entryDate: undefined, // 寮�绁ㄦ棩鏈�
- salesContractNoId: undefined, // 寮�绁ㄦ棩鏈�
- enterDate: dayjs().format("YYYY-MM-DD"),
- productData: [], // 琛ㄦ牸
-});
-
-const selectedContracts = ref([]); // 瀛樺偍閫変腑鐨勫悎鍚屾暟鎹�
-
-const rules = ref({
- invoiceNumber: [
- { required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿", trigger: "blur" },
- { type: "string" },
- ],
- invoiceAmount: [
- { required: true, message: "璇疯緭鍏ュ彂绁ㄩ噾棰�", trigger: "blur" },
- ],
- entryDate: [{ required: true, message: "璇烽�夋嫨寮�绁ㄦ棩鏈�", trigger: "change" }],
- enterDate: [{ required: true, message: "璇烽�夋嫨褰曞叆鏃ユ湡", trigger: "change" }],
-});
-
-const {
- id,
- visible,
- loading: modalLoading,
- openModal,
- modalOptions,
- handleConfirm,
- closeModal,
-} = useModal({
- title: "鏉ョエ鐧昏",
-});
-
-const emit = defineEmits(['refreshList']);
-
-const columns = [
- {
- label: "浜у搧澶х被",
- prop: "productCategory",
- width: 120,
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "specificationModel",
- width: 120,
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- width: 80,
- },
- {
- label: "鏁伴噺",
- prop: "quantity",
- width: 80,
- },
- {
- label: "绋庣巼(%)",
- prop: "taxRate",
- width: 80,
- },
- {
- label: "褰曞叆鏃ユ湡",
- prop: "registerDate",
- width: 120,
- },
- {
- label: "鍚◣鍗曚环(鍏�)",
- prop: "taxInclusiveUnitPrice",
- width: 150,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : 0;
- },
- },
- {
- label: "鍚◣鎬讳环(鍏�)",
- prop: "taxInclusiveTotalPrice",
- width: 150,
- formatData: (val) => {
- return parseFloat(val).toFixed(2) ?? 0;
- },
- },
- {
- label: "涓嶅惈绋庢�讳环(鍏�)",
- prop: "taxExclusiveTotalPrice",
- width: 150,
- formatData: (val) => {
- return parseFloat(val).toFixed(2) ?? 0;
- },
- },
- {
- label: "鏈鏉ョエ鏁�",
- prop: "ticketsNum",
- dataType: "slot",
- slot: "ticketsNumRef",
- width: 180,
- align: "center",
- },
- {
- label: "鏈鏉ョエ閲戦(鍏�)",
- prop: "ticketsAmount",
- dataType: "slot",
- slot: "ticketsAmountRef",
- width: 180,
- align: "center",
- },
- {
- label: "鏈潵绁ㄦ暟",
- prop: "futureTickets",
- width: 100,
- },
- {
- label: "鏈潵绁ㄩ噾棰�(鍏�)",
- prop: "futureTicketsAmount",
- width: 200,
- },
-];
-const formattedNumber = (row, column, cellValue) => {
- if (cellValue == 0) {
- return parseFloat(cellValue).toFixed(2);
- }
- if (cellValue) {
- return parseFloat(cellValue).toFixed(2);
- } else {
- return cellValue;
- }
-};
-const getTableData = async (type, selectedRows) => {
- if (type == "add") {
- // 妫�鏌ユ墍鏈夐�夋嫨鐨勫悎鍚屾槸鍚﹀叿鏈夌浉鍚岀殑渚涘簲鍟嗗悕绉�
- const firstRow = selectedRows[0];
- const isSameSupplier = selectedRows.every(row =>
- row.supplierName === firstRow.supplierName
- );
-
- if (!isSameSupplier) {
- proxy.$modal.msgError("璇烽�夋嫨鐩稿悓渚涘簲鍟嗗悕绉扮殑鍚堝悓");
- return;
- }
-
- // 鍏佽涓嶅悓鐨勯噰璐悎鍚屽彿鎵归噺澶勭悊锛屾棤闇�妫�鏌ラ噸澶�
-
- // 娓呯┖琛ㄥ崟鏁版嵁
- Object.keys(form).forEach(key => {
- if (key !== 'productData') {
- form[key] = undefined;
- }
- });
- form.productData = [];
-
- // 鍔犺浇鎵�鏈夐�変腑鍚堝悓鐨勪骇鍝佹暟鎹�
- const promises = selectedRows.map(row =>
- getInfo({ id: row.id })
- );
-
- Promise.all(promises).then(results => {
- // 鍚堝苟鎵�鏈夊悎鍚岀殑浜у搧鏁版嵁锛屽苟涓烘瘡涓骇鍝佹坊鍔犲搴旂殑鍚堝悓淇℃伅
- const allProductData = [];
- results.forEach((result, index) => {
- const contract = selectedRows[index];
- const contractId = contract.id;
- if (result.data && result.data.productData) {
- result.data.productData.forEach(item => {
- allProductData.push({
- ...item,
- purchaseLedgerId: contractId, // 娣诲姞鍚堝悓ID鐢ㄤ簬绛涢��
- purchaseLedgerNo: contract.purchaseContractNumber, // 娣诲姞閲囪喘鍚堝悓鍙�
- supplierName: contract.supplierName, // 娣诲姞渚涘簲鍟嗗悕绉�
- projectName: contract.projectName // 娣诲姞椤圭洰鍚嶇О
- // 淇濈暀浜у搧鏈韩鐨刬d锛屼笉瑕嗙洊
- });
- });
- }
- });
-
- // 璁剧疆琛ㄥ崟鏁版嵁锛堜娇鐢ㄧ涓�涓悎鍚岀殑鍩烘湰淇℃伅锛岄噰璐悎鍚屽彿鐣欑┖锛�
- form.purchaseLedgerNo = ""; // 閲囪喘鍚堝悓鍙风暀绌猴紝鍥犱负浼氬湪浜у搧琛ㄦ牸涓垎鍒樉绀�
- form.invoiceNumber = "";
- form.entryDate = dayjs().format("YYYY-MM-DD");
- form.enterDate = dayjs().format("YYYY-MM-DD");
- form.salesContractNo = results[0].data.salesContractNo;
- form.projectName = results[0].data.projectName;
- form.supplierName = results[0].data.supplierName;
- // 淇濈暀褰曞叆浜轰俊鎭�
- form.issUerId = userStore.id;
- form.issUer = userStore.nickName;
-
- // 璁剧疆浜у搧鏁版嵁锛屽苟鍒濆鍖栧紑绁ㄦ暟閲忓拰閲戦
- allProductData.forEach(item => {
- // 淇濆瓨"鍘熷鏈潵绁ㄦ暟/閲戦"锛堢敤浜庢牎楠屼笌璁$畻锛�
- // 浼樺厛浣跨敤鍚庣杩斿洖鐨� futureTickets/futureTicketsAmount锛涙病鏈夊垯鍥為��鍒� quantity/taxInclusiveTotalPrice
- item.tempFutureTickets = Number(
- item.futureTickets !== undefined ? item.futureTickets : (item.quantity || 0)
- );
- item.tempFutureTicketsAmount = Number(
- item.futureTicketsAmount !== undefined ? item.futureTicketsAmount : (item.taxInclusiveTotalPrice || 0)
- );
-
- // 濡傛灉鏈潵绁ㄩ噾棰濅负0锛屽垯鏈寮�绁ㄦ暟鍜岄噾棰濋兘璁剧疆涓�0
- if (item.tempFutureTicketsAmount <= 0) {
- item.ticketsNum = 0;
- item.ticketsAmount = 0;
- item.futureTickets = Number(item.tempFutureTickets || 0);
- item.futureTicketsAmount = 0;
- } else {
- // 鏂板鏃讹細鏈寮�绁ㄦ暟榛樿 = 鏈潵绁ㄦ暟锛堜笖涓嶈兘澶т簬鏈潵绁ㄦ暟锛�
- item.ticketsNum = Number(item.tempFutureTickets || 0);
- // 鑱斿姩璁$畻鏈寮�绁ㄩ噾棰濄�佹湭鏉ョエ鏁般�佹湭鏉ョエ閲戦
- const unitPrice = Number(item.taxInclusiveUnitPrice || 0);
- item.ticketsAmount = Number((item.ticketsNum * unitPrice).toFixed(2));
- item.futureTickets = Number((item.tempFutureTickets - item.ticketsNum).toFixed(2));
- item.futureTicketsAmount = Number(
- (item.tempFutureTicketsAmount - item.ticketsAmount).toFixed(2)
- );
- }
- });
-
- form.productData = allProductData;
-
- // 璁$畻鍙戠エ閲戦锛氭墍鏈変骇鍝佺殑鏈寮�绁ㄩ噾棰濅箣鍜岋紙鏂板榛樿 0锛�
- const totalAmount = allProductData.reduce((sum, item) => {
- return sum + (Number(item.ticketsAmount) || 0);
- }, 0);
- form.invoiceAmount = Number(totalAmount.toFixed(2));
-
- // 瀛樺偍閫変腑鐨勫悎鍚屾暟鎹�
- selectedContracts.value = selectedRows;
- });
- } else if (type == "edit") {
- const id = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows;
- const response = await getPurchaseById({ id, type: 2 });
- // 鍏煎涓嶅悓鐨勮繑鍥炴牸寮忥細鍙兘鏄� { code, data } 鎴栫洿鎺ヨ繑鍥炴暟鎹�
- const data = response.data || response;
-
- // 鍏煎涓嶅悓鐨勫瓧娈靛悕锛歱urchaseContractNumber 鎴� purchaseLedgerNo
- form.purchaseLedgerNo = data.purchaseContractNumber || data.purchaseLedgerNo || "";
- form.invoiceAmount = data.invoiceAmount;
- form.invoiceNumber = data.invoiceNumber;
- form.salesContractNo = data.salesContractNo;
- form.projectName = data.projectName;
- form.supplierName = data.supplierName;
- form.entryDate = data.entryDate;
- form.enterDate = data.enterDate || dayjs().format("YYYY-MM-DD");
-
- // 缂栬緫鏃朵篃闇�瑕佸垵濮嬪寲浜у搧鏁版嵁鐨� tempFutureTickets 鍜� tempFutureTicketsAmount
- // 鍚屾椂涓烘瘡涓骇鍝佹坊鍔犲悎鍚屽彿绛変俊鎭�
- const contractNumber = data.purchaseContractNumber || data.purchaseLedgerNo || "";
- if (data.productData && Array.isArray(data.productData)) {
- data.productData.forEach(item => {
- // 淇濆瓨"鍘熷鏈潵绁ㄦ暟/閲戦"锛堢敤浜庢牎楠屼笌璁$畻锛�
- // 浼樺厛浣跨敤鍚庣杩斿洖鐨� futureTickets/futureTicketsAmount锛涙病鏈夊垯鍥為��鍒� quantity/taxInclusiveTotalPrice
- item.tempFutureTickets = Number(
- item.futureTickets !== undefined ? item.futureTickets : (item.quantity || 0)
- );
- item.tempFutureTicketsAmount = Number(
- item.futureTicketsAmount !== undefined ? item.futureTicketsAmount : (item.taxInclusiveTotalPrice || 0)
- );
-
- // 纭繚姣忎釜浜у搧閮芥湁鍚堝悓鍙凤紝鐢ㄤ簬鏄剧ず鍦�"鎵�灞炲悎鍚�"鍒�
- if (!item.purchaseLedgerNo) {
- item.purchaseLedgerNo = contractNumber;
- }
- });
- }
-
- form.productData = data.productData || [];
-
- // 缂栬緫妯″紡涓嬶紝鏍规嵁浜у搧鏁版嵁涓殑鏈寮�绁ㄩ噾棰濊嚜鍔ㄨ绠楀彂绁ㄩ噾棰�
- calculateinvoiceAmount();
- }
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- "ticketsNum",
- "ticketsAmount",
- "ticketsAmountRef",
- "futureTickets",
- "futureTicketsAmount",
- ]);
-};
-//鏈鏉ョエ鏁板け鐒︽搷浣�
-const invoiceNumBlur = (row) => {
- if (!row.ticketsNum || row.ticketsNum === "") {
- row.ticketsNum = 0;
- }
- if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
- proxy.$modal.msgWarning("鏈寮�绁ㄦ暟涓嶈兘澶т簬鏈潵绁ㄦ暟");
- row.ticketsNum = Number(row.tempFutureTickets || 0);
- }
- // 璁$畻鏈鏉ョエ閲戦
- row.ticketsAmount = Number((Number(row.ticketsNum) * Number(row.taxInclusiveUnitPrice || 0)).toFixed(2));
- // 璁$畻鏈潵绁ㄦ暟
- row.futureTickets = Number((Number(row.tempFutureTickets || 0) - Number(row.ticketsNum || 0)).toFixed(2));
- // 璁$畻鏈潵绁ㄩ噾棰�
- row.futureTicketsAmount = Number((Number(row.tempFutureTicketsAmount || 0) - Number(row.ticketsAmount || 0)).toFixed(2));
- calculateinvoiceAmount();
-};
-
-// 鏈鏉ョエ閲戦澶辩劍鎿嶄綔
-const invoiceAmountBlur = (row) => {
- if (!row.ticketsAmount) {
- row.ticketsAmount = 0;
- }
- // 璁$畻鏄惁瓒呰繃鏉ョエ鎬婚噾棰�
- if (row.ticketsAmount > row.tempFutureTicketsAmount) {
- proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鏈潵绁ㄩ噾棰�");
- row.ticketsAmount = Number(row.tempFutureTicketsAmount || 0);
- }
- // 璁$畻鏈鏉ョエ鏁�
- row.ticketsNum = Number(
- (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2)
- );
- // 妫�鏌ユ湰娆″紑绁ㄦ暟鏄惁澶т簬鏈潵绁ㄦ暟
- if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
- proxy.$modal.msgWarning("鏈寮�绁ㄦ暟涓嶈兘澶т簬鏈潵绁ㄦ暟");
- row.ticketsNum = Number(row.tempFutureTickets || 0);
- // 閲嶆柊璁$畻鏈鏉ョエ閲戦
- row.ticketsAmount = Number((Number(row.ticketsNum) * Number(row.taxInclusiveUnitPrice || 0)).toFixed(2));
- }
- // 璁$畻鏈潵绁ㄦ暟
- row.futureTickets = Number((Number(row.tempFutureTickets || 0) - Number(row.ticketsNum || 0)).toFixed(2));
- // 璁$畻鏈潵绁ㄩ噾棰�
- row.futureTicketsAmount = Number((Number(row.tempFutureTicketsAmount || 0) - Number(row.ticketsAmount || 0)).toFixed(2));
- calculateinvoiceAmount();
-};
-
-const calculateinvoiceAmount = () => {
- let invoiceAmountTotal = 0;
- form.productData.forEach((item) => {
- if (item.ticketsAmount) {
- invoiceAmountTotal += Number(item.ticketsAmount);
- }
- });
- form.invoiceAmount = Number(invoiceAmountTotal.toFixed(2));
-};
-
-// 鍒ゆ柇浜у搧鏄惁鍙互缁х画鏉ョエ鎿嶄綔锛氬鏋滄湭鏉ョエ鏁板拰鏈潵绁ㄩ噾棰濋兘涓�0鎴栧皬浜庣瓑浜�0锛屽垯绂佺敤
-const isProductDisabled = (row) => {
- // 浼樺厛浣跨敤 tempFutureTickets锛堝師濮嬫湭鏉ョエ鏁帮級锛屽鏋滄病鏈夊垯浣跨敤 futureTickets
- const futureTickets = Number(row.tempFutureTickets !== undefined
- ? row.tempFutureTickets
- : (row.futureTickets !== undefined ? row.futureTickets : 0));
-
- // 浼樺厛浣跨敤 tempFutureTicketsAmount锛堝師濮嬫湭鏉ョエ閲戦锛夛紝濡傛灉娌℃湁鍒欎娇鐢� futureTicketsAmount
- const futureAmount = Number(row.tempFutureTicketsAmount !== undefined
- ? row.tempFutureTicketsAmount
- : (row.futureTicketsAmount !== undefined ? row.futureTicketsAmount : 0));
-
- // 鍙湁褰撴湭鏉ョエ鏁板拰鏈潵绁ㄩ噾棰濋兘涓�0鎴栧皬浜庣瓑浜�0鏃讹紝鎵嶇鐢�
- return futureTickets <= 0 && futureAmount <= 0;
-};
-
-const open = async (type, selectedRows) => {
- // 纭繚 modalOptions.value 鏄璞�
- if (!modalOptions.value || typeof modalOptions.value !== 'object') {
- modalOptions.value = {};
- }
-
- // 鏍规嵁鎿嶄綔绫诲瀷鍜岄�変腑鏁版嵁璁剧疆鏍囬
- if (Array.isArray(selectedRows) && selectedRows.length > 1) {
- // 鎵归噺鎿嶄綔
- modalOptions.value.title = type === "add" ? `鎵归噺鏂板 (${selectedRows.length}鏉�)` : `鎵归噺缂栬緫 (${selectedRows.length}鏉�)`;
- } else {
- // 鍗曚釜鎿嶄綔 - 鏄庣‘鍒ゆ柇 type 鐨勫��
- if (type === "add" || type === "鏂板") {
- modalOptions.value.title = "鏂板";
- } else if (type === "edit" || type === "缂栬緫") {
- modalOptions.value.title = "缂栬緫";
- } else {
- modalOptions.value.title = "鏉ョエ鐧昏"; // 榛樿鏍囬
- }
- }
-
- visible.value = true;
-
- // 濡傛灉鏄崟涓搷浣滐紝鑾峰彇id
- if (!Array.isArray(selectedRows) || selectedRows.length === 1) {
- const idValue = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows;
- id.value = idValue;
- }
-
- await getTableData(type, selectedRows);
-};
-
-
-const closeAndRefresh = () => {
- closeModal();
- emit('refreshList');
-};
-
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- // 濡傛灉鏄壒閲忔搷浣滐紝灏嗘墍鏈夊悎鍚岀殑鏁版嵁鏀惧湪涓�涓暟缁勯噷锛屽彧璋冪敤涓�娆℃帴鍙�
- if (selectedContracts.value.length > 1) {
- // 鍒涘缓鍖呭惈鎵�鏈夊悎鍚屾暟鎹殑鏁扮粍
- const batchData = selectedContracts.value.map(contract => {
- // 绛涢�夊嚭灞炰簬褰撳墠鍚堝悓鐨勪骇鍝佹暟鎹�
- const contractProductData = form.productData.filter(item =>
- item.purchaseLedgerId === contract.id
- );
-
- // 涓烘瘡涓噰璐悎鍚屽垱寤虹嫭绔嬬殑瀵硅薄
- return {
- // 鍩虹琛ㄥ崟鏁版嵁
- invoiceNumber: form.invoiceNumber,
- invoiceAmount: form.invoiceAmount,
- entryDate: form.entryDate,
- enterDate: form.enterDate,
- issUerId: form.issUerId, // 褰曞叆浜篿d
- issUer: form.issUer, // 褰曞叆浜�
-
- // 鍚堝悓瀹為檯淇℃伅
- purchaseLedgerId: contract.id, // 浣跨敤id浣滀负瀛楁鍚嶏紝鍊间负purchaseLedgerId
- purchaseContractNumber: contract.purchaseContractNumber, // 浣跨敤瀹為檯鐨勯噰璐悎鍚屽彿
- salesContractNo: contract.salesContractNo, // 浣跨敤瀹為檯鐨勯攢鍞悎鍚屽彿
- supplierName: contract.supplierName, // 浣跨敤瀹為檯鐨勪緵搴斿晢鍚嶇О
- projectName: contract.projectName, // 浣跨敤瀹為檯鐨勯」鐩悕绉�
-
- // 浜у搧鏁版嵁
- productData: proxy.HaveJson(contractProductData),
-
- // 鎵归噺鏍囪瘑
- isBatch: true,
- type: 4
- };
- });
-
- // 鍙皟鐢ㄤ竴娆℃帴鍙o紝浼犻�掑寘鍚墍鏈夊悎鍚屾暟鎹殑鏁扮粍
- modalLoading.value = true;
- addOrUpdateRegistration(batchData).then((res) => {
- modalLoading.value = false;
- if (res.code === 200) {
- proxy.$modal.msgSuccess("鎵归噺鐧昏鎴愬姛");
- closeAndRefresh();
- }
- }).catch(() => {
- modalLoading.value = false;
- proxy.$modal.msgError("鎵归噺鐧昏澶辫触");
- });
- } else {
- // 鍗曚釜鍚堝悓鎻愪氦閫昏緫 - 浠ユ暟缁勬牸寮忎紶閫�
- const singleContract = selectedContracts.value[0];
- const singleFormArray = [{
- // 鍩虹琛ㄥ崟鏁版嵁
- invoiceNumber: form.invoiceNumber,
- invoiceAmount: form.invoiceAmount,
- entryDate: form.entryDate,
- enterDate: form.enterDate,
- issUerId: form.issUerId, // 褰曞叆浜篿d
- issUer: form.issUer, // 褰曞叆浜�
-
- // 鍚堝悓瀹為檯淇℃伅
- purchaseLedgerId: singleContract.id, // 浣跨敤id浣滀负瀛楁鍚嶏紝鍊间负purchaseLedgerId
- purchaseContractNumber: singleContract.purchaseContractNumber, // 浣跨敤瀹為檯鐨勯噰璐悎鍚屽彿
- salesContractNo: singleContract.salesContractNo, // 浣跨敤瀹為檯鐨勯攢鍞悎鍚屽彿
- supplierName: singleContract.supplierName, // 浣跨敤瀹為檯鐨勪緵搴斿晢鍚嶇О
- projectName: singleContract.projectName, // 浣跨敤瀹為檯鐨勯」鐩悕绉�
-
- // 浜у搧鏁版嵁
- productData: proxy.HaveJson(form.productData),
-
- // 鎵归噺鏍囪瘑
- isBatch: false,
- type: 4
- }];
-
- modalLoading.value = true;
- addOrUpdateRegistration(singleFormArray).then((res) => {
- modalLoading.value = false;
- if (res.code === 200) {
- proxy.$modal.msgSuccess("鐧昏鎴愬姛");
- closeAndRefresh();
- }
- }).catch(() => {
- modalLoading.value = false;
- proxy.$modal.msgError("鐧昏澶辫触");
- });
- }
- }
- });
-};
-
-defineExpose({
- open,
- closeAndRefresh,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/procurementManagement/invoiceEntry/index.vue b/src/views/procurementManagement/invoiceEntry/index.vue
deleted file mode 100644
index 8c435e0..0000000
--- a/src/views/procurementManagement/invoiceEntry/index.vue
+++ /dev/null
@@ -1,311 +0,0 @@
-<template>
- <div class="app-container">
- <div class="search_form">
- <el-form :model="filters" :inline="true">
- <el-form-item label="渚涘簲鍟嗗悕绉�">
- <el-input
- v-model="filters.supplierName"
- placeholder="璇疯緭鍏ュ悕绉版悳绱�"
- clearable
- prefix-icon="Search"
- @change="getTableData"
- />
- </el-form-item>
- <el-form-item label="閲囪喘璁㈠崟鍙凤細">
- <el-input
- v-model="filters.purchaseContractNumber"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="getTableData"
- />
- </el-form-item>
-
- <el-form-item label="閿�鍞悎鍚屽彿">
- <el-input
- v-model="filters.salesContractNo"
- placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿"
- clearable
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getTableData"> 鎼滅储 </el-button>
- <el-button @click="resetFilters"> 閲嶇疆 </el-button>
- </el-form-item>
- </el-form>
- </div>
- <div class="table_list">
- <div class="actions">
- <div></div>
- <div>
- <el-button @click="handleExport" style="margin-right: 10px">瀵煎嚭</el-button>
- <el-button type="primary" @click="handleAdd('add')" :disabled="isInvoiceDisabled">
- 鏉ョエ鐧昏
- </el-button>
-<!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
- </div>
- </div>
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableData="dataList"
- :tableLoading="loading"
- :isSelection="true"
- :page="{
- current: pagination.currentPage,
- size: pagination.pageSize,
- total: pagination.total,
- }"
- :expand-row-keys="expandRowKeys"
- :summaryMethod="summarizeMainTable"
- :isShowSummary="true"
- @expand-change="expandChange"
- @selection-change="handleSelectionChange"
- @pagination="changePage"
- >
- <template #expand="{ row }">
- <ExpandTable ref="expandTableRef" />
- </template>
- <template #operation="{ row }">
- <el-button
- link
- type="primary"
- @click="handleEdit('edit', row.id)"
- >
- 缂栬緫
- </el-button>
- </template>
- </PIMTable>
- </div>
- <Modal ref="modalRef" @refreshList="getTableData"></Modal>
- </div>
-</template>
-
-<script setup>
-import { usePaginationApi } from "@/hooks/usePaginationApi";
-import {delRegistration, gePurchaseListPage} from "@/api/procurementManagement/invoiceEntry.js";
-import { nextTick, onMounted, getCurrentInstance, ref, computed } from "vue";
-import ExpandTable from "./components/ExpandTable.vue";
-import Modal from "./components/Modal.vue";
-import {ElMessageBox} from "element-plus";
-
-defineOptions({
- name: "鏉ョエ鐧昏",
-});
-
-const { proxy } = getCurrentInstance();
-const expandRowKeys = ref([]);
-const expandTableRef = ref();
-const modalRef = ref();
-const selectedRows = ref([]);
-
-const {
- loading,
- filters,
- columns,
- dataList,
- pagination,
- getTableData,
- resetFilters,
- onCurrentChange,
-} = usePaginationApi(
- gePurchaseListPage,
- {
- purchaseContractNumber: undefined,
- // 鍙煡璇㈠凡瀹℃壒閫氳繃锛堟垨鎸囧畾鐘舵�佷负 3锛夌殑璁板綍
- approvalStatus: 3,
- },
- [
- {
- type: "expand",
- dataType: "slot",
- slot: "expand",
- },
- {
- label: "閲囪喘璁㈠崟鍙�",
- prop: "purchaseContractNumber",
- width:150
- },
- {
- label: "閿�鍞悎鍚屽彿",
- prop: "salesContractNo",
- width:150
- },
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
- width:300
- },
- {
- label: "褰曞叆浜�",
- prop: "recorderName",
- },
- {
- label: "褰曞叆鏃ユ湡",
- prop: "entryDate",
- width:110
- },
- {
- label: "鍚堝悓閲戦(鍏�)",
- prop: "contractAmount",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : 0;
- },
- },
- {
- label: "宸叉潵绁ㄩ噾棰�(鍏�)",
- prop: "receiptPaymentAmount",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : 0;
- },
- },
- {
- label: "寰呮潵绁ㄩ噾棰�(鍏�)",
- prop: "unReceiptPaymentAmount",
- width:200,
- formatData: (val) => {
- return val ? parseFloat(val).toFixed(2) : 0;
- },
- },
- {
- fixed: "right",
- label: "鎿嶄綔",
- dataType: "slot",
- slot: "operation",
- align: "center",
- width: 100,
- },
- ]
-);
-
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection.filter(
- (item) => item.purchaseContractNumber !== undefined
- );
-};
-
-// 璁$畻鏄惁鍙互鏉ョエ鐧昏锛氬鏋滄墍鏈夐�変腑琛岀殑寰呮潵绁ㄩ噾棰濋兘涓�0锛屽垯绂佺敤鎸夐挳
-const isInvoiceDisabled = computed(() => {
- if (selectedRows.value.length === 0) {
- return true;
- }
- // 濡傛灉鎵�鏈夐�変腑琛岀殑寰呮潵绁ㄩ噾棰濋兘涓�0鎴栧皬浜庣瓑浜�0锛屽垯绂佺敤
- return selectedRows.value.every(row => {
- const amount = parseFloat(row.unReceiptPaymentAmount || 0);
- return amount <= 0;
- });
-});
-
-const handleAdd = (type) => {
- if (selectedRows.value.length < 1) {
- proxy.$modal.msgWarning("璇疯嚦灏戦�変腑涓�鏉℃暟鎹�");
- return;
- }
- modalRef.value.open(type, selectedRows.value);
-};
-
-const handleEdit = (type, id) => {
- modalRef.value.open(type, id);
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/purchase/registration/export", {}, "鏉ョエ鐧昏.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 瀵煎嚭閲囪喘鍙拌处
-const handleExport = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/purchase/ledger/exportOne", {}, "鏉ョエ鐧昏.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 鍒犻櫎
-const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- // 鏂板鍒ゆ柇锛氬鏋滄湁閫変腑鐨勬暟鎹病鏈塼icketRegistrationId锛屾彁绀哄苟缁堟
- const noTicket = selectedRows.value.some(item => !item.ticketRegistrationId);
- if (noTicket) {
- proxy.$modal.msgWarning("閲囪喘鍙拌处杩樻湭杩涜鏉ョエ鐧昏,鏃犳硶杩涜鍒犻櫎鎿嶄綔");
- return;
- }
- ids = selectedRows.value.map((item) => item.ticketRegistrationId);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delRegistration(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-const expandChange = async (row, expandedRows) => {
- if (expandedRows.length > 0) {
- await nextTick();
- expandTableRef.value.getList(row.id);
- }
-};
-
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- onCurrentChange(page);
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(
- param,
- ["contractAmount", "receiptPaymentAmount", "unReceiptPaymentAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
-};
-onMounted(() => {
- getTableData();
-});
-</script>
-
-<style lang="scss" scoped>
-.table_list {
- margin-top: unset;
-}
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-</style>
diff --git a/src/views/procurementManagement/paymentEntry/index.vue b/src/views/procurementManagement/paymentEntry/index.vue
deleted file mode 100644
index 9ce59ad..0000000
--- a/src/views/procurementManagement/paymentEntry/index.vue
+++ /dev/null
@@ -1,597 +0,0 @@
-<template>
- <div class="app-container">
- <div class="search_form">
- <el-form :inline="true" :model="searchForm" style="width: 100%">
- <el-row justify="space-between">
- <el-col :span="20">
- <el-form-item label="渚涘簲鍟嗗悕绉�/鍚堝悓鍙�">
- <el-input
- v-model="searchForm.supplierNameOrContractNo"
- style="width: 240px"
- placeholder="杈撳叆渚涘簲鍟嗗悕绉�/鍚堝悓鍙锋悳绱�"
- clearable
- prefix-icon="Search"
- @change="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-checkbox
- v-model="searchForm.status"
- label="涓嶆樉绀哄緟浠樻涓�0"
- @change="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
- </el-form-item>
- </el-col>
- <el-col :span="4">
- <el-form-item style="float: right; margin-right: unset">
- <el-button type="primary" @click="openForm('add')">
- 鏂板浠樻
- </el-button>
- <el-button @click="handleExport" style="margin-right: 10px">瀵煎嚭</el-button>
-<!-- <el-button type="danger" plain @click="handleDelete">-->
-<!-- 鍒犻櫎-->
-<!-- </el-button>-->
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </div>
- <div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :expandRowKeys="expandedRowKeys"
- :isSelection="true"
- :isShowSummary="isShowSummarySon"
- :summaryMethod="summarizeMainTable1"
- @selection-change="handleSelectionChange"
- @expand-change="expandChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"
- >
- <template #expand="{ row }">
- <el-table
- :data="expandData"
- border
- show-summary
- v-loading="childrenLoading"
- :summary-method="summarizeMainTable2"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column label="浠樻鏃ユ湡" prop="paymentDate" />
- <el-table-column label="浠樻閲戦" prop="currentPaymentAmount">
- <template #default="scope">
- <el-input-number :step="0.01" :min="0" style="width: 100%"
- v-model="scope.row.currentPaymentAmount"
- :disabled="!scope.row.editType"
- :precision="2"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </template>
- </el-table-column>
- <el-table-column label="浠樻鏂瑰紡" prop="paymentMethod">
- <template #default="scope">
- <el-select
- :disabled="!scope.row.editType"
- v-model="scope.row.paymentMethod"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option
- v-for="item in checkout_payment"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="鐧昏浜�" prop="registrant" />
- <el-table-column label="鐧昏鏃ユ湡" prop="registrationtDate" />
- <el-table-column label="鎿嶄綔" width="150">
- <template #default="scope">
- <el-button
- link
- type="primary"
- @click="changeEditType(scope.row)"
- v-if="!scope.row.editType"
- >缂栬緫</el-button
- >
- <el-button
- link
- type="primary"
- @click="saveReceiptPayment(scope.row)"
- v-if="scope.row.editType"
- >淇濆瓨</el-button
- >
- <el-button
- link
- type="primary"
- @click="handleDelete(scope.row)"
- >鍒犻櫎</el-button
- >
- </template>
- </el-table-column>
- </el-table>
- </template>
- </PIMTable>
- </div>
- <FormDialog
- v-model="dialogFormVisible"
- title="鏂板浠樻椤甸潰"
- :width="'90%'"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia"
- >
- <el-table
- v-if="forms.length"
- :data="forms"
- border
- style="width: 100%"
- size="small"
- >
- <el-table-column type="index" label="搴忓彿" width="50" align="center"/>
- <el-table-column label="閲囪喘鍚堝悓鍙�" prop="purchaseContractNumber" show-overflow-tooltip />
- <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip />
- <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" show-overflow-tooltip />
- <el-table-column
- label="浜у搧澶х被"
- prop="productCategory"
- show-overflow-tooltip
- width="100"
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- show-overflow-tooltip
- width="150"
- />
- <el-table-column
- label="寰呬粯娆鹃噾棰�(鍏�)"
- prop="pendingTicketsTotal"
- show-overflow-tooltip
- width="170"
- >
- <template #default="{ row, column }">
- <el-text type="danger">
- {{ formattedNumber(row, column, row.pendingTicketsTotal) }}
- </el-text>
- </template>
- </el-table-column>
- <el-table-column label="鏈浠樻閲戦(鍏�)" width="180">
- <template #default="{ row }">
- <el-input-number
- v-model="row.currentPaymentAmount"
- :step="0.01"
- :min="0"
- :max="Number(row.pendingTicketsTotal || 0)"
- :precision="2"
- style="width: 100%"
- placeholder="璇疯緭鍏�"
- />
- </template>
- </el-table-column>
- <el-table-column label="浠樻鏂瑰紡" width="160">
- <template #default="{ row }">
- <el-select v-model="row.paymentMethod" placeholder="璇烽�夋嫨" clearable>
- <el-option
- v-for="item in checkout_payment"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="浠樻鏃ユ湡" width="170">
- <template #default="{ row }">
- <el-date-picker
- v-model="row.paymentDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- style="width: 100%"
- />
- </template>
- </el-table-column>
- <el-table-column label="鐧昏浜�" width="140">
- <template #default="{ row }">
- <el-input v-model="row.registrant" disabled />
- </template>
- </el-table-column>
- <el-table-column label="鐧昏鏃ユ湡" width="170">
- <template #default="{ row }">
- <el-input v-model="row.registrationtDate" />
- </template>
- </el-table-column>
- </el-table>
- <div v-else class="empty-tip">璇烽�夋嫨闇�瑕佷粯娆剧殑璁板綍</div>
- </FormDialog>
- </div>
-</template>
-
-<script setup>
-import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { ref, reactive, toRefs, getCurrentInstance, nextTick, onMounted } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { ElMessageBox } from "element-plus";
-import useUserStore from "@/store/modules/user.js";
-import {
- byPurchaseId,
- paymentRegistrationAdd,
- paymentRegistrationDel,
- paymentRegistrationEdit,
- getTicketNo,
-} from "@/api/procurementManagement/paymentEntry.js";
-import {
- delPaymentRegistration,
- invoiceListPage,
- registrationListPageGetById,
- updatePaymentRegistration
-} from "@/api/procurementManagement/procurementInvoiceLedger.js";
-import useFormData from "@/hooks/useFormData";
-import { getCurrentDate } from "@/utils/index.js";
-
-const { proxy } = getCurrentInstance();
-const { checkout_payment } = proxy.useDict("checkout_payment");
-const tableColumn = ref([
- {
- type: "expand",
- dataType: "slot",
- slot: "expand",
- },
- {
- label: "閲囪喘鍚堝悓鍙�",
- prop: "purchaseContractNumber",
- width:160
- },
- {
- label: "閿�鍞悎鍚屽彿",
- prop: "salesContractNo",
- width:160
- },
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
- },
- {
- label: "浠樻鐘舵��",
- prop: "statusName",
- width:110,
- dataType: "tag",
- formatType: (params) => {
- if (params == '鏈畬鎴愪粯娆�') {
- return "danger";
- } else if (params == '宸插畬鎴愪粯娆�') {
- return "success";
- } else {
- return null;
- }
- },
- },
- {
- label: "浜у搧澶х被",
- prop: "productCategory",
- showOverflowTooltip: true,
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "specificationModel",
- showOverflowTooltip: true,
- width: 150
- },
- {
- label: "宸蹭粯娆鹃噾棰�(鍏�)",
- prop: "ticketsTotal",
- formatData: (params) => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
- },
- {
- label: "寰呬粯娆鹃噾棰�(鍏�)",
- prop: "pendingTicketsTotal",
- formatData: (params) => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
- },
-]);
-const tableData = ref([]);
-const expandData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const childrenLoading = ref(false);
-const forms = ref([]);
-const userStore = useUserStore();
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- supplierNameOrContractNo: "",
- status: false,
- // 鍙煡璇㈠鎵圭姸鎬佷负 3 鐨勮褰�
- approvalStatus: 3,
- },
- form: {
- purchaseContractNumber: "",
- purchaseLedgerId: "",
- salesContractNo: "",
- supplierName: "",
- taxRate: "",
- currentPaymentAmount: "",
- paymentMethod: "",
- registrant: "",
- registrantId: "",
- paymentDate: "",
- registrationtDate: "",
- },
- rules: {
- purchaseLedgerId: [
- { required: true, message: "璇烽�夋嫨", trigger: "change" },
- ],
- currentPaymentAmount: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- paymentMethod: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { form, rules } = toRefs(data);
-const { form: searchForm, resetForm } = useFormData(data.searchForm);
-const isShowSummarySon = ref(true);
-const expandedRowKeys = ref([]);
-
-const getStatusTagType = (statusName = '') => {
- const normalized = statusName.trim();
- if (!normalized) return 'info';
- return normalized === '鏈畬鎴愪粯娆�' ? 'danger' : 'success';
-};
-
-const formattedNumber = (row, column, cellValue) => {
- const val = Number(cellValue ?? 0);
- return Number.isFinite(val) ? val.toFixed(2) : "0.00";
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeMainTable1 = (param) => {
- return proxy.summarizeTable(
- param,
- ["ticketsTotal", "pendingTicketsTotal"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeMainTable2 = (param) => {
- return proxy.summarizeTable(param, ["currentPaymentAmount"], {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- });
-};
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- invoiceListPage({ ...searchForm, ...page }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- page.total = res.data.total;
- if (expandedRowKeys.value.length > 0) {
- const arr = []
- const index = tableData.value.findIndex(item => item.id === expandedRowKeys.value[0]);
- if (index > -1) {
- arr.push(tableData.value[index]);
- expandChange(tableData.value[index], arr)
- }
- }
- });
-};
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
- if (expandedRows.length > 0) {
- nextTick(() => {
- expandedRowKeys.value = [];
- try {
- childrenLoading.value = true;
- registrationListPageGetById({ id: row.id }).then((res) => {
- childrenLoading.value = false;
- const index = tableData.value.findIndex((item) => item.id === row.id);
- if (index > -1) {
- expandData.value = res;
- }
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- childrenLoading.value = false;
- console.log(error);
- }
- })
- } else {
- expandedRowKeys.value = [];
- }
-};
-// 缂栬緫淇敼鐘舵��
-const changeEditType = (row) => {
- row.editType = !row.editType;
-};
-// 淇濆瓨鍥炴璁板綍
-const saveReceiptPayment = (row) => {
- let updateData = {
- id: row.id,
- currentPaymentAmount: row.currentPaymentAmount,
- paymentMethod: row.paymentMethod,
- };
- updatePaymentRegistration(updateData).then((res) => {
- row.editType = !row.editType;
- getList();
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- });
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-// 鎵撳紑寮规
-const openForm = (type, row) => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgError("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
- return;
- }
- const validRows = selectedRows.value.filter((item) => Number(item.pendingTicketsTotal || 0) !== 0);
- if (validRows.length === 0) {
- proxy.$modal.msgWarning("鎵�閫夎褰曞潎鏃犻渶浠樻");
- return;
- }
- forms.value = validRows.map((row) => ({
- purchaseContractNumber: row.purchaseContractNumber || "",
- salesContractNo: row.salesContractNo || "",
- supplierName: row.supplierName || "",
- supplierId: row.supplierId,
- productCategory: row.productCategory || "",
- specificationModel: row.specificationModel || "",
- pendingTicketsTotal: Number(row.pendingTicketsTotal || 0),
- currentPaymentAmount: "",
- paymentMethod: "",
- paymentDate: "",
- registrant: userStore.nickName,
- registrationtDate: getCurrentDate(),
- ticketRegistrationId: row.id,
- purchaseLedgerId: row.salesLedgerId,
- salesLedgerProductId: row.id,
- }));
- dialogFormVisible.value = true;
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- if (forms.value.length === 0) {
- proxy.$modal.msgError("璇烽�夋嫨浠樻璁板綍");
- return;
- }
- for (let i = 0; i < forms.value.length; i++) {
- const item = forms.value[i];
- const pendingAmount = Number(item.pendingTicketsTotal || 0);
- const currentAmount = Number(item.currentPaymentAmount);
- if (!item.currentPaymentAmount && item.currentPaymentAmount !== 0) {
- proxy.$modal.msgError(`绗� ${i + 1} 鏉★細璇峰~鍐欎粯娆鹃噾棰漙);
- return;
- }
- if (currentAmount > pendingAmount) {
- proxy.$modal.msgError(
- `绗� ${i + 1} 鏉★細浠樻閲戦涓嶈兘瓒呰繃寰呬粯娆鹃噾棰濓紙寰呬粯娆撅細${pendingAmount.toFixed(
- 2
- )}锛塦
- );
- return;
- }
- if (!item.paymentMethod) {
- proxy.$modal.msgError(`绗� ${i + 1} 鏉★細璇烽�夋嫨浠樻鏂瑰紡`);
- return;
- }
- if (!item.paymentDate) {
- proxy.$modal.msgError(`绗� ${i + 1} 鏉★細璇烽�夋嫨浠樻鏃ユ湡`);
- return;
- }
- }
- const normalizePaymentMethodValue = (method) => {
- const hit = checkout_payment.value.find((item) => item.value == method || item.label == method);
- return hit ? hit.value : method;
- };
- const submitRows = forms.value.map((item) => ({
- ...item,
- paymentMethod: normalizePaymentMethodValue(item.paymentMethod),
- }));
- paymentRegistrationAdd(submitRows).then(() => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
- forms.value = [];
- dialogFormVisible.value = false;
-};
-// 鍒犻櫎
-const handleDelete = (row) => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- tableLoading.value = true;
- delPaymentRegistration([row.id])
- .then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .finally(() => {
- tableLoading.value = false;
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-// 瀵煎嚭
-const handleExport = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/purchase/registration/exportOne", { ...searchForm, ...page }, "浠樻鐧昏.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table_list {
- margin-top: unset;
-}
-:deep(.el-checkbox__label) {
- font-weight: bold;
-}
-.empty-tip {
- text-align: center;
- padding: 20px 0;
- color: #909399;
-}
-</style>
diff --git a/src/views/procurementManagement/paymentHistory/index.vue b/src/views/procurementManagement/paymentHistory/index.vue
deleted file mode 100644
index c9e9836..0000000
--- a/src/views/procurementManagement/paymentHistory/index.vue
+++ /dev/null
@@ -1,270 +0,0 @@
-<template>
- <div class="app-container">
- <el-form :model="searchForm" :inline="true">
- <el-form-item label="閲囪喘鍚堝悓鍙�">
- <el-input
- v-model="searchForm.purchaseContractNumber"
- style="width: 240px"
- placeholder="杈撳叆閲囪喘鍚堝悓鍙锋悳绱�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search"
- />
- </el-form-item>
- <el-form-item label="渚涘簲鍟嗗悕绉�">
- <el-input
- v-model="searchForm.searchText"
- style="width: 240px"
- placeholder="杈撳叆渚涘簲鍟嗗悕绉版悳绱�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search"
- />
- </el-form-item>
- <el-form-item label="浠樻鏃ユ湡">
- <el-date-picker
- v-model="searchForm.paymentDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- start-placeholder="寮�濮嬫椂闂�"
- end-placeholder="缁撴潫鏃堕棿"
- clearable
- @change="changeDateRange"
- @clear="clearRange"
- />
- </el-form-item>
- <el-form-item>
- <el-button
- type="primary"
- @click="handleQuery"
- style="margin-left: 10px"
- >
- 鎼滅储
- </el-button>
- <el-button @click="handleExport">瀵煎嚭</el-button>
- <el-button
- type="danger"
- :disabled="selectedRows.length === 0"
- @click="handleBatchDelete"
- >
- 鎵归噺鍒犻櫎 ({{ selectedRows.length }})
- </el-button>
- </el-form-item>
- </el-form>
- <div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- :isShowSummary="isShowSummarySon"
- :summaryMethod="summarizeMainTable1"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"
- >
- <template #operation="{ row }">
- <el-button
- type="primary"
- link
- @click="handleDelete(row)"
- >
- 鍒犻櫎
- </el-button>
- </template>
- </PIMTable>
- </div>
- </div>
-</template>
-
-<script setup>
-import { ref, reactive, getCurrentInstance, onMounted } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { ElMessageBox } from "element-plus";
-import { paymentHistoryListPage} from "@/api/procurementManagement/paymentEntry.js";
-import {delPaymentRegistration } from "@/api/procurementManagement/procurementInvoiceLedger.js";
-import useFormData from "@/hooks/useFormData";
-import dayjs from "dayjs";
-
-const { proxy } = getCurrentInstance();
-const isShowSummarySon = ref(true);
-const tableColumn = ref([
- {
- label: "閲囪喘鍚堝悓鍙�",
- prop: "purchaseContractNumber",
- },
- {
- label: "浠樻鏃ユ湡",
- prop: "paymentDate",
- },
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
- width:240
- },
- {
- label: "浠樻閲戦",
- prop: "currentPaymentAmount",
- formatData: (params) => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
- },
- {
- label: "浠樻鏂瑰紡",
- prop: "paymentMethod",
- },
- {
- label: "鐧昏浜�",
- prop: "registrant",
- },
- {
- label: "鐧昏鏃ユ湡",
- prop: "registrationtDate",
- },
- {
- label: "鎿嶄綔",
- dataType: "slot",
- slot: "operation",
- width: 100,
- align: "center",
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const total = ref(0);
-const { form: searchForm } = useFormData({
- searchText: undefined,
- purchaseContractNumber: undefined,
- paymentDate: [],
- paymentDateStart: undefined,
- paymentDateEnd: undefined,
-});
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const { paymentDate, ...rest } = searchForm;
- paymentHistoryListPage({ ...rest, ...page }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.records;
- page.total = res.total;
- });
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeMainTable1 = (param) => {
- return proxy.summarizeTable(param, ["currentPaymentAmount"], {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- });
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-
-const changeDateRange = (date) => {
- if (date) {
- searchForm.paymentDateStart = date[0];
- searchForm.paymentDateEnd = date[1];
- getList();
- }
-};
-
-const clearRange = () => {
- searchForm.paymentDate = [];
- searchForm.paymentDateStart = undefined;
- searchForm.paymentDateEnd = undefined;
- getList();
-};
-
-// 鍒犻櫎
-const handleDelete = (row) => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- tableLoading.value = true;
- delPaymentRegistration([row.id])
- .then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .finally(() => {
- tableLoading.value = false;
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 鎵归噺鍒犻櫎
-const handleBatchDelete = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
- return;
- }
- ElMessageBox.confirm(
- `纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.value.length} 鏉℃暟鎹悧锛焋,
- "鍒犻櫎鎻愮ず",
- {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }
- )
- .then(() => {
- tableLoading.value = true;
- const ids = selectedRows.value.map((item) => item.id);
- delPaymentRegistration(ids)
- .then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- selectedRows.value = [];
- getList();
- })
- .finally(() => {
- tableLoading.value = false;
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 瀵煎嚭
-const handleExport = () => {
- const { paymentDate, ...rest } = searchForm;
- proxy.download("/purchase/paymentRegistration/export", { ...rest, ...page }, "浠樻娴佹按.xlsx");
-};
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table_list {
- margin-top: unset;
-}
-</style>
diff --git a/src/views/procurementManagement/paymentLedger/index.vue b/src/views/procurementManagement/paymentLedger/index.vue
index 23a62aa..99b4b39 100644
--- a/src/views/procurementManagement/paymentLedger/index.vue
+++ b/src/views/procurementManagement/paymentLedger/index.vue
@@ -1,64 +1,54 @@
<template>
<div class="app-container">
- <div class="search_form" style="margin-bottom: 20px;">
+ <div class="search_form"
+ style="margin-bottom: 20px;">
<div>
<span class="search_title">渚涘簲鍟嗗悕绉�:</span>
- <el-input
- v-model="searchForm.supplierName"
- style="width: 240px"
- placeholder="杈撳叆渚涘簲鍟嗗悕绉�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search"
- />
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储</el-button
- >
+ <el-input v-model="searchForm.supplierName"
+ style="width: 240px"
+ placeholder="杈撳叆渚涘簲鍟嗗悕绉�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search" />
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">鎼滅储</el-button>
</div>
<div></div>
</div>
<el-row :gutter="20">
<el-col :span="14">
<div class="table_list">
- <el-table
- ref="multipleTable"
- border
- v-loading="tableLoading"
- :data="tableData"
- :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
- height="calc(100vh - 18.5em)"
- :highlight-current-row="true"
- style="width: 100%"
- tooltip-effect="dark"
- @row-click="rowClick"
- :show-summary="isShowSummary"
- :summary-method="summarizeMainTable"
- class="lims-table"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" />
- <el-table-column
- label="鍚堝悓閲戦(鍏�)"
- prop="invoiceAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
- />
- <el-table-column
- label="浠樻閲戦(鍏�)"
- prop="paymentAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
- />
- <el-table-column
- label="搴斾粯閲戦(鍏�)"
- prop="payableAmount"
- show-overflow-tooltip
- >
+ <el-table ref="multipleTable"
+ border
+ v-loading="tableLoading"
+ :data="tableData"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ height="calc(100vh - 18.5em)"
+ :highlight-current-row="true"
+ style="width: 100%"
+ tooltip-effect="dark"
+ @row-click="rowClick"
+ :show-summary="isShowSummary"
+ :summary-method="summarizeMainTable"
+ class="lims-table">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="渚涘簲鍟嗗悕绉�"
+ prop="supplierName" />
+ <el-table-column label="鍚堝悓閲戦(鍏�)"
+ prop="contractAmounts"
+ show-overflow-tooltip
+ :formatter="formattedNumber" />
+ <el-table-column label="浠樻閲戦(鍏�)"
+ prop="paymentAmount"
+ show-overflow-tooltip
+ :formatter="formattedNumber" />
+ <el-table-column label="搴斾粯閲戦(鍏�)"
+ prop="payableAmount"
+ show-overflow-tooltip>
<template #default="{ row, column }">
<el-text type="danger">
{{ formattedNumber(row, column, row.payableAmount) }}
@@ -66,29 +56,27 @@
</template>
</el-table-column>
</el-table>
- <pagination
- v-show="total > 0"
- @pagination="paginationSearch"
- :total="total"
- :layout="page.layout"
- :page="page.current"
- :limit="page.size"
- />
+ <pagination v-show="total > 0"
+ @pagination="paginationSearch"
+ :total="total"
+ :layout="page.layout"
+ :page="page.current"
+ :limit="page.size" />
</div>
</el-col>
<el-col :span="10">
<div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumnSon"
- :tableData="originalTableDataSon"
- :isSelection="false"
- :isShowPagination="false"
- :tableLoading="tableLoadingSon"
- :isShowSummary="isShowSummarySon"
- :summaryMethod="summarizeMainTable1"
- height="calc(100vh - 18.5em)"
- >
+ <PIMTable rowKey="id"
+ :column="tableColumnSon"
+ :tableData="originalTableDataSon"
+ :isSelection="false"
+ :isShowPagination="true"
+ :page="sonPage"
+ :tableLoading="tableLoadingSon"
+ :isShowSummary="isShowSummarySon"
+ :summaryMethod="summarizeMainTable1"
+ height="calc(100vh - 18.5em)"
+ @pagination="sonPaginationSearch">
<template #payableAmountSlot="{ row }">
<el-text type="danger">
{{ parseFloat(row.payableAmount).toFixed(2) }}
@@ -102,191 +90,205 @@
</template>
<script setup>
-import { ref, toRefs } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import {
- paymentLedgerList,
- paymentRecordList,
-} from "@/api/procurementManagement/paymentLedger.js";
-import Pagination from "../../../components/PIMTable/Pagination.vue";
+ import { ref, toRefs } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import {
+ paymentLedgerList,
+ paymentRecordList,
+ } from "@/api/procurementManagement/paymentLedger.js";
+ import Pagination from "../../../components/PIMTable/Pagination.vue";
-const tableData = ref([]);
-const tableLoading = ref(false);
-const data = reactive({
- searchForm: {
- supplierNameOrContractNo: "",
- },
-});
-const page = reactive({
- current: 1,
- size: 100,
-});
-const sonPage = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const sonTotal = ref(0);
-const isShowSummary = ref(true);
-const { searchForm } = toRefs(data);
-const currentSupplierId = ref("");
-const rowClick = (row) => {
- currentSupplierId.value = row.supplierId;
- getPaymenRecordtList(row.supplierId);
-};
-// 瀛愭ā鍧�
-const tableColumnSon = ref([
- {
- label: "鍙戠敓鏃ユ湡",
- prop: "paymentDate",
- width: 110,
- },
- {
- label: "閲囪喘鍚堝悓鍙�",
- prop: "purchaseContractNumber",
- width: 150,
- },
- {
- label: "鍚堝悓閲戦(鍏�)",
- prop: "invoiceAmount",
- width: 200,
- formatData: (params) => {
- return params ? parseFloat(params).toFixed(2) : 0;
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+ const data = reactive({
+ searchForm: {
+ supplierName: "",
},
- },
- {
- label: "浠樻閲戦(鍏�)",
- prop: "paymentAmount",
- width: 200,
- formatData: (params) => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
- },
- {
- label: "搴斾粯閲戦(鍏�)",
- dataType: "slot",
- width: 200,
- prop: "payableAmount",
- slot: "payableAmountSlot",
- },
-]);
-const tableDataSon = ref([]);
-const originalTableDataSon = ref([]);
-const tableLoadingSon = ref(false);
-const isShowSummarySon = ref(true);
-const detailPageNum = ref(1);
-const detailPageSize = ref(10);
-const { proxy } = getCurrentInstance();
-
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(
- param,
- ["invoiceAmount", "paymentAmount", "payableAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeMainTable1 = (param) => {
- let summarizeTable = proxy.summarizeTable(
- param,
- ["invoiceAmount", "paymentAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
- if (originalTableDataSon.value.length > 0) {
- summarizeTable[summarizeTable.length - 1] =
- originalTableDataSon.value[
- originalTableDataSon.value.length - 1
- ].payableAmount.toFixed(2);
- } else {
- summarizeTable[summarizeTable.length - 1] = 0.0;
- }
- return summarizeTable;
-};
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const paginationSearch = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- paymentLedgerList({
- ...searchForm.value,
- ...page,
- }).then((res) => {
- let result = res.data;
- tableLoading.value = false;
- tableData.value = result.records || [];
- total.value = result.total || 0;
- if (tableData.value.length > 0) {
- getPaymenRecordtList(tableData.value[0].supplierId);
- currentSupplierId.value = tableData.value[0].supplierId;
- }
});
-};
+ const page = reactive({
+ current: 1,
+ size: 100,
+ });
+ const sonPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ layout: "total, sizes, prev, pager, next, jumper",
+ });
+ const total = ref(0);
+ const isShowSummary = ref(true);
+ const { searchForm } = toRefs(data);
+ const currentSupplierId = ref("");
+ const rowClick = row => {
+ currentSupplierId.value = row.supplierId;
+ sonPage.current = 1;
+ getPaymenRecordtList(row.supplierId);
+ };
+ // 瀛愭ā鍧�
+ const tableColumnSon = ref([
+ {
+ label: "鍚堝悓绛捐鏃ユ湡",
+ prop: "executionDate",
+ width: 110,
+ },
+ {
+ label: "閲囪喘鍚堝悓鍙�",
+ prop: "purchaseContractNumber",
+ width: 150,
+ },
+ {
+ label: "鍚堝悓閲戦(鍏�)",
+ prop: "contractAmount",
+ width: 200,
+ formatData: params => {
+ return params ? parseFloat(params).toFixed(2) : 0;
+ },
+ },
+ {
+ label: "浠樻閲戦(鍏�)",
+ prop: "paymentAmount",
+ width: 200,
+ formatData: params => {
+ return params ? parseFloat(params).toFixed(2) : 0;
+ },
+ },
+ {
+ label: "搴斾粯閲戦(鍏�)",
+ dataType: "slot",
+ width: 200,
+ prop: "payableAmount",
+ slot: "payableAmountSlot",
+ },
+ ]);
+ const tableDataSon = ref([]);
+ const originalTableDataSon = ref([]);
+ const tableLoadingSon = ref(false);
+ const isShowSummarySon = ref(true);
+ const { proxy } = getCurrentInstance();
-const getPaymenRecordtList = (supplierId) => {
- tableLoadingSon.value = true;
- paymentRecordList({supplierId: supplierId})
- .then((res) => {
- tableLoadingSon.value = false;
- tableDataSon.value = res.data;
- handlePagination({ page: 1, limit: sonPage.size });
- sonTotal.value = res.data.length;
- })
- .catch((e) => {
- tableLoadingSon.value = false;
+ // 涓昏〃鍚堣鏂规硶
+ const summarizeMainTable = param => {
+ return proxy.summarizeTable(
+ param,
+ ["contractAmounts", "paymentAmount", "payableAmount"],
+ {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ }
+ );
+ };
+ // 瀛愯〃鍚堣鏂规硶
+ const summarizeMainTable1 = param => {
+ let summarizeTable = proxy.summarizeTable(
+ param,
+ ["contractAmount", "invoiceAmount", "paymentAmount"],
+ {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ }
+ );
+ if (originalTableDataSon.value.length > 0) {
+ summarizeTable[summarizeTable.length - 1] =
+ originalTableDataSon.value[
+ originalTableDataSon.value.length - 1
+ ].payableAmount.toFixed(2);
+ } else {
+ summarizeTable[summarizeTable.length - 1] = 0.0;
+ }
+ return summarizeTable;
+ };
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const paginationSearch = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ tableLoading.value = true;
+ paymentLedgerList({
+ ...searchForm.value,
+ ...page,
+ }).then(res => {
+ let result = res.data;
+ tableLoading.value = false;
+ tableData.value = result.records || [];
+ total.value = result.total || 0;
+ if (tableData.value.length > 0) {
+ currentSupplierId.value = tableData.value[0].supplierId;
+ sonPage.current = 1;
+ getPaymenRecordtList(tableData.value[0].supplierId);
+ }
});
-};
-const handlePagination = ({ page, limit }) => {
- sonPage.current = page;
- sonPage.size = limit;
+ };
- const start = (page - 1) * limit;
- const end = start + limit;
+ const getPaymenRecordtList = supplierId => {
+ tableLoadingSon.value = true;
+ paymentRecordList({
+ supplierId: supplierId,
+ current: sonPage.current,
+ size: sonPage.size,
+ })
+ .then(res => {
+ tableLoadingSon.value = false;
+ let result = res.data;
+ if (Array.isArray(result)) {
+ tableDataSon.value = result;
+ sonPage.total = result.length;
+ handlePagination({ page: sonPage.current, limit: sonPage.size });
+ } else {
+ originalTableDataSon.value = result.records || [];
+ sonPage.total = result.total || 0;
+ }
+ })
+ .catch(e => {
+ tableLoadingSon.value = false;
+ });
+ };
+ const handlePagination = ({ page, limit }) => {
+ console.log(page, limit);
+ sonPage.current = page;
+ sonPage.size = limit;
- originalTableDataSon.value = tableDataSon.value.slice(start, end);
-};
+ const start = (page - 1) * limit;
+ const end = start + limit;
-const sonPaginationSearch = (pagination) => {
- // 鎺ユ敹鍒嗛〉鍣ㄥ弬鏁� { page, limit }
- handlePagination(pagination);
-};
-const formattedNumber = (row, column, cellValue) => {
- if (column.property !== "supplierName") {
- return parseFloat(cellValue).toFixed(2);
- } else {
- return cellValue;
- }
-};
-getList();
+ originalTableDataSon.value = tableDataSon.value.slice(start, end);
+ };
+
+ const sonPaginationSearch = pagination => {
+ // 鎺ユ敹鍒嗛〉鍣ㄥ弬鏁� { page, limit }
+ sonPage.current = pagination.page;
+ sonPage.size = pagination.limit;
+ getPaymenRecordtList(currentSupplierId.value);
+ };
+ const formattedNumber = (row, column, cellValue) => {
+ if (column.property !== "supplierName") {
+ return parseFloat(cellValue).toFixed(2);
+ } else {
+ return cellValue;
+ }
+ };
+ getList();
</script>
<style scoped lang="scss">
-.el-pagination {
- width: 100%;
- height: 55px;
- display: flex;
- justify-content: flex-end;
- float: right;
- flex-direction: row;
- align-items: center;
- background: #fff;
- margin: -20px 0 0 0;
- padding: 0 20px;
-}
-.pagination-container {
- margin-top: 0;
-}
+ .el-pagination {
+ width: 100%;
+ height: 55px;
+ display: flex;
+ justify-content: flex-end;
+ float: right;
+ flex-direction: row;
+ align-items: center;
+ background: #fff;
+ margin: -20px 0 0 0;
+ padding: 0 20px;
+ }
+ .pagination-container {
+ margin-top: 0;
+ }
</style>
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue b/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
deleted file mode 100644
index 4e461dc..0000000
--- a/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
+++ /dev/null
@@ -1,238 +0,0 @@
-<template>
- <el-dialog :title="modalOptions.title"
- v-model="visible"
- @close="close">
- <el-form :model="form">
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="閲囪喘鍚堝悓鍙凤細">
- <el-tag size="large">{{ form.purchaseContractNumber }}</el-tag>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�">
- <el-text>{{ form.salesContractNo }}</el-text>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�">
- <el-text type="primary">{{ form.taxInclusiveUnitPrice }}</el-text>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿锛�">
- <el-text>{{ form.createdAt }}</el-text>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍙戠エ鍙凤細">
- <el-input disabled
- v-model="form.invoiceNumber" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏉ョエ鏁帮細">
- <el-input-number :step="0.1"
- :min="0"
- :max="maxTicketsNum"
- style="width: 100%"
- v-model="form.ticketsNum"
- @change="inputTicketsNum"
- :precision="2" />
- <div style="font-size: 12px; color: #909399; margin-top: 4px;">
- 鍙~鍐欐暟閲忥細{{ maxTicketsNum }}
- </div>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏈鏉ョエ閲戦(鍏�)锛�">
- <el-input-number :step="0.1"
- :min="0"
- style="width: 100%"
- v-model="form.ticketsAmount"
- @change="inputTicketsAmount"
- :precision="2" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏈潵绁ㄦ暟锛�">
- <el-text type="success">{{ form.futureTickets }}</el-text>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <el-button type="primary"
- :loading="loading"
- @click="sendForm">
- {{ modalOptions.confirmText }}
- </el-button>
- <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
- </template>
- </el-dialog>
-</template>
-
-<script setup>
-import { useModal } from "@/hooks/useModal";
-import useFormData from "@/hooks/useFormData";
-import { updateRegistration, getProductRecordById } from "@/api/procurementManagement/procurementInvoiceLedger";
-import { ElMessage } from "element-plus";
-import { getCurrentInstance, ref, nextTick, computed } from "vue";
-
-defineOptions({
- name: "鏉ョエ鍙拌处缂栬緫",
-});
-const emits = defineEmits(["success"]);
-
-const saleLedgerProjectId = ref("");
-const temFutureTickets = ref(0);
-const originalTicketsNum = ref(0); // 鍘熷宸叉潵绁ㄦ暟
-const { proxy } = getCurrentInstance();
-
-// 璁$畻鏈�澶у彲濉啓鏁伴噺 = 鍘熷宸叉潵绁ㄦ暟 + 鏈潵绁ㄦ暟
-const maxTicketsNum = computed(() => {
- return Number(originalTicketsNum.value) + Number(temFutureTickets.value);
-});
-
-const {
- id,
- visible,
- loading,
- openModal,
- modalOptions,
- handleConfirm,
- closeModal,
-} = useModal({ title: "鏉ョエ鍙拌处" });
-
-const { form, resetForm } = useFormData({
- id: undefined,
- purchaseContractNumber: undefined, // 閲囪喘鍚堝悓鍙�
- salesContractNo: undefined, // 閿�鍞悎鍚屽彿
- createdAt: undefined, // 鍒涘缓鏃堕棿
- invoiceNumber: undefined, // 鍙戠エ鍙�
- ticketsNum: undefined, // 鏉ョエ鏁�
- ticketsAmount: undefined, // 鏉ョエ閲戦
- taxInclusiveUnitPrice: undefined, // 鍚◣鍗曚环
- futureTickets: undefined, // 鏈潵绁ㄦ暟
-});
-
-const load = async (id, purchaseLedgerId, productModelId) => {
- const { code, data } = await getProductRecordById({
- id: id,
- purchaseLedgerId: purchaseLedgerId,
- productModelId: productModelId,
- });
- if (code === 200) {
- form.id = data.id;
- form.purchaseContractNumber = data.purchaseContractNumber;
- form.salesContractNo = data.salesContractNo;
- form.createdAt = data.createdAt;
- form.invoiceNumber = data.invoiceNumber;
- form.ticketsNum = data.ticketsNum;
- form.ticketsAmount = data.ticketsAmount.toFixed(2);
- form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice;
- form.futureTickets = data.futureTickets;
- temFutureTickets.value = data.futureTickets;
- // 淇濆瓨鍘熷宸叉潵绁ㄦ暟
- originalTicketsNum.value = data.ticketsNum || 0;
- }
-};
-
-const inputTicketsNum = val => {
- // 纭繚鍚◣鍗曚环瀛樺湪涓斾笉涓洪浂
- if (!form.taxInclusiveUnitPrice || Number(form.taxInclusiveUnitPrice) === 0) {
- proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
- return;
- }
-
- // 妫�鏌ユ潵绁ㄦ暟涓嶈兘澶т簬锛堝師濮嬪凡鏉ョエ鏁� + 鏈潵绁ㄦ暟锛�
- const maxNum = maxTicketsNum.value;
- if (Number(form.ticketsNum) > maxNum) {
- proxy.$modal.msgWarning(`鏉ョエ鏁颁笉鑳藉ぇ浜�${maxNum}锛堝凡鏉ョエ鏁�${originalTicketsNum.value} + 鏈潵绁ㄦ暟${temFutureTickets.value}锛塦);
- form.ticketsNum = maxNum;
- return;
- }
-
- // 璁$畻鏈鏂板鐨勬潵绁ㄦ暟锛堝綋鍓嶆潵绁ㄦ暟 - 鍘熷宸叉潵绁ㄦ暟锛�
- const newTicketsNum = Number(form.ticketsNum) - Number(originalTicketsNum.value);
-
- // 濡傛灉鏂板鐨勬潵绁ㄦ暟澶т簬鏈潵绁ㄦ暟锛屽垯闄愬埗
- if (newTicketsNum > Number(temFutureTickets.value)) {
- proxy.$modal.msgWarning("鏈鏂板鏉ョエ鏁颁笉寰楀ぇ浜庢湭鏉ョエ鏁�");
- form.ticketsNum = Number(originalTicketsNum.value) + Number(temFutureTickets.value);
- return;
- }
-
- // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
- const ticketsAmount =
- Number(form.ticketsNum) * Number(form.taxInclusiveUnitPrice);
- const futureTickets =
- Number(temFutureTickets.value) - newTicketsNum;
- form.futureTickets = Number(futureTickets.toFixed(2));
- form.ticketsAmount = Number(ticketsAmount.toFixed(2));
-};
-
-const inputTicketsAmount = val => {
- // 纭繚鍚◣鍗曚环瀛樺湪涓斾笉涓洪浂
- if (!form.taxInclusiveUnitPrice || Number(form.taxInclusiveUnitPrice) === 0) {
- proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
- return;
- }
-
- // 璁$畻鏈�澶у彲濉啓閲戦 = 锛堝師濮嬪凡鏉ョエ鏁� + 鏈潵绁ㄦ暟锛�* 鍚◣鍗曚环
- const maxAmount = maxTicketsNum.value * Number(form.taxInclusiveUnitPrice);
-
- if (Number(val) > maxAmount) {
- proxy.$modal.msgWarning(`鏈鏉ョエ閲戦涓嶅緱澶т簬${maxAmount.toFixed(2)}鍏僠);
- form.ticketsAmount = maxAmount.toFixed(2);
- form.ticketsNum = maxTicketsNum.value;
- return;
- }
-
- // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
- const ticketsNum = Number(val) / Number(form.taxInclusiveUnitPrice);
-
- // 妫�鏌ユ潵绁ㄦ暟涓嶈兘澶т簬鏈�澶у��
- if (ticketsNum > maxTicketsNum.value) {
- proxy.$modal.msgWarning(`鏉ョエ鏁颁笉鑳藉ぇ浜�${maxTicketsNum.value}`);
- form.ticketsNum = maxTicketsNum.value;
- form.ticketsAmount = maxAmount.toFixed(2);
- return;
- }
-
- form.ticketsNum = Number(ticketsNum.toFixed(2));
-
- // 璁$畻鏈潵绁ㄦ暟
- const newTicketsNum = form.ticketsNum - originalTicketsNum.value;
- const futureTickets = Number(temFutureTickets.value) - newTicketsNum;
- form.futureTickets = Number(futureTickets.toFixed(2));
-};
-
-const open = async row => {
- openModal(row.id);
- saleLedgerProjectId.value = row.saleLedgerProjectId;
- await nextTick();
- load(row.id, row.purchaseLedgerId, row.productModelId);
-};
-
-const close = () => {
- resetForm();
- closeModal();
-};
-
-const sendForm = async () => {
- form.saleLedgerProjectId = saleLedgerProjectId.value;
- const { code } = await updateRegistration(form);
- if (code === 200) {
- emits("success");
- ElMessage({ message: "鎿嶄綔鎴愬姛", type: "success" });
- close();
- }
-};
-
-defineExpose({
- open,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/Modal/UploadModal.vue b/src/views/procurementManagement/procurementInvoiceLedger/Modal/UploadModal.vue
deleted file mode 100644
index b82bd10..0000000
--- a/src/views/procurementManagement/procurementInvoiceLedger/Modal/UploadModal.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-<template>
- <el-dialog v-model="upload.open" :title="upload.title" :width="500">
- <FileUpload
- ref="fileUploadRef"
- accept=".xlsx, .xls, .pdf"
- :headers="upload.headers"
- :autoUpload="true"
- :action="upload.url"
- :disabled="upload.isUploading"
- :showTip="false"
- :limit="10"
- @success="handleFileSuccess"
- @remove="removeFile"
- />
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
- <el-button @click="upload.open = false">鍙� 娑�</el-button>
- </div>
- </template>
- </el-dialog>
-</template>
-
-<script setup>
-import { reactive } from "vue";
-import { getToken } from "@/utils/auth.js";
-import { FileUpload } from "@/components/Upload";
-import { ElMessage } from "element-plus";
-import { ref } from "vue";
-import useFormData from "@/hooks/useFormData";
-
-defineOptions({
- name: "鏉ョエ鍙拌处闄勪欢琛ュ厖",
-});
-
-const { form, resetForm } = useFormData({
- id: undefined,
- tempFileIds: [],
-});
-const emits = defineEmits(["uploadSuccess"]);
-const fileUploadRef = ref();
-const upload = reactive({
- // 鏄惁鏄剧ず寮瑰嚭灞傦紙渚涘簲鍟嗗鍏ワ級
- open: false,
- // 寮瑰嚭灞傛爣棰橈紙渚涘簲鍟嗗鍏ワ級
- title: "",
- // 鏄惁绂佺敤涓婁紶
- isUploading: false,
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
-});
-// 鐐瑰嚮瀵煎叆
-const handleImport = (id) => {
- form.id = id;
- upload.open = true;
- upload.title = "鏉ョエ鍙拌处闄勪欢琛ュ厖";
-};
-
-const submitFileForm = () => {
- emits("uploadSuccess", form);
- resetForm();
- upload.open = false;
- // 娓呯┖鏂囦欢鍒楄〃
- fileUploadRef.value.fileList = [];
-};
-
-const handleFileSuccess = (response) => {
- if (response.code == 200) {
- form.tempFileIds.push(response.data.tempId);
- console.log('form',form);
- ElMessage({ message: "瀵煎叆鎴愬姛", type: "success" });
- } else {
- ElMessage({ message: response.msg, type: "error" });
- }
-};
-
-const removeFile = (file) => {
- const { tempId } = file.response.data;
- form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId);
-};
-
-defineExpose({
- handleImport,
-});
-</script>
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/index.vue b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
deleted file mode 100644
index c94d8c2..0000000
--- a/src/views/procurementManagement/procurementInvoiceLedger/index.vue
+++ /dev/null
@@ -1,330 +0,0 @@
-<template>
- <div class="app-container">
- <el-form :model="filters" :inline="true">
- <el-form-item label="閲囪喘鍚堝悓鍙�">
- <el-input
- v-model="filters.purchaseContractNumber"
- style="width: 240px"
- placeholder="璇疯緭鍏�"
- clearable
- :prefix-icon="Search"
- @change="getTableData"
- />
- </el-form-item>
- <el-form-item label="渚涘簲鍟�">
- <el-input
- v-model="filters.supplierName"
- style="width: 240px"
- placeholder="璇疯緭鍏�"
- clearable
- :prefix-icon="Search"
- @change="getTableData"
- />
- </el-form-item>
- <el-form-item label="鏉ョエ鏃ユ湡">
- <el-date-picker
- style="width: 240px"
- v-model="filters.createdAt"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- start-placeholder="寮�濮嬫椂闂�"
- end-placeholder="缁撴潫鏃堕棿"
- clearable
- @change="getTableData"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
- <el-button @click="resetFilters"> 閲嶇疆 </el-button>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- </el-form-item>
- </el-form>
- <div class="table_list">
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableLoading="loading"
- :tableData="dataList"
- :isSelection="true"
- height="calc(100vh - 19.5em)"
- :isShowSummary="true"
- :summaryMethod="summarizeMainTable"
- :page="{
- current: pagination.currentPage,
- size: pagination.pageSize,
- total: pagination.total,
- }"
- @selection-change="handleSelectionChange"
- @pagination="changePage"
- >
- <template #operation="{ row }">
- <el-button
- type="primary"
- link
- @click="openEdit(row)"
- >
- 缂栬緫
- </el-button>
- <el-button
- type="primary"
- link
- @click="openFileDialog(row)"
- >
- 闄勪欢
- </el-button>
- <el-button
- type="primary"
- link
- @click="handleDelete(row)"
- >
- 鍒犻櫎
- </el-button>
- </template>
- </PIMTable>
- </div>
- <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="ticket_registration" :record-id="recordId" />
- <EditModal ref="editmodalRef" @success="getTableData"></EditModal>
- </div>
-</template>
-
-<script setup>
-import { ref, getCurrentInstance } from "vue";
-import { usePaginationApi } from "@/hooks/usePaginationApi";
-import {
- Search,
-} from "@element-plus/icons-vue";
-import {
- delRegistration,
- productRecordPage,
- delCommonFile,
-} from "@/api/procurementManagement/procurementInvoiceLedger.js";
-import request from "@/utils/request";
-import { getToken } from "@/utils/auth";
-import { onMounted } from "vue";
-import { ElMessageBox } from "element-plus";
-import EditModal from "./Modal/EditModal.vue";
-import useUserStore from "@/store/modules/user.js";
-const userStore = useUserStore();
-const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
-
-defineOptions({
- name: "鏉ョエ鍙拌处",
-});
-
-const editmodalRef = ref();
-const fileListRef = ref(null);
-const fileListDialogVisible = ref(false);
-const currentRowId = ref(null); // 褰撳墠鏌ョ湅闄勪欢鐨勮ID
-
-const { proxy } = getCurrentInstance();
-const multipleVal = ref([]);
-const {
- loading,
- filters,
- columns,
- dataList,
- pagination,
- getTableData,
- resetFilters,
- onCurrentChange,
-} = usePaginationApi(
- productRecordPage,
- {
- purchaseContractNumber: undefined, // 閲囪喘鍚堝悓鍙�
- supplierName: undefined, // 渚涘簲鍟�
- createdAt: [], // 鏉ョエ鏃ユ湡
- },
- [
- {
- label: "閲囪喘鍚堝悓鍙�",
- prop: "purchaseContractNumber",
- width: 150,
- },
- {
- label: "閿�鍞悎鍚屽彿",
- prop: "salesContractNo",
- width: 150,
- },
- {
- label: "椤圭洰鍚嶇О",
- prop: "projectName",
- width: 240,
- },
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
- width: 240,
- },
- {
- label: "浜у搧澶х被",
- prop: "productCategory",
- width: 150,
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "specificationModel",
- width: 150,
- },
- {
- label: "鍙戠エ鍙�",
- prop: "invoiceNumber",
- width: 200,
- },
- {
- label: "鍚堝悓閲戦(鍏�)",
- prop: "taxInclusiveTotalPrice",
- width: 200,
- formatData: (cell) => {
- return cell ? parseFloat(cell).toFixed(2) : 0;
- },
- },
- {
- label: "寮�绁ㄦ棩鏈�",
- prop: "createdAt",
- width: 110,
- },
- {
- label: "寮�绁ㄩ噾棰�",
- prop: "ticketsAmount",
- width: 200,
- formatData: (cell) => {
- return cell ? parseFloat(cell).toFixed(2) : 0;
- },
- },
- {
- label: "涓嶅惈绋庨噾棰�",
- prop: "unTicketsPrice",
- width: 200,
- formatData: (cell) => {
- return cell ? parseFloat(cell).toFixed(2) : 0;
- },
- },
- {
- label: "澧炲�肩◣",
- prop: "invoiceAmount",
- width: 200,
- },
- {
- label: "褰曞叆浜�",
- prop: "issUer",
- width: 200,
- },
- {
- fixed: "right",
- width: 200,
- label: "鎿嶄綔",
- dataType: "slot",
- slot: "operation",
- align: "center",
- },
- ],
- {},
- {
- createdAt: (aim) => ({
- createdAtStart: aim ? aim[0] : undefined,
- createdAtEnd: aim ? aim[1] : undefined,
- }),
- }
-);
-
-const summarizeMainTable = (param) => {
- const sums = proxy.summarizeTable(
- param,
- ["ticketsAmount", "unTicketsPrice", "invoiceAmount"],
- {
- ticketsNum: { noDecimal: true },
- futureTickets: { noDecimal: true },
- }
- );
-
- const keySet = new Set();
- let taxInclusiveSum = 0;
- (param.data || []).forEach((row) => {
- const key = `${row.purchaseContractNumber ?? ""}\n${row.salesContractNo ?? ""}\n${row.productCategory ?? ""}\n${row.specificationModel ?? ""}`;
- if (keySet.has(key)) return;
- keySet.add(key);
- const val = Number(row.taxInclusiveTotalPrice);
- if (!isNaN(val)) taxInclusiveSum += val;
- });
- const taxInclusiveIndex = (param.columns || []).findIndex(
- (c) => c.property === "taxInclusiveTotalPrice"
- );
- if (taxInclusiveIndex !== -1) {
- sums[taxInclusiveIndex] = taxInclusiveSum.toFixed(2);
- }
- return sums;
-};
-
-const handleSelectionChange = (val) => {
- multipleVal.value = val;
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/purchase/registration/export", {}, "鏉ョエ鐧昏.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- onCurrentChange(page);
-};
-
-// 鎵撳紑闄勪欢寮圭獥
-const recordId =ref(0)
-const fileDialogVisible = ref(false)
-
-// 鎵撳紑闄勪欢寮规
-const openFileDialog = async (row) => {
- recordId.value = row.id
- fileDialogVisible.value = true
-}
-
-const openEdit = (row) => {
- editmodalRef.value.open(row);
-};
-// 鍒犻櫎
-const handleDelete = (row) => {
- let ids = [];
- ids.push(row.id);
- ElMessageBox.confirm("璇ュ紑绁ㄥ彴璐﹀皢琚垹闄�,鏄惁纭鍒犻櫎", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- loading.value = true;
- delRegistration(ids).then((res) => {
- getTableData();
- });
- loading.value = false;
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-onMounted(() => {
- getTableData();
-});
-</script>
-
-<style lang="scss" scoped>
-.table_list {
- margin-top: unset;
-}
-.tagBox {
- margin-top: 4px;
-}
-</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 100b94c..9c7682b 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -676,7 +676,6 @@
try {
const workOrderRes = await productWorkOrderPage({
npsNo: item.npsNo,
- isProduction: 1,
size: 100,
});
const workOrders = workOrderRes.data.records || [];
diff --git a/src/views/safeProduction/safetyTrainingAssessment/detail.vue b/src/views/safeProduction/safetyTrainingAssessment/detail.vue
index 9796980..9e3af6b 100644
--- a/src/views/safeProduction/safetyTrainingAssessment/detail.vue
+++ b/src/views/safeProduction/safetyTrainingAssessment/detail.vue
@@ -111,8 +111,6 @@
<script setup>
import { onMounted, ref } from "vue";
- import { invoiceLedgerSalesAccount } from "@/api/salesManagement/invoiceLedger.js";
- import { customerInteractions } from "@/api/salesManagement/receiptPayment.js";
import Pagination from "@/components/PIMTable/Pagination.vue";
import {
safeTrainingDetailListPage,
diff --git a/src/views/salesManagement/invoiceLedger/index.vue b/src/views/salesManagement/invoiceLedger/index.vue
deleted file mode 100644
index e52ea47..0000000
--- a/src/views/salesManagement/invoiceLedger/index.vue
+++ /dev/null
@@ -1,438 +0,0 @@
-<template>
- <div class="app-container">
- <div class="search_form">
- <el-form :inline="true" :model="searchForm">
- <el-form-item label="瀹㈡埛鍚嶇О/鍚堝悓鍙�">
- <el-input v-model="searchForm.searchText" style="width: 240px" placeholder="杈撳叆瀹㈡埛鍚嶇О/閿�鍞悎鍚屽彿鎼滅储"
- @change="handleQuery" clearable :prefix-icon="Search" />
- </el-form-item>
- <el-form-item label="寮�绁ㄦ棩鏈�">
- <el-date-picker style="width: 240px" v-model="searchForm.invoiceDate" value-format="YYYY-MM-DD"
- format="YYYY-MM-DD" type="daterange" start-placeholder="寮�濮嬫椂闂�" end-placeholder="缁撴潫鏃堕棿" clearable
- @change="changeDateRange" @clear="clearRange" />
- </el-form-item>
- <el-form-item label="褰曞叆鏃ユ湡">
- <el-date-picker style="width: 100%" v-model="searchForm.createTimeStart" value-format="YYYY-MM-DD HH:mm:ss"
- format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable @change="handleQuery" />
- </el-form-item>
- <el-form-item label="涓嶆樉绀烘湁鍙戠エ琛�">
- <el-checkbox v-model="searchForm.status" @change="handleQuery" />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
- <el-button @click="resetForm"> 閲嶇疆 </el-button>
- <el-button @click="handleOut" type="primary">瀵煎嚭</el-button>
- </el-form-item>
- </el-form>
- </div>
- <div class="table_list">
- <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
- :row-key="(row) => row.id" show-summary :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
- <el-table-column align="center" type="selection" width="55" />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip width="180" />
- <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip width="240" />
- <el-table-column label="浜у搧澶х被" prop="productCategory" width="200" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="160" show-overflow-tooltip />
- <el-table-column label="鍙戠エ鍙�" prop="invoiceNo" width="200" show-overflow-tooltip />
- <el-table-column label="鍙戠エ閲戦(鍏�)" prop="invoiceTotal" show-overflow-tooltip :formatter="formattedNumber"
- width="200" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" show-overflow-tooltip />
- <el-table-column label="褰曞叆浜�" prop="invoicePerson" show-overflow-tooltip />
- <el-table-column label="褰曞叆鏃ユ湡" prop="createTime" show-overflow-tooltip :formatter="formatDate" width="180" />
- <el-table-column label="寮�绁ㄦ棩鏈�" prop="invoiceDate" show-overflow-tooltip width="120" />
- <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
- <template #default="scope">
- <el-button link type="primary" @click="openForm(scope.row)">缂栬緫</el-button>
- <el-button link type="primary" @click="openFileDialog(scope.row)">闄勪欢</el-button>
- <el-button link type="primary" @click="delInvoiceLedger(scope.row)">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
- <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
- :page="page.current" :limit="page.size" @pagination="paginationChange" />
- </div>
- <FormDialog v-model="dialogFormVisible" title="寮�绁ㄥ彴璐﹂〉闈�" :width="'70%'" @close="closeDia" @confirm="submitForm" @cancel="closeDia">
- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
- <el-input v-model="form.salesContractNo" disabled></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName">
- <el-input v-model="form.customerName" placeholder="鑷姩濉厖" clearable disabled />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍙戠エ鍙凤細" prop="invoiceNo">
- <el-input v-model="form.invoiceNo" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item :label="`鍙戠エ閲戦(鍏�)锛� `" prop="invoiceTotal">
- <el-input-number :step="0.01" :min="0" :max="maxInvoiceAmount || form.taxInclusiveTotalPrice" style="width: 100%" v-model="form.invoiceTotal" placeholder="璇疯緭鍏�" clearable :precision="2"/>
- <div v-if="maxInvoiceAmount > 0" style="color: #909399; font-size: 12px; margin-top: 5px;">
- 鍙~鏈�澶ч噾棰濅负锛毬{ maxInvoiceAmount.toFixed(2) }}鍏�
- </div>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�绁ㄤ汉锛�" prop="invoicePerson">
- <el-input v-model="form.invoicePerson" placeholder="璇疯緭鍏�" clearable disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="寮�绁ㄦ棩鏈燂細" prop="invoiceDate">
- <el-date-picker style="width: 100%" v-model="form.invoiceDate" value-format="YYYY-MM-DD"
- format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
- :headers="upload.headers" accept=".pdf" :limit="10" :before-upload="handleBeforeUpload"
- :on-error="handleUploadError" :on-success="handleUploadSuccess">
- <el-button type="primary">涓婁紶</el-button>
- <template #tip>
- <!-- 鏂囦欢鏍煎紡鏀寔 doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z-->
- <div class="el-upload__tip">鏂囦欢鏍煎紡鏀寔 pdf</div>
- </template>
- </el-upload>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </FormDialog>
- <el-dialog title="涓婁紶寮圭獥" width="50%" v-model="uploadModal">
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
- :headers="upload.headers" accept=".pdf" :limit="10" style="width: 100%" :on-exceed="handleExceed"
- :before-upload="handleBeforeUpload" :on-error="handleUploadError" :on-success="handleUploadSuccess"
- :on-remove="handleRemove">
- <el-button type="primary">涓婁紶</el-button>
- <template #tip>
- <div class="el-upload__tip">鏂囦欢鏍煎紡浠呮敮鎸� pdf</div>
- </template>
- </el-upload>
- </el-form-item>
- </el-col>
- </el-row>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="commiInvoicetFile" type="primary">纭</el-button>
- <el-button @click="uploadModal = false">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="invoice_registration_product" :record-id="recordId" />
- </div>
-</template>
-
-<script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { ref } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { ElMessageBox } from "element-plus";
-import { getToken } from "@/utils/auth";
-import {
- invoiceLedgerSaveOrUpdate,
- invoiceLedgerProductInfo,
- commitFile,
- registrationProductPage,
- delInvoiceLedgerByRegProductId,
-} from "@/api/salesManagement/invoiceLedger.js";
-import useUserStore from "@/store/modules/user.js";
-import useFormData from "@/hooks/useFormData";
-import dayjs from "dayjs";
-import { getCurrentDate } from "@/utils/index.js";
-const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
-
-const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const productData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const fileList = ref([]);
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- searchText: "",
- status: false,
- invoiceDate: null,
- invoiceDateStart: undefined,
- invoiceDateEnd: undefined,
- createTimeStart: "", // 褰曞叆鏃ユ湡
- },
- form: {
- salesLedgerId: "",
- customerId: "",
- invoiceNo: "",
- invoiceTotal: "",
- taxRate: "",
- invoicePerson: "",
- invoiceDate: "",
- customerName: "",
- fileList: [],
- createTime: "", // 褰曞叆鏃ユ湡
- },
- rules: {
- salesLedgerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- customerId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- invoiceNo: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- invoiceAmount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- invoicePerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- invoiceDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- customerName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { form, rules } = toRefs(data);
-const { form: searchForm, resetForm } = useFormData(data.searchForm);
-const currentId = ref("");
-const userStore = useUserStore();
-const maxInvoiceAmount = ref(0); // 鍙戠エ閲戦鏈�澶у��
-const upload = reactive({
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/invoiceLedger/uploadFile",
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
-});
-const matchFileType = ref(["pdf"]);
-const uploadModal = ref(false);
-const formattedNumber = (row, column, cellValue) => {
- return parseFloat(cellValue).toFixed(2);
-};
-const formatDate = (row, column, cellValue) => {
- return dayjs(cellValue).format("YYYY-MM-DD HH:mm:ss");
-};
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const { invoiceDate, ...rest } = searchForm;
- // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
- const params = { ...rest, ...page };
- // 绉婚櫎寮�绁ㄦ棩鏈熺殑榛樿鍊艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
- delete params.invoiceDate;
- registrationProductPage(params).then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- total.value = res.data.total;
- });
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, ["invoiceTotal"], {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- });
-};
-// 鎵撳紑寮规
-const openForm = (row) => {
- form.value = {};
- productData.value = [];
- fileList.value = [];
- currentId.value = row.id;
-
- invoiceLedgerProductInfo({ id: row.id }).then((res) => {
- form.value = { ...res.data };
- fileList.value = res.data.fileList;
- // 淇濆瓨ticketRegistrationId鍒拌〃鍗曟暟鎹腑
- if (row.ticketRegistrationId) {
- form.value.ticketRegistrationId = row.ticketRegistrationId;
- }
- if (!form.value.invoicePerson) {
- form.value.invoicePerson = userStore.nickName;
- }
-
- // 璁$畻鍙戠エ閲戦鏈�澶у�硷細noInvoiceAmount + invoiceAmount
- const noInvoiceAmount = parseFloat(res.data.noInvoiceAmount || 0);
- const invoiceAmount = parseFloat(res.data.invoiceAmount || 0);
- maxInvoiceAmount.value = noInvoiceAmount + invoiceAmount;
- });
- dialogFormVisible.value = true;
-};
-// 涓婁紶澶氫釜鏂囦欢灏辫鐩栧師鏉ョ殑
-const handleExceed = (files) => {
- proxy.$refs["fileUpload"].clearFiles();
- const file = files[0];
- file.uid = genFileId();
- proxy.$refs["fileUpload"].handleStart(file);
-};
-// 涓婁紶鍓嶆牎妫�
-function handleBeforeUpload(file) {
- // 鏍℃鏂囦欢澶у皬
- if (file.size > 1024 * 1024 * 10) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
- return false;
- }
- // 鍒ゆ柇鏂囦欢鏍煎紡鏄惁绗﹀悎
- const fileType = file.name.split(".").pop().toLowerCase();
- if (!matchFileType.value.includes(fileType)) {
- proxy.$modal.msgError("鏂囦欢鏍煎紡涓嶅尮閰�");
- return false;
- }
- proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
- return true;
-}
-// 涓婁紶澶辫触
-function handleUploadError(err) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
- proxy.$modal.closeLoading();
-}
-// 涓婁紶鎴愬姛鍥炶皟
-function handleUploadSuccess(res, file, uploadFiles) {
- proxy.$modal.closeLoading();
- if (res.code === 200) {
- proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
- // 灏嗕笂浼犳垚鍔熺殑鏂囦欢淇℃伅娣诲姞鍒癴ileList涓�
- const fileInfo = {
- name: file.name,
- url: res.data.url || file.response?.data?.url || file.url,
- response: file.response
- };
- // 妫�鏌ユ槸鍚﹀凡瀛樺湪鐩稿悓鏂囦欢锛岄伩鍏嶉噸澶嶆坊鍔�
- const existingFileIndex = fileList.value.findIndex(f => f.name === fileInfo.name);
- if (existingFileIndex === -1) {
- fileList.value.push(fileInfo);
- } else {
- fileList.value[existingFileIndex] = fileInfo;
- }
- // 纭繚琛ㄥ崟鏁版嵁涓殑fileList涔熸洿鏂�
- form.value.fileList = fileList.value;
- } else {
- proxy.$modal.msgError(res.msg);
- proxy.$refs.fileUpload.handleRemove(file);
- }
-}
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- form.value.fileList = fileList.value;
- invoiceLedgerSaveOrUpdate(form.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
-};
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/invoiceLedger/export", {}, "寮�绁ㄥ彴璐�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 纭鏂囦欢涓婁紶
-const commiInvoicetFile = () => {
- const object = {
- fileList: fileList.value,
- id: currentId.value,
- };
- commitFile(object).then((res) => {
- if (res.code === 200) {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- uploadModal.value = false;
- }
- getList();
- currentId.value = "";
- fileList.value = [];
- });
-};
-// 鍒犻櫎寮�绁ㄥ彴璐�
-const delInvoiceLedger = (row) => {
- ElMessageBox.confirm("璇ュ彂绁ㄥ彴璐﹀皢琚垹闄�,鏄惁纭鍒犻櫎", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delInvoiceLedgerByRegProductId(row.id).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-const changeDateRange = (date) => {
- if (date) {
- searchForm.invoiceDateStart = date[0];
- searchForm.invoiceDateEnd = date[1];
- getList();
- }
-};
-
-const clearRange = () => {
- searchForm.invoiceDate = [];
- searchForm.invoiceDateStart = undefined;
- searchForm.invoiceDateEnd = undefined;
- getList();
-};
-
-// 鎵撳紑闄勪欢寮圭獥
-const recordId =ref(0)
-const fileDialogVisible = ref(false)
-
-// 鎵撳紑闄勪欢寮规
-const openFileDialog = async (row) => {
- recordId.value = row.id
- fileDialogVisible.value = true
-}
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table_list {
- margin-top: unset;
-}
-</style>
diff --git a/src/views/salesManagement/invoiceRegistration/index.vue b/src/views/salesManagement/invoiceRegistration/index.vue
deleted file mode 100644
index 44e1c4e..0000000
--- a/src/views/salesManagement/invoiceRegistration/index.vue
+++ /dev/null
@@ -1,814 +0,0 @@
-<template>
- <div class="app-container">
- <div class="search_form">
- <el-form :inline="true" :model="searchForm">
- <el-form-item label="瀹㈡埛鍚嶇О">
- <el-input
- v-model="searchForm.customerName"
- style="width: 240px"
- placeholder="璇疯緭鍏ュ悕绉版悳绱�"
- clearable
- :prefix-icon="Search"
- @change="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-checkbox
- v-model="searchForm.status"
- label="涓嶆樉绀烘湭寮�绁ㄩ噾棰濅负0"
- @change="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
- <el-button @click="resetForm"> 閲嶇疆 </el-button>
- <el-button @click="handleExport" style="margin-right: 10px">瀵煎嚭</el-button>
- </el-form-item>
- </el-form>
- </div>
- <div class="table_list">
- <div class="flex justify-between">
- <div></div>
- <div>
- <el-button
- type="primary"
- @click="openForm"
- style="margin-bottom: 8px"
- :disabled="!canInvoice"
- >
- 寮�绁ㄧ櫥璁�
- </el-button>
- </div>
- </div>
- <el-table
- :data="tableData"
- :border="true"
- height="calc(100vh - 21em)"
- v-loading="tableLoading"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- show-summary
- :summary-method="summarizeMainTable"
- @expand-change="expandChange"
- @selection-change="handleSelectionChange"
- >
- <el-table-column align="center" type="selection" width="55" />
- <el-table-column type="expand">
- <template #default="props">
- <el-table
- :data="props.row.children"
- border
- show-summary
- :summary-method="summarizeChildrenTable"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- width="150"
- />
- <el-table-column label="鍗曚綅" prop="unit" width="70" />
- <el-table-column label="鏁伴噺" prop="quantity" width="70" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
- <el-table-column
- label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="寮�绁ㄦ暟"
- prop="invoiceNum"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="寮�绁ㄩ噾棰�(鍏�)"
- prop="invoiceAmount"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鏈紑绁ㄦ暟"
- prop="noInvoiceNum"
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鏈紑绁ㄩ噾棰�(鍏�)"
- prop="noInvoiceAmount"
- :formatter="formattedNumber"
- />
- </el-table>
- </template>
- </el-table-column>
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column
- label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- show-overflow-tooltip
- />
-<!-- <el-table-column-->
-<!-- label="瀹㈡埛鍚堝悓鍙�"-->
-<!-- prop="customerContractNo"-->
-<!-- width="200"-->
-<!-- show-overflow-tooltip-->
-<!-- />-->
- <el-table-column
- label="瀹㈡埛鍚嶇О"
- prop="customerName"
- show-overflow-tooltip
- />
- <el-table-column label="涓氬姟鍛�" prop="salesman" show-overflow-tooltip/>
- <el-table-column
- label="鍚堝悓閲戦(鍏�)"
- prop="contractAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
-
- />
- <el-table-column
- label="宸插紑绁ㄩ噾棰�(鍏�)"
- prop="invoiceTotal"
- show-overflow-tooltip
- :formatter="formattedNumber"
- />
- <el-table-column
- label="鏈紑绁ㄩ噾棰�(鍏�)"
- prop="noInvoiceAmountTotal"
- show-overflow-tooltip
- width="120"
- >
- <template #default="{ row, column }">
- <el-text type="danger">
- {{ formattedNumber(row, column, row.noInvoiceAmountTotal) }}
- </el-text>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="total > 0"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationChange"
- />
- </div>
- <FormDialog
- v-model="dialogFormVisible"
- title="鏂板寮�绁ㄧ櫥璁伴〉闈�"
- :width="'85%'"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia"
- >
- <el-form
- :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef"
- >
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
- <el-input v-model="form.salesContractNo" disabled placeholder="澶氬悎鍚屾壒閲忓鐞嗭紙鍏蜂綋鍚堝悓鍙疯浜у搧鍒楄〃锛�"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName">
- <el-input
- v-model="form.customerName"
- placeholder="鑷姩濉厖"
- disabled
- ></el-input>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="涓氬姟鍛橈細" prop="salesman">
- <el-input
- v-model="form.salesman"
- placeholder="鑷姩濉厖"
- disabled
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍙戠エ鍙风爜锛�" prop="invoiceNo">
- <el-input
- v-model="form.invoiceNo"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�绁ㄦ棩鏈�" prop="issueDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.issueDate"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="褰曞叆浜�" prop="createUer">
- <el-input v-model="form.createUer" placeholder="璇疯緭鍏ュ綍鍏ヤ汉" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="褰曞叆鏃ユ湡锛�" prop="createTime">
- <el-date-picker
- style="width: 100%"
- v-model="form.createTime"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- />
- </el-form-item>
- </el-col>
-
- </el-row>
- <el-row>
- <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate"> </el-form-item>
- </el-row>
- <el-table
- :data="productData"
- border
- show-summary
- :summary-method="summarizeChildrenTable"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column label="鎵�灞炲悎鍚�" prop="salesContractNo" width="200">
- <template #default="{ row }">
- <el-tag type="primary">{{ row.salesContractNo }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- width="150"
- />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="鏁伴噺" prop="quantity" width="70" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
- <el-table-column
- label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber"
- width="150"
- />
- <el-table-column label="鏈寮�绁ㄦ暟" prop="currentInvoiceNum" width="180">
- <template #default="scope">
- <el-input-number
- :step="0.1"
- :min="0"
- style="width: 100%"
- :precision="2"
- v-model="scope.row.currentInvoiceNum"
- @change="invoiceNumBlur(scope.row)"
- :disabled="isProductInvoiceDisabled(scope.row)"
- ></el-input-number>
- </template>
- </el-table-column>
- <el-table-column
- label="鏈寮�绁ㄩ噾棰�(鍏�)"
- prop="currentInvoiceAmount"
- width="180"
- >
- <template #default="scope">
- <el-input-number
- :step="0.01"
- :min="0"
- style="width: 100%"
- :precision="2"
- v-model="scope.row.currentInvoiceAmount"
- @change="invoiceAmountBlur(scope.row)"
- :disabled="isProductInvoiceDisabled(scope.row)"
- ></el-input-number>
- </template>
- </el-table-column>
- <el-table-column label="鏈紑绁ㄦ暟" prop="noInvoiceNum" width="120">
- <template #default="scope">
- <el-input
- type="number"
- min="0"
- disabled
- v-model="scope.row.noInvoiceNum"
- ></el-input>
- </template>
- </el-table-column>
- <el-table-column
- label="鏈紑绁ㄩ噾棰�(鍏�)"
- prop="noInvoiceAmount"
- width="200"
- >
- <template #default="scope">
- <el-input
- type="number"
- min="0"
- disabled
- v-model="scope.row.noInvoiceAmount"
- :formatter="formattedInputNumber"
- :precision="2"
- :step="0.01"
- ></el-input>
- </template>
- </el-table-column>
- <el-table-column label="鐧昏浜�" prop="register" width="100">
- <!-- <template #default="{ row }">
- <el-input
- v-model="row.register"
- placeholder="璇疯緭鍏ョ櫥璁颁汉"
- disabled
- />
- </template> -->
- </el-table-column>
- <el-table-column label="鐧昏鏃ユ湡" prop="registerDate" width="150">
- <!-- <template #default="{ row }">
- <el-date-picker
- style="width: 100%"
- v-model="row.registerDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- disabled
- />
- </template> -->
- </el-table-column>
- </el-table>
- </el-form>
- </FormDialog>
- </div>
-</template>
-
-<script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { onMounted, ref, computed } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { ElMessageBox } from "element-plus";
-// import {userListNoPage} from "@/api/system/user.js";
-import {
- getSalesLedgerWithProducts,
- ledgerListPage,
- productList,
-} from "@/api/salesManagement/salesLedger.js";
-import { invoiceRegistrationSave } from "@/api/salesManagement/invoiceRegistration.js";
-import useFormData from "@/hooks/useFormData";
-import useUserStore from "@/store/modules/user";
-import dayjs from "dayjs";
-
-const { proxy } = getCurrentInstance();
-const userStore = useUserStore();
-const tableData = ref([]);
-const productData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- customerName: "",
- status: false,
- customerContractNo: undefined, // 瀹㈡埛鍚堝悓鍙�
- projectName: undefined, // 椤圭洰鍚嶇О
- createUer: undefined, // 鐧昏浜�
- issueDate: undefined, // 寮�绁ㄦ棩鏈�
- createTime: undefined, // 褰曞叆鏃ユ湡锛�
- productCategory: "",
- isInvoice: 1
- },
- form: {
- salesLedgerId: "",
- customerName: "",
- salesman: "",
- projectName: "",
- productData: [],
- invoiceNo: "",
- createUer: userStore.nickName,
- issueDate: dayjs().format("YYYY-MM-DD"),
- selectedContractIds: [], // 鏂板锛氬瓨鍌ㄦ墍鏈夐�変腑鐨勫悎鍚孖D
- isBatch: false // 鏂板锛氭爣璇嗘槸鍚︿负鎵归噺鎿嶄綔
- },
- rules: {
- createUer: [{ required: true, message: "璇烽�夋嫨", trigger: "blur" }],
- issueDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- invoiceNo: [{ required: true, message: "璇疯緭鍏�", trigger: "change" }],
- createTime: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { form, rules } = toRefs(data);
-const { form: searchForm, resetForm } = useFormData(data.searchForm);
-
-const formattedNumber = (row, column, cellValue) => {
- if (cellValue == 0) {
- return parseFloat(cellValue).toFixed(2);
- }
- if (cellValue) {
- return parseFloat(cellValue).toFixed(2);
- } else {
- return cellValue;
- }
-};
-
-const formattedInputNumber = (value) => {
- return value ? parseFloat(value).toFixed(2) : 0;
-};
-
-// 鍒ゆ柇鏄惁鍙互寮�绁紙鍩轰簬閫変腑鐨勫彴璐︽暟鎹級
-const canInvoice = computed(() => {
- if (selectedRows.value.length === 0) {
- return false;
- }
- // 妫�鏌ユ墍鏈夐�変腑鐨勫彴璐︼紝鍙鏈変竴涓湭寮�绁ㄩ噾棰濆ぇ浜�0锛屽氨鍙互寮�绁�
- return selectedRows.value.some(row => {
- const noInvoiceAmount = parseFloat(row.noInvoiceAmountTotal || 0);
- return noInvoiceAmount > 0;
- });
-});
-
-// 鍒ゆ柇鍗曚釜浜у搧鏄惁鍙互寮�绁�
-const isProductInvoiceDisabled = (row) => {
- // 妫�鏌ユ湭寮�绁ㄩ噾棰濆拰鏈紑绁ㄦ暟锛屽鏋滈兘涓�0鎴栧皬浜庣瓑浜�0锛屽垯绂佺敤
- // 浼樺厛浣跨敤 tempnoInvoiceAmount 鍜� tempNoInvoiceNum锛堝垵濮嬪�硷級锛屽鏋滄病鏈夊垯浣跨敤 noInvoiceAmount 鍜� originalNoInvoiceNum
- const noInvoiceAmount = parseFloat(row.tempnoInvoiceAmount || row.noInvoiceAmount || 0);
- const noInvoiceNum = parseFloat(row.tempNoInvoiceNum || row.originalNoInvoiceNum || row.noInvoiceNum || 0);
- return noInvoiceAmount <= 0 || noInvoiceNum <= 0;
-};
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- ledgerListPage({ ...searchForm, ...page }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.records;
- total.value = res.total;
- expandedRowKeys.value = [];
- });
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- console.log("selection", selection);
- selectedRows.value = selection.filter(
- (item) => item.salesContractNo !== undefined
- );
-};
-const expandedRowKeys = ref([]);
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
- if (expandedRows.length > 0) {
- expandedRowKeys.value = [];
- try {
- productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
- const index = tableData.value.findIndex((item) => item.id === row.id);
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- console.log(error);
- }
- } else {
- expandedRowKeys.value = [];
- }
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, [
- "contractAmount",
- "invoiceTotal",
- "noInvoiceAmountTotal",
- ]);
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- "invoiceNum",
- "invoiceAmount",
- "currentInvoiceAmount",
- "noInvoiceNum",
- "noInvoiceAmount",
- "currentInvoiceNum",
- ]);
-};
-// 鎵撳紑寮规
-const openForm = () => {
- // 鍒ゆ柇鏄惁閫夋嫨浜嗗悎鍚�
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgError("璇疯嚦灏戦�夋嫨涓�鏉″悎鍚�");
- return;
- }
-
- // 妫�鏌ユ墍鏈夐�夋嫨鐨勫悎鍚屾槸鍚﹀叿鏈夌浉鍚岀殑瀹㈡埛鍚嶇О
- const firstRow = selectedRows.value[0];
- const isSameCustomer = selectedRows.value.every(row =>
- row.customerName === firstRow.customerName
- );
-
- if (!isSameCustomer) {
- proxy.$modal.msgError("璇烽�夋嫨鐩稿悓瀹㈡埛鍚嶇О鐨勫悎鍚�");
- return;
- }
-
- // 鍏佽涓嶅悓鐨勯攢鍞悎鍚屽彿鎵归噺澶勭悊锛屾棤闇�妫�鏌ラ噸澶�
-
- form.value = {};
- productData.value = [];
-
- // 鍔犺浇鎵�鏈夐�変腑鍚堝悓鐨勪骇鍝佹暟鎹�
- const promises = selectedRows.value.map(row =>
- getSalesLedgerWithProducts({ id: row.id })
- );
-
- Promise.all(promises).then(results => {
- // 鍚堝苟鎵�鏈夊悎鍚岀殑浜у搧鏁版嵁锛屽苟涓烘瘡涓骇鍝佹坊鍔犲搴旂殑鍚堝悓淇℃伅
- const allProductData = [];
- results.forEach((result, index) => {
- const contract = selectedRows.value[index];
- // const contractId = contract.id;
- if (result.productData) {
- result.productData.forEach(item => {
- allProductData.push({
- ...item,
- // id: contractId, // 鏄庣‘璁剧疆鍚堝悓ID
- salesContractNo: contract.salesContractNo, // 娣诲姞閿�鍞悎鍚屽彿
- customerName: contract.customerName, // 娣诲姞瀹㈡埛鍚嶇О
- customerContractNo: contract.customerContractNo // 娣诲姞瀹㈡埛鍚堝悓鍙�
- });
- });
- }
- });
-
- // 璁剧疆琛ㄥ崟鏁版嵁锛堜娇鐢ㄧ涓�涓悎鍚岀殑鍩烘湰淇℃伅锛岄攢鍞悎鍚屽彿鐣欑┖锛�
- form.value = { ...results[0] };
- form.value.createTime = dayjs().format("YYYY-MM-DD");
- form.value.issueDate = dayjs().format("YYYY-MM-DD");
- form.value.createUer = userStore.nickName;
- form.value.selectedContractIds = selectedRows.value.map(row => row.id); // 瀛樺偍鎵�鏈夐�変腑鐨勫悎鍚孖D
- form.value.salesContractNo = ""; // 閿�鍞悎鍚屽彿鐣欑┖锛屽洜涓轰細鍦ㄤ骇鍝佽〃鏍间腑鍒嗗埆鏄剧ず
-
- productData.value = allProductData;
-
- // 瀵逛簬涓嶈兘寮�绁ㄧ殑浜у搧锛屽皢寮�绁ㄦ暟鍜屽紑绁ㄩ噾棰濊缃负0
- productData.value.forEach(item => {
- if (isProductInvoiceDisabled(item)) {
- item.currentInvoiceNum = 0;
- item.currentInvoiceAmount = 0;
- }
- });
-
- dialogFormVisible.value = true;
- console.log("productData.value ", productData.value);
- });
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- // 濡傛灉鏄壒閲忔搷浣滐紝灏嗘墍鏈夊悎鍚岀殑鏁版嵁鏀惧湪涓�涓暟缁勯噷锛屽彧璋冪敤涓�娆℃帴鍙�
- if (selectedRows.value.length > 1) {
- // 鍒涘缓鍖呭惈鎵�鏈夊悎鍚屾暟鎹殑鏁扮粍
- const batchData = selectedRows.value.map(contract => {
- // 绛涢�夊嚭灞炰簬褰撳墠鍚堝悓鐨勪骇鍝佹暟鎹�
- const contractProductData = productData.value.filter(item =>
- item.salesLedgerId === contract.id
- );
-
- // 涓烘瘡涓攢鍞悎鍚屽彿鍒涘缓鐙珛鐨勫璞�
- return {
- // 鍩虹琛ㄥ崟鏁版嵁
- issueDate: form.value.issueDate,
- createTime: form.value.createTime,
- createUer: form.value.createUer,
- invoiceNo: form.value.invoiceNo,
-
- // 鍚堝悓瀹為檯淇℃伅
- id: contract.id, // 浣跨敤id浣滀负瀛楁鍚嶏紝鍊间负salesLedgerId
- salesContractNo: contract.salesContractNo, // 浣跨敤瀹為檯鐨勯攢鍞悎鍚屽彿
- customerName: contract.customerName, // 浣跨敤瀹為檯鐨勫鎴峰悕绉�
- customerId: contract.customerId, // 娣诲姞瀹㈡埛ID
- customerContractNo: contract.customerContractNo, // 浣跨敤瀹為檯鐨勫鎴峰悎鍚屽彿
- projectName: contract.projectName, // 浣跨敤瀹為檯鐨勯」鐩悕绉�
- salesman: contract.salesman, // 浣跨敤瀹為檯鐨勪笟鍔″憳
-
- // 浜у搧鏁版嵁
- productData: proxy.HaveJson(contractProductData),
-
- // 鎵归噺鏍囪瘑
- isBatch: true
- };
- });
-
- // 鍙皟鐢ㄤ竴娆℃帴鍙o紝浼犻�掑寘鍚墍鏈夊悎鍚屾暟鎹殑鏁扮粍
- invoiceRegistrationSave(batchData).then(() => {
- proxy.$modal.msgSuccess("鎵归噺鏂板鎴愬姛");
- closeDia();
- getList();
- });
- } else {
- // 鍗曚釜鍚堝悓鎻愪氦閫昏緫 - 涔熶互鏁扮粍褰㈠紡浼犻��
- const singleContract = selectedRows.value[0];
- const singleFormArray = [
- {
- // 鍩虹琛ㄥ崟鏁版嵁
- issueDate: form.value.issueDate,
- createTime: form.value.createTime,
- createUer: form.value.createUer,
- invoiceNo: form.value.invoiceNo,
-
- // 鍚堝悓瀹為檯淇℃伅
- id: singleContract.id, // 浣跨敤id浣滀负瀛楁鍚嶏紝鍊间负salesLedgerId
- salesContractNo: singleContract.salesContractNo, // 浣跨敤瀹為檯鐨勯攢鍞悎鍚屽彿
- customerName: singleContract.customerName, // 浣跨敤瀹為檯鐨勫鎴峰悕绉�
- customerId: singleContract.customerId, // 娣诲姞瀹㈡埛ID
- customerContractNo: singleContract.customerContractNo, // 浣跨敤瀹為檯鐨勫鎴峰悎鍚屽彿
- projectName: singleContract.projectName, // 浣跨敤瀹為檯鐨勯」鐩悕绉�
- salesman: singleContract.salesman, // 浣跨敤瀹為檯鐨勪笟鍔″憳
-
- // 浜у搧鏁版嵁
- productData: proxy.HaveJson(productData.value),
-
- // 鎵归噺鏍囪瘑
- isBatch: false
- }
- ];
- invoiceRegistrationSave(singleFormArray).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- }
- });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
-};
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/invoiceRegistration/export", {}, "寮�绁ㄧ櫥璁颁俊鎭�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 瀵煎嚭閿�鍞彴璐�
-const handleExport = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/sales/ledger/exportOne", { ...searchForm, ...page }, "寮�绁ㄧ櫥璁�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-//鏈寮�绁ㄥけ鐒︽搷浣�
-const invoiceNumBlur = (row) => {
- if (!row.currentInvoiceNum) {
- row.currentInvoiceNum = 0;
- }
- if (row.currentInvoiceNum > row.tempNoInvoiceNum) {
- proxy.$modal.msgWarning("鏈寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
- row.currentInvoiceNum = 0;
- }
- // 璁$畻鏈寮�绁ㄩ噾棰�
- row.currentInvoiceAmount = (
- row.currentInvoiceNum * row.taxInclusiveUnitPrice
- ).toFixed(2);
- // 璁$畻鏈紑绁ㄦ暟
- row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
- 2
- );
- // 璁$畻鏈紑绁ㄩ噾棰�
- row.noInvoiceAmount = (
- row.tempnoInvoiceAmount - row.currentInvoiceAmount
- ).toFixed(2);
-};
-// 鏈寮�绁ㄩ噾棰濆け鐒︽搷浣�
-const invoiceAmountBlur = (row) => {
- if (!row.currentInvoiceAmount) {
- row.currentInvoiceAmount = 0;
- }
- // 璁$畻鏄惁瓒呰繃寮�绁ㄦ�婚噾棰�
- if (row.currentInvoiceAmount > row.tempnoInvoiceAmount) {
- proxy.$modal.msgWarning("鏈寮�绁ㄩ噾棰濅笉寰楀ぇ浜庢湭寮�绁ㄩ噾棰�");
- row.currentInvoiceAmount = 0;
- }
- // 璁$畻鏈寮�绁ㄦ暟
- row.currentInvoiceNum = (
- row.currentInvoiceAmount / row.taxInclusiveUnitPrice
- ).toFixed(2);
- console.log("row.currentInvoiceNum ", row.currentInvoiceNum);
- console.log(" row.originalNoInvoiceNum ", row.originalNoInvoiceNum);
- // 璁$畻鏈紑绁ㄦ暟
- row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
- 2
- );
- // 璁$畻鏈紑绁ㄩ噾棰�
- row.noInvoiceAmount = (
- row.tempnoInvoiceAmount - row.currentInvoiceAmount
- ).toFixed(2);
-};
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table_list {
- margin-top: unset;
-}
-.flex {
- display: flex;
-}
-.justify-between {
- justify-content: space-between;
-}
-:deep(.el-checkbox__label) {
- font-weight: bold;
-}
-</style>
-
-
-
-
-
diff --git a/src/views/salesManagement/receiptPayment/index.vue b/src/views/salesManagement/receiptPayment/index.vue
deleted file mode 100644
index 25bd280..0000000
--- a/src/views/salesManagement/receiptPayment/index.vue
+++ /dev/null
@@ -1,605 +0,0 @@
-<template>
- <div class="app-container">
- <div class="search_form">
- <el-form :inline="true" :model="searchForm" style="width: 100%">
- <el-row justify="space-between">
- <el-col :span="24">
- <el-form-item label="瀹㈡埛鍚嶇О">
- <el-input
- v-model="searchForm.customerName"
- placeholder="璇疯緭鍏�"
- @change="handleQuery"
- clearable
- prefix-icon="Search"
- />
- </el-form-item>
- <el-form-item>
- <el-checkbox
- v-model="searchForm.status"
- label="涓嶆樉绀哄緟鍥炴涓�0"
- @change="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </div>
- <div class="table_list">
- <div class="actions">
- <div></div>
- <div>
- <el-button type="primary" @click="openForm('add')">
- 鏂板鍥炴
- </el-button>
- <el-button icon="Download" @click="handleOut"> 瀵煎嚭 </el-button>
- </div>
- </div>
- <el-table
- :data="tableData"
- border
- ref="tableRef"
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :row-key="(row) => row.id"
- show-summary
- :summary-method="summarizeMainTable"
- :expand-row-keys="expandedRowKeys"
- @expand-change="expandChange"
-
- height="calc(100vh - 21.5em)"
- >
- <el-table-column align="center" type="selection" width="55" />
- <el-table-column type="expand">
- <template #default="props">
- <el-table
- :data="props.row.children"
- border
- show-summary
- :summary-method="summarizeChildrenTable"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column label="鍥炴鏃ユ湡" prop="receiptPaymentDate" width="130"/>
- <el-table-column label="鍥炴閲戦" prop="receiptPaymentAmount">
- <template #default="scope">
- <el-input-number :step="0.01" :min="0" style="width: 100%"
- v-model="scope.row.receiptPaymentAmount"
- :disabled="!scope.row.editType"
- :precision="2"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </template>
- </el-table-column>
- <el-table-column label="鍥炴鏂瑰紡" prop="receiptPaymentType">
- <template #default="scope">
- <el-select
- v-model="scope.row.receiptPaymentType"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="!scope.row.editType"
- >
- <el-option
- v-for="item in receipt_payment_type"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="鐧昏浜�" prop="registrant" width="90"/>
- <el-table-column label="鐧昏鏃ユ湡" prop="createTime" width="130"/>
- <el-table-column label="鎿嶄綔" width="150" align="center">
- <template #default="scope">
- <el-button
- link
- type="primary"
- @click="changeEditType(scope.row)"
- v-if="!scope.row.editType"
- >缂栬緫</el-button
- >
- <el-button
- link
- type="primary"
- @click="saveReceiptPayment(scope.row)"
- v-if="scope.row.editType"
- >淇濆瓨</el-button
- >
- <el-button
- link
- type="primary"
- @click="delReceiptRecord(scope.row)"
- >鍒犻櫎</el-button
- >
- </template>
- </el-table-column>
- </el-table>
- </template>
- </el-table-column>
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column
- label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- show-overflow-tooltip
- width="240"
- />
- <el-table-column
- label="瀹㈡埛鍚嶇О"
- prop="customerName"
- show-overflow-tooltip
- width="240"
- />
- <el-table-column
- label="鍥炴鐘舵��"
- prop="statusName"
- width="120"
- >
- <template #default="{ row }">
- <el-tag :type="getStatusTagType(row.statusName)" disable-transitions>
- {{ row.statusName || "--" }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column
- label="浜у搧澶х被"
- prop="productCategory"
- show-overflow-tooltip
- width="100"
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- show-overflow-tooltip
- width="200"
- />
- <el-table-column label="绋庣巼(%)" prop="taxRate" show-overflow-tooltip />
- <el-table-column
- label="宸插洖娆鹃噾棰�(鍏�)"
- prop="invoiceTotal"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="寰呭洖娆鹃噾棰�(鍏�)"
- prop="pendingInvoiceTotal"
- show-overflow-tooltip
- width="200"
- >
- <template #default="{ row, column }">
- <el-text type="danger">
- {{ formattedNumber(row, column, row.pendingInvoiceTotal) }}
- </el-text>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="total > 0"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationChange"
- />
- </div>
- <FormDialog
- v-model="dialogFormVisible"
- title="鏂板鍥炴椤甸潰"
- :width="'90%'"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia"
- >
- <el-table
- v-if="forms.length"
- :data="forms"
- border
- style="width: 100%"
- size="small"
- >
- <el-table-column type="index" label="搴忓彿" width="50" align="center"/>
- <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip />
- <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip />
- <el-table-column
- label="浜у搧澶х被"
- prop="productCategory"
- show-overflow-tooltip
- width="100"
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- show-overflow-tooltip
- width="200"
- />
- <el-table-column label="绋庣巼(%)" width="110">
- <template #default="{ row }">
- <el-input v-model="row.taxRate" disabled />
- </template>
- </el-table-column>
- <el-table-column
- label="寰呭洖娆鹃噾棰�(鍏�)"
- prop="pendingInvoiceTotal"
- show-overflow-tooltip
- width="170"
- >
- <template #default="{ row, column }">
- <el-text type="danger">
- {{ formattedNumber(row, column, row.pendingInvoiceTotal) }}
- </el-text>
- </template>
- </el-table-column>
- <el-table-column label="鏈鍥炴閲戦(鍏�)" width="180">
- <template #default="{ row }">
- <el-input-number
- v-model="row.receiptPaymentAmount"
- :step="0.01"
- :min="0"
- :max="Number(row.pendingInvoiceTotal || 0)"
- :precision="2"
- style="width: 100%"
- placeholder="璇疯緭鍏�"
- />
- </template>
- </el-table-column>
- <el-table-column label="鍥炴褰㈠紡" width="160">
- <template #default="{ row }">
- <el-select v-model="row.receiptPaymentType" placeholder="璇烽�夋嫨" clearable>
- <el-option
- v-for="opt in receipt_payment_type"
- :key="opt.value"
- :label="opt.label"
- :value="opt.value"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="鍥炴鏃ユ湡" width="170">
- <template #default="{ row }">
- <el-date-picker
- v-model="row.receiptPaymentDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- style="width: 100%"
- />
- </template>
- </el-table-column>
- <el-table-column label="鐧昏浜�" width="140">
- <template #default="{ row }">
- <el-input v-model="row.registrant" />
- </template>
- </el-table-column>
- </el-table>
- <div v-else class="empty-tip">璇烽�夋嫨闇�瑕佸洖娆剧殑璁板綍</div>
- </FormDialog>
- </div>
-</template>
-
-<script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { onMounted, ref, reactive, getCurrentInstance } from "vue";
-import {
- receiptPaymentSaveOrUpdate,
- bindInvoiceNoRegPage,
- receiptPaymentHistoryListNoPage,
- receiptPaymentDel,
-} from "../../../api/salesManagement/receiptPayment.js";
-import useUserStore from "@/store/modules/user";
-import { ElMessage, ElMessageBox } from "element-plus";
-import useFormData from "@/hooks/useFormData";
-
-const userStore = useUserStore();
-const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const forms = ref([]);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const expandedRowKeys = ref([]);
-const tableRef = ref(null);
-
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- searchText: "",
- status: true,
- customerName: "",
- specificationModel: "",
- },
-});
-const { form: searchForm } = useFormData(data.searchForm);
-const { receipt_payment_type } = proxy.useDict("receipt_payment_type");
-
-const formattedNumber = (row, column, cellValue) => {
- const val = Number(cellValue ?? 0);
- return Number.isFinite(val) ? val.toFixed(2) : "0.00";
-};
-
-const getStatusTagType = (statusName = '') => {
- const normalized = statusName.trim();
- if (!normalized) return 'info';
- return normalized === '鏈畬鎴愪粯娆�' ? 'danger' : 'success';
-};
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- bindInvoiceNoRegPage({ ...searchForm, ...page })
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- total.value = res.data.total;
- if (expandedRowKeys.value.length > 0) {
- const arr = []
- const index = tableData.value.findIndex(item => item.id === expandedRowKeys.value[0]);
- if (index > -1) {
- arr.push(tableData.value[index]);
- expandChange(tableData.value[index], arr)
- }
- }
- })
- .catch(() => {
- tableLoading.value = false;
- });
-};
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
- if (expandedRows.length > 0) {
- expandedRowKeys.value = [];
- try {
- receiptPaymentHistoryListNoPage({
- invoiceLedgerId: row.id,
- type: 1,
- }).then((res) => {
- const index = tableData.value.findIndex((item) => item.id === row.id);
- if (index > -1) {
- if (res?.length > 0) {
- res.forEach((item) => {
- item.editType = false;
- });
- }
- tableData.value[index].children = res;
- }
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- console.log(error);
- }
- } else {
- expandedRowKeys.value = [];
- }
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- console.log("selection", selection);
- selectedRows.value = selection;
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(
- param,
- ["receiptPaymentAmountTotal", "noReceiptAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
- return proxy.summarizeTable(param, ["receiptPaymentAmount"]);
-};
-// 鎵撳紑寮规
-const openForm = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgError("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
- return;
- }
- // 浠呭厑璁糕�滃緟鍥炴閲戦 > 0鈥濈殑璁板綍杩涘叆鏂板鍥炴寮圭獥锛屽苟杩囨护鎺夊彲鑳芥贩鍏ョ殑绌哄璞�
- const validRows = selectedRows.value.filter((item) => {
- if (!item || !item.id) return false;
- return Number(item.pendingInvoiceTotal ?? 0) > 0;
- });
- if (validRows.length === 0) {
- proxy.$modal.msgWarning("鎵�閫夎褰曞潎鏃犻渶鍥炴");
- return;
- }
- forms.value = validRows.map((row) => ({
- salesContractNo: row.salesContractNo || "",
- customerName: row.customerName || "",
- productCategory: row.productCategory || "",
- specificationModel: row.specificationModel || "",
- pendingInvoiceTotal: Number(row.pendingInvoiceTotal || 0),
- taxRate: row.taxRate ?? "",
- // 榛樿鏈鍥炴閲戦 = 寰呭洖娆鹃噾棰�
- receiptPaymentAmount: Number(row.pendingInvoiceTotal || 0),
- receiptPaymentType: "",
- registrant: userStore.nickName,
- receiptPaymentDate: "",
- invoiceLedgerId: row.id,
- salesLedgerId: row.salesLedgerId,
- salesLedgerProductId: row.id,
- }));
- dialogFormVisible.value = true;
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- if (forms.value.length === 0) {
- proxy.$modal.msgError("璇烽�夋嫨鍥炴璁板綍");
- return;
- }
- for (let i = 0; i < forms.value.length; i++) {
- const item = forms.value[i];
- const pendingAmount = Number(item.pendingInvoiceTotal || 0);
- const currentAmount = Number(item.receiptPaymentAmount);
- if (!item.receiptPaymentAmount && item.receiptPaymentAmount !== 0) {
- proxy.$modal.msgError(`绗� ${i + 1} 鏉★細璇峰~鍐欏洖娆鹃噾棰漙);
- return;
- }
- if (currentAmount > pendingAmount) {
- proxy.$modal.msgError(
- `绗� ${i + 1} 鏉★細鍥炴閲戦涓嶈兘瓒呰繃寰呭洖娆鹃噾棰濓紙寰呭洖娆撅細${pendingAmount.toFixed(
- 2
- )}锛塦
- );
- return;
- }
- if (!item.receiptPaymentType) {
- proxy.$modal.msgError(`绗� ${i + 1} 鏉★細璇烽�夋嫨鍥炴褰㈠紡`);
- return;
- }
- if (!item.receiptPaymentDate) {
- proxy.$modal.msgError(`绗� ${i + 1} 鏉★細璇烽�夋嫨鍥炴鏃ユ湡`);
- return;
- }
- }
- receiptPaymentSaveOrUpdate(forms.value).then(() => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
- forms.value = [];
- dialogFormVisible.value = false;
- // 閬垮厤浜屾鎵撳紑寮圭獥鏃朵粛鎼哄甫涓婁竴娆$殑閫夋嫨瀵艰嚧鈥滃鍑轰竴琛�/鑴忔暟鎹��
- selectedRows.value = [];
- tableRef.value?.clearSelection();
-};
-
-// 鍒犻櫎鍥炴璁板綍
-const delReceiptRecord = (row) => {
- console.log("row", row);
- ElMessageBox.confirm("纭鍒犻櫎璇ヨ褰曞悧锛�", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(async () => {
- try {
- let ids = [];
- ids.push(row.id);
- await receiptPaymentDel(ids);
- ElMessage.success("鍒犻櫎鎴愬姛");
- getList();
- } catch (error) {
- console.error("鍒犻櫎澶辫触:", error);
- ElMessage.error("鍒犻櫎澶辫触");
- }
- })
- .catch(() => {
- ElMessage.info("宸插彇娑堝垹闄�");
- });
-};
-
-// 缂栬緫淇敼鐘舵��
-const changeEditType = (row) => {
- row.editType = !row.editType;
-};
-
-// 淇濆瓨鍥炴璁板綍
-const saveReceiptPayment = (row) => {
- // 瀛愯〃鍥炴閲戦鍚堣鏍¢獙锛氭墍鏈夊洖娆捐褰曢噾棰濅箣鍜屼笉鑳藉ぇ浜庣埗鏁版嵁鍚堝悓閲戦
- // 杩欓噷鐖舵暟鎹�滃悎鍚岄噾棰濃�濇寜锛氬凡鍥炴閲戦( invoiceTotal ) + 寰呭洖娆鹃噾棰�( pendingInvoiceTotal ) 璁$畻
- const findParentRowByChildId = (childId) => {
- return tableData.value.find((p) =>
- Array.isArray(p.children) && p.children.some((c) => c.id === childId)
- );
- };
- const parentRow = findParentRowByChildId(row.id);
- if (parentRow) {
- const contractAmount =
- Number(parentRow.invoiceTotal || 0) + Number(parentRow.pendingInvoiceTotal || 0);
- const sumReceipt = (parentRow.children || []).reduce((sum, item) => {
- const val = Number(item?.receiptPaymentAmount ?? 0);
- return sum + (Number.isFinite(val) ? val : 0);
- }, 0);
- if (sumReceipt > contractAmount) {
- proxy.$modal.msgError(
- `鍥炴閲戦鍚堣(${sumReceipt.toFixed(2)})涓嶈兘澶т簬鍚堝悓閲戦(${contractAmount.toFixed(2)})`
- );
- return;
- }
- }
-
- let updateData = {
- id: row.id,
- receiptPaymentType: row.receiptPaymentType,
- receiptPaymentAmount: row.receiptPaymentAmount,
- };
- receiptPaymentSaveOrUpdate([updateData]).then((res) => {
- row.editType = !row.editType;
- getList();
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- });
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- const ids = selectedRows.value.map((item) => item.id);
- proxy.download(
- `/receiptPayment/export`,
- { ids: `${ids}` },
- "鍥炴鐧昏妗f.xlsx"
- );
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table_list {
- margin-top: unset;
-}
-:deep(.el-checkbox__label) {
- font-weight: bold;
-}
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-.empty-tip {
- text-align: center;
- padding: 20px 0;
- color: #909399;
-}
-</style>
diff --git a/src/views/salesManagement/receiptPaymentHistory/index.vue b/src/views/salesManagement/receiptPaymentHistory/index.vue
deleted file mode 100644
index 11a59a6..0000000
--- a/src/views/salesManagement/receiptPaymentHistory/index.vue
+++ /dev/null
@@ -1,279 +0,0 @@
-<template>
- <div class="app-container">
- <el-form :model="searchForm" :inline="true">
- <el-form-item label="瀹㈡埛鍚嶇О">
- <el-input
- v-model="searchForm.searchText"
- placeholder="杈撳叆瀹㈡埛鍚嶇О鎼滅储"
- @change="handleQuery"
- clearable
- :prefix-icon="Search"
- />
- </el-form-item>
- <el-form-item label="鍥炴鏃ユ湡">
- <el-date-picker
- v-model="searchForm.receiptPaymentDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- start-placeholder="寮�濮嬫椂闂�"
- end-placeholder="缁撴潫鏃堕棿"
- clearable
- style="width: 300px"
- @change="changeDateRange"
- @clear="clearRange"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
- <el-button @click="handleExport">瀵煎嚭</el-button>
- <el-button
- type="danger"
- :disabled="selectedRows.length === 0"
- @click="handleBatchDelete"
- >
- 鎵归噺鍒犻櫎 ({{ selectedRows.length }})
- </el-button>
- </el-form-item>
- </el-form>
- <div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- :isShowSummary="isShowSummarySon"
- :summaryMethod="summarizeMainTable1"
- :tableLoading="tableLoading"
- :total="page.total"
- @pagination="pagination"
- @selection-change="handleSelectionChange"
- >
- <template #operation="{ row }">
- <el-button
- type="primary"
- link
- @click="handleDelete(row)"
- >
- 鍒犻櫎
- </el-button>
- </template>
- </PIMTable>
- </div>
- </div>
-</template>
-
-<script setup>
-import { ref, reactive, getCurrentInstance, onMounted } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { ElMessageBox } from "element-plus";
-import { receiptPaymentHistoryListPage, receiptPaymentDel } from "@/api/salesManagement/receiptPayment.js";
-import useFormData from "@/hooks/useFormData";
-import dayjs from "dayjs";
-
-const { proxy } = getCurrentInstance();
-const tableColumn = ref([
- {
- label: "閿�鍞悎鍚屽彿",
- prop: "salesContractNo",
- width:240
- },
- {
- label: "鍥炴鏃ユ湡",
- prop: "receiptPaymentDate",
- width:100
- },
- {
- label: "瀹㈡埛鍚嶇О",
- prop: "customerName",
- width:240
- },
- {
- label: "鍥炴閲戦锛堝厓锛�",
- prop: "receiptPaymentAmount",
- width:200,
- formatData: (params) => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
- },
- {
- label: "鍥炴鏂瑰紡",
- prop: "receiptPaymentType",
- dataType: "tag",
- formatData: (params) => {
- if (params == 0) {
- return "鐢垫眹";
- } else if (params == 1) {
- return "鎵垮厬";
- } else {
- return null;
- }
- },
- formatType: (params) => {
- return "info";
- },
- },
- {
- label: "鐧昏浜�",
- prop: "registrant",
- },
- {
- label: "鐧昏鏃ユ湡",
- prop: "createTime",
- width:100
- },
- {
- label: "鎿嶄綔",
- dataType: "slot",
- fixed: "right",
- slot: "operation",
- width: 100,
- align: "center",
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const total = ref(0);
-
-const { form: searchForm } = useFormData({
- searchText: undefined,
- receiptPaymentDate: [],
- receiptPaymentDateStart: undefined,
- receiptPaymentDateEnd: undefined,
-});
-const { receipt_payment_type } = proxy.useDict("receipt_payment_type");
-const isShowSummarySon = ref(true);
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const { receiptPaymentDate, ...rest } = searchForm;
- receiptPaymentHistoryListPage({ ...rest, ...page }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.records;
- page.total = res.total;
- });
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeMainTable1 = (param) => {
- return proxy.summarizeTable(param, ["receiptPaymentAmount"], {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- });
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-
-const changeDateRange = (date) => {
- if (date) {
- searchForm.receiptPaymentDateStart = dayjs(date[0]).format(
- "YYYY-MM-DD 00:00:00"
- );
- searchForm.receiptPaymentDateEnd = dayjs(date[1]).format(
- "YYYY-MM-DD 23:59:59"
- );
- getList();
- }
-};
-
-const clearRange = () => {
- searchForm.receiptPaymentDate = [];
- searchForm.receiptPaymentDateStart = undefined;
- searchForm.receiptPaymentDateEnd = undefined;
- getList();
-};
-
-// 鍒犻櫎
-const handleDelete = (row) => {
- ElMessageBox.confirm("纭鍒犻櫎璇ヨ褰曞悧锛�", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(async () => {
- try {
- tableLoading.value = true;
- await receiptPaymentDel([row.id]);
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- } catch (error) {
- console.error("鍒犻櫎澶辫触:", error);
- proxy.$modal.msgError("鍒犻櫎澶辫触");
- } finally {
- tableLoading.value = false;
- }
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑堝垹闄�");
- });
-};
-
-// 鎵归噺鍒犻櫎
-const handleBatchDelete = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
- return;
- }
- ElMessageBox.confirm(
- `纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.value.length} 鏉℃暟鎹悧锛焋,
- "鍒犻櫎鎻愮ず",
- {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }
- )
- .then(async () => {
- try {
- tableLoading.value = true;
- const ids = selectedRows.value.map((item) => item.id);
- await receiptPaymentDel(ids);
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- selectedRows.value = [];
- getList();
- } catch (error) {
- console.error("鍒犻櫎澶辫触:", error);
- proxy.$modal.msgError("鍒犻櫎澶辫触");
- } finally {
- tableLoading.value = false;
- }
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 瀵煎嚭
-const handleExport = () => {
- const { receiptPaymentDate, ...rest } = searchForm;
- proxy.download("/receiptPayment/exportOne", { ...rest, ...page }, "鍥炴娴佹按.xlsx");
-};
-
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped lang="scss">
-.table_list {
- margin-top: unset;
-}
-</style>
diff --git a/src/views/salesManagement/receiptPaymentLedger/index.vue b/src/views/salesManagement/receiptPaymentLedger/index.vue
index e41e24f..d92843d 100644
--- a/src/views/salesManagement/receiptPaymentLedger/index.vue
+++ b/src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -1,268 +1,252 @@
<template>
<div class="app-container">
- <div class="search_form" style="margin-bottom: 20px;">
+ <div class="search_form"
+ style="margin-bottom: 20px;">
<div>
<span class="search_title">瀹㈡埛鍚嶇О锛�</span>
- <el-input
- v-model="searchForm.searchText"
- style="width: 240px"
- placeholder="杈撳叆瀹㈡埛鍚嶇О鎼滅储"
- @change="handleQuery"
- clearable
- prefix-icon="Search"
- />
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储</el-button
- >
+ <el-input v-model="searchForm.searchText"
+ style="width: 240px"
+ placeholder="杈撳叆瀹㈡埛鍚嶇О鎼滅储"
+ @change="handleQuery"
+ clearable
+ prefix-icon="Search" />
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">鎼滅储</el-button>
</div>
</div>
- <div style="display: flex">
- <div class="table_list">
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
- :row-key="(row) => row.id"
- show-summary
- :summary-method="summarizeMainTable"
- @row-click="rowClickMethod"
- height="calc(100vh - 18.5em)"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column
- label="瀹㈡埛鍚嶇О"
- prop="customerName"
- show-overflow-tooltip
- width="200"
- />
- <el-table-column
- label="鍚堝悓閲戦(鍏�)"
- prop="invoiceTotal"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="鍥炴閲戦(鍏�)"
- prop="receiptPaymentAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="搴旀敹閲戦(鍏�)"
- prop="unReceiptPaymentAmount"
- show-overflow-tooltip
- width="200"
- >
- <template #default="{ row, column }">
- <el-text type="danger">
- {{ formattedNumber(row, column, row.unReceiptPaymentAmount) }}
- </el-text>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="total > 0"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationChange"
- />
- </div>
- <div class="table_list">
- <el-table
- :data="receiptRecord"
- border
- :row-key="(row) => row.id"
- show-summary
- :summary-method="summarizeMainTable1"
- height="calc(100vh - 18.5em)"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column
- label="鍙戠敓鏃ユ湡"
- prop="receiptPaymentDate"
- show-overflow-tooltip
- width="110"
- />
- <el-table-column
- label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- show-overflow-tooltip
- width="200"
- />
- <el-table-column
- label="鍚堝悓閲戦(鍏�)"
- prop="invoiceTotal"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="鍥炴閲戦(鍏�)"
- prop="receiptPaymentAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200"
- />
- <el-table-column
- label="搴旀敹閲戦(鍏�)"
- prop="unReceiptPaymentAmount"
- show-overflow-tooltip
- width="200"
- >
- <template #default="{ row, column }">
- <el-text type="danger">
- {{ formattedNumber(row, column, row.unReceiptPaymentAmount) }}
- </el-text>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </div>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <div class="table_list"
+ style="width: 100%">
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ :row-key="(row) => row.customerId"
+ show-summary
+ :summary-method="summarizeMainTable"
+ @row-click="rowClickMethod"
+ highlight-current-row
+ height="calc(100vh - 18.5em)">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="瀹㈡埛鍚嶇О"
+ prop="customerName"
+ show-overflow-tooltip
+ width="200" />
+ <el-table-column label="鍚堝悓閲戦(鍏�)"
+ prop="invoiceTotal"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ width="200" />
+ <el-table-column label="鍥炴閲戦(鍏�)"
+ prop="receiptPaymentAmount"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ width="200" />
+ <el-table-column label="搴旀敹閲戦(鍏�)"
+ prop="unReceiptPaymentAmount"
+ show-overflow-tooltip
+ width="200">
+ <template #default="{ row, column }">
+ <el-text type="danger">
+ {{ formattedNumber(row, column, row.unReceiptPaymentAmount) }}
+ </el-text>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
+ </div>
+ </el-col>
+ <el-col :span="12">
+ <div class="table_list"
+ style="width: 100%">
+ <el-table :data="receiptRecord"
+ border
+ :row-key="(row) => row.id"
+ show-summary
+ :summary-method="summarizeMainTable1"
+ height="calc(100vh - 18.5em)">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="鍚堝悓绛捐鏃ユ湡"
+ prop="executionDate"
+ show-overflow-tooltip
+ width="110" />
+ <el-table-column label="閿�鍞悎鍚屽彿"
+ prop="salesContractNo"
+ show-overflow-tooltip
+ width="200" />
+ <el-table-column label="鍚堝悓閲戦(鍏�)"
+ prop="contractAmount"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ width="200" />
+ <el-table-column label="鍥炴閲戦(鍏�)"
+ prop="receiptPaymentAmount"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ width="200" />
+ <el-table-column label="搴旀敹閲戦(鍏�)"
+ prop="receiptableAmount"
+ show-overflow-tooltip
+ width="200">
+ <template #default="{ row, column }">
+ <el-text type="danger">
+ {{ formattedNumber(row, column, row.receiptableAmount) }}
+ </el-text>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination v-show="recordTotal > 0"
+ :total="recordTotal"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="recordPage.current"
+ :limit="recordPage.size"
+ @pagination="recordPaginationChange" />
+ </div>
+ </el-col>
+ </el-row>
</div>
</template>
<script setup>
-import {onMounted, ref} from "vue";
-import { invoiceLedgerSalesAccount } from "../../../api/salesManagement/invoiceLedger.js";
-import { customerInteractions } from "../../../api/salesManagement/receiptPayment.js";
-import Pagination from "../../../components/PIMTable/Pagination.vue";
-const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const receiptRecord = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const recordPage = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const recordTotal = ref(0);
-const data = reactive({
- searchForm: {
- searchText: "",
- invoiceDate: "",
- },
-});
-const customerId = ref("");
-const { searchForm } = toRefs(data);
-const originReceiptRecord = ref([]);
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- invoiceLedgerSalesAccount({ ...searchForm.value, ...page }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- total.value = res.data.total;
- if (tableData.value.length > 0) {
- recordPage.current = 1;
- customerId.value = tableData.value[0].id;
- receiptPaymentList(customerId.value);
- }
+ import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
+ import {
+ customewTransactions,
+ customewTransactionsDetails,
+ } from "@/api/salesManagement/indicatorStats.js";
+ import Pagination from "../../../components/PIMTable/Pagination.vue";
+ const { proxy } = getCurrentInstance();
+ const tableData = ref([]);
+ const receiptRecord = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
});
-};
-const formattedNumber = (row, column, cellValue) => {
- return parseFloat(cellValue).toFixed(2);
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(
- param,
- ["invoiceTotal", "receiptPaymentAmount", "unReceiptPaymentAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeMainTable1 = (param) => {
- var summarizeTable = proxy.summarizeTable(
- param,
- ["invoiceAmount", "receiptAmount", "unReceiptAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
- // 鍙栨渶鍚庝竴琛屾暟鎹�;
- if (receiptRecord.value?.length > 0) {
- const index = tableData.value.findIndex(
- (item) => item.id == customerId.value
- );
- summarizeTable[summarizeTable.length - 1] =
- tableData.value[index].unReceiptPaymentAmount.toFixed(2);
- } else {
- summarizeTable[summarizeTable.length - 1] = 0.0;
- }
- return summarizeTable;
-};
-
-const receiptPaymentList = (id) => {
- const param = {
- customerId: id,
+ const recordPage = reactive({
+ current: 1,
+ size: 100,
+ });
+ const total = ref(0);
+ const recordTotal = ref(0);
+ const data = reactive({
+ searchForm: {
+ searchText: "",
+ invoiceDate: "",
+ },
+ });
+ const customerId = ref("");
+ const { searchForm } = toRefs(data);
+ const originReceiptRecord = ref([]);
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
};
- console.log("param", param);
- customerInteractions(param).then((res) => {
- originReceiptRecord.value = res.data;
- handlePagination({ page: 1, limit: recordPage.size });
- recordTotal.value = res.data.length;
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ tableLoading.value = true;
+ customewTransactions({ ...searchForm.value, ...page }).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ if (tableData.value.length > 0) {
+ recordPage.current = 1;
+ customerId.value = tableData.value[0].customerId;
+ receiptPaymentList(customerId.value);
+ }
+ });
+ };
+ const formattedNumber = (row, column, cellValue) => {
+ return cellValue ? parseFloat(cellValue).toFixed(2) : "0.00";
+ };
+ // 涓昏〃鍚堣鏂规硶
+ const summarizeMainTable = param => {
+ return proxy.summarizeTable(
+ param,
+ ["invoiceTotal", "receiptPaymentAmount", "unReceiptPaymentAmount"],
+ {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ }
+ );
+ };
+ // 瀛愯〃鍚堣鏂规硶
+ const summarizeMainTable1 = param => {
+ var summarizeTable = proxy.summarizeTable(
+ param,
+ ["contractAmount", "receiptPaymentAmount", "receiptableAmount"],
+ {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ }
+ );
+ return summarizeTable;
+ };
+
+ const receiptPaymentList = id => {
+ const param = {
+ customerId: id,
+ current: recordPage.current,
+ size: recordPage.size,
+ };
+ customewTransactionsDetails(param).then(res => {
+ if (Array.isArray(res.data)) {
+ originReceiptRecord.value = res.data;
+ recordTotal.value = res.data.length;
+ handlePagination({ page: 1, limit: recordPage.size });
+ } else {
+ receiptRecord.value = res.data.records;
+ recordTotal.value = res.data.total;
+ }
+ });
+ };
+
+ // 姹囨璁板綍鍒楄〃鍒嗛〉
+ const recordPaginationChange = pagination => {
+ recordPage.current = pagination.page;
+ recordPage.size = pagination.limit;
+ receiptPaymentList(customerId.value);
+ };
+
+ const rowClickMethod = row => {
+ customerId.value = row.customerId;
+ receiptPaymentList(customerId.value);
+ };
+
+ const handlePagination = ({ page, limit }) => {
+ recordPage.current = page;
+ recordPage.size = limit;
+
+ const start = (page - 1) * limit;
+ const end = start + limit;
+
+ receiptRecord.value = originReceiptRecord.value.slice(start, end);
+ };
+
+ onMounted(() => {
+ getList();
});
-};
-
-// 姹囨璁板綍鍒楄〃鍒嗛〉
-const recordPaginationChange = (pagination) => {
- handlePagination(pagination);
-};
-
-const rowClickMethod = (row) => {
- customerId.value = row.id;
- receiptPaymentList(customerId.value);
-};
-
-const handlePagination = ({ page, limit }) => {
- recordPage.current = page;
- recordPage.size = limit;
-
- const start = (page - 1) * limit;
- const end = start + limit;
-
- receiptRecord.value = originReceiptRecord.value.slice(start, end);
-};
-
-onMounted(() => {
- getList();
-});
</script>
<style scoped lang="scss">
-.table_list {
- width: 50%;
-}
+ .table_list {
+ width: 50%;
+ }
</style>
--
Gitblit v1.9.3