From 9ea5ff67655241271bdf04bb50ca3a8d60c4e22a Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期二, 11 八月 2026 15:07:02 +0800
Subject: [PATCH] fix: 用河南鹤壁代码覆盖山西长治
---
src/views/collaborativeApproval/notificationManagement/summary/index.vue | 8
src/api/basicData/enum.js | 8
src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue | 2
src/views/basicData/product/index.vue | 26
src/views/financialManagement/payable/payment.vue | 22
src/api/collaborativeApproval/knowledgeBase.js | 159
src/views/qualityManagement/rawMaterialInspection/index.vue | 811
src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue | 11
src/api/customerService/index.js | 9
src/views/qualityManagement/finalInspection/index.vue | 860
src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue | 11
src/views/monitor/operlog/index.vue | 8
src/views/qualityManagement/processInspection/index.vue | 839
src/views/collaborativeApproval/sealManagement/index.vue | 94
src/views/financialManagement/payable/input-invoice.vue | 22
src/views/productionManagement/productStructure/index.vue | 42
src/views/productionManagement/workOrderManagement/index.vue | 66
src/views/reportAnalysis/productionAnalysis/components/right-top.vue | 6
src/views/equipmentManagement/upkeep/Form/detailDia.vue | 118
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue | 75
src/api/procurementManagement/paymentLedger.js | 9
src/views/personnelManagement/contractManagement/components/formDia.vue | 151
src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue | 2
src/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue | 30
src/views/productionManagement/productionTraceability/index.vue | 45
src/views/safeProduction/safetyTrainingAssessment/index.vue | 25
src/views/personnelManagement/socialSecuritySet/components/formDia.vue | 808
src/assets/aiIndustrialBrain/reference-chat.png | 0
src/views/financialManagement/receivable/receipt.vue | 103
src/views/personnelManagement/monthlyStatistics/components/formDia.vue | 1430 +-
src/api/basicData/customer.js | 2
src/views/productionManagement/productStructure/StructureEdit.vue | 2
src/views/productionManagement/workOrderEdit/index.vue | 2
src/views/financialManagement/assets/fixedAssets.vue | 21
src/views/financialManagement/receivable/salesReturn.vue | 48
src/components/AIChatSidebar/assistants/financeAssistant.js | 6
src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue | 36
.env.development | 2
src/api/financialManagement/invoiceApply.js | 11
src/api/salesManagement/salesLedger.js | 7
src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue | 4
src/views/reportAnalysis/reportManagement/index.vue | 56
src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue | 6
src/views/customerService/feedbackRegistration/index.vue | 31
src/api/viewIndex.js | 5
src/views/procurementManagement/purchaseReturnOrder/New.vue | 97
src/views/personnelManagement/monthlyStatistics/components/auditDia.vue | 17
src/api/personnelManagement/staffSalaryMain.js | 16
src/views/system/role/index.vue | 2
public/DDGWfavicon.ico | 0
src/views/equipmentManagement/upkeep/Form/PlanModal.vue | 1
src/utils/documentPrint.js | 331
src/views/productionManagement/processRoute/processRouteItem/index.vue | 4
src/views/salesManagement/receiptPaymentLedger/index.vue | 75
src/views/salesManagement/returnOrder/components/detailDia.vue | 20
src/views/financialManagement/voucher/index.vue | 13
src/views/salesManagement/salesLedger/index.vue | 5098 ++++----
src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue | 741
src/views/reportAnalysis/PSIDataAnalysis/index.vue | 4
src/views/qualityManagement/metricBinding/index.vue | 1095 +
src/views/system/menu/index.vue | 2
src/views/procurementManagement/procurementLedger/detail.vue | 246
src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue | 30
src/views/system/dict/data.vue | 2
src/views/financialManagement/assets/intangibleAssets.vue | 26
src/views/financialManagement/receivable/reconciliation.vue | 25
src/views/inventoryManagement/stockManagement/Record.vue | 643
src/views/customerService/afterSalesHandling/index.vue | 16
src/views/collaborativeApproval/knowledgeBase/index.vue | 741 -
src/components/AIChatSidebar/assistants/salesAssistant.js | 4
src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue | 4
src/utils/summarizeTable.js | 21
src/views/equipmentManagement/spareParts/index.vue | 27
src/views/procurementManagement/procurementReport/index.vue | 7
src/assets/styles/sidebar.scss | 37
src/views/system/dept/index.vue | 2
src/components/PIMTable/PIMTable.vue | 15
src/views/basicData/customerFileOpenSea/index.vue | 424
src/views/equipmentManagement/inspectionManagement/index.vue | 20
src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue | 9
src/views/qualityManagement/finalInspection/components/filesDia.vue | 87
src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue | 2
src/views/qualityManagement/nearExpiryReturn/index.vue | 614
src/assets/indexViews/HYSNLogo.png | 0
src/views/personnelManagement/classsSheduling/index.vue | 270
src/api/inventoryManagement/stockOut.js | 9
src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue | 14
src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue | 93
src/views/reportAnalysis/productionAnalysis/components/PanelHeader.vue | 30
src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue | 2
src/views/equipmentManagement/upkeep/Form/formDia.vue | 37
src/views/financialManagement/receivable/outputInvoice.vue | 148
src/views/personnelManagement/monthlyStatistics/index.vue | 16
src/views/financialManagement/payable/purchaseReturn.vue | 44
src/views/safeProduction/dangerInvestigation/index.vue | 2
src/views/index.vue | 217
src/views/basicData/product/ProductSelectDialog.vue | 11
src/views/financialManagement/receivable/salesOut.vue | 279
src/views/collaborativeApproval/rulesRegulationsManagement/index.vue | 2
src/api/procurementManagement/procurementLedger.js | 86
src/views/basicData/parameterMaintenance/index.vue | 27
src/views/reportAnalysis/PSIDataAnalysis/psiNavigation.js | 15
src/views/reportAnalysis/productionAnalysis/components/left-top.vue | 4
src/views/personnelManagement/contractManagement/index.vue | 578
src/views/salesManagement/returnOrder/index.vue | 38
src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue | 146
src/views/collaborativeApproval/purchaseApproval/index.vue | 23
src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue | 2
src/components/Echarts/echarts.vue | 4
src/views/basicData/customerFile/index.vue | 131
src/views/procurementManagement/procurementPlan/index.vue | 1194 -
src/views/reportAnalysis/productionAnalysis/productionNavigation.js | 19
src/views/procurementManagement/purchaseReturnOrder/ProductList.vue | 13
vite.config.js | 10
src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue | 1194 +-
src/views/inventoryManagement/receiptManagement/Record.vue | 612
src/views/equipmentManagement/upkeep/index.vue | 60
src/views/qualityManagement/processInspection/components/formDia.vue | 122
src/views/inventoryManagement/stockManagement/New.vue | 12
src/views/salesManagement/deliveryLedger/index.vue | 30
src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue | 6
src/views/customerService/afterSalesHandling/components/formDia.vue | 29
src/components/AIChatSidebar/assistants/productionAssistant.js | 19
src/utils/numberFormat.js | 47
src/views/personnelManagement/employeeRecord/index.vue | 4
src/views/system/post/index.vue | 4
src/views/equipmentManagement/repair/Modal/RepairModal.vue | 4
src/views/salesManagement/salesQuotation/index.vue | 16
src/router/index.js | 38
src/views/financialManagement/payable/paymentApply.vue | 68
src/views/reportAnalysis/productionAnalysis/components/center-top.vue | 22
src/views/procurementManagement/procurementLedger/index.vue | 3344 ++---
src/views/qualityManagement/nonconformingManagement/components/formDia.vue | 494
src/views/financialManagement/payable/reconciliation.vue | 22
src/views/productionManagement/productionReporting/index.vue | 20
src/views/equipmentManagement/upkeep/Form/RecordDetailDia.vue | 99
src/views/financialManagement/payable/purchaseIn.vue | 24
src/main.js | 17
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue | 1019
src/views/productionManagement/productionOrder/index.vue | 135
src/views/system/dict/index.vue | 2
src/views/customerService/feedbackRegistration/components/formDia.vue | 49
.gitignore | 5
src/views/procurementManagement/qualityInspection/index.vue | 42
src/components/AIChatSidebar/assistants/purchaseAssistant.js | 15
src/views/productionManagement/workOrder/index.vue | 4
src/views/equipmentManagement/inspectionManagement/components/formDia.vue | 8
src/views/procurementManagement/purchaseOrder/index.vue | 27
src/components/ProcessParamListDialog.vue | 12
src/views/customerService/components/viewDia.vue | 123
src/views/productManagement/productIdentifier/index.vue | 21
src/views/reportAnalysis/productionAnalysis/components/center-center.vue | 54
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue | 52
src/views/inventoryManagement/dispatchLog/Record.vue | 1501 +-
src/views/salesManagement/returnOrder/components/formDia.vue | 153
src/views/procurementManagement/purchaseReturnOrder/index.vue | 60
src/layout/components/Sidebar/SidebarItem.vue | 107
src/views/basicData/supplierManage/components/HomeTab.vue | 924
src/assets/aiIndustrialBrain/reference-cards.png | 0
src/views/qualityManagement/finalInspection/components/formDia.vue | 909
src/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue | 32
src/views/financialManagement/receivable/invoiceApply.vue | 53
src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue | 67
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue | 417
src/views/procurementManagement/paymentLedger/index.vue | 85
src/views/productionManagement/productStructure/Detail/index.vue | 6
src/views/personnelManagement/dimission/components/formDia.vue | 463
src/views/login.vue | 20
src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue | 22
src/views/salesManagement/indicatorStats/index.vue | 86
src/views/systemArchitecture/index.vue | 270
package.json | 1
src/views/productionPlan/productionPlan/index.vue | 63
src/components/PIMTable/Pagination.vue | 2
src/views/basicData/supplierManage/components/BlacklistTab.vue | 911
src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue | 21
src/views/personnelManagement/dimission/index.vue | 397
177 files changed, 16,139 insertions(+), 18,327 deletions(-)
diff --git a/.env.development b/.env.development
index e3c6324..e71d4f2 100644
--- a/.env.development
+++ b/.env.development
@@ -6,3 +6,5 @@
# 涓皬浼佷笟鏁板瓧鍖栬浆鍨嬩簩绾у椁愬寘/寮�鍙戠幆澧�
VITE_APP_BASE_API = '/dev-api'
+
+VITE_BASE_API = 'http://localhost:9003'
diff --git a/.gitignore b/.gitignore
index f979342..78a752d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,8 +6,6 @@
yarn-error.log*
**/*.log
-.claude/
-
tests/**/coverage/
tests/e2e/reports
selenium-debug.log
@@ -20,9 +18,6 @@
*.njsproj
*.sln
*.local
-
-# Claude Code
-.claude/
package-lock.json
yarn.lock
diff --git a/package.json b/package.json
index 11fa01d..4e2b8d8 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"element-plus": "2.7.7",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",
+ "html2canvas": "^1.4.1",
"js-beautify": "1.14.11",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
diff --git a/public/DDGWfavicon.ico b/public/DDGWfavicon.ico
new file mode 100644
index 0000000..e1905a1
--- /dev/null
+++ b/public/DDGWfavicon.ico
Binary files differ
diff --git a/src/api/basicData/customer.js b/src/api/basicData/customer.js
index 0934193..436098e 100644
--- a/src/api/basicData/customer.js
+++ b/src/api/basicData/customer.js
@@ -26,7 +26,7 @@
})
}
-// 娴佸叆鍏捣
+// 鍥為��瀹㈡埛鍒伴攢鍞。妗�
export function backCustomer(id) {
return request({
url: '/basic/customer/back/' + id,
diff --git a/src/api/basicData/enum.js b/src/api/basicData/enum.js
index 9e8b503..350df17 100644
--- a/src/api/basicData/enum.js
+++ b/src/api/basicData/enum.js
@@ -1,13 +1,5 @@
import request from "@/utils/request.js";
-/** 瀹℃壒妯℃澘绫诲瀷绛夐�氱敤鏋氫妇锛圱ypeEnums锛� */
-export function getTypeEnums() {
- return request({
- url: '/basic/enum/TypeEnums',
- method: 'get'
- })
-}
-
export function findAllStockRecordTypeOptions() {
return request({
url: '/basic/enum/stockRecordType',
diff --git a/src/api/collaborativeApproval/knowledgeBase.js b/src/api/collaborativeApproval/knowledgeBase.js
index eb44ac2..b195525 100644
--- a/src/api/collaborativeApproval/knowledgeBase.js
+++ b/src/api/collaborativeApproval/knowledgeBase.js
@@ -1,172 +1,55 @@
import request from "@/utils/request";
-import { getToken } from '@/utils/auth';
-/**
- * 鐭ヨ瘑搴撶鐞嗘帴鍙�
- * 浼犲弬瑙勮寖:
- * - GET璇锋眰: 浣跨敤 params
- * - POST璇锋眰: 浣跨敤 data
- * - DELETE璇锋眰: 浣跨敤 data
- * - 娴佸紡璇锋眰: 浣跨敤 Fetch API
- */
-
-// ==================== 鐭ヨ瘑搴揅RUD鎺ュ彛 ====================
-
-/**
- * 鏌ヨ鐭ヨ瘑搴撳垪琛�
- * @param {Object} query - 鏌ヨ鍙傛暟
- * @param {number} query.current - 褰撳墠椤电爜(蹇呭~)
- * @param {number} query.size - 姣忛〉鏉℃暟(蹇呭~)
- * @param {string} [query.title] - 鐭ヨ瘑鏍囬(鍙��,妯$硦鎼滅储)
- * @param {string} [query.type] - 鐭ヨ瘑绫诲瀷(鍙��,绮剧‘鍖归厤)
- * @returns {Promise}
- */
+// 鏌ヨ鐭ヨ瘑搴撳垪琛�
export function listKnowledgeBase(query) {
return request({
url: "/knowledgeBase/getList",
method: "get",
- params: query, // GET璇锋眰浣跨敤params
+ params: query,
});
}
-/**
- * 鏂板鐭ヨ瘑搴�
- * @param {Object} data - 鐭ヨ瘑搴撴暟鎹�
- * @param {string} data.title - 鐭ヨ瘑鏍囬(蹇呭~)
- * @param {string} data.type - 鐭ヨ瘑绫诲瀷(蹇呭~)
- * @param {string} [data.scenario] - 閫傜敤鍦烘櫙(鍙��)
- * @param {string} [data.efficiency] - 瑙e喅鏁堢巼(鍙��)
- * @param {string} data.problem - 闂鎻忚堪(蹇呭~)
- * @param {string} data.solution - 瑙e喅鏂规(蹇呭~)
- * @param {string} [data.keyPoints] - 鍏抽敭瑕佺偣(鍙��)
- * @param {string} [data.creator] - 鍒涘缓浜�(鍙��)
- * @param {number} [data.usageCount=0] - 浣跨敤娆℃暟(鍙��)
- * @returns {Promise}
- */
+// 鏌ヨ鐭ヨ瘑搴撹缁�
+// export function getKnowledgeBase(knowledgeBaseId) {
+// return request({
+// url: "/collaborativeApproval/knowledgeBase/" + knowledgeBaseId,
+// method: "get",
+// });
+// }
+
+// 鏂板鐭ヨ瘑搴�
export function addKnowledgeBase(data) {
return request({
url: "/knowledgeBase/add",
method: "post",
- data: data, // POST璇锋眰浣跨敤data
+ data: data,
});
}
-/**
- * 淇敼鐭ヨ瘑搴�
- * @param {Object} data - 鐭ヨ瘑搴撴暟鎹�
- * @param {number} data.id - 鐭ヨ瘑搴揑D(蹇呭~)
- * @param {string} data.title - 鐭ヨ瘑鏍囬(蹇呭~)
- * @param {string} data.type - 鐭ヨ瘑绫诲瀷(蹇呭~)
- * @returns {Promise}
- */
+// 淇敼鐭ヨ瘑搴�
export function updateKnowledgeBase(data) {
return request({
url: "/knowledgeBase/update",
method: "post",
- data: data, // POST璇锋眰浣跨敤data
+ data: data,
});
}
-/**
- * 鍒犻櫎鐭ヨ瘑搴�(鏀寔鎵归噺鍒犻櫎)
- * @param {number[]} ids - 鐭ヨ瘑搴揑D鏁扮粍
- * @returns {Promise}
- */
-export function delKnowledgeBase(ids) {
+// 鍒犻櫎鐭ヨ瘑搴�
+export function delKnowledgeBase(query) {
return request({
url: "/knowledgeBase/delete",
method: "delete",
- data: ids, // DELETE璇锋眰浣跨敤data浼犻�掓暟缁�
+ data: query,
});
}
-// ==================== 鏂囦欢绠$悊鎺ュ彛 ====================
-
-/**
- * 鏌ヨ鐭ヨ瘑搴撴枃浠跺悜閲忓寲鐘舵��
- * @param {number} knowledgeBaseId - 鐭ヨ瘑搴揑D
- * @returns {Promise} 杩斿洖鏂囦欢鍒楄〃鍙婂悜閲忓寲鐘舵��
- */
-export function getVectorStatus(knowledgeBaseId) {
+// 鎵归噺鍒犻櫎鐭ヨ瘑搴�
+export function delKnowledgeBaseBatch(knowledgeBaseIds) {
return request({
- url: `/knowledgeBase/vector/status/${knowledgeBaseId}`,
- method: "get",
- });
-}
-
-/**
- * 淇濆瓨鐭ヨ瘑搴撴枃浠跺叧鑱�(瑙﹀彂鍚戦噺鍖�)
- * @param {Object} data - 鏂囦欢鍏宠仈鏁版嵁
- * @param {number} data.knowledgeBaseId - 鐭ヨ瘑搴揑D(蹇呭~)
- * @param {number[]} data.storageBlobIds - 鏂囦欢blob ID鏁扮粍(蹇呭~)
- * @returns {Promise}
- */
-export function saveKnowledgeBaseFiles(data) {
- return request({
- url: "/knowledgeBase/file/save",
- method: "post",
- data: data, // POST璇锋眰浣跨敤data
- });
-}
-
-/**
- * 鍒犻櫎鐭ヨ瘑搴撴枃浠�
- * @param {number[]} ids - 鍚戦噺璁板綍ID鏁扮粍
- * @returns {Promise}
- */
-export function deleteKnowledgeBaseFile(ids) {
- return request({
- url: "/knowledgeBase/file/delete",
+ url: "/knowledgeBase/batch",
method: "delete",
- data: ids, // DELETE璇锋眰浣跨敤data浼犻�掓暟缁�
+ data: knowledgeBaseIds,
});
}
-/**
- * 閲嶆柊鍚戦噺鍖栨枃浠�
- * @param {number} vectorId - 鍚戦噺璁板綍ID
- * @returns {Promise}
- */
-export function reprocessVector(vectorId) {
- return request({
- url: `/knowledgeBase/vector/reprocess/${vectorId}`,
- method: "post",
- });
-}
-
-// ==================== 鐭ヨ瘑闂瓟鎺ュ彛 ====================
-
-/**
- * 鐭ヨ瘑搴撻棶绛�(娴佸紡)
- * 鍚庣鎺ュ彛: POST /ai/knowledge/chat
- * 鍝嶅簲绫诲瀷: text/stream;charset=utf-8 (Spring Flux<String>)
- *
- * @param {Object} data - 闂瓟鍙傛暟
- * @param {number} data.knowledgeBaseId - 鐭ヨ瘑搴揑D(蹇呭~)
- * @param {string} data.memoryId - 浼氳瘽ID(蹇呭~,鐢ㄤ簬淇濇寔涓婁笅鏂�)
- * @param {string} data.question - 鐢ㄦ埛闂(蹇呭~)
- * @returns {Promise<Response>} 杩斿洖Fetch Response瀵硅薄
- */
-export function knowledgeChat(data) {
- const token = getToken();
- return fetch(import.meta.env.VITE_APP_BASE_API + '/ai/knowledge/chat', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': 'Bearer ' + token
- },
- body: JSON.stringify(data)
- });
-}
-
-/**
- * 鏌ヨ鐭ヨ瘑搴撻棶绛斿巻鍙�
- * @param {string} memoryId - 浼氳瘽ID
- * @returns {Promise}
- */
-export function getKnowledgeHistory(memoryId) {
- return request({
- url: `/ai/knowledge/history/${memoryId}`,
- method: "get",
- });
-}
diff --git a/src/api/customerService/index.js b/src/api/customerService/index.js
index 571601a..e115ae8 100644
--- a/src/api/customerService/index.js
+++ b/src/api/customerService/index.js
@@ -130,3 +130,12 @@
params: query,
})
}
+
+// 鍞悗鍗曡鎯�
+export function getAfterSalesServiceById(id) {
+ return request({
+ url: '/afterSalesService/getById',
+ method: 'get',
+ params: { id }
+ })
+}
diff --git a/src/api/financialManagement/invoiceApply.js b/src/api/financialManagement/invoiceApply.js
index 8806bbc..a567d1c 100644
--- a/src/api/financialManagement/invoiceApply.js
+++ b/src/api/financialManagement/invoiceApply.js
@@ -56,13 +56,4 @@
url: `/accountInvoiceApplication/deleteAccountInvoiceApplication?${query}`,
method: "delete",
});
-}
-
-/** 鏍规嵁瀹㈡埛id鏌ヨ寮�绁ㄧ敵璇峰彴璐� */
-export function getAccountInvoiceApplicationList(query) {
- return request({
- url: '/accountInvoiceApplication/getAccountInvoiceApplicationList',
- method: "get",
- params: query,
- });
-}
+}
\ No newline at end of file
diff --git a/src/api/inventoryManagement/stockOut.js b/src/api/inventoryManagement/stockOut.js
index b54e004..004ba99 100644
--- a/src/api/inventoryManagement/stockOut.js
+++ b/src/api/inventoryManagement/stockOut.js
@@ -35,12 +35,3 @@
data,
});
}
-
-// 鎵归噺鍙嶅鍑哄簱璁板綍
-export const batchUnapproveStockOutRecords = (data) => {
- return request({
- url: "/stockOutRecord/reAudit",
- method: "post",
- data,
- });
-}
diff --git a/src/api/personnelManagement/staffSalaryMain.js b/src/api/personnelManagement/staffSalaryMain.js
index 7ff6667..a42f96b 100644
--- a/src/api/personnelManagement/staffSalaryMain.js
+++ b/src/api/personnelManagement/staffSalaryMain.js
@@ -17,14 +17,6 @@
});
}
-export function staffSalaryMainCalculateByEmployeeId(data) {
- return request({
- url: "/staffSalaryMain/calculateByEmployeeId",
- method: "post",
- data,
- });
-}
-
export function staffSalaryMainAdd(data) {
return request({
url: "/staffSalaryMain/add",
@@ -49,11 +41,3 @@
});
}
-// 鑾峰彇鍙敤閮ㄩ棬鍒楄〃锛堟牴鎹湀浠芥煡璇紝鎺掗櫎宸插彂鏀惧伐璧勮〃鐨勯儴闂級
-export function staffSalaryMainAvailableDepts(salaryMonth) {
- return request({
- url: "/staffSalaryMain/availableDepts",
- method: "get",
- params: { salaryMonth },
- });
-}
\ No newline at end of file
diff --git a/src/api/procurementManagement/paymentLedger.js b/src/api/procurementManagement/paymentLedger.js
index 537ba9f..6c5d9de 100644
--- a/src/api/procurementManagement/paymentLedger.js
+++ b/src/api/procurementManagement/paymentLedger.js
@@ -18,12 +18,3 @@
params,
});
}
-
-/** 浠樻鍙拌处 - 浠樻鐧昏鍒楄〃 */
-export function registrationList(params) {
- return request({
- url: "/purchase/report/registration",
- method: "get",
- params,
- });
-}
diff --git a/src/api/procurementManagement/procurementLedger.js b/src/api/procurementManagement/procurementLedger.js
index c389582..3bdee66 100644
--- a/src/api/procurementManagement/procurementLedger.js
+++ b/src/api/procurementManagement/procurementLedger.js
@@ -9,14 +9,6 @@
params: query,
});
}
-// 閲囪喘閫�璐у彲閫夐噰璐彴璐�
-export function purchaseReturnableList(query) {
- return request({
- url: "/purchase/ledger/returnableList",
- method: "get",
- params: query,
- });
-}
// 鏌ヨ鍚堝悓鍙�
export function getSalesNo(query) {
return request({
@@ -74,69 +66,67 @@
});
}
-export function createPurchaseNo(entryDate) {
+export function createPurchaseNo() {
return request({
url: "/purchase/ledger/createPurchaseNo",
method: "get",
- params: { entryDate },
});
}
export function updateApprovalStatus(query) {
- return request({
- url: "/purchase/ledger/updateApprovalStatus",
- method: "post",
- data: query,
- });
+ return request({
+ url: "/purchase/ledger/updateApprovalStatus",
+ method: "post",
+ data: query,
+ });
}
// 淇濆瓨閲囪喘妯℃澘
export function addPurchaseTemplate(data) {
- return request({
- url: "/purchaseLedgerTemplate/add",
- method: "post",
- data: data,
- });
+ return request({
+ url: "/purchaseLedgerTemplate/add",
+ method: "post",
+ data: data,
+ });
}
// 淇敼閲囪喘妯℃澘
export function updatePurchaseTemplate(data) {
- return request({
- url: "/purchaseLedgerTemplate/update",
- method: "post",
- data: data,
- });
+ return request({
+ url: "/purchaseLedgerTemplate/update",
+ method: "post",
+ data: data,
+ });
}
// 鏌ヨ閲囪喘妯℃澘
export function getPurchaseTemplateList(query) {
- return request({
- url: "/purchase/ledger/getPurchaseTemplateList",
- method: "get",
- params: query,
- });
+ return request({
+ url: "/purchase/ledger/getPurchaseTemplateList",
+ method: "get",
+ params: query,
+ });
}
// 鍒犻櫎閲囪喘妯℃澘
export function delPurchaseTemplate(id) {
- return request({
- url: "/purchaseLedgerTemplate/delete",
- method: "delete",
- data: id,
- });
+ return request({
+ url: "/purchaseLedgerTemplate/delete",
+ method: "delete",
+ data: id,
+ });
}
// 鏌ヨ閲囪喘璇︽儏
export function getPurchaseByCode(id) {
- return request({
- url: "/purchase/ledger/getPurchaseByCode",
- method: "get",
- params: id,
- });
+ return request({
+ url: "/purchase/ledger/getPurchaseByCode",
+ method: "get",
+ params: id,
+ });
}
-
-export function batchGeneratePurchaseInboundSteps(query) {
- return request({
- url: "/purchase/ledger/batchInsertPurchaseSteps",
- method: "post",
- data: query,
- });
-}
+// 鑾峰彇閲囪喘鍗曟墦鍗版暟鎹�
+export function getPrintData(id) {
+ return request({
+ url: '/purchase/ledger/printData/' + id,
+ method: 'get',
+ });
+}
\ No newline at end of file
diff --git a/src/api/salesManagement/salesLedger.js b/src/api/salesManagement/salesLedger.js
index 6548927..841a8a1 100644
--- a/src/api/salesManagement/salesLedger.js
+++ b/src/api/salesManagement/salesLedger.js
@@ -116,4 +116,11 @@
method: "get",
params: query,
});
+}
+// 鑾峰彇閿�鍞崟鎵撳嵃鏁版嵁
+export function getPrintData(id) {
+ return request({
+ url: '/sales/ledger/printData/' + id,
+ method: 'get',
+ });
}
\ No newline at end of file
diff --git a/src/api/viewIndex.js b/src/api/viewIndex.js
index 0087d66..9cae219 100644
--- a/src/api/viewIndex.js
+++ b/src/api/viewIndex.js
@@ -349,7 +349,8 @@
export const productionOrderProgress = (params = {}) => {
const safePageNum = Math.max(1, Number(params.pageNum || 1));
- const safeTab = ["all", "inProgress", "completed", "end"].includes(params.tab)
+ const safePageSize = Math.min(50, Math.max(1, Number(params.pageSize || 10)));
+ const safeTab = ["all", "inProgress", "completed", "paused"].includes(params.tab)
? params.tab
: "all";
return request({
@@ -359,7 +360,7 @@
...params,
tab: safeTab,
pageNum: safePageNum,
- pageSize: params.pageSize,
+ pageSize: safePageSize,
},
headers: {
handleAuthError: false,
diff --git a/src/assets/aiIndustrialBrain/reference-cards.png b/src/assets/aiIndustrialBrain/reference-cards.png
new file mode 100644
index 0000000..72fdb93
--- /dev/null
+++ b/src/assets/aiIndustrialBrain/reference-cards.png
Binary files differ
diff --git a/src/assets/aiIndustrialBrain/reference-chat.png b/src/assets/aiIndustrialBrain/reference-chat.png
new file mode 100644
index 0000000..d026388
--- /dev/null
+++ b/src/assets/aiIndustrialBrain/reference-chat.png
Binary files differ
diff --git a/src/assets/indexViews/HYSNLogo.png b/src/assets/indexViews/HYSNLogo.png
new file mode 100644
index 0000000..70148cc
--- /dev/null
+++ b/src/assets/indexViews/HYSNLogo.png
Binary files differ
diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss
index 5da0e59..685a0eb 100644
--- a/src/assets/styles/sidebar.scss
+++ b/src/assets/styles/sidebar.scss
@@ -216,37 +216,32 @@
& .nest-menu .el-sub-menu > .el-sub-menu__title,
& .el-sub-menu .el-menu-item {
min-width: 0 !important;
- width: calc(100% - 32px) !important;
- margin: 0 16px 6px !important;
- height: 40px;
- line-height: 40px;
- padding-left: 12px !important;
- padding-right: 12px !important;
- border-radius: 8px;
+ width: calc(100% - 24px) !important;
+ margin: 0 12px 8px !important;
+ height: 46px;
+ line-height: 46px;
+ padding-left: 14px !important;
+ padding-right: 14px !important;
+ border-radius: 12px;
transition: all 0.24s ease;
color: var(--sidebar-text);
- border: none !important;
- background: transparent;
- font-size: 13px;
+ border: 1px solid rgba(255, 255, 255, 0.06) !important;
+ background: linear-gradient(128deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
&:hover {
- background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.12) !important;
- transform: translateX(4px);
+ background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.07)) !important;
+ border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3) !important;
+ transform: translateX(2px);
}
&.is-active {
- background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.85) !important;
+ background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
+ background-size: 180% 180%;
color: #fff !important;
font-weight: 500;
- box-shadow: 0 4px 12px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.25);
+ box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
+ animation: sidebarActiveFlow 4.6s ease infinite;
}
- }
-
- // 瀛愯彍鍗曞鍣ㄦ牱寮� - 澧炲姞缂╄繘鍜岃瑙夊眰娆�
- & .el-sub-menu .el-menu {
- padding: 4px 0 8px;
- margin-left: 8px;
- border-left: 2px solid rgba(255, 255, 255, 0.08);
}
}
diff --git a/src/components/AIChatSidebar/assistants/financeAssistant.js b/src/components/AIChatSidebar/assistants/financeAssistant.js
index f5dd7c6..e8df3f4 100644
--- a/src/components/AIChatSidebar/assistants/financeAssistant.js
+++ b/src/components/AIChatSidebar/assistants/financeAssistant.js
@@ -14,15 +14,13 @@
allowFileUpload: false,
emptySessionText: '鏆傛棤璐㈠姟浼氳瘽',
quickPrompts: [
- '鏌ョ湅缁忚惀椹鹃┒鑸�',
- '鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�',
'鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級',
'鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜',
- '鏌ヨ杩�30澶╀簭鎹熻鍗�',
'杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂�',
+ '鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�',
+ '鏌ヨ杩�30澶╀簭鎹熻鍗�',
'鍒嗘瀽杩�30澶╁簱瀛樿祫閲戝崰鐢�',
'棰勬祴鏈潵3涓湀鐜伴噾娴�',
- '鏌ヨ搴旀敹鍥炴椋庨櫓',
'鍝釜宸ュ簭鎴愭湰鏈�楂�'
]
}
diff --git a/src/components/AIChatSidebar/assistants/productionAssistant.js b/src/components/AIChatSidebar/assistants/productionAssistant.js
index d5b4924..fb2d737 100644
--- a/src/components/AIChatSidebar/assistants/productionAssistant.js
+++ b/src/components/AIChatSidebar/assistants/productionAssistant.js
@@ -14,15 +14,14 @@
allowFileUpload: false,
emptySessionText: '鏆傛棤鐢熶骇浼氳瘽',
quickPrompts: [
- '鏌ヨ鐢熶骇鐜板満鏁版嵁',
- '鏌ヨ鐢熶骇璁″垝鎵ц鎯呭喌',
- '鏌ヨ宸ュ崟鎵ц鎯呭喌',
- '鏌ヨ璁惧杩愯鎯呭喌',
- '鏌ヨ璐ㄩ噺寮傚父鏁版嵁',
- '鏌ヨ鐗╂枡鐩稿叧鏁版嵁',
- '鏌ョ湅鍒堕�犻璀︾湅鏉�',
- '鍒嗘瀽鏈湀鍒堕�犵粡钀ユ儏鍐�',
- '鍒嗘瀽杩�7澶╃敓浜у紓甯�',
- '鐢熸垚鍒堕�犲姙鐞嗗缓璁�'
+ '鏌ヨ鏈湀鐢熶骇璁″垝',
+ '鏌ョ湅鏈�杩�10鏉″伐鍗�',
+ '鏌ヨ澶嘇-01鐨勭淮淇儏鍐�',
+ '鏌ヨ川閲忎笉鍚堟牸璁板綍',
+ '鏌ヤ綆搴撳瓨鐗╂枡',
+ '鏌ヨ繎7澶╁紓甯稿鐞�',
+ '鐢熸垚鍒堕�犻璀︾湅鏉�',
+ '鍒嗘瀽鏈湀鐢熶骇瀹屾垚鐜囧拰寮傚父鐜�',
+ '缁欏嚭宸ュ崟閫炬湡鍜岃澶囧緟淇殑鍔炵悊寤鸿'
]
}
diff --git a/src/components/AIChatSidebar/assistants/purchaseAssistant.js b/src/components/AIChatSidebar/assistants/purchaseAssistant.js
index 5dd85e7..4f2e72c 100644
--- a/src/components/AIChatSidebar/assistants/purchaseAssistant.js
+++ b/src/components/AIChatSidebar/assistants/purchaseAssistant.js
@@ -16,15 +16,10 @@
fileAnalyzeUrl: '/purchase-ai/analyze-files',
emptySessionText: '鏆傛棤閲囪喘浼氳瘽',
quickPrompts: [
- '鏌ヨ閲囪喘鍙拌处鍒楄〃',
- '鏌ヨ鏈�杩�10鏉¢噰璐彴璐�',
- '缁熻鏈湀閲囪喘鏁版嵁',
- '鏌ヨ鏈湀閲囪喘鐗╂枡閲戦鎺掕',
- '鏌ヨ鏈叆搴撻噰璐鍗�',
- '鏌ヨ閲囪喘鍒拌揣寮傚父',
- '鏌ヨ寰呬粯娆鹃噰璐崟',
- '鏌ヨ鏈湀閲囪喘閫�璐ф儏鍐�',
- '鏌ヨ鏌愪釜閲囪喘鍙拌处璇︽儏',
- '鍒嗘瀽渚涘簲鍟嗛噰璐噾棰濇帓鍚�'
+ '鏈湀閲囪喘閲戦鎺掑悕鍓嶅崄鐨勭墿鏂欐湁鍝簺锛�',
+ '鍝簺閲囪喘璁㈠崟杩樻湭鍏ュ簱锛�',
+ '鏈�杩�7澶╀緵搴斿晢鍒拌揣寮傚父鏈夊摢浜涳紵',
+ '甯垜缁熻寰呬粯娆鹃噰璐崟锛�',
+ '鍒楀嚭鏈湀閲囪喘閫�璐ф儏鍐�'
]
}
diff --git a/src/components/AIChatSidebar/assistants/salesAssistant.js b/src/components/AIChatSidebar/assistants/salesAssistant.js
index 03cb102..c598bec 100644
--- a/src/components/AIChatSidebar/assistants/salesAssistant.js
+++ b/src/components/AIChatSidebar/assistants/salesAssistant.js
@@ -14,8 +14,8 @@
allowFileUpload: false,
emptySessionText: '鏆傛棤閿�鍞細璇�',
quickPrompts: [
- '鏌ヨ绉佹捣瀹㈡埛妗f鍓�10鏉�',
- '鏌ヨ鍏捣瀹㈡埛妗f',
+ '鏌ヨ閿�鍞。妗堝墠10鏉�',
+ '鏌ヨ瀹㈡埛妗f',
'鏌ヨ鏈湀閿�鍞姤浠�',
'鏌ヨ鏈湀閿�鍞彴璐�',
'鏌ヨ杩�30澶╅攢鍞��璐�',
diff --git a/src/components/Echarts/echarts.vue b/src/components/Echarts/echarts.vue
index 54a6c39..626f60d 100644
--- a/src/components/Echarts/echarts.vue
+++ b/src/components/Echarts/echarts.vue
@@ -203,6 +203,10 @@
clearInitTimer()
})
+defineExpose({
+ resize: windowResizeListener,
+})
+
// Watch all reactive props that affect the chart
watch(
() => [props.xAxis, props.yAxis, props.series, props.legend, props.tooltip, props.visualMap],
diff --git a/src/components/PIMTable/PIMTable.vue b/src/components/PIMTable/PIMTable.vue
index 74615af..aad24fa 100644
--- a/src/components/PIMTable/PIMTable.vue
+++ b/src/components/PIMTable/PIMTable.vue
@@ -8,10 +8,11 @@
:highlight-current-row="highlightCurrentRow"
:row-class-name="rowClassName"
:row-style="rowStyle"
+ :cell-style="cellStyle"
:row-key="rowKey"
:style="tableStyle"
tooltip-effect="dark"
- :tooltip-options="{ popperOptions: { strategy: 'absolute' } }"
+ :tooltip-options="{ appendTo: 'body' }"
:expand-row-keys="expandRowKeys"
:show-summary="isShowSummary"
:summary-method="summaryMethod"
@@ -120,6 +121,7 @@
<el-button v-show="o.type != 'upload'"
v-if="o.showHide ? o.showHide(scope.row) : true"
:disabled="isOperationDisabled(o, scope.row)"
+ :loading="isOperationLoading(o, scope.row)"
:plain="o.plain"
type="primary"
:style="{
@@ -292,6 +294,10 @@
type: [Object, Function],
default: () => ({}),
},
+ cellStyle: {
+ type: [Object, Function],
+ default: () => ({}),
+ },
tableData: {
type: Array,
default: () => [],
@@ -373,6 +379,13 @@
: !!operation.disabled;
};
+ const isOperationLoading = (operation, row) => {
+ if (!operation?.loading) return false;
+ return typeof operation.loading === "function"
+ ? !!operation.loading(row)
+ : !!operation.loading;
+ };
+
const parseHexToRgb = hex => {
const normalized = String(hex || "")
.trim()
diff --git a/src/components/PIMTable/Pagination.vue b/src/components/PIMTable/Pagination.vue
index 001f19a..1b7895f 100644
--- a/src/components/PIMTable/Pagination.vue
+++ b/src/components/PIMTable/Pagination.vue
@@ -34,7 +34,7 @@
},
pageSizes: {
type: Array,
- default: () => [10, 20, 30, 50, 100]
+ default: () => [10, 20, 30, 50, 100, 200, 500]
},
pagerCount: {
type: Number,
diff --git a/src/components/ProcessParamListDialog.vue b/src/components/ProcessParamListDialog.vue
index 5af24bb..deee249 100644
--- a/src/components/ProcessParamListDialog.vue
+++ b/src/components/ProcessParamListDialog.vue
@@ -372,14 +372,7 @@
size: paramPage.value.size,
}).then(res => {
if (res.code === 200) {
- const existingParamIds = new Set(
- (props.paramList || [])
- .map(item => Number(item.paramId || item.technologyOperationParamId))
- .filter(id => Number.isFinite(id) && id > 0)
- );
- filteredParamList.value = (res.data?.records || []).filter(
- item => !existingParamIds.has(Number(item.id))
- );
+ filteredParamList.value = res.data?.records || [];
paramPage.value.total = res.data.total || 0;
} else {
ElMessage.error(res.msg || "鏌ヨ澶辫触");
@@ -409,6 +402,7 @@
addProcessRouteItemParamOrder({
productionOrderId: Number(props.orderId),
productionOrderRoutingOperationId: props.process.id,
+ technologyRoutingOperationParamId: props.process.id,
paramId: selectedParam.value.id,
standardValue: selectedParam.value.standardValue || "",
isRequired: selectedParam.value.isRequired || 0,
@@ -673,4 +667,4 @@
.detail-text {
font-weight: 500;
}
-</style>
+</style>
\ No newline at end of file
diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue
index 3712c68..003b489 100644
--- a/src/layout/components/Sidebar/SidebarItem.vue
+++ b/src/layout/components/Sidebar/SidebarItem.vue
@@ -102,70 +102,57 @@
</script>
<style lang="scss" scoped>
-.sidebar-item-wrapper {
- :deep(.menu-icon) {
- width: 26px;
- height: 26px;
- margin-right: 12px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- transition: color 0.2s ease;
- color: var(--sidebar-text);
- opacity: 0.88;
- }
-
- :deep(.el-menu-item:hover .menu-icon),
- :deep(.el-sub-menu__title:hover .menu-icon) {
- color: #ffffff;
- opacity: 1;
- }
+.sidebar-item-wrapper {
+ :deep(.menu-icon) {
+ width: 26px;
+ height: 26px;
+ margin-right: 12px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ transition: color 0.2s ease;
+ color: var(--sidebar-text);
+ opacity: 0.88;
+ }
+
+ :deep(.el-menu-item:hover .menu-icon),
+ :deep(.el-sub-menu__title:hover .menu-icon) {
+ color: #ffffff;
+ opacity: 1;
+ }
:deep(.el-menu-item.is-active .menu-icon) {
color: var(--menu-active-text) !important;
opacity: 1;
}
- :deep(.menu-title) {
- font-weight: 500;
- transition: color 0.2s ease;
- color: var(--sidebar-text);
- opacity: 0.82;
- }
-
- :deep(.el-menu-item:hover .menu-title),
- :deep(.el-sub-menu__title:hover .menu-title) {
- color: #ffffff;
- opacity: 1;
- }
-
- :deep(.el-menu-item.is-active .menu-title) {
- color: var(--menu-active-text) !important;
- opacity: 1;
- }
-
- :deep(.nest-menu) {
- .menu-icon {
- width: 18px;
- height: 18px;
- margin-right: 8px;
- opacity: 0.7;
- }
-
- .menu-title {
- font-size: 13px;
- opacity: 0.85;
- }
-
- .el-menu-item.is-active {
- .menu-icon {
- opacity: 1;
- }
- .menu-title {
- opacity: 1;
- }
- }
- }
-}
+ :deep(.menu-title) {
+ font-weight: 500;
+ transition: color 0.2s ease;
+ color: var(--sidebar-text);
+ opacity: 0.82;
+ }
+
+ :deep(.el-menu-item:hover .menu-title),
+ :deep(.el-sub-menu__title:hover .menu-title) {
+ color: #ffffff;
+ opacity: 1;
+ }
+
+ :deep(.el-menu-item.is-active .menu-title) {
+ color: var(--menu-active-text) !important;
+ opacity: 1;
+ }
+
+ :deep(.nest-menu) {
+ .menu-icon {
+ width: 22px;
+ height: 22px;
+ margin-right: 10px;
+ }
+
+ .menu-title { font-size: 13px; }
+ }
+}
</style>
diff --git a/src/main.js b/src/main.js
index 025ff14..4282195 100644
--- a/src/main.js
+++ b/src/main.js
@@ -115,5 +115,22 @@
size: Cookies.get("size") || "default",
});
app._context.components.ElDialog.props.closeOnClickModal.default = false;
+const ElTable = app._context.components.ElTable;
+if (ElTable?.props?.tooltipOptions) {
+ if (ElTable.props.tooltipOptions === Object) {
+ ElTable.props.tooltipOptions = {
+ type: Object,
+ default: () => ({
+ appendTo: "body",
+ }),
+ };
+ } else if (typeof ElTable.props.tooltipOptions === "object") {
+ ElTable.props.tooltipOptions.default =
+ ElTable.props.tooltipOptions.default ||
+ (() => ({
+ appendTo: "body",
+ }));
+ }
+}
app.mount("#app");
diff --git a/src/router/index.js b/src/router/index.js
index 000a0c5..7be3668 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -97,44 +97,6 @@
},
],
},
- // 鏁欏婕旂ず妯″潡
- {
- path: "/productionManagement/teachingDemo",
- component: Layout,
- hidden: true,
- children: [
- {
- path: "",
- component: () => import("@/views/productionManagement/teachingDemo/index.vue"),
- name: "TeachingDemo",
- meta: { title: "宸ヨ壓璺嚎涓嶣OM鏁欏婕旂ず", icon: "education" },
- },
- {
- path: "bom",
- component: () => import("@/views/productionManagement/teachingDemo/BomDemo.vue"),
- name: "BomDemo",
- meta: { title: "BOM缁撴瀯婕旂ず", activeMenu: "/productionManagement/teachingDemo" },
- },
- {
- path: "processRoute",
- component: () => import("@/views/productionManagement/teachingDemo/ProcessRouteDemo.vue"),
- name: "ProcessRouteDemo",
- meta: { title: "宸ヨ壓璺嚎婕旂ず", activeMenu: "/productionManagement/teachingDemo" },
- },
- {
- path: "combined",
- component: () => import("@/views/productionManagement/teachingDemo/CombinedDemo.vue"),
- name: "CombinedDemo",
- meta: { title: "鑱斿姩婕旂ず", activeMenu: "/productionManagement/teachingDemo" },
- },
- {
- path: "factory",
- component: () => import("@/views/productionManagement/teachingDemo/FactoryDemo.vue"),
- name: "FactoryDemo",
- meta: { title: "鍔ㄦ�佸伐鍘傛紨绀�", activeMenu: "/productionManagement/teachingDemo" },
- },
- ],
- },
{
path: "/user",
component: Layout,
diff --git a/src/utils/documentPrint.js b/src/utils/documentPrint.js
new file mode 100644
index 0000000..2db84f3
--- /dev/null
+++ b/src/utils/documentPrint.js
@@ -0,0 +1,331 @@
+import html2canvas from 'html2canvas'
+
+function esc(s) {
+ if (!s) return ''
+ return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
+}
+
+function fmtDate(v) {
+ if (!v) return ''
+ const d = new Date(v)
+ const y = d.getFullYear()
+ const m = String(d.getMonth() + 1).padStart(2, '0')
+ const day = String(d.getDate()).padStart(2, '0')
+ return y + '-' + m + '-' + day
+}
+
+function fmtMoney(v) {
+ if (v == null) return '0.00'
+ return Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+function digitUppercase(n) {
+ const digits = ['闆�', '澹�', '璐�', '鍙�', '鑲�', '浼�', '闄�', '鏌�', '鎹�', '鐜�']
+ const radices = ['', '鎷�', '浣�', '浠�', '涓�', '鎷�', '浣�', '浠�', '浜�']
+ let num = Math.abs(n)
+ let result = ''
+ const intPart = Math.floor(num)
+ const intStr = String(intPart)
+ const len = intStr.length
+ if (intPart === 0) {
+ result = '闆�'
+ } else {
+ let zeroFlag = false
+ for (let i = 0; i < len; i++) {
+ const d = parseInt(intStr[i])
+ const pos = len - 1 - i
+ if (d === 0) {
+ zeroFlag = true
+ if (pos % 4 === 0) {
+ result += radices[pos]
+ zeroFlag = false
+ }
+ } else {
+ if (zeroFlag) {
+ result += '闆�'
+ zeroFlag = false
+ }
+ result += digits[d] + radices[pos]
+ }
+ }
+ if (result.endsWith('闆�')) result = result.slice(0, -1)
+ }
+ result += '鍏�'
+ const decPart = Math.round((num - intPart) * 100)
+ if (decPart === 0) {
+ result += '鏁�'
+ } else {
+ const jiao = Math.floor(decPart / 10)
+ const fen = decPart % 10
+ if (jiao > 0) result += digits[jiao] + '瑙�'
+ if (fen > 0) result += digits[fen] + '鍒�'
+ }
+ return result
+}
+
+function coreCss() {
+ return `*{margin:0;padding:0;box-sizing:border-box}body{font-family:"Microsoft YaHei","SimSun",sans-serif;padding:30px 36px;color:#333;background:#fff}.title{text-align:center;font-size:18px;font-weight:bold;letter-spacing:6px;margin-bottom:4px}.sub{text-align:center;font-size:12px;color:#999;margin-bottom:18px}.info-top{display:flex;justify-content:space-between;font-size:13px;margin-bottom:14px;padding-bottom:10px;border-bottom:1px dashed #ccc}.info-top .left,.info-top .right{line-height:2}.info-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px 36px;font-size:13px;margin-bottom:14px;padding-bottom:8px;border-bottom:1px solid #ccc}.info-grid .l{color:#666}.info-grid .v{font-weight:500}table{width:100%;border-collapse:collapse;font-size:13px;margin-bottom:14px}th,td{border:1px solid #333;padding:5px 6px;text-align:center}th{background:#eee;font-weight:500}td.r{text-align:right}.summary{text-align:right;font-size:13px;margin-bottom:16px;line-height:2.2}.summary .cn{font-weight:bold;color:#cf1322}`
+}
+
+function productRows(products) {
+ if (!products || !products.length) return ''
+ let html = ''
+ products.forEach((p, i) => {
+ const name = p.productCategory || ''
+ const spec = p.specificationModel || ''
+ html += '<tr>'
+ html += '<td>' + (i + 1) + '</td>'
+ html += '<td style="text-align:left">' + esc(name)
+ if (spec) html += '<br><span style="color:#888;font-size:12px">' + esc(spec) + '</span>'
+ html += '</td>'
+ html += '<td>' + esc(p.unit || '') + '</td>'
+ html += '<td class="r">' + (p.quantity != null ? Number(p.quantity).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : '') + '</td>'
+ html += '<td class="r">' + fmtMoney(p.taxInclusiveUnitPrice) + '</td>'
+ html += '<td class="r">' + fmtMoney(p.taxInclusiveTotalPrice) + '</td>'
+ html += '<td>' + (p.taxRate != null ? p.taxRate + '%' : '') + '</td>'
+ html += '<td>' + esc(p.invoiceType || '') + '</td>'
+ html += '</tr>'
+ })
+ return html
+}
+
+function calcTotals(products) {
+ let total = 0, totalNoTax = 0
+ if (products) {
+ products.forEach(p => {
+ if (p.taxInclusiveTotalPrice != null) total += Number(p.taxInclusiveTotalPrice)
+ if (p.taxExclusiveTotalPrice != null) totalNoTax += Number(p.taxExclusiveTotalPrice)
+ })
+ }
+ return { total, totalNoTax }
+}
+
+function buildSalesHtml(companyName, ledger, forPrint) {
+ const products = ledger.productData || []
+ const { total, totalNoTax } = calcTotals(products)
+ const toolbar = forPrint ? '<div class="toolbar"><button onclick="window.print()">鎵撳嵃 / 鍙﹀瓨涓� PDF</button></div>' : ''
+ const printCss = forPrint ? '@media print{body{padding:15px 24px}.toolbar{display:none}}' : ''
+ const printScript = forPrint ? '<script>window.onload=function(){setTimeout(function(){window.print();},300);};<\/script>' : ''
+
+ return `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8">
+<title>閿�鍞崟 - ${esc(ledger.salesContractNo)} - ${esc(companyName)}</title>
+<style>.toolbar{text-align:center;margin-bottom:16px}.toolbar button{padding:6px 20px;font-size:14px;cursor:pointer;background:#1890ff;color:#fff;border:none;border-radius:4px}.toolbar button:hover{background:#40a9ff}${coreCss()}${printCss}</style></head><body>
+${toolbar}
+<div class="title">${esc(companyName)}</div>
+<div class="sub">閿�鍞悎鍚� / 閿�鍞崟</div>
+<div class="info-top">
+ <div class="left"><div><strong>閿�鏂瑰悕绉帮細</strong>${esc(companyName)}</div></div>
+ <div class="right"><div><strong>鍚堝悓缂栧彿锛�</strong>${esc(ledger.salesContractNo)}</div><div><strong>绛捐鏃ユ湡锛�</strong>${fmtDate(ledger.executionDate)}</div></div>
+</div>
+<div class="info-grid">
+ <div><span class="l">瀹㈡埛鍚嶇О锛�</span><span class="v">${esc(ledger.customerName)}</span></div>
+ <div><span class="l">椤圭洰鍚嶇О锛�</span><span class="v">${esc(ledger.projectName)}</span></div>
+ <div><span class="l">涓氬姟鍛橈細</span><span class="v">${esc(ledger.salesman)}</span></div>
+ <div><span class="l">浠樻鏂瑰紡锛�</span><span class="v">${esc(ledger.paymentMethod)}</span></div>
+ <div><span class="l">褰曞叆鏃ユ湡锛�</span><span class="v">${fmtDate(ledger.entryDate)}</span></div>
+ <div><span class="l">浜よ揣鏃ユ湡锛�</span><span class="v">${fmtDate(ledger.deliveryDate)}</span></div>
+ ${ledger.remarks ? `<div style="grid-column:1/-1"><span class="l">澶囨敞锛�</span><span class="v">${esc(ledger.remarks)}</span></div>` : ''}
+</div>
+<table><thead><tr><th>搴忓彿</th><th>浜у搧鍚嶇О / 瑙勬牸鍨嬪彿</th><th>鍗曚綅</th><th>鏁伴噺</th><th>鍚◣鍗曚环</th><th>鍚◣鎬讳环</th><th>绋庣巼</th><th>鍙戠エ绫诲瀷</th></tr></thead><tbody>
+${productRows(products)}
+</tbody></table>
+<div class="summary">
+ <div>涓嶅惈绋庡悎璁★細<strong>${fmtMoney(totalNoTax)}</strong></div>
+ <div>鍚◣鍚堣锛堝ぇ鍐欙級锛�<span class="cn">${digitUppercase(total)}</span></div>
+ <div>鍚◣鍚堣锛堝皬鍐欙級锛�<strong>楼${fmtMoney(total)}</strong></div>
+</div>
+${printScript}
+</body></html>`
+}
+
+function buildPurchaseHtml(companyName, ledger, products, forPrint) {
+ const { total, totalNoTax } = calcTotals(products)
+ const contractAmount = ledger.contractAmount != null ? Number(ledger.contractAmount) : total
+ const toolbar = forPrint ? '<div class="toolbar"><button onclick="window.print()">鎵撳嵃 / 鍙﹀瓨涓� PDF</button></div>' : ''
+ const printCss = forPrint ? '@media print{body{padding:15px 24px}.toolbar{display:none}}' : ''
+ const printScript = forPrint ? '<script>window.onload=function(){setTimeout(function(){window.print();},300);};<\/script>' : ''
+
+ return `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8">
+<title>閲囪喘鍗� - ${esc(ledger.purchaseContractNumber)} - ${esc(companyName)}</title>
+<style>.toolbar{text-align:center;margin-bottom:16px}.toolbar button{padding:6px 20px;font-size:14px;cursor:pointer;background:#1890ff;color:#fff;border:none;border-radius:4px}.toolbar button:hover{background:#40a9ff}${coreCss()}${printCss}</style></head><body>
+${toolbar}
+<div class="title">${esc(companyName)}</div>
+<div class="info-top">
+ <div class="left"><div><strong>璐柟鍚嶇О锛�</strong>${esc(companyName)}</div></div>
+ <div class="right"><div><strong>鍚堝悓缂栧彿锛�</strong>${esc(ledger.purchaseContractNumber)}</div><div><strong>绛捐鏃ユ湡锛�</strong>${fmtDate(ledger.executionDate)}</div></div>
+</div>
+<div class="info-grid">
+ <div><span class="l">渚涘簲鍟嗗悕绉帮細</span><span class="v">${esc(ledger.supplierName)}</span></div>
+ <div><span class="l">椤圭洰鍚嶇О锛�</span><span class="v">${esc(ledger.projectName)}</span></div>
+ <div><span class="l">褰曞叆浜猴細</span><span class="v">${esc(ledger.recorderName)}</span></div>
+ <div><span class="l">浠樻鏂瑰紡锛�</span><span class="v">${esc(ledger.paymentMethod)}</span></div>
+ <div><span class="l">褰曞叆鏃ユ湡锛�</span><span class="v">${fmtDate(ledger.entryDate)}</span></div>
+ ${ledger.salesContractNo ? `<div><span class="l">鍏宠仈閿�鍞悎鍚屽彿锛�</span><span class="v">${esc(ledger.salesContractNo)}</span></div>` : ''}
+ ${ledger.remarks ? `<div style="grid-column:1/-1"><span class="l">澶囨敞锛�</span><span class="v">${esc(ledger.remarks)}</span></div>` : ''}
+</div>
+<table><thead><tr><th>搴忓彿</th><th>浜у搧鍚嶇О / 瑙勬牸鍨嬪彿</th><th>鍗曚綅</th><th>鏁伴噺</th><th>鍚◣鍗曚环</th><th>鍚◣鎬讳环</th><th>绋庣巼</th><th>鍙戠エ绫诲瀷</th></tr></thead><tbody>
+${productRows(products)}
+</tbody></table>
+<div class="summary">
+ <div>涓嶅惈绋庡悎璁★細<strong>${fmtMoney(totalNoTax)}</strong></div>
+ <div>鍚◣鍚堣锛堝ぇ鍐欙級锛�<span class="cn">${digitUppercase(total)}</span></div>
+ <div>鍚◣鍚堣锛堝皬鍐欙級锛�<strong>楼${fmtMoney(total)}</strong></div>
+ <div>鍚堝悓閲戦锛堝ぇ鍐欙級锛�<span class="cn">${digitUppercase(contractAmount)}</span></div>
+ <div>鍚堝悓閲戦锛堝皬鍐欙級锛�<strong>楼${fmtMoney(contractAmount)}</strong></div>
+</div>
+${printScript}
+</body></html>`
+}
+
+export function buildSalesDocument(companyName, ledger) {
+ return buildSalesHtml(companyName, ledger, false)
+}
+
+export function buildPurchaseDocument(companyName, ledger, products) {
+ return buildPurchaseHtml(companyName, ledger, products, false)
+}
+
+function buildSalesPrintHtml(companyName, ledger) {
+ return buildSalesHtml(companyName, ledger, true)
+}
+
+function buildPurchasePrintHtml(companyName, ledger, products) {
+ return buildPurchaseHtml(companyName, ledger, products, true)
+}
+
+export function openPrintWindow(html) {
+ const w = window.open('', '_blank', 'width=900,height=700')
+ if (!w) return
+ w.document.write(html)
+ w.document.close()
+}
+
+export async function downloadAsJpg(html, filename) {
+ const iframe = document.createElement('iframe')
+ iframe.style.position = 'fixed'
+ iframe.style.left = '0'
+ iframe.style.top = '0'
+ iframe.style.width = '900px'
+ iframe.style.height = '600px'
+ iframe.style.opacity = '0'
+ iframe.style.pointerEvents = 'none'
+ iframe.style.zIndex = '99999'
+ document.body.appendChild(iframe)
+
+ return new Promise((resolve, reject) => {
+ const iframeDoc = iframe.contentDocument || iframe.contentWindow.document
+ iframeDoc.open()
+ iframeDoc.write(html)
+ iframeDoc.close()
+
+ const doCapture = async () => {
+ try {
+ const body = iframeDoc.body
+ iframe.style.height = Math.max(body.scrollHeight, 600) + 'px'
+ await new Promise(r => setTimeout(r, 100))
+ const canvas = await html2canvas(body, {
+ scale: 2,
+ useCORS: true,
+ backgroundColor: '#ffffff',
+ windowWidth: 900
+ })
+ document.body.removeChild(iframe)
+ canvas.toBlob(blob => {
+ const url = URL.createObjectURL(blob)
+ const a = document.createElement('a')
+ a.href = url
+ a.download = filename
+ a.click()
+ URL.revokeObjectURL(url)
+ resolve()
+ }, 'image/jpeg', 0.95)
+ } catch (e) {
+ document.body.removeChild(iframe)
+ reject(e)
+ }
+ }
+
+ iframe.onload = () => setTimeout(doCapture, 300)
+ setTimeout(doCapture, 1000)
+ })
+}
+
+export function downloadSalesJpg(companyName, ledger, filename) {
+ const html = buildSalesHtml(companyName, ledger, false)
+ return downloadAsJpg(html, filename)
+}
+
+export function downloadPurchaseJpg(companyName, ledger, products, filename) {
+ const html = buildPurchaseHtml(companyName, ledger, products, false)
+ return downloadAsJpg(html, filename)
+}
+
+export function printSales(companyName, ledger) {
+ const html = buildSalesPrintHtml(companyName, ledger)
+ openPrintWindow(html)
+}
+
+export function printPurchase(companyName, ledger, products) {
+ const html = buildPurchasePrintHtml(companyName, ledger, products)
+ openPrintWindow(html)
+}
+
+export function printSalesMulti(companyName, orders) {
+ let bodies = ''
+ orders.forEach((ledger, i) => {
+ const html = buildSalesHtml(companyName, ledger, true)
+ const bodyMatch = html.match(/<body>([\s\S]*)<\/body>/)
+ if (bodyMatch) {
+ const body = bodyMatch[1].replace(/<script>[\s\S]*?<\/script>/g, '')
+ bodies += '<div class="print-page' + (i < orders.length - 1 ? ' page-break' : '') + '">' + body + '</div>'
+ }
+ })
+ const combined = `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8">
+<title>閿�鍞崟 - ${esc(companyName)}</title>
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:"Microsoft YaHei","SimSun",sans-serif;padding:20px 36px;color:#333;background:#fff}
+.toolbar{text-align:center;margin-bottom:20px}
+.toolbar button{padding:6px 24px;font-size:14px;cursor:pointer;background:#1890ff;color:#fff;border:none;border-radius:4px}
+.toolbar button:hover{background:#40a9ff}
+${coreCss()}
+.print-page{page-break-inside:avoid}
+.page-break{page-break-after:always}
+@media print{body{padding:15px 24px}.toolbar{display:none}}
+</style></head><body>
+<div class="toolbar"><button onclick="window.print()">鎵撳嵃鍏ㄩ儴 (鍏�${orders.length}浠�)</button></div>
+${bodies}
+<script>window.onload=function(){setTimeout(function(){window.print();},300);};<\/script>
+</body></html>`
+ openPrintWindow(combined)
+}
+
+export function printPurchaseMulti(companyName, orders) {
+ let bodies = ''
+ orders.forEach((item, i) => {
+ const html = buildPurchaseHtml(companyName, item.ledger, item.products, true)
+ const bodyMatch = html.match(/<body>([\s\S]*)<\/body>/)
+ if (bodyMatch) {
+ const body = bodyMatch[1].replace(/<script>[\s\S]*?<\/script>/g, '')
+ bodies += '<div class="print-page' + (i < orders.length - 1 ? ' page-break' : '') + '">' + body + '</div>'
+ }
+ })
+ const combined = `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8">
+<title>閲囪喘鍗� - ${esc(companyName)}</title>
+<style>
+*{margin:0;padding:0;box-sizing:border-box}
+body{font-family:"Microsoft YaHei","SimSun",sans-serif;padding:20px 36px;color:#333;background:#fff}
+.toolbar{text-align:center;margin-bottom:20px}
+.toolbar button{padding:6px 24px;font-size:14px;cursor:pointer;background:#1890ff;color:#fff;border:none;border-radius:4px}
+.toolbar button:hover{background:#40a9ff}
+${coreCss()}
+.print-page{page-break-inside:avoid}
+.page-break{page-break-after:always}
+@media print{body{padding:15px 24px}.toolbar{display:none}}
+</style></head><body>
+<div class="toolbar"><button onclick="window.print()">鎵撳嵃鍏ㄩ儴 (鍏�${orders.length}浠�)</button></div>
+${bodies}
+<script>window.onload=function(){setTimeout(function(){window.print();},300);};<\/script>
+</body></html>`
+ openPrintWindow(combined)
+}
diff --git a/src/utils/numberFormat.js b/src/utils/numberFormat.js
new file mode 100644
index 0000000..50175f0
--- /dev/null
+++ b/src/utils/numberFormat.js
@@ -0,0 +1,47 @@
+/** 閲戦绫诲瓧娈甸粯璁ゆ渶澶у皬鏁颁綅鏁� */
+export const AMOUNT_DECIMAL_SCALE = 6
+
+/**
+ * 鏍煎紡鍖栨暟瀛楋細鏈�澶氫繚鐣� scale 浣嶅皬鏁帮紝骞跺幓闄ゆ湯灏惧浣欑殑 0
+ */
+export function formatDecimal(value, scale = AMOUNT_DECIMAL_SCALE, fallback = '0') {
+ if (value === null || value === undefined || value === '') {
+ return fallback
+ }
+ const num = Number(value)
+ if (Number.isNaN(num)) {
+ return fallback
+ }
+ return parseFloat(num.toFixed(scale)).toString()
+}
+
+/** 甯﹁揣甯佺鍙风殑閲戦灞曠ず */
+export function formatCurrency(value, scale = AMOUNT_DECIMAL_SCALE) {
+ return `楼${formatDecimal(value, scale)}`
+}
+
+/** el-table-column formatter */
+export function tableAmountFormatter(row, column, cellValue) {
+ return formatDecimal(cellValue)
+}
+
+/** 璁$畻鍚庝繚鐣欐寚瀹氫綅灏忔暟 */
+export function roundAmount(value, scale = AMOUNT_DECIMAL_SCALE) {
+ if (value === null || value === undefined || value === '') {
+ return 0
+ }
+ const num = Number(value)
+ if (Number.isNaN(num)) {
+ return 0
+ }
+ return parseFloat(num.toFixed(scale))
+}
+
+/** 鏋勫缓 summarizeTable 閲戦鍒楁牸寮忛厤缃� */
+export function buildAmountSummaryFormat(fields, extraFormat = {}) {
+ const format = { ...extraFormat }
+ fields.forEach(field => {
+ format[field] = { decimalPlaces: AMOUNT_DECIMAL_SCALE }
+ })
+ return format
+}
diff --git a/src/utils/summarizeTable.js b/src/utils/summarizeTable.js
index 1ad480d..3602523 100644
--- a/src/utils/summarizeTable.js
+++ b/src/utils/summarizeTable.js
@@ -1,3 +1,5 @@
+import { formatDecimal, AMOUNT_DECIMAL_SCALE } from './numberFormat'
+
/**
* 閫氱敤鐨勮〃鏍煎悎璁℃柟娉�
* @param {Object} param - 鍖呭惈琛ㄦ牸鍒楅厤缃拰鏁版嵁婧愮殑瀵硅薄
@@ -26,28 +28,35 @@
// 濡傛灉鎸囧畾浜嗕笉闇�瑕佷繚鐣欏皬鏁帮紝鍒欑洿鎺ヨ浆鎹负鏁存暟
sums[index] = Math.round(sum).toString();
} else {
- // 榛樿淇濈暀涓や綅灏忔暟
- sums[index] = parseFloat(sum).toFixed(
+ sums[index] = formatDecimal(
+ sum,
specialFormat[prop]?.decimalPlaces ?? 2
);
}
} else {
- sums[index] = "";
+ sums[index] = '';
}
} else {
- sums[index] = "";
+ sums[index] = '';
}
});
return sums;
};
+
// 涓嶅惈绋庢�讳环璁$畻
const calculateTaxExclusiveTotalPrice = (taxInclusiveTotalPrice, taxRate) => {
const taxRateDecimal = taxRate / 100;
- return (taxInclusiveTotalPrice / (1 + taxRateDecimal)).toFixed(2);
+ return formatDecimal(
+ Number(taxInclusiveTotalPrice) / (1 + taxRateDecimal),
+ AMOUNT_DECIMAL_SCALE
+ );
};
// 鍚◣鎬讳环璁$畻
const calculateTaxIncludeTotalPrice = (taxInclusiveUnitPrice, quantity) => {
- return (taxInclusiveUnitPrice * quantity).toFixed(2);
+ return formatDecimal(
+ Number(taxInclusiveUnitPrice) * Number(quantity),
+ AMOUNT_DECIMAL_SCALE
+ );
};
// 瀵煎嚭鍑芥暟渚涘叾浠栨枃浠朵娇鐢�
export {
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index c565a69..f0f7c4d 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -1,6 +1,7 @@
<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.customerName"
@@ -17,8 +18,8 @@
@change="handleQuery">
<el-option label="闆跺敭瀹㈡埛"
value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="缁忛攢鍟嗗鎴�"
+ value="缁忛攢鍟嗗鎴�" />
</el-select>
<el-button type="primary"
@click="handleQuery"
@@ -130,8 +131,8 @@
clearable>
<el-option label="闆跺敭瀹㈡埛"
value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="缁忛攢鍟嗗鎴�"
+ value="缁忛攢鍟嗗鎴�" />
</el-select>
</el-form-item>
</el-col>
@@ -280,7 +281,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitReminderForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitReminderForm">纭</el-button>
<el-button @click="closeReminderDialog">鍙栨秷</el-button>
</div>
</template>
@@ -363,7 +365,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitNegotiationForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitNegotiationForm">纭</el-button>
<el-button @click="closeNegotiationDialog">鍙栨秷</el-button>
</div>
</template>
@@ -412,14 +415,14 @@
<span class="info-value">{{ detailForm.companyAddress }}</span>
</div>
</el-col>
- <el-col :span="12">
+ <!-- <el-col :span="12">
<div class="info-item">
<span class="info-label">閾惰鍩烘湰鎴凤細</span>
<span class="info-value">{{ detailForm.basicBankAccount }}</span>
</div>
- </el-col>
+ </el-col> -->
</el-row>
- <el-row :gutter="20">
+ <!-- <el-row :gutter="20">
<el-col :span="12">
<div class="info-item">
<span class="info-label">閾惰璐﹀彿锛�</span>
@@ -432,7 +435,7 @@
<span class="info-value">{{ detailForm.bankCode }}</span>
</div>
</el-col>
- </el-row>
+ </el-row> -->
<el-row :gutter="20">
<el-col :span="12">
<div class="info-item">
@@ -464,14 +467,9 @@
</div>
</div>
<!-- 娲借皥杩涘害璁板綍 -->
- <div class="detail-section">
+ <!-- <div class="detail-section">
<div class="section-header">
<h3 class="section-title">娲借皥杩涘害璁板綍</h3>
- <el-button type="primary"
- size="small"
- @click="openNegotiationDialog(detailForm)">
- 娣诲姞杩涘害
- </el-button>
</div>
<el-table :data="negotiationRecords"
border
@@ -501,7 +499,6 @@
<Paperclip />
</el-icon>
闄勪欢
- <!-- {{ row.fileList && row.fileList.length > 0 ? row.fileList.length : '涓婁紶' }} -->
</el-button>
</template>
</el-table-column>
@@ -526,7 +523,7 @@
class="no-records">
鏆傛棤娲借皥杩涘害璁板綍
</div>
- </div>
+ </div> -->
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDetailDialog">鍏抽棴</el-button>
@@ -622,7 +619,14 @@
addReturnVisit,
getReturnVisit,
} from "@/api/basicData/customerFile.js";
- import {listCustomer, getCustomer, addCustomer, updateCustomer, delCustomer, backCustomer} from "@/api/basicData/customer.js";
+ import {
+ listCustomer,
+ getCustomer,
+ addCustomer,
+ updateCustomer,
+ delCustomer,
+ backCustomer,
+ } from "@/api/basicData/customer.js";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import useUserStore from "@/store/modules/user";
@@ -654,7 +658,7 @@
const negotiationFormRef = ref();
const negotiationForm = reactive({
customerName: "",
- customerId: "",
+ customerId: "",
followUpMethod: "",
followUpLevel: "",
followUpTime: "",
@@ -738,16 +742,16 @@
prop: "contactPhone",
width: 150,
},
- {
- label: "璺熻繘杩涘害",
- prop: "followUpLevel",
- width: 120,
- },
- {
- label: "璺熻繘鏃堕棿",
- prop: "followUpTime",
- width: 120,
- },
+ // {
+ // label: "璺熻繘杩涘害",
+ // prop: "followUpLevel",
+ // width: 120,
+ // },
+ // {
+ // label: "璺熻繘鏃堕棿",
+ // prop: "followUpTime",
+ // width: 120,
+ // },
{
label: "閾惰鍩烘湰鎴�",
prop: "basicBankAccount",
@@ -767,7 +771,7 @@
label: "缁存姢浜�",
prop: "maintainer",
},
- {
+ /*{
label: "瀹㈡埛鏉ユ簮",
prop: "type",
dataType: "tag",
@@ -784,7 +788,7 @@
}
return "success";
},
- },
+ },*/
{
label: "缁存姢鏃堕棿",
prop: "maintenanceTime",
@@ -800,36 +804,31 @@
{
name: "缂栬緫",
type: "text",
- showHide: row => !isCustomerEditLocked(row),
clickFun: row => {
- if (isCustomerEditLocked(row)) {
- proxy.$modal.msgWarning("宸茶閿�鍞ā鍧楀紩鐢ㄧ殑绉佹捣瀹㈡埛涓嶈兘缂栬緫");
- return;
- }
openForm("edit", row);
},
},
- {
- name: "娣诲姞娲借皥杩涘害",
- type: "text",
- clickFun: row => {
- openNegotiationDialog(row);
- },
- },
+ // {
+ // name: "娣诲姞娲借皥杩涘害",
+ // type: "text",
+ // clickFun: row => {
+ // openNegotiationDialog(row);
+ // },
+ // },
+ // {
+ // name: "鍥炶鎻愰啋",
+ // type: "text",
+ // clickFun: row => {
+ // openReminderDialog(row);
+ // },
+ // },
{
- name: "鍥炶鎻愰啋",
+ name: "璇︽儏",
type: "text",
clickFun: row => {
- openReminderDialog(row);
+ openDetailDialog(row);
},
},
- {
- name: "璇︽儏",
- type: "text",
- clickFun: row => {
- openDetailDialog(row);
- },
- },
],
},
]);
@@ -860,7 +859,7 @@
searchForm: {
customerName: "",
customerType: "",
- type: 0
+ type: 0,
},
form: {
customerName: "",
@@ -875,7 +874,7 @@
bankAccount: "",
bankCode: "",
customerType: "",
- type: 0
+ type: 0,
},
rules: {
customerName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -908,7 +907,7 @@
// 涓婁紶鐨勫湴鍧�
url: import.meta.env.VITE_APP_BASE_API + "/basic/customer/importData",
data: {
- type: 0
+ type: 0,
},
// 鏂囦欢涓婁紶鍓嶇殑鍥炶皟
beforeUpload: file => {
@@ -1006,10 +1005,6 @@
}
// 鎵撳紑寮规
const openForm = (type, row) => {
- if (type === "edit" && isCustomerEditLocked(row)) {
- proxy.$modal.msgWarning("宸茶閿�鍞ā鍧楀紩鐢ㄧ殑绉佹捣瀹㈡埛涓嶈兘缂栬緫");
- return;
- }
operationType.value = type;
form.value = {};
form.value.maintainer = userStore.nickName;
@@ -1038,12 +1033,6 @@
});
}
dialogFormVisible.value = true;
- };
- const isCustomerEditLocked = row => {
- const salesReferenced = Number(row?.salesReferenceFlag || 0) === 1;
- const customerType = Number(row?.type);
- const usageStatus = Number(row?.usageStatus || 0);
- return salesReferenced && (customerType === 0 || (customerType === 1 && usageStatus === 1));
};
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
@@ -1101,7 +1090,7 @@
type: "warning",
})
.then(() => {
- proxy.download("/basic/customer/export", {type: 0}, "瀹㈡埛妗f.xlsx");
+ proxy.download("/basic/customer/export", { type: 0 }, "瀹㈡埛妗f.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
@@ -1214,7 +1203,7 @@
if (reminderForm.id) {
submitvalue.value = {
id: reminderForm.id,
- customerId: currentCustomerId.value,
+ customerId: currentCustomerId.value,
isEnabled: reminderForm.reminderSwitch ? 1 : 0,
content: reminderForm.reminderContent,
reminderTime: reminderForm.reminderTime,
@@ -1333,7 +1322,7 @@
// 灏嗗綋鍓嶈褰曟暟鎹~鍏呭埌琛ㄥ崟
Object.assign(negotiationForm, {
customerName: row.customerName,
- customerId: row.customerId,
+ customerId: row.customerId,
followUpMethod: row.followUpMethod,
followUpLevel: row.followUpLevel,
followUpTime: row.followUpTime,
@@ -1461,7 +1450,7 @@
const downloadAttachment = row => {
if (row.url) {
// proxy.download(row.url, {}, row.name);
- proxy.$download.byUrl(row.url, row.originalFilename);
+ proxy.$download.byUrl(row.url, row.originalFilename);
} else {
proxy.$modal.msgError("涓嬭浇閾炬帴涓嶅瓨鍦�");
}
diff --git a/src/views/basicData/customerFileOpenSea/index.vue b/src/views/basicData/customerFileOpenSea/index.vue
index f36ce02..23d192b 100644
--- a/src/views/basicData/customerFileOpenSea/index.vue
+++ b/src/views/basicData/customerFileOpenSea/index.vue
@@ -1,6 +1,7 @@
<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.customerName"
@@ -17,8 +18,8 @@
@change="handleQuery">
<el-option label="闆跺敭瀹㈡埛"
value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="缁忛攢鍟嗗鎴�"
+ value="缁忛攢鍟嗗鎴�" />
</el-select>
<el-button type="primary"
@click="handleQuery"
@@ -92,7 +93,7 @@
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30">
+ <!-- <el-row :gutter="30">
<el-col :span="12">
<el-form-item label="閾惰鍩烘湰鎴凤細"
prop="basicBankAccount">
@@ -109,16 +110,16 @@
clearable />
</el-form-item>
</el-col>
- </el-row>
+ </el-row> -->
<el-row :gutter="30">
- <el-col :span="12">
+ <!-- <el-col :span="12">
<el-form-item label="寮�鎴疯鍙凤細"
prop="bankCode">
<el-input v-model="form.bankCode"
placeholder="璇疯緭鍏�"
clearable />
</el-form-item>
- </el-col>
+ </el-col> -->
<el-col :span="12">
<el-form-item label="瀹㈡埛鍒嗙被锛�"
prop="customerType">
@@ -127,8 +128,8 @@
clearable>
<el-option label="闆跺敭瀹㈡埛"
value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="缁忛攢鍟嗗鎴�"
+ value="缁忛攢鍟嗗鎴�" />
</el-select>
</el-form-item>
</el-col>
@@ -199,75 +200,6 @@
<el-button type="primary"
@click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="assignDialogVisible"
- title="鍒嗛厤瀹㈡埛"
- width="500px"
- @close="closeAssignDialog">
- <el-form :model="assignForm"
- :rules="assignRules"
- ref="assignFormRef"
- label-width="100px">
- <el-form-item label="瀹㈡埛鍚嶇О">
- <el-input v-model="assignForm.customerName"
- disabled />
- </el-form-item>
- <el-form-item label="鍒嗛厤浜哄憳"
- prop="boundId">
- <el-select v-model="assignForm.boundId"
- placeholder="璇烽�夋嫨鍒嗛厤浜哄憳"
- style="width: 100%"
- filterable>
- <el-option v-for="item in userList"
- :key="item.userId || item.nickName"
- :label="item.nickName"
- :value="item.userId" />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitAssignForm">纭</el-button>
- <el-button @click="closeAssignDialog">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="shareDialogVisible"
- title="鍏变韩瀹㈡埛"
- width="500px"
- @close="closeShareDialog">
- <el-form :model="shareForm"
- :rules="shareRules"
- ref="shareFormRef"
- label-width="100px">
- <el-form-item label="瀹㈡埛鍚嶇О">
- <el-input v-model="shareForm.customerName"
- disabled />
- </el-form-item>
- <el-form-item label="鍏变韩浜哄憳"
- prop="boundIds">
- <el-select v-model="shareForm.boundIds"
- placeholder="璇烽�夋嫨鍏变韩浜哄憳"
- style="width: 100%"
- filterable
- multiple
- collapse-tags
- collapse-tags-tooltip>
- <el-option v-for="item in userList"
- :key="item.userId || item.nickName"
- :label="item.nickName"
- :value="item.userId" />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitShareForm">纭</el-button>
- <el-button @click="closeShareDialog">鍙栨秷</el-button>
</div>
</template>
</el-dialog>
@@ -346,7 +278,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitReminderForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitReminderForm">纭</el-button>
<el-button @click="closeReminderDialog">鍙栨秷</el-button>
</div>
</template>
@@ -429,7 +362,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitNegotiationForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitNegotiationForm">纭</el-button>
<el-button @click="closeNegotiationDialog">鍙栨秷</el-button>
</div>
</template>
@@ -478,14 +412,14 @@
<span class="info-value">{{ detailForm.companyAddress }}</span>
</div>
</el-col>
- <el-col :span="12">
+ <!-- <el-col :span="12">
<div class="info-item">
<span class="info-label">閾惰鍩烘湰鎴凤細</span>
<span class="info-value">{{ detailForm.basicBankAccount }}</span>
</div>
- </el-col>
+ </el-col> -->
</el-row>
- <el-row :gutter="20">
+ <!-- <el-row :gutter="20">
<el-col :span="12">
<div class="info-item">
<span class="info-label">閾惰璐﹀彿锛�</span>
@@ -498,7 +432,7 @@
<span class="info-value">{{ detailForm.bankCode }}</span>
</div>
</el-col>
- </el-row>
+ </el-row> -->
<el-row :gutter="20">
<el-col :span="12">
<div class="info-item">
@@ -530,14 +464,9 @@
</div>
</div>
<!-- 娲借皥杩涘害璁板綍 -->
- <div class="detail-section">
+ <!-- <div class="detail-section">
<div class="section-header">
<h3 class="section-title">娲借皥杩涘害璁板綍</h3>
- <el-button type="primary"
- size="small"
- @click="openNegotiationDialog(detailForm)">
- 娣诲姞杩涘害
- </el-button>
</div>
<el-table :data="negotiationRecords"
border
@@ -567,7 +496,6 @@
<Paperclip />
</el-icon>
闄勪欢
- <!-- {{ row.fileList && row.fileList.length > 0 ? row.fileList.length : '涓婁紶' }} -->
</el-button>
</template>
</el-table-column>
@@ -592,7 +520,7 @@
class="no-records">
鏆傛棤娲借皥杩涘害璁板綍
</div>
- </div>
+ </div> -->
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDetailDialog">鍏抽棴</el-button>
@@ -690,41 +618,17 @@
} from "@/api/basicData/customerFile.js";
import {
listCustomer,
- addCustomer,
- delCustomer,
- updateCustomer,
getCustomer,
- assignCustomer,
- recycleCustomer,
- shareCustomer,
+ addCustomer,
+ updateCustomer,
+ delCustomer,
} from "@/api/basicData/customer.js";
-
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
- const assignDialogVisible = ref(false);
- const assignFormRef = ref();
- const assignForm = reactive({
- id: undefined,
- customerName: "",
- boundId: undefined,
- });
- const assignRules = {
- boundId: [{ required: true, message: "璇烽�夋嫨鍒嗛厤浜哄憳", trigger: "change" }],
- };
- const shareDialogVisible = ref(false);
- const shareFormRef = ref();
- const shareForm = reactive({
- id: undefined,
- customerName: "",
- boundIds: [],
- });
- const shareRules = {
- boundIds: [{ required: true, message: "璇烽�夋嫨鍏变韩浜哄憳", trigger: "change" }],
- };
// 鍥炶鎻愰啋鐩稿叧
const reminderDialogVisible = ref(false);
@@ -822,7 +726,7 @@
},
{
label: "鍦板潃鍙婅仈绯绘柟寮�",
- prop: "addressPhone",
+ prop: "companyAddress",
width: 250,
},
{
@@ -844,116 +748,65 @@
// prop: "followUpTime",
// width: 120,
// },
- {
- label: "閾惰鍩烘湰鎴�",
- prop: "basicBankAccount",
- width: 220,
- },
- {
- label: "閾惰璐﹀彿",
- prop: "bankAccount",
- width: 220,
- },
- {
- label: "寮�鎴疯鍙�",
- prop: "bankCode",
- width: 220,
- },
+ // {
+ // label: "閾惰鍩烘湰鎴�",
+ // prop: "basicBankAccount",
+ // width: 220,
+ // },
+ // {
+ // label: "閾惰璐﹀彿",
+ // prop: "bankAccount",
+ // width: 220,
+ // },
+ // {
+ // label: "寮�鎴疯鍙�",
+ // prop: "bankCode",
+ // width: 220,
+ // },
{
label: "缁存姢浜�",
prop: "maintainer",
},
- {
- label: "缁存姢鏃堕棿",
- prop: "maintenanceTime",
- width: 100,
- },
{
- label: "棰嗙敤浜�",
- prop: "usageUserName",
- width: 120,
- fixed: "right",
- },
- {
- label: "棰嗙敤鐘舵��",
- prop: "usageStatus",
- dataType: "tag",
+ label: "缁存姢鏃堕棿",
+ prop: "maintenanceTime",
width: 100,
- fixed: "right",
- formatData: value => {
- if (value === 1 || value === "1") {
- return "宸查鐢�";
- }
- return "鏈鐢�";
- },
- formatType: value => {
- if (value === 1 || value === "1") {
- return "success";
- }
- return "info";
- },
},
- {
- label: "鍏变韩浜�",
- prop: "togetherUserNames",
- width: 120,
- fixed: "right",
- },
{
dataType: "action",
label: "鎿嶄綔",
align: "center",
fixed: "right",
- width: 200,
+ width: 140,
operation: [
{
- name: "鍒嗛厤",
+ name: "缂栬緫",
type: "text",
- showHide: row => row.usageStatus != 1,
clickFun: row => {
- openAssignDialog(row);
+ openForm("edit", row);
},
},
- {
- name: "鍥炴敹",
- type: "text",
- disabled: row => isCustomerRecoveryLocked(row),
- showHide: row => row.usageStatus == 1,
- clickFun: row => {
- if (isCustomerRecoveryLocked(row)) {
- proxy.$modal.msgWarning("宸查鐢ㄥ苟涓旇閿�鍞ā鍧楀紩鐢ㄧ殑鍏捣瀹㈡埛涓嶈兘鍥炴敹");
- return;
- }
- recycle(row);
- },
- },
- {
- name: "鍏变韩",
- type: "text",
- showHide: row => row.usageStatus == 1,
- clickFun: row => {
- openShareDialog(row);
- },
- },
- {
- name: "缂栬緫",
- type: "text",
- disabled: row => isCustomerEditLocked(row),
- clickFun: row => {
- if (isCustomerEditLocked(row)) {
- proxy.$modal.msgWarning("宸查鐢ㄥ苟涓旇閿�鍞ā鍧楀紩鐢ㄧ殑鍏捣瀹㈡埛涓嶈兘缂栬緫");
- return;
- }
- openForm("edit", row);
- },
- },
// {
- // name: "璇︽儏",
+ // name: "娣诲姞娲借皥杩涘害",
// type: "text",
// clickFun: row => {
- // openDetailDialog(row);
+ // openNegotiationDialog(row);
// },
// },
+ // {
+ // name: "鍥炶鎻愰啋",
+ // type: "text",
+ // clickFun: row => {
+ // openReminderDialog(row);
+ // },
+ // },
+ {
+ name: "璇︽儏",
+ type: "text",
+ clickFun: row => {
+ openDetailDialog(row);
+ },
+ },
],
},
]);
@@ -984,7 +837,6 @@
searchForm: {
customerName: "",
customerType: "",
- type: 1
},
form: {
customerName: "",
@@ -999,15 +851,14 @@
bankAccount: "",
bankCode: "",
customerType: "",
- type: 1
},
rules: {
customerName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // taxpayerIdentificationNumber: [
+ // { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ // ],
+ // companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
// contactPerson: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
// contactPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
@@ -1031,9 +882,7 @@
headers: { Authorization: "Bearer " + getToken() },
// 涓婁紶鐨勫湴鍧�
url: import.meta.env.VITE_APP_BASE_API + "/basic/customer/importData",
- data: {
- type: 1
- },
+ data: {},
// 鏂囦欢涓婁紶鍓嶇殑鍥炶皟
beforeUpload: file => {
console.log("鏂囦欢鍗冲皢涓婁紶", file);
@@ -1104,8 +953,7 @@
};
const getList = () => {
tableLoading.value = true;
- const { total, ...queryPage } = page;
- listCustomer({ ...searchForm.value, ...queryPage }).then(res => {
+ listCustomer({ ...searchForm.value, ...page }).then(res => {
tableLoading.value = false;
tableData.value = res.data.records;
page.total = res.data.total;
@@ -1131,10 +979,6 @@
}
// 鎵撳紑寮规
const openForm = (type, row) => {
- if (type === "edit" && isCustomerEditLocked(row)) {
- proxy.$modal.msgWarning("宸查鐢ㄥ苟涓旇閿�鍞ā鍧楀紩鐢ㄧ殑鍏捣瀹㈡埛涓嶈兘缂栬緫");
- return;
- }
operationType.value = type;
form.value = {};
form.value.maintainer = userStore.nickName;
@@ -1145,7 +989,6 @@
},
];
form.value.maintenanceTime = getCurrentDate();
- form.value.type = 1;
userListNoPage().then(res => {
userList.value = res.data;
});
@@ -1164,11 +1007,6 @@
}
dialogFormVisible.value = true;
};
- const isCustomerSalesReferenced = row => Number(row?.salesReferenceFlag || 0) === 1;
- const isCustomerRecoveryLocked = row => Number(row?.usageStatus || 0) === 1 && isCustomerSalesReferenced(row);
- const isCustomerEditLocked = row => isCustomerSalesReferenced(row) && (
- Number(row?.type) === 0 || (Number(row?.type) === 1 && Number(row?.usageStatus || 0) === 1)
- );
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
proxy.$refs["formRef"].validate(valid => {
@@ -1217,92 +1055,6 @@
proxy.resetForm("formRef");
dialogFormVisible.value = false;
};
- const ensureUserList = () => {
- if (userList.value.length) {
- return Promise.resolve();
- }
- return userListNoPage().then(res => {
- userList.value = res.data || [];
- });
- };
- const openAssignDialog = row => {
- assignForm.id = row.id;
- assignForm.customerName = row.customerName;
- assignForm.boundId = undefined;
- ensureUserList().then(() => {
- assignDialogVisible.value = true;
- });
- };
- const closeAssignDialog = () => {
- proxy.resetForm("assignFormRef");
- assignForm.id = undefined;
- assignForm.customerName = "";
- assignForm.boundId = undefined;
- assignDialogVisible.value = false;
- };
- const openShareDialog = row => {
- shareForm.id = row.id;
- shareForm.customerName = row.customerName;
- shareForm.boundIds = row.userIds || [];
- ensureUserList().then(() => {
- shareDialogVisible.value = true;
- });
- };
- const closeShareDialog = () => {
- proxy.resetForm("shareFormRef");
- shareForm.id = undefined;
- shareForm.customerName = "";
- shareForm.boundIds = [];
- shareDialogVisible.value = false;
- };
- const submitAssignForm = () => {
- proxy.$refs.assignFormRef.validate(valid => {
- if (!valid) {
- return;
- }
- assignCustomer({
- id: assignForm.id,
- usageUser: assignForm.boundId,
- }).then(() => {
- proxy.$modal.msgSuccess("鍒嗛厤鎴愬姛");
- closeAssignDialog();
- getList();
- });
- });
- };
- const submitShareForm = () => {
- proxy.$refs.shareFormRef.validate(valid => {
- if (!valid) {
- return;
- }
- shareCustomer({
- id: shareForm.id,
- userIds: shareForm.boundIds,
- }).then(() => {
- proxy.$modal.msgSuccess("鍏变韩鎴愬姛");
- closeShareDialog();
- getList();
- });
- });
- };
- const recycle = row => {
- ElMessageBox.confirm("纭鍥炴敹瀹㈡埛鈥�" + row.customerName + "鈥濆悧锛�", "鍥炴敹鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- return recycleCustomer({id: row.id}).then(() => {
- proxy.$modal.msgSuccess("鍥炴敹鎴愬姛");
- getList();
- })
- })
- .catch(error => {
- if (error === "cancel" || error === "close") {
- proxy.$modal.msg("宸插彇娑�");
- }
- });
- };
// 瀵煎嚭
const handleOut = () => {
ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
@@ -1311,7 +1063,7 @@
type: "warning",
})
.then(() => {
- proxy.download("/basic/customer/export", {type: 1}, "瀹㈡埛妗f.xlsx");
+ proxy.download("/basic/customer/export", {}, "瀹㈡埛妗f.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
@@ -1321,14 +1073,6 @@
const handleDelete = () => {
let ids = [];
if (selectedRows.value.length > 0) {
- // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
- const unauthorizedData = selectedRows.value.filter(
- item => item.maintainer !== userStore.nickName
- );
- if (unauthorizedData.length > 0) {
- proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
- return;
- }
ids = selectedRows.value.map(item => item.id);
} else {
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
@@ -1342,7 +1086,7 @@
.then(() => {
tableLoading.value = true;
delCustomer(ids)
- .then(res => {
+ .then(() => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
})
@@ -1411,8 +1155,6 @@
};
}
- console.log("鎻愪氦鍥炶鎻愰啋鏁版嵁:", submitvalue.value);
-
// 璋冪敤鎺ュ彛
addReturnVisit(submitvalue.value)
.then(res => {
@@ -1440,14 +1182,6 @@
negotiationForm.followUpTime = "";
negotiationForm.followerUserName = userStore.nickName; // 榛樿褰撳墠鐧诲綍浜�
negotiationForm.content = "";
- // {
- // "customerId": 152,
- // "followUpMethod": "鐢佃瘽娌熼��",
- // "followUpLevel": "娌℃湁鎰忓悜",
- // "followUpTime": "2026-03-04T15:30:00",
- // "followerUserName": "绠$悊鍛樿处鍙�",
- // "content": "111"
- // }
negotiationDialogVisible.value = true;
};
@@ -1469,23 +1203,6 @@
if (isEdit) {
// 淇敼鎿嶄綔
- console.log("淇敼娲借皥杩涘害鏁版嵁:", negotiationForm);
- // 杩欓噷鍙互璋冪敤鏇存柊鎺ュ彛
- // 瀹為檯椤圭洰涓渶瑕佹牴鎹悗绔帴鍙h繘琛岃皟鏁�
- // 绀轰緥锛歶pdateCustomerFollow(negotiationForm).then(res => {
- // // 鏇存柊鏈湴鏁版嵁
- // const index = negotiationForm.editIndex;
- // negotiationRecords.value[index] = {
- // followUpTime: negotiationForm.followUpTime,
- // followUpMethod: negotiationForm.followUpMethod,
- // followUpLevel: negotiationForm.followUpLevel,
- // followerUserName: negotiationForm.followerUserName,
- // content: negotiationForm.content,
- // id: negotiationForm.id,
- // };
- // proxy.$modal.msgSuccess("淇敼鎴愬姛");
- // closeNegotiationDialog();
- // });
updateCustomerFollow(negotiationForm).then(res => {
// 鏇存柊鏈湴鏁版嵁
getCustomer(negotiationForm.customerId).then(res => {
@@ -1520,7 +1237,6 @@
// 鎵撳紑璇︽儏寮圭獥
const openDetailDialog = row => {
- // 璋冪敤getCustomer鎺ュ彛鑾峰彇瀹㈡埛璇︽儏
getCustomer(row.id).then(res => {
// 濉厖瀹㈡埛鍩烘湰淇℃伅
Object.assign(detailForm, res.data);
@@ -1670,7 +1386,7 @@
const downloadAttachment = row => {
if (row.url) {
// proxy.download(row.url, {}, row.name);
- proxy.$download.byUrl(row.url, row.originalFilename);
+ proxy.$download.byUrl(row.url, row.originalFilename);
} else {
proxy.$modal.msgError("涓嬭浇閾炬帴涓嶅瓨鍦�");
}
diff --git a/src/views/basicData/parameterMaintenance/index.vue b/src/views/basicData/parameterMaintenance/index.vue
index 38ddd4f..7f9bfb0 100644
--- a/src/views/basicData/parameterMaintenance/index.vue
+++ b/src/views/basicData/parameterMaintenance/index.vue
@@ -50,7 +50,7 @@
prop="paramCode">
<el-input v-model="formData.paramCode"
disabled
- placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" />
+ placeholder="鑷姩鐢熸垚" />
</el-form-item>
<el-form-item label="鍙傛暟鍚嶇О"
prop="paramName">
@@ -82,14 +82,6 @@
value="2" />
</el-select>
</el-form-item> -->
- <el-form-item label="鍒涘缓鏃堕棿"
- prop="createTime">
- <el-date-picker v-model="formCreateTimeDate"
- type="date"
- placeholder="閫夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- style="width: 100%" />
- </el-form-item>
<el-form-item label="鍗曚綅"
prop="unit">
<el-input v-model="formData.unit"
@@ -215,8 +207,7 @@
</template>
<script setup>
- import { onMounted, ref, reactive, computed } from "vue";
- import dayjs from "dayjs";
+ import { onMounted, ref, reactive } from "vue";
import {
parameterListPage,
addParameter,
@@ -232,6 +223,7 @@
import { deptTreeSelect } from "@/api/system/user.js";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { ElMessage, ElMessageBox } from "element-plus";
+ import { parseTime } from "@/utils/ruoyi";
const tableColumn = ref([
{
@@ -302,6 +294,10 @@
{
label: "鍒涘缓鏃堕棿",
prop: "createTime",
+ formatData: val => {
+ if (!val) return "";
+ return parseTime(val, "{y}-{m}-{d} {h}:{i}:{s}");
+ },
},
{
label: "鎿嶄綔",
@@ -350,7 +346,6 @@
remark: "",
isRequired: 0,
paramFormat: "",
- createTime: "",
});
const rules = reactive({
paramName: [{ required: true, message: "璇疯緭鍏ュ弬鏁板悕绉�", trigger: "blur" }],
@@ -370,12 +365,6 @@
},
},
],
- });
- const formCreateTimeDate = computed({
- get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""),
- set: (value) => {
- formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
// const productTypes = ref([]);
const isEdit = ref(false);
@@ -535,7 +524,6 @@
formData.unit = "";
formData.remark = "";
formData.isRequired = 0;
- formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
dialogVisible.value = true;
};
@@ -554,7 +542,6 @@
formData.remark = row.remark || "";
formData.paramFormat = row.paramFormat || "";
formData.isRequired = row.isRequired || 0;
- formData.createTime = row.createTime || "";
dialogVisible.value = true;
};
diff --git a/src/views/basicData/product/ProductSelectDialog.vue b/src/views/basicData/product/ProductSelectDialog.vue
index ad27baa..590f8ca 100644
--- a/src/views/basicData/product/ProductSelectDialog.vue
+++ b/src/views/basicData/product/ProductSelectDialog.vue
@@ -2,11 +2,11 @@
<el-dialog v-model="visible" title="閫夋嫨浜у搧" width="900px" destroy-on-close :close-on-click-modal="false">
<el-form :inline="true" :model="query" class="mb-2">
<el-form-item label="浜у搧鍚嶇О">
- <el-input v-model="query.productName" placeholder="杈撳叆浜у搧鍚嶇О" clearable @keyup.enter="onSearch" />
+ <el-input v-model="query.productName" placeholder="杈撳叆浜у搧鍚嶇О" clearable @keyup.enter="onSearch" style="width: 200px" />
</el-form-item>
<el-form-item label="浜у搧鍨嬪彿">
- <el-input v-model="query.model" placeholder="杈撳叆浜у搧鍨嬪彿" clearable @keyup.enter="onSearch" />
+ <el-input v-model="query.model" placeholder="杈撳叆浜у搧鍨嬪彿" clearable @keyup.enter="onSearch" style="width: 200px" />
</el-form-item>
<el-form-item>
@@ -20,9 +20,10 @@
@selection-change="handleSelectionChange" @select="handleSelect">
<el-table-column type="selection" width="55" />
<el-table-column type="index" label="搴忓彿" width="60" />
- <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="160" />
- <el-table-column prop="model" label="浜у搧鍨嬪彿" min-width="200" />
- <el-table-column prop="unit" label="鍗曚綅" min-width="160" />
+ <el-table-column prop="topProductName" label="浜у搧澶х被" min-width="120" />
+ <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="140" />
+ <el-table-column prop="model" label="浜у搧鍨嬪彿" min-width="180" />
+ <el-table-column prop="unit" label="鍗曚綅" min-width="100" />
</el-table>
<div class="mt-3 flex justify-end">
diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index b05b215..15f817d 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -104,8 +104,10 @@
<el-form-item label="浜у搧鍚嶇О锛�"
prop="productName">
<el-input v-model="form.productName"
+ type="textarea"
+ resize="vertical"
placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
- maxlength="20"
+ maxlength="50"
show-word-limit
clearable
@keydown.enter.prevent />
@@ -132,17 +134,15 @@
:rules="modelRules"
ref="modelFormRef">
<el-row>
- <el-row>
- <el-col :span="24">
- <el-form-item label="浜у搧缂栧彿锛�"
- prop="productCode">
- <el-input v-model="modelForm.productCode"
- placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�"
- clearable
- @keydown.enter.prevent />
- </el-form-item>
- </el-col>
- </el-row>
+ <el-col :span="24">
+ <el-form-item label="浜у搧缂栧彿锛�"
+ prop="productCode">
+ <el-input v-model="modelForm.productCode"
+ placeholder="璇疯緭鍏ヤ骇鍝佺紪鍙�"
+ clearable
+ @keydown.enter.prevent />
+ </el-form-item>
+ </el-col>
<el-col :span="24">
<el-form-item label="瑙勬牸鍨嬪彿锛�"
prop="model">
@@ -335,7 +335,7 @@
rules: {
productName: [
{ required: true, message: "璇疯緭鍏�", trigger: "blur" },
- { max: 20, message: "浜у搧鍚嶇О涓嶈兘瓒呰繃20涓瓧绗�", trigger: "blur" },
+ { max: 50, message: "浜у搧鍚嶇О涓嶈兘瓒呰繃50涓瓧绗�", trigger: "blur" },
],
},
modelForm: {
diff --git a/src/views/basicData/supplierManage/components/BlacklistTab.vue b/src/views/basicData/supplierManage/components/BlacklistTab.vue
index 206ba62..9e5a75f 100644
--- a/src/views/basicData/supplierManage/components/BlacklistTab.vue
+++ b/src/views/basicData/supplierManage/components/BlacklistTab.vue
@@ -3,179 +3,126 @@
<div class="search_form">
<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>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- ></PIMTable>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"></PIMTable>
</div>
- <el-dialog
- v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板渚涘簲鍟嗕俊鎭�' : '缂栬緫渚涘簲鍟嗕俊鎭�'"
- width="70%"
- @close="closeDia"
- >
- <el-form
- :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef"
- >
+ <el-dialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板渚涘簲鍟嗕俊鎭�' : '缂栬緫渚涘簲鍟嗕俊鎭�'"
+ width="70%"
+ @close="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="supplierName">
- <el-input
- v-model="form.supplierName"
- placeholder="璇疯緭鍏�"
- clearable
- />
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細"
+ prop="supplierName">
+ <el-input v-model="form.supplierName"
+ placeholder="璇疯緭鍏�"
+ clearable />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item
- label="绾崇◣浜鸿瘑鍒彿锛�"
- prop="taxpayerIdentificationNum"
- >
- <el-input
- v-model="form.taxpayerIdentificationNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
+ <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�"
+ prop="taxpayerIdentificationNum">
+ <el-input v-model="form.taxpayerIdentificationNum"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍏徃鍦板潃锛�"
+ prop="companyAddress">
+ <el-input v-model="form.companyAddress"
+ placeholder="璇疯緭鍏�"
+ clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
- <el-input
- v-model="form.companyAddress"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍏徃鐢佃瘽锛�" prop="companyPhone">
- <el-input
- v-model="form.companyPhone"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�鎴疯锛�" prop="bankAccountName">
- <el-input
- v-model="form.bankAccountName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璐﹀彿锛�" prop="bankAccountNum">
- <el-input
- v-model="form.bankAccountNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細" prop="contactUserName">
- <el-input
- v-model="form.contactUserName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="contactUserPhone">
- <el-input
- v-model="form.contactUserPhone"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="缁存姢浜猴細" prop="maintainUserId">
- <el-select
- v-model="form.maintainUserId"
- placeholder="璇烽�夋嫨"
- clearable
- disabled
- >
- <el-option
- v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.userId"
- />
+ <el-form-item label="缁存姢浜猴細"
+ prop="maintainUserId">
+ <el-select v-model="form.maintainUserId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled>
+ <el-option v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="缁存姢鏃堕棿锛�" prop="maintainTime">
- <el-date-picker
- style="width: 100%"
- v-model="form.maintainTime"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- />
+ <el-form-item label="缁存姢鏃堕棿锛�"
+ prop="maintainTime">
+ <el-date-picker style="width: 100%"
+ v-model="form.maintainTime"
+ 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="12">
- <el-form-item label="渚涘簲鍟嗙被鍨嬶細" prop="supplierType">
- <el-select v-model="form.supplierType" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鐢�" value="鐢�" />
- <el-option label="涔�" value="涔�" />
- <el-option label="涓�" value="涓�" />
- <el-option label="涓�" value="涓�" />
+ <!-- <el-col :span="12">
+ <el-form-item label="渚涘簲鍟嗙被鍨嬶細"
+ prop="supplierType">
+ <el-select v-model="form.supplierType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="涔�"
+ value="涔�" />
+ <el-option label="涓�"
+ value="涓�" />
+ <el-option label="涓�"
+ value="涓�" />
</el-select>
</el-form-item>
- </el-col>
+ </el-col> -->
<el-col :span="12">
- <el-form-item label="鏄惁鐧藉悕鍗曪細" prop="isWhite">
- <el-select v-model="form.isWhite" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鏄�" :value="0" />
- <el-option label="鍚�" :value="1" />
+ <el-form-item label="鏄惁鐧藉悕鍗曪細"
+ prop="isWhite">
+ <el-select v-model="form.isWhite"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鏄�"
+ :value="0" />
+ <el-option label="鍚�"
+ :value="1" />
</el-select>
</el-form-item>
</el-col>
@@ -183,50 +130,44 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
</el-dialog>
-
<!-- 渚涘簲鍟嗗鍏ュ璇濇 -->
- <el-dialog
- :title="upload.title"
- v-model="upload.open"
- width="400px"
- append-to-body
- >
- <el-upload
- ref="uploadRef"
- :limit="1"
- accept=".xlsx, .xls"
- :headers="upload.headers"
- :action="upload.url + '?updateSupport=' + upload.updateSupport"
- :disabled="upload.isUploading"
- :on-progress="handleFileUploadProgress"
- :on-success="handleFileSuccess"
- :on-error="handleFileError"
- :auto-upload="false"
- drag
- >
+ <el-dialog :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body>
+ <el-upload ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :on-error="handleFileError"
+ :auto-upload="false"
+ drag>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
- <el-link
- type="primary"
- :underline="false"
- style="font-size: 12px; vertical-align: baseline"
- @click="importTemplate"
- >涓嬭浇妯℃澘</el-link
- >
+ <el-link type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline"
+ @click="importTemplate">涓嬭浇妯℃澘</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button type="primary"
+ @click="submitFileForm">纭� 瀹�</el-button>
<el-button @click="upload.open = false">鍙� 娑�</el-button>
</div>
</template>
@@ -239,352 +180,330 @@
</template>
<script setup>
-import { onMounted, ref } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { delSupplier } from "@/api/basicData/supplierManageFile.js";
-import { ElMessageBox } from "element-plus";
-import { userListNoPage } from "@/api/system/user.js";
-import {
- addSupplier,
- getSupplier,
- listSupplier,
- updateSupplier,
-} from "@/api/basicData/supplierManageFile.js";
-import useUserStore from "@/store/modules/user";
-import { getToken } from "@/utils/auth.js";
-const FileList = defineAsyncComponent(() =>
+ import { onMounted, ref } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import { delSupplier } from "@/api/basicData/supplierManageFile.js";
+ import { ElMessageBox } from "element-plus";
+ import { userListNoPage } from "@/api/system/user.js";
+ import {
+ addSupplier,
+ getSupplier,
+ listSupplier,
+ updateSupplier,
+ } from "@/api/basicData/supplierManageFile.js";
+ import useUserStore from "@/store/modules/user";
+ import { getToken } from "@/utils/auth.js";
+ const FileList = defineAsyncComponent(() =>
import("@/components/Dialog/FileList.vue")
-);
-const { proxy } = getCurrentInstance();
-const userStore = useUserStore();
+ );
+ const { proxy } = getCurrentInstance();
+ const userStore = useUserStore();
-const tableColumn = ref([
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
- width: 250,
- },
- {
- label: "渚涘簲鍟嗙被鍨�",
- prop: "supplierType",
- width: 120,
- },
- {
- label: "绾崇◣浜鸿瘑鍒彿",
- prop: "taxpayerIdentificationNum",
- width: 230,
- },
- {
- label: "鍏徃鍦板潃",
- prop: "companyAddress",
- width: 220,
- },
- {
- label: "鑱旂郴鏂瑰紡",
- prop: "companyPhone",
- width:150
- },
- {
- label: "寮�鎴疯",
- prop: "bankAccountName",
- width: 220,
- },
- {
- label: "璐﹀彿",
- prop: "bankAccountNum",
- width: 220,
- },
- {
- label: "鑱旂郴浜�",
- prop: "contactUserName",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "contactUserPhone",
- width: 150,
- },
- {
- label: "缁存姢浜�",
- prop: "maintainUserName",
- },
+ const tableColumn = ref([
+ {
+ label: "渚涘簲鍟嗗悕绉�",
+ prop: "supplierName",
+ // width: 250,
+ },
+ // {
+ // label: "渚涘簲鍟嗙被鍨�",
+ // prop: "supplierType",
+ // width: 120,
+ // },
+ {
+ label: "绾崇◣浜鸿瘑鍒彿",
+ prop: "taxpayerIdentificationNum",
+ // width: 230,
+ },
+ {
+ label: "鍏徃鍦板潃",
+ prop: "companyAddress",
+ // width: 300,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainUserName",
+ },
- {
- label: "缁存姢鏃堕棿",
- prop: "maintainTime",
- width:100
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: 'right',
- width: 150,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintainTime",
+ // width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 150,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
},
- },
- {
- //璧勮川闄勪欢
- name: "璧勮川鏂囦欢",
- type: "text",
- clickFun: (row) => {
- openFileDialog(row)
+ // {
+ // //璧勮川闄勪欢
+ // name: "璧勮川鏂囦欢",
+ // type: "text",
+ // clickFun: row => {
+ // openFileDialog(row);
+ // },
+ // },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const userList = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ const fileListDialogVisible = ref(false);
+ const recordId = ref();
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const data = reactive({
+ searchForm: {
+ supplierName: "",
+ },
+ form: {
+ supplierName: "",
+ taxpayerIdentificationNum: "",
+ companyAddress: "",
+ maintainUserId: "",
+ maintainTime: "",
+ supplierType: "",
+ isWhite: "",
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxpayerIdentificationNum: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ // supplierType: [
+ // { required: true, message: "璇烽�夋嫨渚涘簲鍟嗙被鍨�", trigger: "change" },
+ // ],
+ },
+ });
+ const { searchForm, form, rules } = toRefs(data);
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ /** 鎻愪氦涓婁紶鏂囦欢 */
+ function submitFileForm() {
+ upload.isUploading = true;
+ proxy.$refs["uploadRef"].submit();
+ }
+ const getList = () => {
+ tableLoading.value = true;
+ listSupplier({ ...searchForm.value, ...page, isWhite: 1 }).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+ };
+ const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙渚涘簲鍟嗗鍏ワ級
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙渚涘簲鍟嗗鍏ワ級
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
+ });
+ /** 瀵煎叆鎸夐挳鎿嶄綔 */
+ function handleImport() {
+ upload.title = "渚涘簲鍟嗗鍏�";
+ upload.open = true;
+ }
+ /** 涓嬭浇妯℃澘 */
+ function importTemplate() {
+ proxy.download(
+ "/system/supplier/downloadTemplate",
+ {},
+ "渚涘簲鍟嗗鍏ユā鏉�.xlsx"
+ );
+ }
+
+ /**鏂囦欢涓婁紶涓鐞� */
+ const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+ };
+
+ /** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+ const handleFileSuccess = (response, file, fileList) => {
+ upload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ upload.open = false;
+ proxy.$refs["uploadRef"].clearFiles();
+ getList();
+ } else if (response.code === 500) {
+ proxy.$modal.msgError(response.msg);
+ } else {
+ proxy.$modal.msgWarning(response.msg);
+ }
+ };
+
+ /** 鏂囦欢涓婁紶澶辫触澶勭悊 */
+ const handleFileError = (error, file, fileList) => {
+ upload.isUploading = false;
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ };
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainUserId = userStore.id;
+ form.value.maintainTime = getCurrentDate();
+ userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getSupplier(row.id).then(res => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+ };
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
}
}
- ],
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const userList = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const fileListDialogVisible = ref(false);
-const recordId = ref();
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- supplierName: "",
- },
- form: {
- supplierName: "",
- taxpayerIdentificationNum: "",
- companyAddress: "",
- companyPhone: "",
- bankAccountName: "",
- bankAccountNum: "",
- contactUserName: "",
- contactUserPhone: "",
- maintainUserId: "",
- maintainTime: "",
- supplierType: "",
- isWhite: "",
- },
- rules: {
- supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNum: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserPhone: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
- maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
- supplierType: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟嗙被鍨�", trigger: "change" }],
- },
-});
-const { searchForm, form, rules } = toRefs(data);
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-/** 鎻愪氦涓婁紶鏂囦欢 */
-function submitFileForm() {
- upload.isUploading = true;
- proxy.$refs["uploadRef"].submit();
-}
-const getList = () => {
- tableLoading.value = true;
- listSupplier({ ...searchForm.value, ...page, isWhite: 1 }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- page.total = res.data.total;
- });
-};
-const upload = reactive({
- // 鏄惁鏄剧ず寮瑰嚭灞傦紙渚涘簲鍟嗗鍏ワ級
- open: false,
- // 寮瑰嚭灞傛爣棰橈紙渚涘簲鍟嗗鍏ワ級
- title: "",
- // 鏄惁绂佺敤涓婁紶
- isUploading: false,
- // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
- updateSupport: 1,
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
-});
-/** 瀵煎叆鎸夐挳鎿嶄綔 */
-function handleImport() {
- upload.title = "渚涘簲鍟嗗鍏�";
- upload.open = true;
-}
-/** 涓嬭浇妯℃澘 */
-function importTemplate() {
- proxy.download("/system/supplier/downloadTemplate", {}, "渚涘簲鍟嗗鍏ユā鏉�.xlsx");
-}
-
-/**鏂囦欢涓婁紶涓鐞� */
-const handleFileUploadProgress = (event, file, fileList) => {
- upload.isUploading = true;
-};
-
-/** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
-const handleFileSuccess = (response, file, fileList) => {
- upload.isUploading = false;
- if(response.code === 200){
- proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
- upload.open = false;
- proxy.$refs["uploadRef"].clearFiles();
- getList();
- }else if(response.code === 500){
- proxy.$modal.msgError(response.msg);
- }else{
- proxy.$modal.msgWarning(response.msg);
- }
-};
-
-/** 鏂囦欢涓婁紶澶辫触澶勭悊 */
-const handleFileError = (error, file, fileList) => {
- upload.isUploading = false;
- proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-// 鎵撳紑寮规
-const openForm = (type, row) => {
- operationType.value = type;
- form.value = {};
- form.value.maintainUserId = userStore.id;
- form.value.maintainTime = getCurrentDate();
- userListNoPage().then((res) => {
- userList.value = res.data;
- });
- if (type === "edit") {
- getSupplier(row.id).then((res) => {
- form.value = { ...res.data };
});
- }
- dialogFormVisible.value = true;
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- if (operationType.value === "edit") {
- submitEdit();
- } else {
- submitAdd();
- }
- }
- });
-};
-// 鎻愪氦鏂板
-const submitAdd = () => {
- addSupplier(form.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
-};
-// 鎻愪氦淇敼
-const submitEdit = () => {
- updateSupplier(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",
- })
+ };
+ // 鎻愪氦鏂板
+ const submitAdd = () => {
+ addSupplier(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ };
+ // 鎻愪氦淇敼
+ const submitEdit = () => {
+ updateSupplier(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("/system/supplier/export", { isWhite: 1 }, "渚涘簲鍟嗘。妗�.xlsx");
+ proxy.download(
+ "/system/supplier/export",
+ { isWhite: 1 },
+ "渚涘簲鍟嗘。妗�.xlsx"
+ );
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
-// 鍒犻櫎
-const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
- const unauthorizedData = selectedRows.value.filter(item => item.maintainUserName !== userStore.nickName);
- if (unauthorizedData.length > 0) {
- proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ };
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(
+ item => item.maintainUserName !== userStore.nickName
+ );
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
}
- ids = selectedRows.value.map((item) => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
tableLoading.value = true;
delSupplier(ids)
- .then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .finally(() => {
- tableLoading.value = false;
- });
+ .then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
-function getCurrentDate() {
- const today = new Date();
- const year = today.getFullYear();
- const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
- const day = String(today.getDate()).padStart(2, "0");
- return `${year}-${month}-${day}`;
-}
-// 鎵撳紑闄勪欢寮规
-const openFileDialog = async row => {
- recordId.value = row.id;
- fileListDialogVisible.value = true;
-};
+ // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+ function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+ }
+ // 鎵撳紑闄勪欢寮规
+ const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileListDialogVisible.value = true;
+ };
-onMounted(() => {
- getList();
-});
+ onMounted(() => {
+ getList();
+ });
-defineExpose({
- getList,
-});
+ defineExpose({
+ getList,
+ });
</script>
diff --git a/src/views/basicData/supplierManage/components/HomeTab.vue b/src/views/basicData/supplierManage/components/HomeTab.vue
index da62ca4..2c78f95 100644
--- a/src/views/basicData/supplierManage/components/HomeTab.vue
+++ b/src/views/basicData/supplierManage/components/HomeTab.vue
@@ -3,185 +3,132 @@
<div class="search_form">
<div style="margin-bottom: 10px;">
<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 style="margin-bottom: 10px;">
- <el-button type="primary" @click="openForm('add')"
- >鏂板渚涘簲鍟�</el-button
- >
+ <el-button type="primary"
+ @click="openForm('add')">鏂板渚涘簲鍟�</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="info" plain icon="Upload" @click="handleImport"
- >瀵煎叆</el-button
- >
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="info"
+ plain
+ icon="Upload"
+ @click="handleImport">瀵煎叆</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- ></PIMTable>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"></PIMTable>
</div>
- <el-dialog
- v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板渚涘簲鍟嗕俊鎭�' : '缂栬緫渚涘簲鍟嗕俊鎭�'"
- width="70%"
- @close="closeDia"
- >
- <el-form
- :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef"
- >
+ <el-dialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板渚涘簲鍟嗕俊鎭�' : '缂栬緫渚涘簲鍟嗕俊鎭�'"
+ width="70%"
+ @close="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="supplierName">
- <el-input
- v-model="form.supplierName"
- placeholder="璇疯緭鍏�"
- clearable
- />
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細"
+ prop="supplierName">
+ <el-input v-model="form.supplierName"
+ placeholder="璇疯緭鍏�"
+ clearable />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item
- label="绾崇◣浜鸿瘑鍒彿锛�"
- prop="taxpayerIdentificationNum"
- >
- <el-input
- v-model="form.taxpayerIdentificationNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
+ <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�"
+ prop="taxpayerIdentificationNum">
+ <el-input v-model="form.taxpayerIdentificationNum"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍏徃鍦板潃锛�"
+ prop="companyAddress">
+ <el-input v-model="form.companyAddress"
+ placeholder="璇疯緭鍏�"
+ clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
- <el-input
- v-model="form.companyAddress"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍏徃鐢佃瘽锛�" prop="companyPhone">
- <el-input
- v-model="form.companyPhone"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�鎴疯锛�" prop="bankAccountName">
- <el-input
- v-model="form.bankAccountName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璐﹀彿锛�" prop="bankAccountNum">
- <el-input
- v-model="form.bankAccountNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細" prop="contactUserName">
- <el-input
- v-model="form.contactUserName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="contactUserPhone">
- <el-input
- v-model="form.contactUserPhone"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="缁存姢浜猴細" prop="maintainUserId">
- <el-select
- v-model="form.maintainUserId"
- placeholder="璇烽�夋嫨"
- clearable
- disabled
- >
- <el-option
- v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.userId"
- />
+ <el-form-item label="缁存姢浜猴細"
+ prop="maintainUserId">
+ <el-select v-model="form.maintainUserId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled>
+ <el-option v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="缁存姢鏃堕棿锛�" prop="maintainTime">
- <el-date-picker
- style="width: 100%"
- v-model="form.maintainTime"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- />
+ <el-form-item label="缁存姢鏃堕棿锛�"
+ prop="maintainTime">
+ <el-date-picker style="width: 100%"
+ v-model="form.maintainTime"
+ 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="12">
- <el-form-item label="渚涘簲鍟嗙被鍨嬶細" prop="supplierType">
- <el-select v-model="form.supplierType" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鐢�" value="鐢�" />
- <el-option label="涔�" value="涔�" />
- <el-option label="涓�" value="涓�" />
- <el-option label="涓�" value="涓�" />
+ <!-- <el-col :span="12">
+ <el-form-item label="渚涘簲鍟嗙被鍨嬶細"
+ prop="supplierType">
+ <el-select v-model="form.supplierType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="涔�"
+ value="涔�" />
+ <el-option label="涓�"
+ value="涓�" />
+ <el-option label="涓�"
+ value="涓�" />
</el-select>
</el-form-item>
- </el-col>
+ </el-col> -->
<el-col :span="12">
- <el-form-item label="鏄惁鐧藉悕鍗曪細" prop="isWhite">
- <el-select v-model="form.isWhite" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鏄�" :value="0" />
- <el-option label="鍚�" :value="1" />
+ <el-form-item label="鏄惁鐧藉悕鍗曪細"
+ prop="isWhite">
+ <el-select v-model="form.isWhite"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鏄�"
+ :value="0" />
+ <el-option label="鍚�"
+ :value="1" />
</el-select>
</el-form-item>
</el-col>
@@ -189,50 +136,44 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
</el-dialog>
-
<!-- 渚涘簲鍟嗗鍏ュ璇濇 -->
- <el-dialog
- :title="upload.title"
- v-model="upload.open"
- width="400px"
- append-to-body
- >
- <el-upload
- ref="uploadRef"
- :limit="1"
- accept=".xlsx, .xls"
- :headers="upload.headers"
- :action="upload.url + '?updateSupport=' + upload.updateSupport"
- :disabled="upload.isUploading"
- :on-progress="handleFileUploadProgress"
- :on-success="handleFileSuccess"
- :on-error="handleFileError"
- :auto-upload="false"
- drag
- >
+ <el-dialog :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body>
+ <el-upload ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :on-error="handleFileError"
+ :auto-upload="false"
+ drag>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
- <el-link
- type="primary"
- :underline="false"
- style="font-size: 12px; vertical-align: baseline"
- @click="importTemplate"
- >涓嬭浇妯℃澘</el-link
- >
+ <el-link type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline"
+ @click="importTemplate">涓嬭浇妯℃澘</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button type="primary"
+ @click="submitFileForm">纭� 瀹�</el-button>
<el-button @click="upload.open = false">鍙� 娑�</el-button>
</div>
</template>
@@ -245,351 +186,330 @@
</template>
<script setup>
-import { onMounted, ref } from "vue";
-import { Search } from "@element-plus/icons-vue";
-import { delSupplier } from "@/api/basicData/supplierManageFile.js";
-import { ElMessageBox } from "element-plus";
-import { userListNoPage } from "@/api/system/user.js";
-import {
- addSupplier,
- getSupplier,
- listSupplier,
- updateSupplier,
-} from "@/api/basicData/supplierManageFile.js";
-import useUserStore from "@/store/modules/user";
-import { getToken } from "@/utils/auth.js";
-const FileList = defineAsyncComponent(() =>
+ import { onMounted, ref } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import { delSupplier } from "@/api/basicData/supplierManageFile.js";
+ import { ElMessageBox } from "element-plus";
+ import { userListNoPage } from "@/api/system/user.js";
+ import {
+ addSupplier,
+ getSupplier,
+ listSupplier,
+ updateSupplier,
+ } from "@/api/basicData/supplierManageFile.js";
+ import useUserStore from "@/store/modules/user";
+ import { getToken } from "@/utils/auth.js";
+ const FileList = defineAsyncComponent(() =>
import("@/components/Dialog/FileList.vue")
-);
-const { proxy } = getCurrentInstance();
-const userStore = useUserStore();
+ );
+ const { proxy } = getCurrentInstance();
+ const userStore = useUserStore();
-const tableColumn = ref([
- {
- label: "渚涘簲鍟嗗悕绉�",
- prop: "supplierName",
- width: 250,
- },
- {
- label: "渚涘簲鍟嗙被鍨�",
- prop: "supplierType",
- width: 120,
- },
- {
- label: "绾崇◣浜鸿瘑鍒彿",
- prop: "taxpayerIdentificationNum",
- width: 230,
- },
- {
- label: "鍏徃鍦板潃",
- prop: "companyAddress",
- width: 220,
- },
- {
- label: "鑱旂郴鏂瑰紡",
- prop: "companyPhone",
- width:150
- },
- {
- label: "寮�鎴疯",
- prop: "bankAccountName",
- width: 220,
- },
- {
- label: "璐﹀彿",
- prop: "bankAccountNum",
- width: 220,
- },
- {
- label: "鑱旂郴浜�",
- prop: "contactUserName",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "contactUserPhone",
- width: 150,
- },
- {
- label: "缁存姢浜�",
- prop: "maintainUserName",
- },
+ const tableColumn = ref([
+ {
+ label: "渚涘簲鍟嗗悕绉�",
+ prop: "supplierName",
+ // width: 250,
+ },
+ // {
+ // label: "渚涘簲鍟嗙被鍨�",
+ // prop: "supplierType",
+ // width: 120,
+ // },
+ {
+ label: "绾崇◣浜鸿瘑鍒彿",
+ prop: "taxpayerIdentificationNum",
+ // width: 230,
+ },
+ {
+ label: "鍏徃鍦板潃",
+ prop: "companyAddress",
+ // width: 220,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainUserName",
+ // width: 220,
+ },
- {
- label: "缁存姢鏃堕棿",
- prop: "maintainTime",
- width:100
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: 'right',
- width: 150,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintainTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 150,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
},
- },
- {
- //璧勮川闄勪欢
- name: "璧勮川鏂囦欢",
- type: "text",
- clickFun: (row) => {
- openFileDialog(row)
+ // {
+ // //璧勮川闄勪欢
+ // name: "璧勮川鏂囦欢",
+ // type: "text",
+ // clickFun: row => {
+ // openFileDialog(row);
+ // },
+ // },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const userList = ref([]);
+ const tableLoading = ref(false);
+ const fileListDialogVisible = ref(false);
+ const recordId = ref();
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const data = reactive({
+ searchForm: {
+ supplierName: "",
+ },
+ form: {
+ supplierName: "",
+ taxpayerIdentificationNum: "",
+ companyAddress: "",
+ maintainUserId: "",
+ maintainTime: "",
+ supplierType: "",
+ isWhite: "",
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxpayerIdentificationNum: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ // supplierType: [
+ // { required: true, message: "璇烽�夋嫨渚涘簲鍟嗙被鍨�", trigger: "change" },
+ // ],
+ },
+ });
+ const { searchForm, form, rules } = toRefs(data);
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ /** 鎻愪氦涓婁紶鏂囦欢 */
+ function submitFileForm() {
+ upload.isUploading = true;
+ proxy.$refs["uploadRef"].submit();
+ }
+ const getList = () => {
+ tableLoading.value = true;
+ listSupplier({ ...searchForm.value, ...page, isWhite: 0 }).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+ };
+ const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙渚涘簲鍟嗗鍏ワ級
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙渚涘簲鍟嗗鍏ワ級
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
+ });
+ /** 瀵煎叆鎸夐挳鎿嶄綔 */
+ function handleImport() {
+ upload.title = "渚涘簲鍟嗗鍏�";
+ upload.open = true;
+ }
+ /** 涓嬭浇妯℃澘 */
+ function importTemplate() {
+ proxy.download(
+ "/system/supplier/downloadTemplate",
+ {},
+ "渚涘簲鍟嗗鍏ユā鏉�.xlsx"
+ );
+ }
+
+ /**鏂囦欢涓婁紶涓鐞� */
+ const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+ };
+
+ /** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+ const handleFileSuccess = (response, file, fileList) => {
+ upload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ upload.open = false;
+ proxy.$refs["uploadRef"].clearFiles();
+ getList();
+ } else if (response.code === 500) {
+ proxy.$modal.msgError(response.msg);
+ } else {
+ proxy.$modal.msgWarning(response.msg);
+ }
+ };
+
+ /** 鏂囦欢涓婁紶澶辫触澶勭悊 */
+ const handleFileError = (error, file, fileList) => {
+ upload.isUploading = false;
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ };
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainUserId = userStore.id;
+ form.value.maintainTime = getCurrentDate();
+ userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getSupplier(row.id).then(res => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+ };
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
}
}
- ],
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const userList = ref([]);
-const tableLoading = ref(false);
-const fileListDialogVisible = ref(false);
-const recordId = ref();
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- supplierName: "",
- },
- form: {
- supplierName: "",
- taxpayerIdentificationNum: "",
- companyAddress: "",
- companyPhone: "",
- bankAccountName: "",
- bankAccountNum: "",
- contactUserName: "",
- contactUserPhone: "",
- maintainUserId: "",
- maintainTime: "",
- supplierType: "",
- isWhite: "",
- },
- rules: {
- supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNum: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserPhone: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
- maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
- supplierType: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟嗙被鍨�", trigger: "change" }],
- },
-});
-const { searchForm, form, rules } = toRefs(data);
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-/** 鎻愪氦涓婁紶鏂囦欢 */
-function submitFileForm() {
- upload.isUploading = true;
- proxy.$refs["uploadRef"].submit();
-}
-const getList = () => {
- tableLoading.value = true;
- listSupplier({ ...searchForm.value, ...page, isWhite: 0 }).then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- page.total = res.data.total;
- });
-};
-const upload = reactive({
- // 鏄惁鏄剧ず寮瑰嚭灞傦紙渚涘簲鍟嗗鍏ワ級
- open: false,
- // 寮瑰嚭灞傛爣棰橈紙渚涘簲鍟嗗鍏ワ級
- title: "",
- // 鏄惁绂佺敤涓婁紶
- isUploading: false,
- // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
- updateSupport: 1,
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
-});
-/** 瀵煎叆鎸夐挳鎿嶄綔 */
-function handleImport() {
- upload.title = "渚涘簲鍟嗗鍏�";
- upload.open = true;
-}
-/** 涓嬭浇妯℃澘 */
-function importTemplate() {
- proxy.download("/system/supplier/downloadTemplate", {}, "渚涘簲鍟嗗鍏ユā鏉�.xlsx");
-}
-
-/**鏂囦欢涓婁紶涓鐞� */
-const handleFileUploadProgress = (event, file, fileList) => {
- upload.isUploading = true;
-};
-
-/** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
-const handleFileSuccess = (response, file, fileList) => {
- upload.isUploading = false;
- if(response.code === 200){
- proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
- upload.open = false;
- proxy.$refs["uploadRef"].clearFiles();
- getList();
- }else if(response.code === 500){
- proxy.$modal.msgError(response.msg);
- }else{
- proxy.$modal.msgWarning(response.msg);
- }
-};
-
-/** 鏂囦欢涓婁紶澶辫触澶勭悊 */
-const handleFileError = (error, file, fileList) => {
- upload.isUploading = false;
- proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-// 鎵撳紑寮规
-const openForm = (type, row) => {
- operationType.value = type;
- form.value = {};
- form.value.maintainUserId = userStore.id;
- form.value.maintainTime = getCurrentDate();
- userListNoPage().then((res) => {
- userList.value = res.data;
- });
- if (type === "edit") {
- getSupplier(row.id).then((res) => {
- form.value = { ...res.data };
});
- }
- dialogFormVisible.value = true;
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- if (operationType.value === "edit") {
- submitEdit();
- } else {
- submitAdd();
- }
- }
- });
-};
-// 鎻愪氦鏂板
-const submitAdd = () => {
- addSupplier(form.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
-};
-// 鎻愪氦淇敼
-const submitEdit = () => {
- updateSupplier(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",
- })
+ };
+ // 鎻愪氦鏂板
+ const submitAdd = () => {
+ addSupplier(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ };
+ // 鎻愪氦淇敼
+ const submitEdit = () => {
+ updateSupplier(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("/system/supplier/export", { isWhite: 0 }, "渚涘簲鍟嗘。妗�.xlsx");
+ proxy.download(
+ "/system/supplier/export",
+ { isWhite: 0 },
+ "渚涘簲鍟嗘。妗�.xlsx"
+ );
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
-// 鍒犻櫎
-const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
- const unauthorizedData = selectedRows.value.filter(item => item.maintainUserName !== userStore.nickName);
- if (unauthorizedData.length > 0) {
- proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ };
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(
+ item => item.maintainUserName !== userStore.nickName
+ );
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
}
- ids = selectedRows.value.map((item) => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
tableLoading.value = true;
delSupplier(ids)
- .then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .finally(() => {
- tableLoading.value = false;
- });
+ .then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
-function getCurrentDate() {
- const today = new Date();
- const year = today.getFullYear();
- const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
- const day = String(today.getDate()).padStart(2, "0");
- return `${year}-${month}-${day}`;
-}
-// 鎵撳紑闄勪欢寮规
-const openFileDialog = async row => {
- recordId.value = row.id;
- fileListDialogVisible.value = true;
-};
+ // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+ function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+ }
+ // 鎵撳紑闄勪欢寮规
+ const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileListDialogVisible.value = true;
+ };
-onMounted(() => {
- getList();
-});
+ onMounted(() => {
+ getList();
+ });
-defineExpose({
- getList,
-});
+ defineExpose({
+ getList,
+ });
</script>
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index 0605fe5..e8908e6 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -22,14 +22,10 @@
<el-row>
<el-col :span="24">
<el-form-item label="鐢宠閮ㄩ棬锛�">
- <el-select disabled
- v-model="form.approveDeptId"
- placeholder="閫夋嫨閮ㄩ棬">
- <el-option v-for="user in productOptions"
- :key="user.deptId"
- :label="user.deptName"
- :value="user.deptId" />
- </el-select>
+ <el-input v-model="form.approveDeptName"
+ placeholder=""
+ clearable
+ disabled />
</el-form-item>
</el-col>
</el-row>
@@ -42,6 +38,18 @@
clearable
type="textarea"
disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row v-if="Number(props.approveType) === 4">
+ <el-col :span="24">
+ <el-form-item label="鎶ラ攢閲戦锛�">
+ <el-input-number v-model="form.price"
+ disabled
+ :min="0"
+ :precision="2"
+ style="width: 100%"
+ placeholder="" />
</el-form-item>
</el-col>
</el-row>
@@ -75,7 +83,7 @@
<el-descriptions-item label="鎶ヤ环鎬婚"
:span="2">
<span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
- 楼{{ Number(currentQuotation.totalAmount ?? 0).toFixed(2) }}
+ {{ formatCurrency(currentQuotation.totalAmount) }}
</span>
</el-descriptions-item>
</el-descriptions>
@@ -92,7 +100,7 @@
label="鍗曚綅" />
<el-table-column prop="unitPrice"
label="鍗曚环">
- <template #default="scope">楼{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template>
+ <template #default="scope">{{ formatCurrency(scope.row.unitPrice) }}</template>
</el-table-column>
</el-table>
</div>
@@ -135,7 +143,7 @@
<el-descriptions-item label="鍚堝悓閲戦"
:span="2">
<span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
- 楼{{ Number(currentPurchase.contractAmount ?? 0).toFixed(2) }}
+ {{ formatCurrency(currentPurchase.contractAmount) }}
</span>
</el-descriptions-item>
</el-descriptions>
@@ -154,11 +162,11 @@
label="鏁伴噺" />
<el-table-column prop="taxInclusiveUnitPrice"
label="鍚◣鍗曚环">
- <template #default="scope">楼{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template>
+ <template #default="scope">{{ formatCurrency(scope.row.taxInclusiveUnitPrice) }}</template>
</el-table-column>
<el-table-column prop="taxInclusiveTotalPrice"
label="鍚◣鎬讳环">
- <template #default="scope">楼{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template>
+ <template #default="scope">{{ formatCurrency(scope.row.taxInclusiveTotalPrice) }}</template>
</el-table-column>
</el-table>
</div>
@@ -295,8 +303,10 @@
v-if="operationType === 'approval'">
<div class="dialog-footer">
<el-button type="primary"
+ :loading="submitLoading"
@click="submitForm(2)">涓嶉�氳繃</el-button>
<el-button type="primary"
+ :loading="submitLoading"
@click="submitForm(1)">閫氳繃</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
@@ -330,6 +340,7 @@
import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
import { getDeliveryDetailByShippingNo } from "@/api/salesManagement/deliveryLedger.js";
import ImagePreview from "@/components/AttachmentPreview/image/index.vue";
+ import { formatCurrency } from "@/utils/numberFormat";
const emit = defineEmits(["close"]);
const { proxy } = getCurrentInstance();
@@ -353,6 +364,7 @@
const deliveryLoading = ref(false);
const currentDelivery = ref({});
const deliveryProductList = ref([]);
+ const submitLoading = ref(false);
const isQuotationApproval = computed(() => Number(props.approveType) === 6);
const isPurchaseApproval = computed(() => Number(props.approveType) === 5);
const isDeliveryApproval = computed(() => Number(props.approveType) === 7);
@@ -581,10 +593,15 @@
// 鍒ゆ柇鏄惁涓烘渶鍚庝竴姝�
const isLast =
activities.value.findIndex(a => a.isShen) === activities.value.length - 1;
- updateApproveNode({ ...currentActivity, isLast }).then(() => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
+ submitLoading.value = true;
+ updateApproveNode({ ...currentActivity, isLast })
+ .then(() => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
};
// 鍏抽棴寮规
const closeDia = () => {
@@ -594,6 +611,7 @@
currentQuotation.value = {};
purchaseLoading.value = false;
currentPurchase.value = {};
+ submitLoading.value = false;
emit("close");
};
defineExpose({
diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index f50d06b..43fee33 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -225,167 +225,18 @@
</div>
</div>
</FormDialog>
-
- <!-- 鏂囦欢绠$悊寮圭獥 -->
- <FormDialog
- v-model="filesDialogVisible"
- title="鏂囦欢绠$悊"
- :width="'900px'"
- @close="closeFilesDialog"
- @confirm="closeFilesDialog"
- @cancel="closeFilesDialog"
- >
- <div class="file-manager">
- <!-- 鏂囦欢涓婁紶 -->
- <div class="upload-section">
- <el-upload
- :action="uploadUrl"
- :headers="uploadHeaders"
- :on-success="handleUploadSuccess"
- :on-error="handleUploadError"
- :before-upload="beforeUpload"
- name="files"
- multiple
- :show-file-list="false"
- accept=".txt,.md,.docx,.xlsx,.xls,.pdf"
- >
- <el-button type="primary">涓婁紶鏂囦欢</el-button>
- </el-upload>
- <el-button
- type="success"
- @click="saveFiles"
- :disabled="uploadedBlobIds.length === 0"
- :loading="savingFiles"
- style="margin-left: 10px"
- >
- 淇濆瓨鏂囦欢鍏宠仈
- </el-button>
- <el-button
- v-if="uploadedBlobIds.length > 0"
- type="text"
- @click="clearUploadedFiles"
- style="margin-left: 10px"
- >
- 娓呯┖寰呬繚瀛樺垪琛�
- </el-button>
- </div>
-
- <!-- 寰呬繚瀛樼殑鏂囦欢鍒楄〃 -->
- <div v-if="uploadedBlobIds.length > 0" class="uploaded-list">
- <div class="uploaded-tip">
- <el-icon style="color: #409eff"><InfoFilled /></el-icon>
- <span>宸蹭笂浼� {{ uploadedBlobIds.length }} 涓枃浠�,璇风偣鍑�"淇濆瓨鏂囦欢鍏宠仈"鎸夐挳瑙﹀彂鍚戦噺鍖栧鐞�</span>
- </div>
- </div>
-
- <!-- 鏂囦欢鍒楄〃涓庡悜閲忓寲鐘舵�� -->
- <el-table :data="fileList" style="margin-top: 20px" border>
- <el-table-column prop="fileName" label="鏂囦欢鍚�" show-overflow-tooltip />
- <el-table-column prop="fileType" label="鏂囦欢绫诲瀷" width="100" />
- <el-table-column label="鍚戦噺鍖栫姸鎬�" width="120">
- <template #default="{ row }">
- <el-tag :type="getStatusType(row.vectorStatus)">
- {{ getStatusText(row.vectorStatus) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="chunkCount" label="鍒囩墖鏁�" width="100" align="center" />
- <el-table-column label="閿欒淇℃伅" width="200" show-overflow-tooltip>
- <template #default="{ row }">
- <span v-if="row.vectorError" style="color: #f56c6c">{{ row.vectorError }}</span>
- <span v-else style="color: #909399">-</span>
- </template>
- </el-table-column>
- <el-table-column prop="createTime" label="涓婁紶鏃堕棿" width="180" />
- <el-table-column label="鎿嶄綔" width="150" align="center">
- <template #default="{ row }">
- <el-button
- v-if="row.vectorStatus === 3"
- type="text"
- @click="reprocessFile(row)"
- >
- 閲嶆柊澶勭悊
- </el-button>
- <el-button type="text" @click="deleteFile(row)" style="color: #f56c6c">
- 鍒犻櫎
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </FormDialog>
-
- <!-- 鐭ヨ瘑搴撻棶绛斿脊绐� -->
- <FormDialog
- v-model="chatDialogVisible"
- title="鐭ヨ瘑搴撻棶绛�"
- :width="'800px'"
- @close="closeChatDialog"
- @confirm="closeChatDialog"
- @cancel="closeChatDialog"
- >
- <div class="knowledge-chat">
- <div class="chat-header">
- <el-tag type="success">褰撳墠鐭ヨ瘑搴�: {{ currentKnowledgeBase?.title }}</el-tag>
- </div>
-
- <!-- 瀵硅瘽鍖哄煙 -->
- <div class="chat-messages" ref="chatMessagesRef">
- <div
- v-for="(msg, index) in messages"
- :key="index"
- :class="['message', msg.role]"
- >
- <div class="message-role">{{ msg.role === 'user' ? '鎴�' : 'AI鍔╂墜' }}</div>
- <div class="message-content">{{ msg.content }}</div>
- </div>
- <div v-if="chatLoading" class="message assistant">
- <div class="message-role">AI鍔╂墜</div>
- <div class="message-content typing">姝e湪鎬濊�冧腑...</div>
- </div>
- </div>
-
- <!-- 杈撳叆妗� -->
- <div class="chat-input">
- <el-input
- v-model="inputQuestion"
- placeholder="璇疯緭鍏ラ棶棰�,鎸夊洖杞﹀彂閫�(Ctrl+Enter蹇嵎鍙戦��)"
- @keyup.enter="sendMessage"
- :disabled="chatLoading"
- >
- <template #append>
- <el-button @click="sendMessage" :loading="chatLoading">鍙戦��</el-button>
- </template>
- </el-input>
- <div class="chat-actions">
- <el-button type="text" size="small" @click="clearMessages">娓呯┖瀵硅瘽</el-button>
- </div>
- </div>
- </div>
- </FormDialog>
</div>
</template>
<script setup>
-import { Search, InfoFilled } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed, watch, nextTick } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed, watch } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import FormDialog from '@/components/Dialog/FormDialog.vue';
-import {
- listKnowledgeBase,
- delKnowledgeBase,
- addKnowledgeBase,
- updateKnowledgeBase,
- getVectorStatus,
- reprocessVector,
- saveKnowledgeBaseFiles,
- deleteKnowledgeBaseFile,
- knowledgeChat
-} from "@/api/collaborativeApproval/knowledgeBase.js";
+import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
import useUserStore from '@/store/modules/user';
import { userListNoPageByTenantId } from '@/api/system/user.js';
-import { getToken } from "@/utils/auth";
// 琛ㄥ崟楠岃瘉瑙勫垯
const rules = {
@@ -432,18 +283,7 @@
dialogTitle: "",
dialogType: "add",
viewDialogVisible: false,
- currentKnowledge: {},
- filesDialogVisible: false,
- currentKnowledgeBase: null,
- fileList: [],
- uploadedBlobIds: [],
- savingFiles: false,
- vectorStatusTimer: null, // 鍚戦噺鍖栫姸鎬佽疆璇㈠畾鏃跺櫒
- chatDialogVisible: false,
- messages: [],
- inputQuestion: "",
- chatLoading: false,
- memoryId: ""
+ currentKnowledge: {}
});
const {
@@ -457,18 +297,7 @@
dialogTitle,
dialogType,
viewDialogVisible,
- currentKnowledge,
- filesDialogVisible,
- currentKnowledgeBase,
- fileList,
- uploadedBlobIds,
- savingFiles,
- vectorStatusTimer,
- chatDialogVisible,
- messages,
- inputQuestion,
- chatLoading,
- memoryId
+ currentKnowledge
} = toRefs(data);
// 琛ㄥ崟寮曠敤
@@ -476,12 +305,6 @@
// 鐢ㄦ埛鐩稿叧
const userStore = useUserStore();
const userList = ref([]);
-// 鑱婂ぉ娑堟伅瀹瑰櫒寮曠敤
-const chatMessagesRef = ref();
-
-// 鏂囦欢涓婁紶鐩稿叧
-const uploadUrl = import.meta.env.VITE_APP_BASE_API + "/common/upload";
-const uploadHeaders = { Authorization: "Bearer " + getToken() };
// 琛ㄦ牸鍒楅厤缃�
const tableColumn = ref([
@@ -529,18 +352,6 @@
}
},
{
- label: "鏂囦欢鏁伴噺",
- prop: "fileCount",
- width: 100,
- align: "center"
- },
- {
- label: "鍒囩墖鏁伴噺",
- prop: "totalChunkCount",
- width: 100,
- align: "center"
- },
- {
label: "浣跨敤娆℃暟",
prop: "usageCount",
width: 100,
@@ -568,20 +379,6 @@
type: "text",
clickFun: (row) => {
openForm("edit", row);
- }
- },
- {
- name: "鏂囦欢",
- type: "text",
- clickFun: (row) => {
- openFilesDialog(row);
- }
- },
- {
- name: "闂瓟",
- type: "text",
- clickFun: (row) => {
- openChatDialog(row);
}
},
{
@@ -625,31 +422,21 @@
const getList = () => {
tableLoading.value = true;
-
- // 鉁� GET璇锋眰浣跨敤params浼犲弬
- listKnowledgeBase({
- current: page.value.current,
- size: page.value.size,
- title: searchForm.value.title,
- type: searchForm.value.type
- })
+ listKnowledgeBase({...page.value, ...searchForm.value})
.then(res => {
tableLoading.value = false;
page.value.total = res.data.total;
-
- // 濡傛灉褰撳墠椤垫暟瓒呰繃鎬婚〉鏁�,閲嶇疆鍒扮1椤靛苟閲嶆柊鏌ヨ
+ // 濡傛灉褰撳墠椤垫暟瓒呰繃鎬婚〉鏁帮紝閲嶇疆鍒扮1椤靛苟閲嶆柊鏌ヨ
const maxPage = Math.ceil(res.data.total / page.value.size) || 1;
if (page.value.current > maxPage && maxPage > 0) {
page.value.current = 1;
+ // 閲嶆柊鏌ヨ绗�1椤垫暟鎹�
return getList();
}
-
tableData.value = res.data.records;
- })
- .catch(err => {
+ }).catch(err => {
tableLoading.value = false;
- console.error("鏌ヨ鐭ヨ瘑搴撳垪琛ㄥけ璐�:", err);
- });
+ })
};
// 鍒嗛〉澶勭悊
@@ -824,47 +611,27 @@
const submitForm = async () => {
try {
await formRef.value.validate();
-
- // 鉁� POST璇锋眰浣跨敤data浼犲弬,鏄庣‘鍙傛暟缁撴瀯
- const formData = {
- title: form.value.title,
- type: form.value.type,
- scenario: form.value.scenario || "",
- efficiency: form.value.efficiency || "",
- problem: form.value.problem,
- solution: form.value.solution,
- keyPoints: form.value.keyPoints || "",
- creator: form.value.creator || "",
- usageCount: form.value.usageCount || 0
- };
-
if (dialogType.value === "add") {
// 鏂板鐭ヨ瘑
- addKnowledgeBase(formData).then(res => {
+ addKnowledgeBase({...form.value}).then(res => {
if(res.code == 200){
ElMessage.success("娣诲姞鎴愬姛");
closeKnowledgeDialog();
getList();
}
}).catch(err => {
- console.error("娣诲姞鐭ヨ瘑搴撳け璐�:", err);
- ElMessage.error(err.msg || "娣诲姞澶辫触");
- });
+ ElMessage.error(err.msg);
+ })
} else {
- // 鏇存柊鐭ヨ瘑 - 娣诲姞id鍙傛暟
- updateKnowledgeBase({
- id: form.value.id,
- ...formData
- }).then(res => {
+ updateKnowledgeBase({...form.value}).then(res => {
if(res.code == 200){
ElMessage.success("鏇存柊鎴愬姛");
closeKnowledgeDialog();
getList();
}
}).catch(err => {
- console.error("鏇存柊鐭ヨ瘑搴撳け璐�:", err);
- ElMessage.error(err.msg || "鏇存柊澶辫触");
- });
+ ElMessage.error(err.msg);
+ })
}
} catch (error) {
console.error("琛ㄥ崟楠岃瘉澶辫触:", error);
@@ -878,22 +645,19 @@
return;
}
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄�,鏄惁纭鍒犻櫎?", "鍒犻櫎", {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
}).then(() => {
- // 鉁� DELETE璇锋眰浣跨敤data浼犻�扞D鏁扮粍
+ // console.log(selectedIds.value);
delKnowledgeBase(selectedIds.value).then(res => {
if(res.code == 200){
ElMessage.success("鍒犻櫎鎴愬姛");
selectedIds.value = [];
getList();
}
- }).catch(err => {
- console.error("鍒犻櫎鐭ヨ瘑搴撳け璐�:", err);
- ElMessage.error(err.msg || "鍒犻櫎澶辫触");
- });
+ })
}).catch(() => {
// 鐢ㄦ埛鍙栨秷
});
@@ -916,364 +680,6 @@
const handleExport = () => {
proxy.download('/knowledgeBase/export', { ...searchForm.value }, '鐭ヨ瘑搴�.xlsx')
}
-
-// ============ 鏂囦欢绠$悊鐩稿叧 ============
-
-// 鎵撳紑鏂囦欢绠$悊寮圭獥
-const openFilesDialog = (row) => {
- currentKnowledgeBase.value = row;
- filesDialogVisible.value = true;
- loadFileList();
-};
-
-// 鍔犺浇鏂囦欢鍒楄〃
-const loadFileList = async () => {
- if (!currentKnowledgeBase.value?.id) return;
-
- try {
- const res = await getVectorStatus(currentKnowledgeBase.value.id);
- fileList.value = res.data || [];
-
- // 妫�鏌ユ槸鍚︽湁澶勭悊涓殑鏂囦欢,濡傛灉鏈夊垯鍚姩杞
- const hasProcessing = res.data.some(item => item.vectorStatus === 1);
- if (hasProcessing && !vectorStatusTimer.value) {
- startVectorStatusPolling();
- } else if (!hasProcessing && vectorStatusTimer.value) {
- stopVectorStatusPolling();
- }
- } catch (error) {
- console.error("鍔犺浇鏂囦欢鍒楄〃澶辫触:", error);
- ElMessage.error("鍔犺浇鏂囦欢鍒楄〃澶辫触");
- }
-};
-
-// 寮�濮嬭疆璇㈠悜閲忓寲鐘舵��
-const startVectorStatusPolling = () => {
- vectorStatusTimer.value = setInterval(async () => {
- try {
- const res = await getVectorStatus(currentKnowledgeBase.value.id);
- fileList.value = res.data || [];
-
- // 妫�鏌ユ槸鍚﹁繕鏈夊鐞嗕腑鐨勬枃浠�
- const hasProcessing = res.data.some(item => item.vectorStatus === 1);
- if (!hasProcessing) {
- stopVectorStatusPolling();
- ElMessage.success("鎵�鏈夋枃浠跺悜閲忓寲澶勭悊瀹屾垚");
- }
- } catch (error) {
- console.error("杞鍚戦噺鍖栫姸鎬佸け璐�:", error);
- stopVectorStatusPolling();
- }
- }, 3000); // 姣�3绉掕疆璇竴娆�
-};
-
-// 鍋滄杞鍚戦噺鍖栫姸鎬�
-const stopVectorStatusPolling = () => {
- if (vectorStatusTimer.value) {
- clearInterval(vectorStatusTimer.value);
- vectorStatusTimer.value = null;
- }
-};
-
-// 涓婁紶鍓嶆牎楠�
-const beforeUpload = (file) => {
- const allowedTypes = ['.txt', '.md', '.docx', '.xlsx', '.xls', '.pdf'];
- const fileName = file.name.toLowerCase();
- const isAllowed = allowedTypes.some(type => fileName.endsWith(type));
-
- if (!isAllowed) {
- ElMessage.error('鍙敮鎸� txt銆乵d銆乨ocx銆亁lsx銆亁ls銆乸df 鏍煎紡鐨勬枃浠�');
- return false;
- }
-
- const isLt50M = file.size / 1024 / 1024 < 50;
- if (!isLt50M) {
- ElMessage.error('鏂囦欢澶у皬涓嶈兘瓒呰繃 50MB');
- return false;
- }
-
- return true;
-};
-
-// 涓婁紶鎴愬姛
-const handleUploadSuccess = (response, file) => {
- console.log("涓婁紶鍝嶅簲:", response); // 璋冭瘯鏃ュ織
-
- if (response.code === 200) {
- // 鉁� 鍚庣杩斿洖鐨勬槸 List<StorageBlobVO>,鎵�浠ata鏄暟缁�
- if (Array.isArray(response.data) && response.data.length > 0) {
- // 鍙栨暟缁勭涓�涓厓绱犵殑id
- const blobId = response.data[0].id;
- if (blobId) {
- uploadedBlobIds.value.push(blobId);
- ElMessage.success(`鏂囦欢 ${file.name} 涓婁紶鎴愬姛`);
- } else {
- console.error("涓婁紶鍝嶅簲涓湭鎵惧埌id:", response.data[0]);
- ElMessage.error("涓婁紶澶辫触: 鏈幏鍙栧埌鏂囦欢ID");
- }
- } else {
- console.error("涓婁紶鍝嶅簲鏍煎紡閿欒:", response);
- ElMessage.error("涓婁紶澶辫触: 鍝嶅簲鏍煎紡閿欒");
- }
- } else {
- ElMessage.error(response.msg || "涓婁紶澶辫触");
- }
-};
-
-// 涓婁紶澶辫触
-const handleUploadError = (error, file) => {
- ElMessage.error(`鏂囦欢 ${file.name} 涓婁紶澶辫触`);
-};
-
-// 淇濆瓨鏂囦欢鍏宠仈
-const saveFiles = async () => {
- // 鍙傛暟鏍¢獙
- if (!currentKnowledgeBase.value?.id) {
- ElMessage.error("鐭ヨ瘑搴撲俊鎭紓甯�");
- return;
- }
-
- if (uploadedBlobIds.value.length === 0) {
- ElMessage.warning("璇峰厛涓婁紶鏂囦欢");
- return;
- }
-
- savingFiles.value = true;
-
- try {
- // 鉁� POST璇锋眰浣跨敤data浼犲弬,鏄庣‘鍙傛暟缁撴瀯
- await saveKnowledgeBaseFiles({
- knowledgeBaseId: currentKnowledgeBase.value.id, // 鐭ヨ瘑搴揑D
- storageBlobIds: uploadedBlobIds.value // 鏂囦欢blob ID鏁扮粍
- });
-
- ElMessage.success("鏂囦欢鍏宠仈淇濆瓨鎴愬姛,姝e湪鍚庡彴澶勭悊鍚戦噺鍖�");
- uploadedBlobIds.value = [];
-
- // 寤惰繜鍒锋柊鏂囦欢鍒楄〃,缁欏悗鍙板鐞嗘椂闂�
- setTimeout(() => {
- loadFileList();
- }, 1000);
- } catch (error) {
- console.error("淇濆瓨鏂囦欢鍏宠仈澶辫触:", error);
- ElMessage.error("淇濆瓨鏂囦欢鍏宠仈澶辫触");
- } finally {
- savingFiles.value = false;
- }
-};
-
-// 閲嶆柊澶勭悊鍚戦噺鍖栫殑鏂囦欢
-const reprocessFile = async (row) => {
- try {
- await reprocessVector(row.id);
- ElMessage.success("宸查噸鏂版彁浜ゅ悜閲忓寲浠诲姟");
- // 寤惰繜鍒锋柊
- setTimeout(() => {
- loadFileList();
- }, 1000);
- } catch (error) {
- console.error("閲嶆柊澶勭悊澶辫触:", error);
- ElMessage.error("閲嶆柊澶勭悊澶辫触");
- }
-};
-
-// 娓呯┖寰呬繚瀛樼殑鏂囦欢鍒楄〃
-const clearUploadedFiles = () => {
- uploadedBlobIds.value = [];
- ElMessage.success("宸叉竻绌哄緟淇濆瓨鏂囦欢鍒楄〃");
-};
-
-// 鍒犻櫎鏂囦欢
-const deleteFile = async (row) => {
- try {
- await ElMessageBox.confirm(
- "纭畾瑕佸垹闄よ鏂囦欢鍚�?鍒犻櫎鍚庡皢鏃犳硶鎭㈠鍚戦噺鏁版嵁",
- "鍒犻櫎纭",
- {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning"
- }
- );
-
- // 鉁� DELETE璇锋眰浣跨敤data浼犻�扞D鏁扮粍
- await deleteKnowledgeBaseFile([row.id]); // 娉ㄦ剰: row.id鏄悜閲忚褰旾D,涓嶆槸storageBlobId
- ElMessage.success("鍒犻櫎鎴愬姛");
- loadFileList();
- } catch (error) {
- if (error !== 'cancel') {
- console.error("鍒犻櫎鏂囦欢澶辫触:", error);
- ElMessage.error("鍒犻櫎鏂囦欢澶辫触");
- }
- }
-};
-
-// 鐘舵�佹枃鏈槧灏�
-const getStatusText = (status) => {
- const map = {
- 0: '寰呭鐞�',
- 1: '澶勭悊涓�',
- 2: '宸插畬鎴�',
- 3: '澶辫触'
- };
- return map[status] || '鏈煡';
-};
-
-// 鐘舵�佹爣绛剧被鍨嬫槧灏�
-const getStatusType = (status) => {
- const map = {
- 0: 'info',
- 1: 'warning',
- 2: 'success',
- 3: 'danger'
- };
- return map[status] || 'info';
-};
-
-// 鍏抽棴鏂囦欢绠$悊寮圭獥
-const closeFilesDialog = () => {
- filesDialogVisible.value = false;
- currentKnowledgeBase.value = null;
- fileList.value = [];
- uploadedBlobIds.value = [];
- stopVectorStatusPolling(); // 鍋滄杞
- getList(); // 鍒锋柊涓诲垪琛�,鏇存柊鏂囦欢鏁伴噺
-};
-
-// ============ 鐭ヨ瘑搴撻棶绛旂浉鍏� ============
-
-// 鐢熸垚UUID鐨刦allback鏂规
-const generateUUID = () => {
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
- return crypto.randomUUID();
- }
- // fallback: 鍏煎涓嶆敮鎸� crypto.randomUUID 鐨勭幆澧�
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- const r = Math.random() * 16 | 0;
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
-};
-
-// 鎵撳紑闂瓟寮圭獥
-const openChatDialog = (row) => {
- currentKnowledgeBase.value = row;
- chatDialogVisible.value = true;
- memoryId.value = generateUUID();
- messages.value = [];
- inputQuestion.value = "";
-};
-
-// 鍙戦�佹秷鎭�
-const sendMessage = async () => {
- // 鍙傛暟鏍¢獙
- if (!inputQuestion.value.trim()) {
- ElMessage.warning("璇疯緭鍏ラ棶棰�");
- return;
- }
-
- if (!currentKnowledgeBase.value?.id) {
- ElMessage.error("鐭ヨ瘑搴撲俊鎭紓甯�");
- return;
- }
-
- const question = inputQuestion.value.trim();
-
- // 娣诲姞鐢ㄦ埛娑堟伅
- messages.value.push({
- role: 'user',
- content: question
- });
-
- inputQuestion.value = "";
- chatLoading.value = true;
-
- // 婊氬姩鍒板簳閮�
- await nextTick();
- scrollToBottom();
-
- try {
- // 鉁� 娴佸紡璇锋眰浣跨敤Fetch API
- const response = await knowledgeChat({
- knowledgeBaseId: currentKnowledgeBase.value.id, // 鐭ヨ瘑搴揑D
- memoryId: memoryId.value, // 浼氳瘽ID
- question: question // 鐢ㄦ埛闂
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(errorText || '璇锋眰澶辫触');
- }
-
- // 鉁� 鍚庣杩斿洖 text/stream;charset=utf-8
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
- let aiContent = '';
-
- messages.value.push({ role: 'assistant', content: '' });
-
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
-
- const text = decoder.decode(value, { stream: true }); // 鉁� 娣诲姞stream閫夐」
- aiContent += text;
- messages.value[messages.value.length - 1].content = aiContent;
-
- // 婊氬姩鍒板簳閮�
- await nextTick();
- scrollToBottom();
- }
-
- // 濡傛灉AI杩斿洖绌哄唴瀹�,鏄剧ず鎻愮ず
- if (!aiContent.trim()) {
- messages.value[messages.value.length - 1].content = '鎶辨瓑,鐭ヨ瘑搴撲腑鏈壘鍒扮浉鍏冲唴瀹�,璇峰皾璇曞叾浠栭棶棰樸��';
- }
- } catch (error) {
- console.error("闂瓟璇锋眰澶辫触:", error);
- ElMessage.error("闂瓟璇锋眰澶辫触,璇风◢鍚庨噸璇�");
- messages.value.push({
- role: 'assistant',
- content: '鎶辨瓑,鍙戠敓浜嗛敊璇�,璇风◢鍚庨噸璇�'
- });
- } finally {
- chatLoading.value = false;
- }
-};
-
-// 娓呯┖瀵硅瘽
-const clearMessages = () => {
- ElMessageBox.confirm(
- "纭畾瑕佹竻绌烘墍鏈夊璇濊褰曞悧?",
- "娓呯┖纭",
- {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning"
- }
- ).then(() => {
- messages.value = [];
- memoryId.value = generateUUID(); // 閲嶆柊鐢熸垚浼氳瘽ID
- ElMessage.success("瀵硅瘽宸叉竻绌�");
- }).catch(() => {
- // 鐢ㄦ埛鍙栨秷
- });
-};
-
-// 婊氬姩鍒板簳閮�
-const scrollToBottom = () => {
- if (chatMessagesRef.value) {
- chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight;
- }
-};
-
-// 鍏抽棴闂瓟寮圭獥
-const closeChatDialog = () => {
- chatDialogVisible.value = false;
- currentKnowledgeBase.value = null;
- messages.value = [];
- inputQuestion.value = "";
-};
</script>
<style scoped>
@@ -1349,113 +755,4 @@
font-size: 14px;
color: #909399;
}
-
-/* 鏂囦欢绠$悊鏍峰紡 */
-.file-manager {
- padding: 20px 0;
-}
-
-.upload-section {
- display: flex;
- align-items: center;
-}
-
-.uploaded-list {
- margin-top: 16px;
- padding: 12px;
- background: #f0f9ff;
- border-radius: 6px;
- border: 1px solid #b3d8ff;
-}
-
-.uploaded-tip {
- display: flex;
- align-items: center;
- gap: 8px;
- color: #409eff;
- font-size: 14px;
-}
-
-/* 鐭ヨ瘑搴撻棶绛旀牱寮� */
-.knowledge-chat {
- display: flex;
- flex-direction: column;
- height: 500px;
-}
-
-.chat-header {
- margin-bottom: 16px;
-}
-
-.chat-messages {
- flex: 1;
- overflow-y: auto;
- padding: 16px;
- background: #f5f7fa;
- border-radius: 8px;
- margin-bottom: 16px;
-}
-
-.message {
- margin-bottom: 16px;
- max-width: 80%;
-}
-
-.message.user {
- margin-left: auto;
- text-align: right;
-}
-
-.message.assistant {
- margin-right: auto;
-}
-
-.message-role {
- font-size: 12px;
- color: #909399;
- margin-bottom: 4px;
-}
-
-.message-content {
- display: inline-block;
- padding: 10px 14px;
- border-radius: 8px;
- line-height: 1.6;
- word-wrap: break-word;
- white-space: pre-wrap;
-}
-
-.message.user .message-content {
- background: #409eff;
- color: white;
-}
-
-.message.assistant .message-content {
- background: white;
- color: #303133;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-}
-
-.typing {
- animation: typing 1.5s infinite;
-}
-
-@keyframes typing {
- 0%, 50%, 100% {
- opacity: 1;
- }
- 25%, 75% {
- opacity: 0.5;
- }
-}
-
-.chat-input {
- margin-top: auto;
-}
-
-.chat-actions {
- margin-top: 8px;
- text-align: right;
-}
-
</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
index ac7a123..b2fb88d 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
@@ -1,148 +1,154 @@
<template>
- <div>
-
- <!-- 鐢宠绫诲瀷閫夋嫨 -->
- <el-card class="type-card">
- <div class="type-selector">
- <div
- v-for="type in applicationTypes"
- :key="type.value"
- class="type-item"
- :class="{ active: currentType === type.value }"
- @click="changeType(type.value)"
- >
- <div class="type-icon">
- <el-icon :size="24"><component :is="type.icon"/></el-icon>
- </div>
- <div class="type-info">
- <div class="type-name">{{ type.name }}</div>
- <div class="type-desc">{{ type.desc }}</div>
- </div>
- </div>
- </div>
- </el-card>
-
- <!-- 浼氳鐢宠琛ㄥ崟 -->
- <el-card>
- <div class="form-header">
- <h3>{{ getCurrentTypeName() }}鐢宠</h3>
- </div>
-
- <el-form
- ref="meetingFormRef"
- :model="meetingForm"
- :rules="rules"
- label-width="100px"
- >
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="浼氳涓婚" prop="title">
- <el-input v-model="meetingForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�"/>
- </el-form-item>
- </el-col>
- </el-row>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="浼氳瀹�" prop="roomId">
- <el-select v-model="meetingForm.roomId" placeholder="璇烽�夋嫨浼氳瀹�" style="width: 100%">
- <el-option
- v-for="room in meetingRooms"
- :key="room.id"
- :label="`${room.name} (${room.location})`"
- :value="room.id"
- />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓绘寔浜�" prop="host">
- <el-input v-model="meetingForm.host" placeholder="璇疯緭鍏ヤ富鎸佷汉濮撳悕"/>
- </el-form-item>
- </el-col>
- </el-row>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="浼氳鏃ユ湡" prop="meetingDate">
- <el-date-picker
- v-model="meetingForm.meetingDate"
- type="date"
- placeholder="璇烽�夋嫨浼氳鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- :disabled-date="disabledDate"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <!-- 绌哄垪锛屼繚鎸佸竷灞� -->
- </el-col>
- </el-row>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="寮�濮嬫椂闂�" prop="startTime">
- <el-time-picker
- v-model="meetingForm.startTime"
- placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
- format="HH:mm"
- value-format="HH:mm"
- :disabled-hours="disabledStartHours"
- :disabled-minutes="disabledStartMinutes"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="缁撴潫鏃堕棿" prop="endTime">
- <el-time-picker
- v-model="meetingForm.endTime"
- placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
- format="HH:mm"
- value-format="HH:mm"
- :disabled-hours="disabledEndHours"
- :disabled-minutes="disabledEndMinutes"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
-
- <el-form-item label="鍙備細浜哄憳" prop="participants">
- <el-select
- v-model="meetingForm.participants"
- multiple
- filterable
- placeholder="璇烽�夋嫨鍙備細浜哄憳"
- style="width: 100%"
- >
- <el-option
- v-for="person in employees"
- :key="person.id"
- :label="`${person.staffName}${person.postName ? ` (${person.postName})` : ''}`"
- :value="person.id"
- />
- </el-select>
- </el-form-item>
-
- <el-form-item label="浼氳璇存槑" prop="description">
- <el-input
- v-model="meetingForm.description"
- type="textarea"
- :rows="4"
- placeholder="璇疯緭鍏ヤ細璁鏄�"
- />
- </el-form-item>
- </el-form>
-
- <div class="form-footer">
- <el-button @click="resetForm">閲嶇疆</el-button>
- <el-button type="primary" @click="submitForm">鎻愪氦</el-button>
- </div>
- </el-card>
- </div>
+ <div>
+
+ <!-- 鐢宠绫诲瀷閫夋嫨 -->
+ <el-card class="type-card">
+ <div class="type-selector">
+ <div
+ v-for="type in applicationTypes"
+ :key="type.value"
+ class="type-item"
+ :class="{ active: currentType === type.value }"
+ @click="changeType(type.value)"
+ >
+ <div class="type-icon">
+ <el-icon :size="24"><component :is="type.icon"/></el-icon>
+ </div>
+ <div class="type-info">
+ <div class="type-name">{{ type.name }}</div>
+ <div class="type-desc">{{ type.desc }}</div>
+ </div>
+ </div>
+ </div>
+ </el-card>
+
+ <!-- 浼氳鐢宠琛ㄥ崟 -->
+ <el-card>
+ <div class="form-header">
+ <h3>{{ getCurrentTypeName() }}鐢宠</h3>
+ </div>
+
+ <el-form
+ ref="meetingFormRef"
+ :model="meetingForm"
+ :rules="rules"
+ label-width="100px"
+ >
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浼氳涓婚" prop="title">
+ <el-input v-model="meetingForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浼氳瀹�" prop="roomId">
+ <el-select v-model="meetingForm.roomId" placeholder="璇烽�夋嫨浼氳瀹�" style="width: 100%">
+ <el-option
+ v-for="room in meetingRooms"
+ :key="room.id"
+ :label="`${room.name} (${room.location})`"
+ :value="room.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓绘寔浜�" prop="host">
+ <el-input v-model="meetingForm.host" placeholder="璇疯緭鍏ヤ富鎸佷汉濮撳悕"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浼氳鏃ユ湡" prop="meetingDate">
+ <el-date-picker
+ v-model="meetingForm.meetingDate"
+ type="date"
+ placeholder="璇烽�夋嫨浼氳鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ :disabled-date="disabledDate"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <!-- 绌哄垪锛屼繚鎸佸竷灞� -->
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="寮�濮嬫椂闂�" prop="startTime">
+ <el-select
+ v-model="meetingForm.startTime"
+ placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="time in startTimeOptions"
+ :key="time.value"
+ :label="time.label"
+ :value="time.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁撴潫鏃堕棿" prop="endTime">
+ <el-select
+ v-model="meetingForm.endTime"
+ placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="time in endTimeOptions"
+ :key="time.value"
+ :label="time.label"
+ :value="time.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-form-item label="鍙備細浜哄憳" prop="participants">
+ <el-select
+ v-model="meetingForm.participants"
+ multiple
+ filterable
+ placeholder="璇烽�夋嫨鍙備細浜哄憳"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="person in employees"
+ :key="person.id"
+ :label="`${person.staffName}${person.postName ? ` (${person.postName})` : ''}`"
+ :value="person.id"
+ />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="浼氳璇存槑" prop="description">
+ <el-input
+ v-model="meetingForm.description"
+ type="textarea"
+ :rows="4"
+ placeholder="璇疯緭鍏ヤ細璁鏄�"
+ />
+ </el-form-item>
+ </el-form>
+
+ <div class="form-footer">
+ <el-button @click="resetForm">閲嶇疆</el-button>
+ <el-button type="primary" @click="submitForm">鎻愪氦</el-button>
+ </div>
+ </el-card>
+ </div>
</template>
<script setup>
@@ -157,37 +163,37 @@
// 鐢宠绫诲瀷閫夐」
const applicationTypes = ref([
- {
- value: 'approval',
- name: '瀹℃壒娴佺▼浼氳',
- desc: '闇�瑕佺粡杩囧绾у鎵圭殑浼氳鐢宠',
- icon: Document
- },
- {
- value: 'department',
- name: '閮ㄩ棬绾т細璁�',
- desc: '閮ㄩ棬鍐呴儴浼氳鐢宠娴佺▼',
- icon: Promotion
- },
- {
- value: 'notification',
- name: '浼氳閫氱煡',
- desc: '鏃犻渶瀹℃壒鐩存帴鍙戝竷鐨勪細璁�氱煡',
- icon: Bell
- }
+ {
+ value: 'approval',
+ name: '瀹℃壒娴佺▼浼氳',
+ desc: '闇�瑕佺粡杩囧绾у鎵圭殑浼氳鐢宠',
+ icon: Document
+ },
+ {
+ value: 'department',
+ name: '閮ㄩ棬绾т細璁�',
+ desc: '閮ㄩ棬鍐呴儴浼氳鐢宠娴佺▼',
+ icon: Promotion
+ },
+ {
+ value: 'notification',
+ name: '浼氳閫氱煡',
+ desc: '鏃犻渶瀹℃壒鐩存帴鍙戝竷鐨勪細璁�氱煡',
+ icon: Bell
+ }
])
// 琛ㄥ崟鏁版嵁
const meetingForm = reactive({
- title: '',
- type: '',
- roomId: '',
- host: '',
- meetingDate: '',
- startTime: '',
- endTime: '',
- participants: [],
- description: ''
+ title: '',
+ type: '',
+ roomId: '',
+ host: '',
+ meetingDate: '',
+ startTime: '',
+ endTime: '',
+ participants: [],
+ description: ''
})
// 琛ㄥ崟寮曠敤
@@ -199,270 +205,307 @@
// 鍛樺伐鍒楄〃
const employees = ref([])
+// 鏃堕棿閫夐」锛堜互鍗婂皬鏃朵负闂撮殧锛�
+const timeOptions = ref([])
+
const getTimeInMinutes = (time) => {
- if (!time) return -1
- const [hour, minute] = time.split(':').map(Number)
- return hour * 60 + minute
+ if (!time) return -1
+ const [hour, minute] = time.split(':').map(Number)
+ return hour * 60 + minute
}
const isToday = (dateText) => {
- if (!dateText) return false
- const [year, month, day] = dateText.split('-').map(Number)
- const now = new Date()
- return year === now.getFullYear() && month === now.getMonth() + 1 && day === now.getDate()
+ if (!dateText) return false
+ const [year, month, day] = dateText.split('-').map(Number)
+ const now = new Date()
+ return year === now.getFullYear() && month === now.getMonth() + 1 && day === now.getDate()
}
const validateStartTime = (_rule, value, callback) => {
- if (!value) {
- callback()
- return
- }
- callback()
+ if (!value) {
+ callback()
+ return
+ }
+
+ if (isToday(meetingForm.meetingDate)) {
+ const now = new Date()
+ const currentMinutes = now.getHours() * 60 + now.getMinutes()
+ if (getTimeInMinutes(value) > currentMinutes) {
+ callback(new Error('褰撳ぉ寮�濮嬫椂闂翠笉鑳芥櫄浜庡綋鍓嶆椂闂�'))
+ return
+ }
+ }
+
+ callback()
}
const validateEndTime = (_rule, value, callback) => {
- if (!value || !meetingForm.startTime) {
- callback()
- return
- }
- if (getTimeInMinutes(value) <= getTimeInMinutes(meetingForm.startTime)) {
- callback(new Error('缁撴潫鏃堕棿蹇呴』澶т簬寮�濮嬫椂闂�'))
- return
- }
- callback()
+ if (!value || !meetingForm.startTime) {
+ callback()
+ return
+ }
+
+ if (getTimeInMinutes(value) <= getTimeInMinutes(meetingForm.startTime)) {
+ callback(new Error('缁撴潫鏃堕棿蹇呴』澶т簬寮�濮嬫椂闂�'))
+ return
+ }
+
+ callback()
}
+// 琛ㄥ崟鏍¢獙瑙勫垯
const rules = {
- title: [{required: true, message: '璇疯緭鍏ヤ細璁富棰�', trigger: 'blur'}],
- roomId: [{required: true, message: '璇烽�夋嫨浼氳瀹�', trigger: 'change'}],
- host: [{required: true, message: '璇疯緭鍏ヤ富鎸佷汉', trigger: 'blur'}],
- meetingDate: [{required: true, message: '璇烽�夋嫨浼氳鏃ユ湡', trigger: 'change'}],
- startTime: [
- {required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change'},
- {validator: validateStartTime, trigger: 'change'}
- ],
- endTime: [
- {required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change'},
- {validator: validateEndTime, trigger: 'change'}
- ],
- participants: [{required: true, message: '璇烽�夋嫨鍙備細浜哄憳', trigger: 'change'}]
+ title: [{required: true, message: '璇疯緭鍏ヤ細璁富棰�', trigger: 'blur'}],
+ roomId: [{required: true, message: '璇烽�夋嫨浼氳瀹�', trigger: 'change'}],
+ host: [{required: true, message: '璇疯緭鍏ヤ富鎸佷汉', trigger: 'blur'}],
+ meetingDate: [{required: true, message: '璇烽�夋嫨浼氳鏃ユ湡', trigger: 'change'}],
+ startTime: [
+ {required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change'},
+ {validator: validateStartTime, trigger: 'change'}
+ ],
+ endTime: [
+ {required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change'},
+ {validator: validateEndTime, trigger: 'change'}
+ ],
+ participants: [{required: true, message: '璇烽�夋嫨鍙備細浜哄憳', trigger: 'change'}]
}
-// 鏃堕棿閫夋嫨鍣ㄧ鐢ㄩ�昏緫
-const disabledStartHours = () => {
- const hours = []
- for (let h = 0; h < 24; h++) {
- if (h < 8 || h > 18) hours.push(h)
- }
- if (isToday(meetingForm.meetingDate)) {
- const now = new Date()
- for (let h = 8; h < now.getHours(); h++) {
- if (!hours.includes(h)) hours.push(h)
- }
- }
- return hours
+const startTimeOptions = computed(() => {
+ if (!isToday(meetingForm.meetingDate)) {
+ return timeOptions.value
+ }
+ const now = new Date()
+ const currentMinutes = now.getHours() * 60 + now.getMinutes()
+ return timeOptions.value.filter(item => getTimeInMinutes(item.value) <= currentMinutes)
+})
+
+const endTimeOptions = computed(() => {
+ if (!meetingForm.startTime) {
+ return timeOptions.value
+ }
+ const startMinutes = getTimeInMinutes(meetingForm.startTime)
+ return timeOptions.value.filter(item => getTimeInMinutes(item.value) > startMinutes)
+})
+
+// 鍒濆鍖栨椂闂撮�夐」
+const initTimeOptions = () => {
+ const options = []
+ const now = new Date()
+ const currentHour = now.getHours()
+ const currentMinute = now.getMinutes()
+ // meetingDate 鏄� "yyyy-MM-dd"
+ const meetingDate = new Date(meetingForm.meetingDate)
+
+ const isSameDay =
+ now.getFullYear() === meetingDate.getFullYear() &&
+ now.getMonth() === meetingDate.getMonth() &&
+ now.getDate() === meetingDate.getDate()
+
+ console.log('鏄惁鍚屼竴澶�:', isSameDay)
+ for (let hour = 8; hour <= 18; hour++) {
+ // 寮�濮嬫椂闂村繀椤绘櫄浜庡綋鍓嶆椂闂�
+ if (hour < currentHour && isSameDay) {
+ continue
+ }
+ if (hour === currentHour && currentMinute > 30 && isSameDay) {
+ continue
+ }
+ // 姣忎釜灏忔椂娣诲姞涓や釜閫夐」锛氭暣鐐瑰拰鍗婄偣
+ options.push({
+ value: `${hour.toString().padStart(2, '0')}:00`,
+ label: `${hour.toString().padStart(2, '0')}:00`
+ })
+
+ if (hour < 18) { // 18:00涔嬪悗娌℃湁鍗婄偣閫夐」
+ options.push({
+ value: `${hour.toString().padStart(2, '0')}:30`,
+ label: `${hour.toString().padStart(2, '0')}:30`
+ })
+ }
+ }
+ timeOptions.value = options
}
-const disabledStartMinutes = (hour) => {
- const minutes = []
- for (let m = 0; m < 60; m++) {
- if (m !== 0 && m !== 30) minutes.push(m)
- }
- if (isToday(meetingForm.meetingDate)) {
- const now = new Date()
- if (hour === now.getHours()) {
- if (now.getMinutes() >= 30) {
- minutes.push(0)
- }
- }
- }
- return minutes
-}
-
-const disabledEndHours = () => {
- const hours = []
- for (let h = 0; h < 24; h++) {
- if (h < 8 || h > 18) hours.push(h)
- }
- if (meetingForm.startTime) {
- const startHour = parseInt(meetingForm.startTime.split(':')[0])
- for (let h = 8; h < startHour; h++) {
- if (!hours.includes(h)) hours.push(h)
- }
- }
- return hours
-}
-
-const disabledEndMinutes = (hour) => {
- const minutes = []
- for (let m = 0; m < 60; m++) {
- if (m !== 0 && m !== 30) minutes.push(m)
- }
- if (meetingForm.startTime) {
- const startHour = parseInt(meetingForm.startTime.split(':')[0])
- const startMinute = parseInt(meetingForm.startTime.split(':')[1])
- if (hour === startHour) {
- if (startMinute >= 0) minutes.push(0)
- if (startMinute >= 30) minutes.push(30)
- // only keep minutes > startMinute
- for (let m = 0; m <= startMinute; m++) {
- if (!minutes.includes(m)) minutes.push(m)
- }
- }
- }
- return minutes
-}
+watch(() => meetingForm.meetingDate, () => {
+ if (meetingForm.startTime && !startTimeOptions.value.some(item => item.value === meetingForm.startTime)) {
+ meetingForm.startTime = ''
+ }
+ if (meetingForm.endTime && !endTimeOptions.value.some(item => item.value === meetingForm.endTime)) {
+ meetingForm.endTime = ''
+ }
+ if (meetingForm.startTime) {
+ meetingFormRef.value?.validateField('startTime')
+ }
+ if (meetingForm.endTime) {
+ meetingFormRef.value?.validateField('endTime')
+ }
+ initTimeOptions()
+})
watch(() => meetingForm.startTime, () => {
- if (meetingForm.endTime && getTimeInMinutes(meetingForm.endTime) <= getTimeInMinutes(meetingForm.startTime)) {
- meetingForm.endTime = ''
- }
- if (meetingForm.endTime) {
- meetingFormRef.value?.validateField('endTime')
- }
-
+ if (meetingForm.endTime && getTimeInMinutes(meetingForm.endTime) <= getTimeInMinutes(meetingForm.startTime)) {
+ meetingForm.endTime = ''
+ }
+ if (meetingForm.endTime) {
+ meetingFormRef.value?.validateField('endTime')
+ }
+
})
// 绂佺敤鏃ユ湡锛堢鐢ㄤ粖澶╀箣鍓嶇殑鏃ユ湡锛�
const disabledDate = (time) => {
- // 绂佺敤浠婂ぉ涔嬪墠鐨勬棩鏈�
- return time.getTime() < Date.now() - 86400000
+ // 绂佺敤浠婂ぉ涔嬪墠鐨勬棩鏈�
+ return time.getTime() < Date.now() - 86400000
}
// 鍒囨崲鐢宠绫诲瀷
const changeType = (type) => {
- currentType.value = type
+ currentType.value = type
}
// 鑾峰彇褰撳墠绫诲瀷鍚嶇О
const getCurrentTypeName = () => {
- const type = applicationTypes.value.find(t => t.value === currentType.value)
- return type ? type.name : ''
+ const type = applicationTypes.value.find(t => t.value === currentType.value)
+ return type ? type.name : ''
}
// 閲嶇疆琛ㄥ崟
const resetForm = () => {
- meetingFormRef.value?.resetFields()
+ meetingFormRef.value?.resetFields()
}
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
- meetingFormRef.value?.validate((valid) => {
- if (valid) {
-
- let formData = {...meetingForm}
- formData.applicationType = currentType.value
- formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00`
- formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00`
- formData.participants = JSON.stringify(formData.participants)
- console.log(formData)
- saveMeetingApplication(formData).then(() => {
-
- // 妯℃嫙鎻愪氦鎿嶄綔
- ElMessage.success(`${getCurrentTypeName()}鎻愪氦鎴愬姛`)
- resetForm()
- })
-
- }
- })
+ meetingFormRef.value?.validate((valid) => {
+ if (valid) {
+
+ let formData = {...meetingForm}
+ formData.applicationType = currentType.value
+ formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00`
+ formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00`
+ formData.participants = JSON.stringify(formData.participants)
+ console.log(formData)
+ saveMeetingApplication(formData).then(() => {
+
+ // 妯℃嫙鎻愪氦鎿嶄綔
+ ElMessage.success(`${getCurrentTypeName()}鎻愪氦鎴愬姛`)
+
+ // 鏍规嵁涓嶅悓绫诲瀷鎵ц涓嶅悓鎿嶄綔
+ switch (currentType.value) {
+ case 'approval':
+ ElMessage.info('浼氳宸叉彁浜ゅ鎵规祦绋�')
+ break
+ case 'department':
+ ElMessage.info('閮ㄩ棬绾т細璁敵璇峰凡鎻愪氦')
+ break
+ case 'notification':
+ ElMessage.info('浼氳閫氱煡宸插彂甯�')
+ break
+ }
+ resetForm()
+ })
+
+ }
+ })
}
// 椤甸潰鍔犺浇鏃跺垵濮嬪寲
onMounted(() => {
- getRoomEnum().then(res => {
- meetingRooms.value = res.data
- })
- staffOnJobListPage({
- current: -1,
- size: -1,
- staffState: 1
- }).then(res => {
- employees.value = res.data.records.sort((a, b) => (a.postName || '').localeCompare(b.postName || ''))
- })
+ initTimeOptions()
+ getRoomEnum().then(res => {
+ meetingRooms.value = res.data
+ })
+ staffOnJobListPage({
+ current: -1,
+ size: -1,
+ staffState: 1
+ }).then(res => {
+ employees.value = res.data.records.sort((a, b) => (a.postName || '').localeCompare(b.postName || ''))
+ })
})
</script>
<style scoped>
.app-container {
- padding: 20px;
+ padding: 20px;
}
.page-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
}
.page-header h2 {
- margin: 0;
- color: #303133;
+ margin: 0;
+ color: #303133;
}
.type-card {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
.type-selector {
- display: flex;
- gap: 20px;
+ display: flex;
+ gap: 20px;
}
.type-item {
- flex: 1;
- display: flex;
- align-items: center;
- padding: 20px;
- border: 1px solid #ebeef5;
- border-radius: 8px;
- cursor: pointer;
- transition: all 0.3s;
+ flex: 1;
+ display: flex;
+ align-items: center;
+ padding: 20px;
+ border: 1px solid #ebeef5;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.3s;
}
.type-item:hover {
- border-color: #409eff;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border-color: #409eff;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.type-item.active {
- border-color: #409eff;
- background-color: #ecf5ff;
+ border-color: #409eff;
+ background-color: #ecf5ff;
}
.type-icon {
- margin-right: 15px;
- color: #409eff;
+ margin-right: 15px;
+ color: #409eff;
}
.type-name {
- font-size: 16px;
- font-weight: 500;
- color: #303133;
- margin-bottom: 5px;
+ font-size: 16px;
+ font-weight: 500;
+ color: #303133;
+ margin-bottom: 5px;
}
.type-desc {
- font-size: 14px;
- color: #909399;
+ font-size: 14px;
+ color: #909399;
}
.form-header {
- margin-bottom: 20px;
- padding-bottom: 15px;
- border-bottom: 1px solid #ebeef5;
+ margin-bottom: 20px;
+ padding-bottom: 15px;
+ border-bottom: 1px solid #ebeef5;
}
.form-header h3 {
- margin: 0;
- color: #303133;
+ margin: 0;
+ color: #303133;
}
.form-footer {
- display: flex;
- justify-content: flex-end;
- gap: 10px;
- margin-top: 30px;
- padding-top: 20px;
- border-top: 1px solid #ebeef5;
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-top: 30px;
+ padding-top: 20px;
+ border-top: 1px solid #ebeef5;
}
</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
index dea9495..26e2c24 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
@@ -36,7 +36,7 @@
<el-table-column prop="location" label="浼氳鍦扮偣" align="center" width="150"/>
<el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
<template #default="scope">
- {{ scope.row.staffCount }}浜�
+ {{ scope.row.participants.length }}浜�
</template>
</el-table-column>
<el-table-column prop="status" label="瀹℃壒鐘舵��" align="center" width="120">
@@ -233,9 +233,9 @@
let resp = await getExamineList({...searchForm, ...queryParams})
approvalList.value = resp.data.records.map(it => {
let room = roomEnum.value.find(room => it.roomId === room.id)
- it.location = room ? `${room.name}(${room.location})` : ''
+ it.location = `${room.name}(${room.location})`
let staffs = JSON.parse(it.participants)
- it.staffCount = staffs.length
+ it.staffCount = staffs.size
it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
return {
diff --git a/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
index 235faa3..9b5325f 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
@@ -145,11 +145,10 @@
if (endIdx === -1) {
endIdx = timeSlots.value.length
}
- // 寰�鍚庡欢浼镐竴鏍硷紝璁╀細璁牸瀛愯鐩栧埌缁撴潫鏃堕棿鍒椾笂
- const displayEndIdx = Math.min(endIdx + 1, timeSlots.value.length)
- if (startIdx !== -1) {
+ console.log('endIdx111', endIdx)
+ if (startIdx !== -1 && endIdx !== -1) {
// 鏍囪琚崰鐢ㄧ殑鏃堕棿娈�
- for (let i = startIdx; i < displayEndIdx; i++) {
+ for (let i = startIdx; i < endIdx; i++) {
occupiedSlots.add(timeSlots.value[i].value)
}
@@ -157,7 +156,7 @@
cells.push({
type: 'meeting',
meeting: meeting,
- span: displayEndIdx - startIdx,
+ span: endIdx - startIdx,
startTime: meeting.startTime,
endTime: meeting.endTime
})
diff --git a/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
index a3ae223..dace531 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
@@ -34,7 +34,7 @@
<el-table-column prop="location" label="浼氳鍦扮偣" align="center" width="150"/>
<el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
<template #default="scope">
- {{ scope.row.staffCount }}浜�
+ {{ scope.row.participants.length }}浜�
</template>
</el-table-column>
<el-table-column prop="status" label="鍙戝竷鐘舵��" align="center" width="120">
@@ -231,9 +231,9 @@
let resp = await getMeetingPublish({...searchForm, ...queryParams})
approvalList.value = resp.data.records.map(it => {
let room = roomEnum.value.find(room => it.roomId === room.id)
- it.location = room ? `${room.name}(${room.location})` : ''
+ it.location = `${room.name}(${room.location})`
let staffs = JSON.parse(it.participants)
- it.staffCount = staffs.length
+ it.staffCount = staffs.size
it.status = it.publishStatus
it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
diff --git a/src/views/collaborativeApproval/notificationManagement/summary/index.vue b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
index 9f3fc7f..bf6e230 100644
--- a/src/views/collaborativeApproval/notificationManagement/summary/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
@@ -28,7 +28,7 @@
<el-table-column prop="location" label="浼氳鍦扮偣" align="center" width="150" />
<el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
<template #default="scope">
- {{ scope.row.staffCount }}浜�
+ {{ scope.row.participants.length }}浜�
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" align="center" width="200" fixed="right">
@@ -207,9 +207,9 @@
let resp = await getMeetingPublish({ ...searchForm, ...queryParams })
meetingList.value = resp.data.records.map(it => {
let room = roomEnum.value.find(room => it.roomId === room.id)
- it.location = room ? `${room.name}(${room.location})` : ''
+ it.location = `${room.name}(${room.location})`
let staffs = JSON.parse(it.participants)
- it.staffCount = staffs.length
+ it.staffCount = staffs.size
it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => {
return {
@@ -260,7 +260,7 @@
<p><strong>涓绘寔浜猴細</strong>${row.host}</p>
<p><strong>鍙備細浜哄憳锛�</strong></p>
<ol>
- ${(row.participants || []).map(p => `<li>${p?.name || ''}</li>`).join('')}
+ ${row.participants.map(p => `<li>${p.name}</li>`).join('')}
</ol>
<p><strong>浼氳鍐呭锛�</strong></p>
<ol>
diff --git a/src/views/collaborativeApproval/purchaseApproval/index.vue b/src/views/collaborativeApproval/purchaseApproval/index.vue
index d39748f..b276bec 100644
--- a/src/views/collaborativeApproval/purchaseApproval/index.vue
+++ b/src/views/collaborativeApproval/purchaseApproval/index.vue
@@ -278,7 +278,7 @@
},
rules: {
purchaseContractNumber: [
- { required: false, message: "璇疯緭鍏�", trigger: "blur" },
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
],
projectName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -448,7 +448,9 @@
productData.value = [];
fileList.value = [];
if (operationType.value == "add") {
- form.value.purchaseContractNumber = "";
+ createPurchaseNo().then(res => {
+ form.value.purchaseContractNumber = res.data;
+ });
}
userListNoPage().then(res => {
userList.value = res.data;
@@ -519,7 +521,7 @@
}
// 鎻愪氦琛ㄥ崟
const submitForm = n => {
- proxy.$refs["formRef"].validate(async valid => {
+ proxy.$refs["formRef"].validate(valid => {
if (valid) {
if (productData.value.length > 0) {
form.value.productData = proxy.HaveJson(productData.value);
@@ -534,21 +536,6 @@
form.value.tempFileIds = tempFileIds;
form.value.type = 2;
form.value.approvalStatus = n;
-
- // 濡傛灉閲囪喘鍚堝悓鍙蜂负绌猴紝鍒欐牴鎹綍鍏ユ棩鏈熻嚜鍔ㄧ敓鎴�
- if (!form.value.purchaseContractNumber) {
- try {
- const purchaseNoRes = await createPurchaseNo(form.value.entryDate);
- if (purchaseNoRes?.data) {
- form.value.purchaseContractNumber = purchaseNoRes.data;
- }
- } catch (error) {
- console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
- proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
- return;
- }
- }
-
addOrEditPurchase(form.value).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
diff --git a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
index f7ba9d9..edf045c 100644
--- a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
+++ b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -318,7 +318,7 @@
formatData: (v) => (v === "active" ? "鐢熸晥涓�" : "宸插簾姝�"),
formatType: (v) => (v === "active" ? "success" : "info"),
},
- { label: "宸茶浜烘暟", prop: "readCount", width: 100 },
+ // { label: "宸茶浜烘暟", prop: "readCount", width: 100 },
{
dataType: "action",
label: "鎿嶄綔",
diff --git a/src/views/collaborativeApproval/sealManagement/index.vue b/src/views/collaborativeApproval/sealManagement/index.vue
index a06f6d5..9d68848 100644
--- a/src/views/collaborativeApproval/sealManagement/index.vue
+++ b/src/views/collaborativeApproval/sealManagement/index.vue
@@ -7,6 +7,7 @@
</div>
</template>
+
<!-- 鐢ㄥ嵃鐢宠绠$悊 -->
<div class="tab-content">
<el-row :gutter="20" class="mb-20 ">
@@ -44,7 +45,7 @@
:isShowPagination="true"
@pagination="paginationChange"
/>
- </div>
+ </div>
</el-card>
<!-- 鐢ㄥ嵃鐢宠瀵硅瘽妗� -->
@@ -176,7 +177,6 @@
const sealFormRef = ref()
const userList = ref([])
const sealForm = reactive({
- id: null,
applicationNum: '',
title: '',
sealType: '',
@@ -241,9 +241,9 @@
// 鐢ㄥ嵃鐢宠琛ㄦ牸鍒楅厤缃紙闇�鍦� getStatusText/getSealTypeText 绛変箣鍚庡畾涔夛級
const sealTableColumn = ref([
- { label: '鐢宠缂栧彿', prop: 'applicationNum' },
+ { label: '鐢宠缂栧彿', prop: 'applicationNum',},
{ label: '鐢宠鏍囬', prop: 'title', showOverflowTooltip: true },
- { label: '鐢宠浜�', prop: 'createUserName' },
+ { label: '鐢宠浜�', prop: 'createUserName', },
{ label: '鎵�灞為儴闂�', prop: 'department', width: 150 },
{
label: '鐢ㄥ嵃绫诲瀷',
@@ -261,38 +261,34 @@
formatData: (v) => getStatusText(v),
formatType: (v) => getStatusType(v)
},
- { label: '瀹℃壒浜�', prop: 'approveUserName', width: 100 },
{
dataType: 'action',
label: '鎿嶄綔',
- width: 250,
+ width: 200,
fixed: 'right',
align: 'center',
operation: [
{
name: '瀹℃壒',
clickFun: (row) => approveSeal(row),
- showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId
+ showHide: (row) => row.status === 'pending'
},
{
name: '鎷掔粷',
clickFun: (row) => rejectSeal(row),
- showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId
+ showHide: (row) => row.status === 'pending'
},
- {
- name: '閲嶆柊鐢宠',
- clickFun: (row) => reapplySeal(row),
- showHide: (row) => row.status === 'rejected' && Number(userStore.id) === row.createUser
- },
- { name: '璇︽儏', clickFun: (row) => viewSealDetail(row) }
+ { name: '璇︽儏', clickFun: (row) => viewSealDetail(row) }
]
}
])
// 鎼滅储鍗扮珷鐢宠
const searchSealApplications = () => {
- page.current = 1
+ page.current=1
getSealApplicationList()
+
+ // ElMessage.success('鎼滅储瀹屾垚')
}
// 閲嶇疆鍗扮珷鐢宠鎼滅储
const resetSealSearch = () => {
@@ -301,58 +297,37 @@
sealSearchForm.applicationNum = ''
searchSealApplications()
}
-
-// 閲嶆柊鐢宠鐢ㄥ嵃
-const reapplySeal = (row) => {
- // 棰勫~琛ㄥ崟鏁版嵁
- Object.assign(sealForm, {
- id: row.id,
- applicationNum: row.applicationNum,
- title: row.title,
- sealType: row.sealType,
- reason: row.reason,
- approveUserId: row.approveUserId,
- urgency: row.urgency || 'normal',
- status: 'pending',
- storageBlobDTOs: row.storageBlobVOList || []
- })
- showSealApplyDialog.value = true
-}
-
// 鎻愪氦鐢ㄥ嵃鐢宠
const submitSealApplication = async () => {
try {
await sealFormRef.value.validate()
- const request = sealForm.id ? updateSealApplication : addSealApplication
- request(sealForm).then(res => {
- if (res.code == 200) {
- ElMessage.success(sealForm.id ? '閲嶆柊鐢宠鎴愬姛' : '鐢宠鎻愪氦鎴愬姛')
+ addSealApplication(sealForm).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鐢宠鎻愪氦鎴愬姛')
closeSealApplyDialog()
getSealApplicationList()
Object.assign(sealForm, {
- id: null,
- applicationNum: '',
- title: '',
- sealType: '',
- reason: '',
- approveUserId: '',
- urgency: 'normal',
- status: 'pending',
- storageBlobDTOs: []
- })
+ applicationNum: '',
+ title: '',
+ sealType: '',
+ reason: '',
+ approveUserId: '',
+ urgency: 'normal',
+ status: 'pending',
+ storageBlobDTOs: []
+ })
}
}).catch(err => {
console.log(err.msg)
})
+
} catch (error) {
}
}
-
// 鍏抽棴鐢ㄥ嵃鐢宠瀵硅瘽妗�
const closeSealApplyDialog = () => {
// 娓呯┖琛ㄥ崟鏁版嵁
Object.assign(sealForm, {
- id: null,
applicationNum: '',
title: '',
sealType: '',
@@ -408,7 +383,7 @@
}).then(() => {
row.status = 'approved'
updateSealApplication(row).then(res => {
- if (res.code == 200) {
+ if(res.code == 200){
ElMessage.success('瀹℃壒閫氳繃')
getSealApplicationList()
}
@@ -424,9 +399,8 @@
inputErrorMessage: '鎷掔粷鍘熷洜涓嶈兘涓虹┖'
}).then(({ value }) => {
row.status = 'rejected'
- row.reason = value
updateSealApplication(row).then(res => {
- if (res.code == 200) {
+ if(res.code == 200){
ElMessage.success('宸叉嫆缁濈敵璇�')
getSealApplicationList()
}
@@ -444,13 +418,13 @@
const getSealApplicationList = async () => {
tableLoading.value = true
listSealApplication(page, sealSearchForm)
- .then(res => {
- sealApplications.value = res.data.records
- page.total = res.data.total
- tableLoading.value = false
- }).catch(err => {
- tableLoading.value = false
- })
+ .then(res => {
+ sealApplications.value = res.data.records
+ page.total = res.data.total
+ tableLoading.value = false
+ }).catch(err => {
+ tableLoading.value = false
+ })
}
// 鍒嗛〉鍙樺寲澶勭悊
const paginationChange = (obj) => {
@@ -517,4 +491,4 @@
.attachment-table {
border-radius: 4px;
}
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/customerService/afterSalesHandling/components/formDia.vue b/src/views/customerService/afterSalesHandling/components/formDia.vue
index 4b2964b..9abf4fc 100644
--- a/src/views/customerService/afterSalesHandling/components/formDia.vue
+++ b/src/views/customerService/afterSalesHandling/components/formDia.vue
@@ -82,6 +82,33 @@
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璇勫垎锛�" prop="rating">
+ <el-rate
+ v-model="form.rating"
+ :disabled="operationType === 'view'"
+ :max="5"
+ show-text
+ :texts="['闈炲父涓嶆弧鎰�', '涓嶆弧鎰�', '涓�鑸�', '婊℃剰', '闈炲父婊℃剰']"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="璇勪环鍐呭鎻忚堪锛�" prop="evaluation">
+ <el-input
+ v-model="form.evaluation"
+ placeholder="璇疯緭鍏ヨ瘎浠峰唴瀹规弿杩�"
+ clearable
+ :disabled="operationType === 'view'"
+ type="textarea"
+ :rows="3"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
</el-form>
<el-row :gutter="30">
<el-col :span="12">
@@ -148,6 +175,8 @@
disposeUserId: "",
disDate: "",
disRes: "",
+ rating: null,
+ evaluation: "",
},
rules: {
feedbackDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
diff --git a/src/views/customerService/afterSalesHandling/index.vue b/src/views/customerService/afterSalesHandling/index.vue
index a42337d..a3adcc9 100644
--- a/src/views/customerService/afterSalesHandling/index.vue
+++ b/src/views/customerService/afterSalesHandling/index.vue
@@ -102,6 +102,7 @@
></PIMTable>
</div>
<form-dia ref="formDia" @close="handleQuery"></form-dia>
+ <view-dia ref="viewDia"></view-dia>
<FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="after_sales_service" :record-id="recordId" />
</div>
</template>
@@ -109,6 +110,7 @@
<script setup>
import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick, defineAsyncComponent} from "vue";
import FormDia from "@/views/customerService/afterSalesHandling/components/formDia.vue";
+import ViewDia from "@/views/customerService/components/viewDia.vue";
import { ElMessageBox } from "element-plus";
import {
afterSalesServiceListPage,
@@ -213,6 +215,15 @@
},
align: "center"
},
+ {
+ label: "鏁伴噺",
+ prop: "productModelQuantities",
+ align: "center",
+ formatData: params => {
+ if (!params) return "0";
+ return String(params).split(',').reduce((sum, val) => sum + (Number(val) || 0), 0);
+ }
+ },
{
label: "闂鎻忚堪",
prop: "proDesc",
@@ -247,10 +258,10 @@
}
},
{
- name: "鏌ョ湅",
+ name: "璇︽儏",
type: "text",
clickFun: (row) => {
- openForm("view", row);
+ viewDia.value?.openDialog(row);
},
},
// TODO 涓哄啓鎶ュ憡娣诲姞鐨�
@@ -278,6 +289,7 @@
selectedRows.value = selection;
};
const formDia = ref()
+const viewDia = ref()
const fileListRef = ref(null)
const fileListDialogVisible = ref(false)
const currentFileRow = ref(null)
diff --git a/src/views/customerService/components/viewDia.vue b/src/views/customerService/components/viewDia.vue
new file mode 100644
index 0000000..96452b4
--- /dev/null
+++ b/src/views/customerService/components/viewDia.vue
@@ -0,0 +1,123 @@
+<template>
+ <el-dialog v-model="dialogVisible" title="鍞悗鍗曡鎯�" width="80%" @close="closeDia">
+ <div v-loading="loading">
+ <span class="descriptions">鍩虹璧勬枡</span>
+ <el-descriptions :column="4" border style="margin-top: 10px;">
+ <el-descriptions-item label="瀹㈡埛鍚嶇О">{{ detail.customerName || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鍞悗绫诲瀷">{{ getDictLabel(classificationOptions, detail.serviceType) }}</el-descriptions-item>
+ <el-descriptions-item label="鍏宠仈閿�鍞崟鍙�">{{ detail.salesContractNo || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="绱ф�ョ▼搴�">{{ getDictLabel(degreeOfUrgencyOptions, detail.urgency) }}</el-descriptions-item>
+ <el-descriptions-item label="宸ュ崟缂栧彿">{{ detail.afterSalesServiceNo || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="澶勭悊鐘舵��">
+ <el-tag :type="detail.status === 1 ? 'danger' : 'success'" size="small">
+ {{ detail.status === 1 ? '寰呭鐞�' : '宸插鐞�' }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="鐧昏浜�">{{ detail.checkNickName || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鍙嶉鏃ユ湡">{{ detail.feedbackDate || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="瀹㈡埛璇夋眰" :span="4">{{ detail.proDesc || '-' }}</el-descriptions-item>
+ </el-descriptions>
+
+ <div style="margin-top: 20px;">
+ <span class="descriptions">澶勭悊淇℃伅</span>
+ <el-descriptions :column="3" border style="margin-top: 10px;">
+ <el-descriptions-item label="澶勭悊浜�">{{ detail.disposeNickName || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="澶勭悊鏃ユ湡">{{ detail.disDate || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="澶勭悊缁撴灉" :span="3">{{ detail.disRes || '-' }}</el-descriptions-item>
+ </el-descriptions>
+ </div>
+
+ <div style="margin-top: 20px;">
+ <span class="descriptions">鍏宠仈浜у搧</span>
+ <el-table :data="tableData" border style="width: 100%; margin-top: 10px;">
+ <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+ <el-table-column prop="productCategory" label="浜у搧澶х被" align="center" />
+ <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" align="center" />
+ <el-table-column prop="unit" label="鍗曚綅" align="center" />
+ <el-table-column prop="expressCompany" label="蹇�掑叕鍙�" align="center" />
+ <el-table-column prop="expressNumber" label="蹇�掑崟鍙�" align="center" />
+ <el-table-column prop="shippingCarNumber" label="鍙戣揣杞︾墝" align="center" />
+ <el-table-column prop="shippingDate" label="鍙戣揣鏃ユ湡" align="center" />
+ <el-table-column prop="quantity" label="鍞悗鏁伴噺" align="center" />
+ </el-table>
+ </div>
+ </div>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍏抽棴</el-button>
+ </div>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { ref, computed, getCurrentInstance } from 'vue';
+import { getAfterSalesServiceById } from '@/api/customerService/index.js';
+
+const { proxy } = getCurrentInstance();
+const dialogVisible = ref(false);
+const loading = ref(false);
+const detail = ref({});
+const tableData = ref([]);
+
+const { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
+ "post_sale_waiting_list",
+ "degree_of_urgency"
+);
+const classificationOptions = computed(() => post_sale_waiting_list?.value || []);
+const degreeOfUrgencyOptions = computed(() => degree_of_urgency?.value || []);
+
+const getDictLabel = (options, value) => {
+ if (!value) return '-';
+ const item = options.find(i => String(i.value) === String(value));
+ return item ? item.label : value;
+};
+
+const openDialog = (row) => {
+ dialogVisible.value = true;
+ loading.value = true;
+ detail.value = {};
+ tableData.value = [];
+
+ getAfterSalesServiceById(row.id).then(res => {
+ loading.value = false;
+ if (res.code === 200) {
+ detail.value = res.data || {};
+ let productData = res.data?.salesLedgerDto?.productData || [];
+ const selectedIds = res.data.productModelIds ? String(res.data.productModelIds).split(",") : [];
+ tableData.value = productData.filter(item => selectedIds.includes(String(item.id)));
+ }
+ }).catch(() => {
+ loading.value = false;
+ });
+};
+
+const closeDia = () => {
+ dialogVisible.value = false;
+};
+
+defineExpose({
+ openDialog
+});
+</script>
+
+<style scoped>
+.descriptions {
+ 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;
+}
+</style>
diff --git a/src/views/customerService/feedbackRegistration/components/formDia.vue b/src/views/customerService/feedbackRegistration/components/formDia.vue
index fd3091e..e606107 100644
--- a/src/views/customerService/feedbackRegistration/components/formDia.vue
+++ b/src/views/customerService/feedbackRegistration/components/formDia.vue
@@ -97,6 +97,9 @@
{{ getShippingStatusText(row) }}
</el-tag>
</template>
+ <template #quantity="{ row }">
+ <el-input-number v-model="row.quantity" :min="0" size="small" />
+ </template>
</PIMTable>
</div>
</div>
@@ -147,6 +150,7 @@
salesContractNo: "",
proDesc: "",
customerName: "",
+ productModelQuantities: "",
},
rules: {
customerName: [
@@ -240,25 +244,12 @@
align: "center",
},
{ label: "鍙戣揣鏃ユ湡", prop: "shippingDate", minWidth: 100, align: "center" },
- { label: "鏁伴噺", prop: "quantity", width: 100 },
- { label: "绋庣巼(%)", prop: "taxRate", width: 100 },
{
- label: "鍚◣鍗曚环(鍏�)",
- prop: "taxInclusiveUnitPrice",
- width: 160,
- formatData: formatCurrency,
- },
- {
- label: "鍚◣鎬讳环(鍏�)",
- prop: "taxInclusiveTotalPrice",
- width: 160,
- formatData: formatCurrency,
- },
- {
- label: "涓嶅惈绋庢�讳环(鍏�)",
- prop: "taxExclusiveTotalPrice",
- width: 160,
- formatData: formatCurrency,
+ label: "鏁伴噺",
+ prop: "quantity",
+ width: 140,
+ dataType: "slot",
+ slot: "quantity",
},
{
dataType: "action",
@@ -326,7 +317,7 @@
form.value.customerId = null;
}
getSalesLedger({
- customerName: form.value.customerName,
+ customerId: form.value.customerId,
}).then(res => {
if (res.code === 200) {
associatedSalesOrderNumberOptions.value = res.data.records.map(item => ({
@@ -434,7 +425,7 @@
form.value = { ...row };
if (form.value.customerName) {
const res = await getSalesLedger({
- customerName: form.value.customerName,
+ customerId: form.value.customerId,
});
if (res?.code === 200) {
console.log(res);
@@ -446,6 +437,21 @@
id: item.id,
})
);
+ const opt = associatedSalesOrderNumberOptions.value.find(
+ item => item.value === form.value.salesContractNo
+ );
+ if (opt) {
+ let restoredData = (opt.productData || []).map(normalizeProductRow);
+ const selectedIds = form.value.productModelIds ? String(form.value.productModelIds).split(",") : [];
+ const quantities = form.value.productModelQuantities ? String(form.value.productModelQuantities).split(",") : [];
+ tableData.value = restoredData.filter(item => selectedIds.includes(String(item.id))).map(item => {
+ let qIndex = selectedIds.indexOf(String(item.id));
+ if (qIndex !== -1 && qIndex < quantities.length && quantities[qIndex] !== "") {
+ item.quantity = Number(quantities[qIndex]);
+ }
+ return item;
+ });
+ }
}
}
console.log(form.value);
@@ -458,6 +464,9 @@
form.value.productModelIds = tableData.value
.map(item => item.id)
.join(",");
+ form.value.productModelQuantities = tableData.value
+ .map(item => item.quantity || 0)
+ .join(",");
if (operationType.value === "add") {
afterSalesServiceAdd(form.value).then(response => {
proxy.$modal.msgSuccess("鏂板鎴愬姛");
diff --git a/src/views/customerService/feedbackRegistration/index.vue b/src/views/customerService/feedbackRegistration/index.vue
index 1e57bdb..bcbb326 100644
--- a/src/views/customerService/feedbackRegistration/index.vue
+++ b/src/views/customerService/feedbackRegistration/index.vue
@@ -112,6 +112,7 @@
</div>
<form-dia ref="formDia"
@close="handleQuery"></form-dia>
+ <view-dia ref="viewDia"></view-dia>
</div>
</template>
@@ -126,6 +127,7 @@
nextTick,
} from "vue";
import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue";
+ import ViewDia from "@/views/customerService/components/viewDia.vue";
import { ElMessageBox } from "element-plus";
import {
afterSalesServiceDelete,
@@ -149,14 +151,14 @@
{
icon: markRaw(FolderOpened),
count: 0,
- label: "宸插鐞�",
+ label: "寰呭鐞�",
color: "#ff9a2e",
bgColor: "#fff5e6",
},
{
icon: markRaw(UserFilled),
count: 0,
- label: "宸插畬鎴�",
+ label: "宸插鐞�",
color: "#00b42a",
bgColor: "#e6f7ed",
},
@@ -255,6 +257,15 @@
align: "center",
},
{
+ label: "鏁伴噺",
+ prop: "productModelQuantities",
+ align: "center",
+ formatData: params => {
+ if (!params) return "0";
+ return String(params).split(',').reduce((sum, val) => sum + (Number(val) || 0), 0);
+ }
+ },
+ {
label: "瀹㈡埛璇夋眰",
prop: "proDesc",
width: 300,
@@ -269,7 +280,16 @@
dataType: "action",
label: "鎿嶄綔",
fixed: "right",
+ width: 180,
+ align: "center",
operation: [
+ {
+ name: "璇︽儏",
+ type: "text",
+ clickFun: row => {
+ viewDia.value?.openDialog(row);
+ },
+ },
{
name: "缂栬緫",
type: "text",
@@ -307,9 +327,10 @@
selectedRows.value = selection;
};
const formDia = ref();
+ const viewDia = ref();
// 瀛楀吀鑾峰彇
- /*
+ /*
post_sale_waiting_list 鏂板鐨勫敭鍚庡垎绫�
degree_of_urgency 鏂板鐨勭揣鎬ョ▼搴�
work_order_status 涓婚〉鐨勫伐鍗曠姸鎬�
@@ -424,8 +445,8 @@
if (res.code === 200) {
const statsData = Array.isArray(res.data) ? res.data : [];
statsList.value[0].count = getStatsCountByStatus(statsData, 3);
- statsList.value[1].count = getStatsCountByStatus(statsData, 2);
- statsList.value[2].count = getStatsCountByStatus(statsData, 1);
+ statsList.value[1].count = getStatsCountByStatus(statsData, 1);
+ statsList.value[2].count = getStatsCountByStatus(statsData, 2);
}
});
};
diff --git a/src/views/equipmentManagement/inspectionManagement/components/formDia.vue b/src/views/equipmentManagement/inspectionManagement/components/formDia.vue
index 74cbb58..0f94f66 100644
--- a/src/views/equipmentManagement/inspectionManagement/components/formDia.vue
+++ b/src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -237,6 +237,14 @@
form.value = {...row}
form.value.inspector = form.value.inspectorIds.split(',').map(Number)
+ // 澶勭悊WEEKLY棰戠巼鐨勫洖鏄撅細灏唂requencyDetail鎷嗗垎涓簑eek鍜宼ime
+ if (form.value.frequencyType === 'WEEKLY' && form.value.frequencyDetail) {
+ const parts = form.value.frequencyDetail.split(',')
+ form.value.week = parts[0] || ''
+ form.value.time = parts[1] || ''
+ form.value.frequencyDetail = ''
+ }
+
// 濡傛灉鏈夎澶嘔D锛岃嚜鍔ㄨ缃澶囦俊鎭�
if (form.value.taskId) {
setDeviceModel(form.value.taskId);
diff --git a/src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue b/src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue
index 36256c8..481ea85 100644
--- a/src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue
+++ b/src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue
@@ -1,117 +1,131 @@
<template>
- <FormDialog
- v-model="dialogVisible"
- title="涓婁紶宸℃璁板綍"
- width="980px"
- @close="handleClose"
- @cancel="handleClose"
- >
+ <FormDialog v-model="dialogVisible"
+ :title="operationType === 'view' ? '宸℃璁板綍璇︽儏' : '涓婁紶宸℃璁板綍'"
+ width="980px"
+ :operation-type="operationType"
+ @close="handleClose"
+ @cancel="handleClose">
<main class="upload-content">
- <el-card v-if="taskInfo" class="section-card">
- <el-descriptions :column="1" border>
+ <el-card v-if="taskInfo"
+ class="section-card">
+ <el-descriptions :column="2"
+ border>
<el-descriptions-item label="宸℃浠诲姟鍚嶇О">
{{ taskInfo.taskName || "-" }}
</el-descriptions-item>
<el-descriptions-item label="宸℃椤圭洰">
{{ taskInfo.inspectionProject || "-" }}
</el-descriptions-item>
+ <el-descriptions-item label="鎵ц宸℃浜�">
+ <template v-if="formattedInspector && formattedInspector.length">
+ <el-tag v-for="tag in formattedInspector"
+ :key="tag"
+ size="small"
+ style="margin-right: 4px">
+ {{ tag }}
+ </el-tag>
+ </template>
+ <span v-else>--</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="棰戞">
+ {{ formatFrequencyType(taskInfo.frequencyType) || "-" }}
+ </el-descriptions-item>
+ <el-descriptions-item label="寮�濮嬫棩鏈熶笌鏃堕棿">
+ {{ formatFrequencyDetail(taskInfo.frequencyDetail) || "-" }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鐧昏浜�">
+ {{ taskInfo.registrant || "-" }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鐧昏鏃ユ湡">
+ {{ formatDateTime(taskInfo.createTime) || "-" }}
+ </el-descriptions-item>
<el-descriptions-item label="澶囨敞">
{{ taskInfo.remarks || "-" }}
</el-descriptions-item>
</el-descriptions>
</el-card>
-
<el-card class="section-card">
<h3>宸℃鐘舵��</h3>
- <el-radio-group v-model="hasException">
+ <el-radio-group v-model="hasException"
+ :disabled="operationType === 'view'">
<el-radio-button :value="false">姝e父</el-radio-button>
<el-radio-button :value="true">瀛樺湪寮傚父</el-radio-button>
</el-radio-group>
</el-card>
-
- <el-card v-if="hasException === true" class="section-card">
+ <el-card v-if="hasException === true"
+ class="section-card">
<h3>寮傚父鎻忚堪</h3>
- <el-input
- v-model="abnormalDescription"
- type="textarea"
- maxlength="500"
- show-word-limit
- :rows="4"
- placeholder="璇锋弿杩板紓甯告儏鍐�..."
- />
+ <el-input v-model="abnormalDescription"
+ type="textarea"
+ maxlength="500"
+ show-word-limit
+ :rows="4"
+ :disabled="operationType === 'view'"
+ placeholder="璇锋弿杩板紓甯告儏鍐�..." />
</el-card>
-
- <el-card v-if="hasException === true" class="section-card">
- <el-tabs v-model="currentUploadType">
- <el-tab-pane label="鐢熶骇鍓�" name="before" />
- <el-tab-pane label="鐢熶骇涓�" name="after" />
- <el-tab-pane label="鐢熶骇鍚�" name="issue" />
- </el-tabs>
-
- <div class="upload-buttons">
- <el-upload
- :show-file-list="false"
- :http-request="uploadFile"
- :disabled="getCurrentFiles().length >= uploadConfig.limit || uploading"
- accept="image/*"
- >
- <el-button type="primary" :loading="uploading">
- <el-icon><Camera /></el-icon>
+ <el-card v-if="hasException === true"
+ class="section-card">
+ <div class="upload-buttons"
+ v-if="operationType !== 'view'">
+ <el-upload :show-file-list="false"
+ :http-request="uploadFile"
+ :disabled="beforeModelValue.length >= uploadConfig.limit || uploading"
+ accept="image/*">
+ <el-button type="primary"
+ :loading="uploading">
+ <el-icon>
+ <Camera />
+ </el-icon>
閫夋嫨鍥剧墖
</el-button>
</el-upload>
-
- <el-upload
- :show-file-list="false"
- :http-request="uploadFile"
- :disabled="getCurrentFiles().length >= uploadConfig.limit || uploading"
- accept="video/*"
- >
- <el-button type="success" :loading="uploading">
- <el-icon><VideoCamera /></el-icon>
+ <el-upload :show-file-list="false"
+ :http-request="uploadFile"
+ :disabled="beforeModelValue.length >= uploadConfig.limit || uploading"
+ accept="video/*">
+ <el-button type="success"
+ :loading="uploading">
+ <el-icon>
+ <VideoCamera />
+ </el-icon>
閫夋嫨瑙嗛
</el-button>
</el-upload>
</div>
-
- <el-progress
- v-if="uploading"
- :percentage="uploadProgress"
- class="upload-progress"
- />
-
- <div v-if="getCurrentFiles().length" class="file-list">
- <div
- v-for="(file, index) in getCurrentFiles()"
- :key="file.uid || file.id || index"
- class="file-item"
- >
+ <el-progress v-if="uploading"
+ :percentage="uploadProgress"
+ class="upload-progress" />
+ <div v-if="beforeModelValue.length"
+ class="file-list">
+ <div v-for="(file, index) in beforeModelValue"
+ :key="file.uid || file.id || index"
+ class="file-item">
<div class="file-preview-container">
- <el-image
- v-if="file.type === 'image' || !file.type"
- :src="file.url || file.tempFilePath || file.path || file.downloadUrl"
- fit="cover"
- class="file-preview"
- :preview-src-list="[file.url || file.tempFilePath || file.path || file.downloadUrl]"
- preview-teleported
- />
-
- <div v-else class="video-preview" @click="previewVideo(file)">
- <el-icon><VideoCamera /></el-icon>
+ <el-image v-if="file.type === 'image' || !file.type"
+ :src="file.url || file.tempFilePath || file.path || file.downloadUrl"
+ fit="cover"
+ class="file-preview"
+ :preview-src-list="[file.url || file.tempFilePath || file.path || file.downloadUrl]"
+ preview-teleported />
+ <div v-else
+ class="video-preview"
+ @click="previewVideo(file)">
+ <el-icon>
+ <VideoCamera />
+ </el-icon>
<span>瑙嗛</span>
</div>
-
- <el-button
- class="delete-btn"
- type="danger"
- circle
- size="small"
- @click="removeFile(index)"
- >
- <el-icon><Close /></el-icon>
+ <el-button class="delete-btn"
+ type="danger"
+ circle
+ size="small"
+ v-if="operationType !== 'view'"
+ @click="removeFile(index)">
+ <el-icon>
+ <Close />
+ </el-icon>
</el-button>
</div>
-
<div class="file-info">
<div class="file-name">
{{ file.bucketFilename || file.name || (file.type === "image" ? "鍥剧墖" : "瑙嗛") }}
@@ -120,561 +134,559 @@
</div>
</div>
</div>
-
- <el-empty
- v-else
- :description="`璇烽�夋嫨瑕佷笂浼犵殑${getUploadTypeText()}鍥剧墖鎴栬棰慲"
- />
-
- <el-alert
- class="upload-summary"
- type="info"
- :closable="false"
- :title="`鐢熶骇鍓嶏細${beforeModelValue.length}涓枃浠� | 鐢熶骇涓細${afterModelValue.length}涓枃浠� | 鐢熶骇鍚庯細${issueModelValue.length}涓枃浠禶"
- />
+ <el-empty v-else
+ :description="operationType === 'view' ? '鏆傛棤寮傚父鐓х墖鎴栬棰�' : '璇烽�夋嫨瑕佷笂浼犵殑宸℃鍥剧墖鎴栬棰�'" />
</el-card>
-
- <el-result
- v-if="hasException === false"
- icon="success"
- title="璁惧杩愯姝e父"
- sub-title="鏃犻渶涓婁紶鐓х墖"
- />
+ <el-result v-if="hasException === false"
+ icon="success"
+ title="璁惧杩愯姝e父"
+ :sub-title="operationType === 'view' ? '' : '鏃犻渶涓婁紶鐓х墖'" />
</main>
-
<template #footer>
<footer class="footer-buttons">
- <el-button type="primary" @click="submitUpload">鎻愪氦</el-button>
- <el-button v-if="hasException === true" type="warning" @click="goToRepair">
+ <el-button type="primary"
+ v-if="operationType !== 'view'"
+ @click="submitUpload">鎻愪氦</el-button>
+ <el-button v-if="hasException === true && operationType !== 'view'"
+ type="warning"
+ @click="goToRepair">
鏂板鎶ヤ慨
</el-button>
- <el-button @click="handleClose">鍙栨秷</el-button>
+ <el-button @click="handleClose">{{ operationType === 'view' ? '鍏抽棴' : '鍙栨秷' }}</el-button>
</footer>
</template>
</FormDialog>
-
- <el-dialog
- v-model="showVideoDialog"
- :title="currentVideoFile?.originalFilename || currentVideoFile?.name || '瑙嗛棰勮'"
- width="720px"
- >
- <video
- v-if="currentVideoFile"
- :src="currentVideoFile.url || currentVideoFile.downloadUrl"
- class="video-player"
- controls
- autoplay
- />
+ <el-dialog v-model="showVideoDialog"
+ :title="currentVideoFile?.originalFilename || currentVideoFile?.name || '瑙嗛棰勮'"
+ width="720px">
+ <video v-if="currentVideoFile"
+ :src="currentVideoFile.url || currentVideoFile.downloadUrl"
+ class="video-player"
+ controls
+ autoplay />
</el-dialog>
</template>
<script setup>
-import { computed, ref } from "vue";
-import { useRouter } from "vue-router";
-import { ElLoading, ElMessage, ElMessageBox } from "element-plus";
-import { Camera, Close, VideoCamera } from "@element-plus/icons-vue";
-import axios from "axios";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import { uploadInspectionTask } from "@/api/inspectionManagement/index.js";
-import { getToken } from "@/utils/auth";
+ import { computed, ref } from "vue";
+ import { useRouter } from "vue-router";
+ import { ElLoading, ElMessage, ElMessageBox } from "element-plus";
+ import { Camera, Close, VideoCamera } from "@element-plus/icons-vue";
+ import axios from "axios";
+ import dayjs from "dayjs";
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import { uploadInspectionTask } from "@/api/inspectionManagement/index.js";
+ import { getToken } from "@/utils/auth";
-const emit = defineEmits(["closeDia", "success"]);
-const router = useRouter();
+ const emit = defineEmits(["closeDia", "success"]);
+ const router = useRouter();
-const dialogVisible = ref(false);
-const taskInfo = ref(null);
-const uploading = ref(false);
-const uploadProgress = ref(0);
+ const dialogVisible = ref(false);
+ const taskInfo = ref(null);
+ const uploading = ref(false);
+ const uploadProgress = ref(0);
+ const operationType = ref("add"); // add, view
-const beforeModelValue = ref([]);
-const afterModelValue = ref([]);
-const issueModelValue = ref([]);
+ const beforeModelValue = ref([]);
-const currentUploadType = ref("before");
-const hasException = ref(null);
-const abnormalDescription = ref("");
-
-const showVideoDialog = ref(false);
-const currentVideoFile = ref(null);
-
-const uploadConfig = {
- action: "/common/upload",
- limit: 10,
- fileSize: 50,
- fileType: ["jpg", "jpeg", "png", "mp4", "mov"],
-};
-
-const uploadFileUrl = computed(
- () => `${import.meta.env.VITE_APP_BASE_API}${uploadConfig.action}`
-);
-
-const processFileUrl = fileUrl => {
- if (!fileUrl) return "";
-
- let currentUrl = String(fileUrl);
- if (currentUrl.includes("\\")) {
- const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
- if (uploadsIndex > -1) {
- currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
- } else {
- const fileName = currentUrl.split("\\").pop();
- currentUrl = `/uploads/${fileName}`;
+ const formattedInspector = computed(() => {
+ if (!taskInfo.value?.inspector) return [];
+ if (Array.isArray(taskInfo.value.inspector)) return taskInfo.value.inspector;
+ if (typeof taskInfo.value.inspector === "string") {
+ return taskInfo.value.inspector
+ .split(",")
+ .map(s => s.trim())
+ .filter(s => s);
}
- }
-
- if (currentUrl && !currentUrl.startsWith("http")) {
- if (!currentUrl.startsWith("/")) {
- currentUrl = `/${currentUrl}`;
- }
- currentUrl = __BASE_API__ + currentUrl;
- }
-
- return currentUrl;
-};
-
-const normalizeList = (list, fileType) => {
- if (!Array.isArray(list)) return [];
-
- return list.filter(Boolean).map(item => {
- let currentType = item.type;
- if (!currentType && item.contentType) {
- currentType = item.contentType.startsWith("video") ? "video" : "image";
- } else if (!currentType) {
- currentType = fileType || "image";
- }
-
- return {
- ...item,
- url: processFileUrl(item.url || item.previewURL || item.downloadUrl || item.path || ""),
- downloadUrl: processFileUrl(
- item.downloadUrl || item.url || item.previewURL || item.path || ""
- ),
- name: item.name || item.originalFilename || item.bucketFilename,
- tempId: item.tempId || item.id || item.tempFileId,
- tempFileId: item.tempFileId || item.tempId || item.id,
- size: item.size || item.byteSize || 0,
- type: currentType,
- status: "success",
- uid: item.uid || `${Date.now()}-${Math.random()}`,
- };
- });
-};
-
-const resetState = () => {
- taskInfo.value = null;
- beforeModelValue.value = [];
- afterModelValue.value = [];
- issueModelValue.value = [];
- currentUploadType.value = "before";
- hasException.value = null;
- abnormalDescription.value = "";
- uploading.value = false;
- uploadProgress.value = 0;
- showVideoDialog.value = false;
- currentVideoFile.value = null;
-};
-
-const openDialog = row => {
- const raw = JSON.parse(JSON.stringify(row?.__raw || row || {}));
- taskInfo.value = raw;
-
- beforeModelValue.value = normalizeList(
- raw.commonFileListBeforeVO || raw.commonFileListBefore || [],
- "image"
- );
- afterModelValue.value = normalizeList(
- raw.commonFileListVO || raw.commonFileList || [],
- "image"
- );
- issueModelValue.value = normalizeList(
- raw.commonFileListAfterVO || raw.commonFileListAfter || [],
- "image"
- );
-
- abnormalDescription.value = raw.abnormalDescription || "";
-
- if (raw.hasException !== undefined && raw.hasException !== null) {
- hasException.value = raw.hasException;
- } else if (raw.inspectionResult !== undefined && raw.inspectionResult !== null) {
- hasException.value = String(raw.inspectionResult) === "0";
- } else {
- hasException.value = null;
- }
-
- if (
- hasException.value !== true &&
- (beforeModelValue.value.length || afterModelValue.value.length || issueModelValue.value.length)
- ) {
- hasException.value = true;
- }
-
- dialogVisible.value = true;
-};
-
-const handleClose = () => {
- dialogVisible.value = false;
- resetState();
- emit("closeDia");
-};
-
-const getCurrentFiles = () => {
- if (currentUploadType.value === "before") return beforeModelValue.value;
- if (currentUploadType.value === "after") return afterModelValue.value;
- if (currentUploadType.value === "issue") return issueModelValue.value;
- return [];
-};
-
-const getUploadTypeText = () => {
- if (currentUploadType.value === "before") return "鐢熶骇鍓�";
- if (currentUploadType.value === "after") return "鐢熶骇涓�";
- if (currentUploadType.value === "issue") return "鐢熶骇鍚�";
- return "";
-};
-
-const getTabType = () => {
- if (currentUploadType.value === "before") return 10;
- if (currentUploadType.value === "after") return 11;
- if (currentUploadType.value === "issue") return 12;
- return 10;
-};
-
-const previewVideo = file => {
- currentVideoFile.value = file;
- showVideoDialog.value = true;
-};
-
-const uploadFile = async uploadRequest => {
- const rawFile = uploadRequest.file;
-
- if (getCurrentFiles().length >= uploadConfig.limit) {
- ElMessage.warning(`鏈�澶氬彧鑳介�夋嫨${uploadConfig.limit}涓枃浠禶);
- return;
- }
-
- const ext = rawFile.name.split(".").pop()?.toLowerCase();
- if (!uploadConfig.fileType.includes(ext)) {
- ElMessage.warning(`鏂囦欢鏍煎紡涓嶆敮鎸侊紝璇蜂笂浼� ${uploadConfig.fileType.join("/")} 鏍煎紡`);
- return;
- }
-
- if (rawFile.size > uploadConfig.fileSize * 1024 * 1024) {
- ElMessage.warning(`鏂囦欢澶у皬涓嶈兘瓒呰繃 ${uploadConfig.fileSize}MB`);
- return;
- }
-
- const token = getToken();
- if (!token) {
- ElMessage.warning("鐢ㄦ埛鏈櫥褰�");
- return;
- }
-
- const formData = new FormData();
- formData.append("files", rawFile);
- formData.append("type", getTabType());
-
- uploading.value = true;
- uploadProgress.value = 0;
-
- try {
- const { data } = await axios.post(uploadFileUrl.value, formData, {
- headers: {
- Authorization: `Bearer ${token}`,
- "Content-Type": "multipart/form-data",
- },
- onUploadProgress: event => {
- if (event.total) {
- uploadProgress.value = Math.round((event.loaded / event.total) * 100);
- }
- },
- });
-
- if (data.code !== 200) {
- ElMessage.error(data.msg || "涓婁紶澶辫触");
- return;
- }
-
- const resultData = Array.isArray(data.data) ? data.data[0] : data.data;
- const finalUrl = processFileUrl(
- resultData.url || resultData.previewURL || resultData.downloadUrl || ""
- );
- const finalName = resultData.name || resultData.originalFilename || resultData.bucketFilename;
- const finalId = resultData.tempId || resultData.id || resultData.tempFileId;
-
- const uploadedFile = {
- ...resultData,
- url: finalUrl,
- downloadUrl: finalUrl,
- name: finalName,
- tempId: finalId,
- tempFileId: resultData.tempFileId || finalId,
- size: rawFile.size || resultData.size || resultData.byteSize || 0,
- type: rawFile.type?.startsWith("video") ? "video" : "image",
- status: "success",
- uid: `${Date.now()}-${Math.random()}`,
- };
-
- getCurrentFiles().push(uploadedFile);
- ElMessage.success("涓婁紶鎴愬姛");
- } catch (error) {
- ElMessage.error(error?.message || "涓婁紶澶辫触");
- } finally {
- uploading.value = false;
- }
-};
-
-const buildFileItem = item => ({
- id: item?.id,
- tempId: item?.tempId,
- tempFileId: item?.tempFileId,
- url: item?.downloadUrl || item?.url || "",
- downloadUrl: item?.downloadUrl || item?.url || "",
- name: item?.name,
- bucketFilename: item?.bucketFilename || item?.name,
- originalFilename: item?.originalFilename || item?.name,
- size: item?.size || 0,
- byteSize: item?.byteSize || item?.size || 0,
- contentType: item?.contentType || "",
- type: item?.type,
-});
-
-const submitUpload = async () => {
- if (hasException.value === null) {
- ElMessage.warning("璇烽�夋嫨宸℃鐘舵��");
- return;
- }
-
- if (hasException.value === true) {
- const totalFiles =
- beforeModelValue.value.length +
- afterModelValue.value.length +
- issueModelValue.value.length;
-
- if (!totalFiles) {
- ElMessage.warning("璇蜂笂浼犲紓甯哥収鐗囨垨瑙嗛");
- return;
- }
-
- if (!abnormalDescription.value.trim()) {
- ElMessage.warning("璇峰~鍐欏紓甯告弿杩�");
- return;
- }
- }
-
- const loading = ElLoading.service({
- text: "鎻愪氦涓�...",
- background: "rgba(0, 0, 0, 0.3)",
+ return [taskInfo.value.inspector];
});
- try {
- const allFiles = [
- ...beforeModelValue.value,
- ...afterModelValue.value,
- ...issueModelValue.value,
- ];
-
- const tempFileIds = allFiles
- .map(item => item?.tempId ?? item?.tempFileId ?? item?.id)
- .filter(Boolean);
-
- const {
- createTime,
- updateTime,
- storageBlobDTO,
- commonFileListAfterVO,
- commonFileListVO,
- commonFileListBeforeVO,
- commonFileListAfter,
- commonFileList,
- commonFileListBefore,
- __raw,
- ...baseTaskInfo
- } = taskInfo.value || {};
-
- const submitData = {
- ...baseTaskInfo,
- commonFileListBeforeDTO: beforeModelValue.value.map(buildFileItem),
- commonFileListDTO: afterModelValue.value.map(buildFileItem),
- commonFileListAfterDTO: issueModelValue.value.map(buildFileItem),
- hasException: hasException.value,
- inspectionResult: hasException.value ? 0 : 1,
- abnormalDescription: abnormalDescription.value,
- tempFileIds,
+ const formatFrequencyType = type => {
+ const mapping = {
+ DAILY: "姣忔棩",
+ WEEKLY: "姣忓懆",
+ MONTHLY: "姣忔湀",
+ QUARTERLY: "瀛e害",
};
-
- const result = await uploadInspectionTask(submitData);
-
- if (result && (result.code === 200 || result.success)) {
- ElMessage.success("鎻愪氦鎴愬姛");
- dialogVisible.value = false;
- resetState();
- emit("success");
- emit("closeDia");
- } else {
- ElMessage.error(result?.msg || result?.message || "鎻愪氦澶辫触");
- }
- } catch (error) {
- ElMessage.error(error?.message || "鎻愪氦澶辫触");
- } finally {
- loading.close();
- }
-};
-
-const removeFile = async index => {
- try {
- await ElMessageBox.confirm("纭畾瑕佸垹闄よ繖涓枃浠跺悧锛�", "纭鍒犻櫎", {
- type: "warning",
- });
- getCurrentFiles().splice(index, 1);
- } catch {}
-};
-
-const goToRepair = () => {
- const taskData = {
- taskId: taskInfo.value?.taskId || taskInfo.value?.id,
- taskName: taskInfo.value?.taskName,
- inspectionLocation: taskInfo.value?.inspectionLocation,
- inspector: taskInfo.value?.inspector,
- hasException: hasException.value,
- inspectionResult: hasException.value ? 0 : 1,
- commonFileListBeforeDTO: beforeModelValue.value.map(buildFileItem),
- commonFileListDTO: afterModelValue.value.map(buildFileItem),
- commonFileListAfterDTO: issueModelValue.value.map(buildFileItem),
- uploadedFiles: {
- before: beforeModelValue.value,
- after: afterModelValue.value,
- issue: issueModelValue.value,
- },
+ return mapping[type] || type;
};
- sessionStorage.setItem("repairTaskInfo", JSON.stringify(taskData));
- router.push("/equipmentManagement/repair/add");
-};
+ const formatFrequencyDetail = detail => {
+ if (typeof detail !== "string") return detail;
+ const replacements = {
+ MON: "鍛ㄤ竴",
+ TUE: "鍛ㄤ簩",
+ WED: "鍛ㄤ笁",
+ THU: "鍛ㄥ洓",
+ FRI: "鍛ㄤ簲",
+ SAT: "鍛ㄥ叚",
+ SUN: "鍛ㄦ棩",
+ };
+ return detail.replace(
+ /MON|TUE|WED|THU|FRI|SAT|SUN/g,
+ match => replacements[match]
+ );
+ };
-const formatFileSize = size => {
- if (!size) return "0 B";
+ const formatDateTime = date => {
+ if (!date) return "-";
+ return dayjs(date).format("YYYY-MM-DD");
+ };
- const units = ["B", "KB", "MB", "GB"];
- let index = 0;
- let fileSize = size;
+ const hasException = ref(null);
+ const abnormalDescription = ref("");
- while (fileSize >= 1024 && index < units.length - 1) {
- fileSize /= 1024;
- index += 1;
- }
+ const showVideoDialog = ref(false);
+ const currentVideoFile = ref(null);
- return `${fileSize.toFixed(2)} ${units[index]}`;
-};
+ const uploadConfig = {
+ action: "/common/upload",
+ limit: 10,
+ fileSize: 50,
+ fileType: ["jpg", "jpeg", "png", "mp4", "mov"],
+ };
-defineExpose({
- openDialog,
-});
+ const uploadFileUrl = computed(
+ () => `${import.meta.env.VITE_APP_BASE_API}${uploadConfig.action}`
+ );
+
+ const processFileUrl = fileUrl => {
+ if (!fileUrl) return "";
+
+ let currentUrl = String(fileUrl);
+ if (currentUrl.includes("\\")) {
+ const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
+ if (uploadsIndex > -1) {
+ currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
+ } else {
+ const fileName = currentUrl.split("\\").pop();
+ currentUrl = `/uploads/${fileName}`;
+ }
+ }
+
+ if (currentUrl && !currentUrl.startsWith("http")) {
+ if (!currentUrl.startsWith("/")) {
+ currentUrl = `/${currentUrl}`;
+ }
+ currentUrl = __BASE_API__ + currentUrl;
+ }
+
+ return currentUrl;
+ };
+
+ const normalizeList = (list, fileType) => {
+ if (!Array.isArray(list)) return [];
+
+ return list.filter(Boolean).map(item => {
+ let currentType = item.type;
+ if (!currentType && item.contentType) {
+ currentType = item.contentType.startsWith("video") ? "video" : "image";
+ } else if (!currentType) {
+ currentType = fileType || "image";
+ }
+
+ return {
+ ...item,
+ url: processFileUrl(
+ item.url || item.previewURL || item.downloadUrl || item.path || ""
+ ),
+ downloadUrl: processFileUrl(
+ item.downloadUrl || item.url || item.previewURL || item.path || ""
+ ),
+ name: item.name || item.originalFilename || item.bucketFilename,
+ tempId: item.tempId || item.id || item.tempFileId,
+ tempFileId: item.tempFileId || item.tempId || item.id,
+ size: item.size || item.byteSize || 0,
+ type: currentType,
+ status: "success",
+ uid: item.uid || `${Date.now()}-${Math.random()}`,
+ };
+ });
+ };
+
+ const resetState = () => {
+ taskInfo.value = null;
+ beforeModelValue.value = [];
+ hasException.value = null;
+ abnormalDescription.value = "";
+ uploading.value = false;
+ uploadProgress.value = 0;
+ showVideoDialog.value = false;
+ currentVideoFile.value = null;
+ operationType.value = "add";
+ };
+
+ const openDialog = (type, row) => {
+ operationType.value = type || "add";
+ const raw = JSON.parse(JSON.stringify(row?.__raw || row || {}));
+ taskInfo.value = raw;
+
+ beforeModelValue.value = normalizeList(
+ raw.commonFileListBeforeVO || raw.commonFileListBefore || [],
+ "image"
+ );
+
+ abnormalDescription.value = raw.abnormalDescription || "";
+
+ if (raw.hasException !== undefined && raw.hasException !== null) {
+ hasException.value = raw.hasException;
+ } else if (
+ raw.inspectionResult !== undefined &&
+ raw.inspectionResult !== null
+ ) {
+ hasException.value = String(raw.inspectionResult) === "0";
+ } else {
+ hasException.value = null;
+ }
+
+ if (hasException.value !== true && beforeModelValue.value.length) {
+ hasException.value = true;
+ }
+
+ dialogVisible.value = true;
+ };
+
+ const handleClose = () => {
+ dialogVisible.value = false;
+ resetState();
+ emit("closeDia");
+ };
+
+ const previewVideo = file => {
+ currentVideoFile.value = file;
+ showVideoDialog.value = true;
+ };
+
+ const uploadFile = async uploadRequest => {
+ const rawFile = uploadRequest.file;
+
+ if (beforeModelValue.value.length >= uploadConfig.limit) {
+ ElMessage.warning(`鏈�澶氬彧鑳介�夋嫨${uploadConfig.limit}涓枃浠禶);
+ return;
+ }
+
+ const ext = rawFile.name.split(".").pop()?.toLowerCase();
+ if (!uploadConfig.fileType.includes(ext)) {
+ ElMessage.warning(
+ `鏂囦欢鏍煎紡涓嶆敮鎸侊紝璇蜂笂浼� ${uploadConfig.fileType.join("/")} 鏍煎紡`
+ );
+ return;
+ }
+
+ if (rawFile.size > uploadConfig.fileSize * 1024 * 1024) {
+ ElMessage.warning(`鏂囦欢澶у皬涓嶈兘瓒呰繃 ${uploadConfig.fileSize}MB`);
+ return;
+ }
+
+ const token = getToken();
+ if (!token) {
+ ElMessage.warning("鐢ㄦ埛鏈櫥褰�");
+ return;
+ }
+
+ const formData = new FormData();
+ formData.append("files", rawFile);
+ formData.append("type", 10); // 鐢熶骇鍓嶅浐瀹氫负10
+
+ uploading.value = true;
+ uploadProgress.value = 0;
+
+ try {
+ const { data } = await axios.post(uploadFileUrl.value, formData, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "multipart/form-data",
+ },
+ onUploadProgress: event => {
+ if (event.total) {
+ uploadProgress.value = Math.round((event.loaded / event.total) * 100);
+ }
+ },
+ });
+
+ if (data.code !== 200) {
+ ElMessage.error(data.msg || "涓婁紶澶辫触");
+ return;
+ }
+
+ const resultData = Array.isArray(data.data) ? data.data[0] : data.data;
+ const finalUrl = processFileUrl(
+ resultData.url || resultData.previewURL || resultData.downloadUrl || ""
+ );
+ const finalName =
+ resultData.name ||
+ resultData.originalFilename ||
+ resultData.bucketFilename;
+ const finalId = resultData.tempId || resultData.id || resultData.tempFileId;
+
+ const uploadedFile = {
+ ...resultData,
+ url: finalUrl,
+ downloadUrl: finalUrl,
+ name: finalName,
+ tempId: finalId,
+ tempFileId: resultData.tempFileId || finalId,
+ size: rawFile.size || resultData.size || resultData.byteSize || 0,
+ type: rawFile.type?.startsWith("video") ? "video" : "image",
+ status: "success",
+ uid: `${Date.now()}-${Math.random()}`,
+ };
+
+ beforeModelValue.value.push(uploadedFile);
+ ElMessage.success("涓婁紶鎴愬姛");
+ } catch (error) {
+ ElMessage.error(error?.message || "涓婁紶澶辫触");
+ } finally {
+ uploading.value = false;
+ }
+ };
+
+ const buildFileItem = item => ({
+ id: item?.id,
+ tempId: item?.tempId,
+ tempFileId: item?.tempFileId,
+ url: item?.downloadUrl || item?.url || "",
+ downloadUrl: item?.downloadUrl || item?.url || "",
+ name: item?.name,
+ bucketFilename: item?.bucketFilename || item?.name,
+ originalFilename: item?.originalFilename || item?.name,
+ size: item?.size || 0,
+ byteSize: item?.byteSize || item?.size || 0,
+ contentType: item?.contentType || "",
+ type: item?.type,
+ });
+
+ const submitUpload = async () => {
+ if (hasException.value === null) {
+ ElMessage.warning("璇烽�夋嫨宸℃鐘舵��");
+ return;
+ }
+
+ if (hasException.value === true) {
+ const totalFiles = beforeModelValue.value.length;
+
+ if (!totalFiles) {
+ ElMessage.warning("璇蜂笂浼犲紓甯哥収鐗囨垨瑙嗛");
+ return;
+ }
+
+ if (!abnormalDescription.value.trim()) {
+ ElMessage.warning("璇峰~鍐欏紓甯告弿杩�");
+ return;
+ }
+ }
+
+ const loading = ElLoading.service({
+ text: "鎻愪氦涓�...",
+ background: "rgba(0, 0, 0, 0.3)",
+ });
+
+ try {
+ const allFiles = [...beforeModelValue.value];
+
+ const tempFileIds = allFiles
+ .map(item => item?.tempId ?? item?.tempFileId ?? item?.id)
+ .filter(Boolean);
+
+ const {
+ createTime,
+ updateTime,
+ storageBlobDTO,
+ commonFileListAfterVO,
+ commonFileListVO,
+ commonFileListBeforeVO,
+ commonFileListAfter,
+ commonFileList,
+ commonFileListBefore,
+ __raw,
+ ...baseTaskInfo
+ } = taskInfo.value || {};
+
+ const submitData = {
+ ...baseTaskInfo,
+ commonFileListBeforeDTO: beforeModelValue.value.map(buildFileItem),
+ commonFileListDTO: [],
+ commonFileListAfterDTO: [],
+ hasException: hasException.value,
+ inspectionResult: hasException.value ? 0 : 1,
+ abnormalDescription: abnormalDescription.value,
+ tempFileIds,
+ };
+
+ const result = await uploadInspectionTask(submitData);
+
+ if (result && (result.code === 200 || result.success)) {
+ ElMessage.success("鎻愪氦鎴愬姛");
+ dialogVisible.value = false;
+ resetState();
+ emit("success");
+ emit("closeDia");
+ } else {
+ ElMessage.error(result?.msg || result?.message || "鎻愪氦澶辫触");
+ }
+ } catch (error) {
+ ElMessage.error(error?.message || "鎻愪氦澶辫触");
+ } finally {
+ loading.close();
+ }
+ };
+
+ const removeFile = async index => {
+ try {
+ await ElMessageBox.confirm("纭畾瑕佸垹闄よ繖涓枃浠跺悧锛�", "纭鍒犻櫎", {
+ type: "warning",
+ });
+ beforeModelValue.value.splice(index, 1);
+ } catch {}
+ };
+
+ const goToRepair = () => {
+ const taskData = {
+ taskId: taskInfo.value?.taskId || taskInfo.value?.id,
+ taskName: taskInfo.value?.taskName,
+ inspectionLocation: taskInfo.value?.inspectionLocation,
+ inspector: taskInfo.value?.inspector,
+ hasException: hasException.value,
+ inspectionResult: hasException.value ? 0 : 1,
+ commonFileListBeforeDTO: beforeModelValue.value.map(buildFileItem),
+ commonFileListDTO: [],
+ commonFileListAfterDTO: [],
+ uploadedFiles: {
+ before: beforeModelValue.value,
+ after: [],
+ issue: [],
+ },
+ };
+
+ sessionStorage.setItem("repairTaskInfo", JSON.stringify(taskData));
+ router.push("/equipmentManagement/repair/add");
+ };
+
+ const formatFileSize = size => {
+ if (!size) return "0 B";
+
+ const units = ["B", "KB", "MB", "GB"];
+ let index = 0;
+ let fileSize = size;
+
+ while (fileSize >= 1024 && index < units.length - 1) {
+ fileSize /= 1024;
+ index += 1;
+ }
+
+ return `${fileSize.toFixed(2)} ${units[index]}`;
+ };
+
+ defineExpose({
+ openDialog,
+ });
</script>
<style scoped>
-.inspection-upload-page {
- min-height: 70vh;
- background: #f5f7fa;
- padding: 20px 20px 90px;
- box-sizing: border-box;
-}
+ .inspection-upload-page {
+ min-height: 70vh;
+ background: #f5f7fa;
+ padding: 20px 20px 90px;
+ box-sizing: border-box;
+ }
-.upload-content {
- max-width: 960px;
- margin: 20px auto 0;
-}
+ .upload-content {
+ max-width: 960px;
+ margin: 20px auto 0;
+ }
-.section-card {
- margin-bottom: 16px;
-}
+ .section-card {
+ margin-bottom: 16px;
+ }
-.section-card h3 {
- margin: 0 0 16px;
- font-size: 16px;
-}
+ .section-card h3 {
+ margin: 0 0 16px;
+ font-size: 16px;
+ }
-.upload-buttons {
- display: flex;
- gap: 12px;
- margin: 16px 0;
-}
+ .upload-buttons {
+ display: flex;
+ gap: 12px;
+ margin: 16px 0;
+ }
-.upload-progress {
- margin-bottom: 16px;
-}
+ .upload-progress {
+ margin-bottom: 16px;
+ }
-.file-list {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
- gap: 12px;
-}
+ .file-list {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
+ gap: 12px;
+ }
-.file-preview-container {
- position: relative;
- aspect-ratio: 1;
- border-radius: 8px;
- overflow: hidden;
- background: #f2f3f5;
-}
+ .file-preview-container {
+ position: relative;
+ aspect-ratio: 1;
+ border-radius: 8px;
+ overflow: hidden;
+ background: #f2f3f5;
+ }
-.file-preview {
- width: 100%;
- height: 100%;
-}
+ .file-preview {
+ width: 100%;
+ height: 100%;
+ }
-.video-preview {
- width: 100%;
- height: 100%;
- background: #303133;
- color: #fff;
- display: flex;
- gap: 6px;
- align-items: center;
- justify-content: center;
- cursor: pointer;
-}
+ .video-preview {
+ width: 100%;
+ height: 100%;
+ background: #303133;
+ color: #fff;
+ display: flex;
+ gap: 6px;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ }
-.delete-btn {
- position: absolute;
- top: 6px;
- right: 6px;
-}
+ .delete-btn {
+ position: absolute;
+ top: 6px;
+ right: 6px;
+ }
-.file-info {
- margin-top: 6px;
- font-size: 12px;
-}
+ .file-info {
+ margin-top: 6px;
+ font-size: 12px;
+ }
-.file-name {
- color: #606266;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
+ .file-name {
+ color: #606266;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
-.file-size {
- color: #909399;
- margin-top: 2px;
-}
+ .file-size {
+ color: #909399;
+ margin-top: 2px;
+ }
-.upload-summary {
- margin-top: 16px;
-}
+ .upload-summary {
+ margin-top: 16px;
+ }
-.footer-buttons {
- position: sticky;
- left: 0;
- right: 0;
- bottom: 0;
- padding: 14px 20px 0;
- background: #f5f7fa;
- display: flex;
- justify-content: center;
- gap: 12px;
-}
+ .footer-buttons {
+ position: sticky;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: 14px 20px 0;
+ background: #f5f7fa;
+ display: flex;
+ justify-content: center;
+ gap: 12px;
+ }
-.video-player {
- width: 100%;
- max-height: 70vh;
- background: #000;
-}
+ .video-player {
+ width: 100%;
+ max-height: 70vh;
+ background: #000;
+ }
</style>
diff --git a/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue b/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
index b5604fe..1aac0bf 100644
--- a/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
+++ b/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -1,37 +1,35 @@
<template>
<div>
- <el-dialog title="鏌ョ湅闄勪欢" v-model="dialogVisitable" width="800px" @close="cancel">
+ <el-dialog title="鏌ョ湅闄勪欢"
+ v-model="dialogVisitable"
+ width="800px"
+ @close="cancel">
<div class="upload-container">
<div class="form-container">
- <div class="title">鐢熶骇鍓�</div>
-
+ <div class="title">鍥剧墖鍒楄〃</div>
<div class="media-list">
- <img
- v-for="(item, index) in beforeProductionImgs"
- :key="`before-img-${index}`"
- :src="item"
- alt=""
- class="media-image"
- @click="showMedia(beforeProductionImgs, index, 'image')"
- />
+ <img v-for="(item, index) in beforeProductionImgs"
+ :key="`before-img-${index}`"
+ :src="item"
+ alt=""
+ class="media-image"
+ @click="showMedia(beforeProductionImgs, index, 'image')" />
</div>
-
<div class="media-list">
- <div
- v-for="(videoUrl, index) in beforeProductionVideos"
- :key="`before-video-${index}`"
- class="video-item"
- @click="showMedia(beforeProductionVideos, index, 'video')"
- >
+ <div v-for="(videoUrl, index) in beforeProductionVideos"
+ :key="`before-video-${index}`"
+ class="video-item"
+ @click="showMedia(beforeProductionVideos, index, 'video')">
<div class="video-thumb">
- <img src="@/assets/images/video.png" alt="鎾斁" class="video-icon" />
+ <img src="@/assets/images/video.png"
+ alt="鎾斁"
+ class="video-icon" />
</div>
<div class="video-text">鐐瑰嚮鎾斁</div>
</div>
</div>
</div>
-
- <div class="form-container">
+ <!-- <div class="form-container">
<div class="title">鐢熶骇涓�</div>
<div class="media-list">
@@ -87,22 +85,25 @@
<div class="video-text">鐐瑰嚮鎾斁</div>
</div>
</div>
- </div>
+ </div> -->
</div>
</el-dialog>
-
- <div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer">
- <div class="media-viewer-content" @click.stop>
- <vue-easy-lightbox
- v-if="mediaType === 'image'"
- :visible="isMediaViewerVisible"
- :imgs="mediaList"
- :index="currentMediaIndex"
- @hide="closeMediaViewer"
- />
-
- <div v-else-if="mediaType === 'video'" class="video-player-wrap">
- <video :src="mediaList[currentMediaIndex]" autoplay controls class="video-player" />
+ <div v-if="isMediaViewerVisible"
+ class="media-viewer-overlay"
+ @click.self="closeMediaViewer">
+ <div class="media-viewer-content"
+ @click.stop>
+ <vue-easy-lightbox v-if="mediaType === 'image'"
+ :visible="isMediaViewerVisible"
+ :imgs="mediaList"
+ :index="currentMediaIndex"
+ @hide="closeMediaViewer" />
+ <div v-else-if="mediaType === 'video'"
+ class="video-player-wrap">
+ <video :src="mediaList[currentMediaIndex]"
+ autoplay
+ controls
+ class="video-player" />
</div>
</div>
</div>
@@ -110,215 +111,215 @@
</template>
<script setup>
-import { ref } from "vue";
-import VueEasyLightbox from "vue-easy-lightbox";
+ import { ref } from "vue";
+ import VueEasyLightbox from "vue-easy-lightbox";
-const dialogVisitable = ref(false);
+ const dialogVisitable = ref(false);
-const beforeProductionImgs = ref([]);
-const afterProductionImgs = ref([]);
-const productionIssuesImgs = ref([]);
+ const beforeProductionImgs = ref([]);
+ const afterProductionImgs = ref([]);
+ const productionIssuesImgs = ref([]);
-const beforeProductionVideos = ref([]);
-const afterProductionVideos = ref([]);
-const productionIssuesVideos = ref([]);
+ const beforeProductionVideos = ref([]);
+ const afterProductionVideos = ref([]);
+ const productionIssuesVideos = ref([]);
-const isMediaViewerVisible = ref(false);
-const currentMediaIndex = ref(0);
-const mediaList = ref([]);
-const mediaType = ref("image");
+ const isMediaViewerVisible = ref(false);
+ const currentMediaIndex = ref(0);
+ const mediaList = ref([]);
+ const mediaType = ref("image");
-const processFileUrl = fileUrl => {
- if (!fileUrl) return "";
+ const processFileUrl = fileUrl => {
+ if (!fileUrl) return "";
- let currentUrl = String(fileUrl);
- if (currentUrl.includes("\\")) {
- const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
- if (uploadsIndex > -1) {
- currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
- } else {
- const fileName = currentUrl.split("\\").pop();
- currentUrl = `/uploads/${fileName}`;
+ let currentUrl = String(fileUrl);
+ if (currentUrl.includes("\\")) {
+ const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
+ if (uploadsIndex > -1) {
+ currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
+ } else {
+ const fileName = currentUrl.split("\\").pop();
+ currentUrl = `/uploads/${fileName}`;
+ }
}
- }
- if (currentUrl && !currentUrl.startsWith("http")) {
- if (!currentUrl.startsWith("/")) {
- currentUrl = `/${currentUrl}`;
+ if (currentUrl && !currentUrl.startsWith("http")) {
+ if (!currentUrl.startsWith("/")) {
+ currentUrl = `/${currentUrl}`;
+ }
+ currentUrl = __BASE_API__ + currentUrl;
}
- currentUrl = __BASE_API__ + currentUrl;
- }
- return currentUrl;
-};
+ return currentUrl;
+ };
-const processItems = items => {
- const images = [];
- const videos = [];
+ const processItems = items => {
+ const images = [];
+ const videos = [];
- if (!Array.isArray(items)) {
+ if (!Array.isArray(items)) {
+ return { images, videos };
+ }
+
+ items.forEach(item => {
+ if (!item) return;
+
+ const fileUrl = processFileUrl(
+ item.previewURL || item.url || item.downloadUrl || item.path || ""
+ );
+ const contentType = String(item.contentType || "").toLowerCase();
+
+ if (!fileUrl) return;
+
+ if (contentType.startsWith("video/")) {
+ videos.push(fileUrl);
+ return;
+ }
+
+ images.push(fileUrl);
+ });
+
return { images, videos };
- }
+ };
- items.forEach(item => {
- if (!item) return;
-
- const fileUrl = processFileUrl(
- item.previewURL || item.url || item.downloadUrl || item.path || ""
+ const openDialog = row => {
+ const { images: beforeImgs, videos: beforeVids } = processItems(
+ row.commonFileListBeforeVO || []
);
- const contentType = String(item.contentType || "").toLowerCase();
+ const { images: afterImgs, videos: afterVids } = processItems(
+ row.commonFileListVO || []
+ );
+ const { images: issueImgs, videos: issueVids } = processItems(
+ row.commonFileListAfterVO || []
+ );
- if (!fileUrl) return;
+ beforeProductionImgs.value = beforeImgs;
+ beforeProductionVideos.value = beforeVids;
+ afterProductionImgs.value = afterImgs;
+ afterProductionVideos.value = afterVids;
+ productionIssuesImgs.value = issueImgs;
+ productionIssuesVideos.value = issueVids;
+ dialogVisitable.value = true;
+ };
- if (contentType.startsWith("video/")) {
- videos.push(fileUrl);
- return;
- }
+ const showMedia = (items, index, type) => {
+ mediaList.value = items;
+ currentMediaIndex.value = index;
+ mediaType.value = type;
+ isMediaViewerVisible.value = true;
+ };
- images.push(fileUrl);
- });
+ const closeMediaViewer = () => {
+ isMediaViewerVisible.value = false;
+ mediaList.value = [];
+ mediaType.value = "image";
+ };
- return { images, videos };
-};
+ const cancel = () => {
+ dialogVisitable.value = false;
+ };
-const openDialog = row => {
- const { images: beforeImgs, videos: beforeVids } = processItems(
- row.commonFileListBeforeVO || []
- );
- const { images: afterImgs, videos: afterVids } = processItems(
- row.commonFileListVO || []
- );
- const { images: issueImgs, videos: issueVids } = processItems(
- row.commonFileListAfterVO || []
- );
-
- beforeProductionImgs.value = beforeImgs;
- beforeProductionVideos.value = beforeVids;
- afterProductionImgs.value = afterImgs;
- afterProductionVideos.value = afterVids;
- productionIssuesImgs.value = issueImgs;
- productionIssuesVideos.value = issueVids;
- dialogVisitable.value = true;
-};
-
-const showMedia = (items, index, type) => {
- mediaList.value = items;
- currentMediaIndex.value = index;
- mediaType.value = type;
- isMediaViewerVisible.value = true;
-};
-
-const closeMediaViewer = () => {
- isMediaViewerVisible.value = false;
- mediaList.value = [];
- mediaType.value = "image";
-};
-
-const cancel = () => {
- dialogVisitable.value = false;
-};
-
-defineExpose({ openDialog });
+ defineExpose({ openDialog });
</script>
<style scoped lang="scss">
-.upload-container {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 20px;
- border: 1px solid #dcdfe6;
- box-sizing: border-box;
+ .upload-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 20px;
+ border: 1px solid #dcdfe6;
+ box-sizing: border-box;
- .form-container {
- flex: 1;
- width: 100%;
- margin-bottom: 20px;
+ .form-container {
+ flex: 1;
+ width: 100%;
+ margin-bottom: 20px;
+ }
}
-}
-.title {
- font-size: 14px;
- color: #165dff;
- line-height: 20px;
- font-weight: 600;
- padding-left: 10px;
- position: relative;
- margin: 6px 0;
+ .title {
+ font-size: 14px;
+ color: #165dff;
+ line-height: 20px;
+ font-weight: 600;
+ padding-left: 10px;
+ position: relative;
+ margin: 6px 0;
- &::before {
- content: "";
- position: absolute;
- left: 0;
- top: 3px;
- width: 4px;
- height: 14px;
- background-color: #165dff;
+ &::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 3px;
+ width: 4px;
+ height: 14px;
+ background-color: #165dff;
+ }
}
-}
-.media-list {
- display: flex;
- flex-wrap: wrap;
-}
+ .media-list {
+ display: flex;
+ flex-wrap: wrap;
+ }
-.media-image {
- max-width: 100px;
- height: 100px;
- margin: 5px;
- cursor: pointer;
-}
+ .media-image {
+ max-width: 100px;
+ height: 100px;
+ margin: 5px;
+ cursor: pointer;
+ }
-.video-item {
- position: relative;
- margin: 10px;
- cursor: pointer;
-}
+ .video-item {
+ position: relative;
+ margin: 10px;
+ cursor: pointer;
+ }
-.video-thumb {
- width: 160px;
- height: 90px;
- background-color: #333;
- display: flex;
- align-items: center;
- justify-content: center;
-}
+ .video-thumb {
+ width: 160px;
+ height: 90px;
+ background-color: #333;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
-.video-icon {
- width: 30px;
- height: 30px;
- opacity: 0.8;
-}
+ .video-icon {
+ width: 30px;
+ height: 30px;
+ opacity: 0.8;
+ }
-.video-text {
- text-align: center;
- font-size: 12px;
- color: #666;
-}
+ .video-text {
+ text-align: center;
+ font-size: 12px;
+ color: #666;
+ }
-.media-viewer-overlay {
- position: fixed;
- inset: 0;
- background-color: rgba(0, 0, 0, 0.8);
- z-index: 9999;
- display: flex;
- align-items: center;
- justify-content: center;
-}
+ .media-viewer-overlay {
+ position: fixed;
+ inset: 0;
+ background-color: rgba(0, 0, 0, 0.8);
+ z-index: 9999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
-.media-viewer-content {
- position: relative;
- max-width: 90vw;
- max-height: 90vh;
- overflow: hidden;
-}
+ .media-viewer-content {
+ position: relative;
+ max-width: 90vw;
+ max-height: 90vh;
+ overflow: hidden;
+ }
-.video-player-wrap {
- position: relative;
-}
+ .video-player-wrap {
+ position: relative;
+ }
-.video-player {
- max-width: 90vw;
- max-height: 80vh;
-}
+ .video-player {
+ max-width: 90vw;
+ max-height: 80vh;
+ }
</style>
diff --git a/src/views/equipmentManagement/inspectionManagement/index.vue b/src/views/equipmentManagement/inspectionManagement/index.vue
index 8c0d52c..c6c21d9 100644
--- a/src/views/equipmentManagement/inspectionManagement/index.vue
+++ b/src/views/equipmentManagement/inspectionManagement/index.vue
@@ -197,7 +197,7 @@
formatData: cell => {
if (!cell) return "-";
try {
- return dayjs(cell).format("YYYY-MM-DD HH:mm:ss");
+ return dayjs(cell).format("YYYY-MM-DD");
} catch {
return cell;
}
@@ -231,6 +231,12 @@
operation: operations
.map(op => {
switch (op) {
+ case "view":
+ return {
+ name: "璇︽儏",
+ clickFun: openViewDialog,
+ color: "#409EFF",
+ };
case "edit":
return {
name: "缂栬緫",
@@ -273,14 +279,14 @@
];
operationsArr.value = ["edit"];
} else if (value === "task") {
- const operationColumn = getOperationColumn(["upload", "viewFile"]);
+ const operationColumn = getOperationColumn(["view", "upload", "viewFile"]);
// 宸℃璁板綍涓嶅睍绀�"鏄惁鍚敤"鍒�
const taskColumns = columns.value.filter(col => col.prop !== "isEnabled");
tableColumns.value = [
...taskColumns,
...(operationColumn ? [operationColumn] : []),
];
- operationsArr.value = ["upload", "viewFile"];
+ operationsArr.value = ["view", "upload", "viewFile"];
}
pageNum.value = 1;
pageSize.value = 10;
@@ -377,7 +383,13 @@
const openUploadDialog = row => {
nextTick(() => {
- uploadFiles.value?.openDialog(row);
+ uploadFiles.value?.openDialog("add", row);
+ });
+ };
+
+ const openViewDialog = row => {
+ nextTick(() => {
+ uploadFiles.value?.openDialog("view", row);
});
};
diff --git a/src/views/equipmentManagement/repair/Modal/RepairModal.vue b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
index 4a10071..b260d62 100644
--- a/src/views/equipmentManagement/repair/Modal/RepairModal.vue
+++ b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -49,9 +49,9 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鎶ヤ慨鎶ヤ慨椤圭洰">
+ <el-form-item label="鎶ヤ慨椤圭洰">
<el-input v-model="form.machineryCategory"
- placeholder="璇疯緭鍏ユ姤淇姤淇」鐩�"
+ placeholder="璇疯緭鍏ユ姤淇」鐩�"
:disabled="operationType === 'view'" />
</el-form-item>
</el-col>
diff --git a/src/views/equipmentManagement/spareParts/index.vue b/src/views/equipmentManagement/spareParts/index.vue
index 8abe35d..a1a4026 100644
--- a/src/views/equipmentManagement/spareParts/index.vue
+++ b/src/views/equipmentManagement/spareParts/index.vue
@@ -29,6 +29,7 @@
:tableLoading="loading"
:page="pagination"
:isShowPagination="true"
+ :row-class-name="rowClassName"
@pagination="handleSizeChange"
>
<template #status="{ row }">
@@ -95,7 +96,7 @@
</el-dialog>
</el-tab-pane>
- <el-tab-pane label="澶囦欢棰嗙敤璁板綍" name="usage">
+ <el-tab-pane label="澶囦欢浣跨敤璁板綍" name="usage">
<div class="search_form">
<el-form :inline="true" :model="usageQuery" class="search-form">
<el-form-item label="澶囦欢鍚嶇О">
@@ -521,9 +522,17 @@
onMounted(() => {
fetchListData();
});
+
+// 鏍规嵁鏁伴噺杩涜鍒ゆ柇鑳屾櫙棰滆壊
+const rowClassName = ({ row }) => {
+ const num = Number(row.quantity);
+ if (num <= 1) return 'row-qty-low';
+ if (num >= 8) return 'row-qty-high';
+ return 'row-qty-mid';
+};
</script>
-<style scoped>
+<style>
.spare-part-category {
padding: 20px;
}
@@ -547,8 +556,17 @@
font-weight: 600;
}
-.el-table__row:hover > td {
- background-color: #fafafa;
+.el-table .row-qty-low td.el-table__cell,
+.el-table .row-qty-low:hover > td.el-table__cell {
+ background-color: #fde8e8 !important;
+}
+.el-table .row-qty-mid td.el-table__cell,
+.el-table .row-qty-mid:hover > td.el-table__cell {
+ background-color: #f0f4f8 !important;
+}
+.el-table .row-qty-high td.el-table__cell,
+.el-table .row-qty-high:hover > td.el-table__cell {
+ background-color: #e8f5e9 !important;
}
/* 鎸夐挳缁勬牱寮� */
@@ -567,4 +585,5 @@
font-size: 12px;
margin-right: 4px;
}
+
</style>
\ No newline at end of file
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
index 8a9cd98..29e218a 100644
--- a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -35,6 +35,7 @@
<el-form-item label="淇濆吇椤圭洰">
<el-input
v-model="form.machineryCategory"
+ type="textarea"
placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
/>
</el-form-item>
diff --git a/src/views/equipmentManagement/upkeep/Form/RecordDetailDia.vue b/src/views/equipmentManagement/upkeep/Form/RecordDetailDia.vue
new file mode 100644
index 0000000..074628c
--- /dev/null
+++ b/src/views/equipmentManagement/upkeep/Form/RecordDetailDia.vue
@@ -0,0 +1,99 @@
+<template>
+ <FormDialog
+ v-model="dialogVisitable"
+ title="淇濆吇璁板綍璇︽儏"
+ width="800px"
+ operation-type="detail"
+ @close="cancel"
+ >
+ <el-descriptions border :column="2">
+ <el-descriptions-item label="璁惧鍚嶇О">
+ {{ detailData.deviceName || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="瑙勬牸鍨嬪彿">
+ {{ detailData.deviceModel || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="璁″垝淇濆吇鏃ユ湡">
+ {{ formatDate(detailData.maintenancePlanTime) }}
+ </el-descriptions-item>
+ <el-descriptions-item label="褰曞叆浜�">
+ {{ detailData.createUserName || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="淇濆吇椤圭洰" :span="2">
+ {{ detailData.machineryCategory || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="瀹為檯淇濆吇浜�">
+ {{ detailData.maintenanceActuallyName || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="瀹為檯淇濆吇鏃ユ湡">
+ {{ formatDate(detailData.maintenanceActuallyTime) }}
+ </el-descriptions-item>
+ <el-descriptions-item label="淇濆吇缁撴灉" :span="2">
+ {{ detailData.maintenanceResult || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鐘舵��" :span="2">
+ <el-tag v-if="detailData.status === 2" type="danger">澶辫触</el-tag>
+ <el-tag v-else-if="detailData.status === 1" type="success">瀹岀粨</el-tag>
+ <el-tag v-else type="warning">寰呬繚鍏�</el-tag>
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <div v-if="fileList && fileList.length > 0" class="image-section">
+ <div class="image-title">淇濆吇闄勪欢(鍥剧墖)锛�</div>
+ <AttachmentUploadImage
+ v-model:fileList="fileList"
+ :disabled="true"
+ />
+ </div>
+ </FormDialog>
+</template>
+
+<script setup>
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ref } from "vue";
+import dayjs from "dayjs";
+import { attachmentList } from "@/api/basicData/storageAttachment.js";
+import AttachmentUploadImage from '@/components/AttachmentUpload/image/index.vue';
+
+const dialogVisitable = ref(false);
+const detailData = ref({});
+const fileList = ref([]);
+
+const formatDate = (date) => {
+ return date ? dayjs(date).format("YYYY-MM-DD") : "--";
+};
+
+const openDialog = (row) => {
+ dialogVisitable.value = true;
+ detailData.value = { ...row };
+ fileList.value = [];
+
+ if (row.id) {
+ attachmentList({
+ recordType: 'device_maintenance',
+ recordId: row.id,
+ }).then(res => {
+ if (res && res.data) {
+ fileList.value = res.data || [];
+ }
+ });
+ }
+};
+
+const cancel = () => {
+ dialogVisitable.value = false;
+};
+
+defineExpose({ openDialog });
+</script>
+
+<style scoped>
+.image-section {
+ margin-top: 20px;
+}
+.image-title {
+ font-weight: bold;
+ margin-bottom: 10px;
+ color: #606266;
+}
+</style>
diff --git a/src/views/equipmentManagement/upkeep/Form/detailDia.vue b/src/views/equipmentManagement/upkeep/Form/detailDia.vue
new file mode 100644
index 0000000..c80691a
--- /dev/null
+++ b/src/views/equipmentManagement/upkeep/Form/detailDia.vue
@@ -0,0 +1,118 @@
+<template>
+ <FormDialog
+ v-model="dialogVisitable"
+ title="淇濆吇浠诲姟璇︽儏"
+ width="800px"
+ operation-type="detail"
+ @close="cancel"
+ >
+ <el-descriptions border :column="2">
+ <el-descriptions-item label="璁惧鍚嶇О">
+ {{ detailData.taskName || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="瑙勬牸鍨嬪彿">
+ {{ detailData.deviceModel || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="褰曞叆浜�">
+ {{ detailData.registrant || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鐧昏鏃堕棿">
+ {{ detailData.registrationDate || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="淇濆吇椤圭洰" :span="2">
+ {{ detailData.machineryCategory || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="淇濆吇浜�">
+ {{ detailData.maintenancePerson || '--' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="浠诲姟棰戠巼">
+ {{ formatFrequencyType(detailData.frequencyType) }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鎵ц鏃堕棿">
+ {{ formatFrequencyDetail(detailData.frequencyDetail) }}
+ </el-descriptions-item>
+ <el-descriptions-item label="瀹氭椂浠诲姟">
+ <el-tag :type="detailData.isActive === 1 ? 'success' : 'info'">
+ {{ detailData.isActive === 1 ? '寮�鍚�' : '鍏抽棴' }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="澶囨敞" :span="2">
+ {{ detailData.remarks || '--' }}
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <div v-if="fileList && fileList.length > 0" class="image-section">
+ <div class="image-title">璁惧鍥剧墖锛�</div>
+ <AttachmentUploadImage
+ v-model:fileList="fileList"
+ :disabled="true"
+ />
+ </div>
+ </FormDialog>
+</template>
+
+<script setup>
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ref } from "vue";
+import { getLedgerById } from "@/api/equipmentManagement/ledger";
+import AttachmentUploadImage from '@/components/AttachmentUpload/image/index.vue';
+
+const dialogVisitable = ref(false);
+const detailData = ref({});
+const fileList = ref([]);
+
+const formatFrequencyType = (type) => {
+ const map = {
+ DAILY: "姣忔棩",
+ WEEKLY: "姣忓懆",
+ MONTHLY: "姣忔湀",
+ QUARTERLY: "瀛e害",
+ };
+ return map[type] || "--";
+};
+
+const formatFrequencyDetail = (detail) => {
+ if (!detail) return "--";
+ const replacements = {
+ MON: "鍛ㄤ竴",
+ TUE: "鍛ㄤ簩",
+ WED: "鍛ㄤ笁",
+ THU: "鍛ㄥ洓",
+ FRI: "鍛ㄤ簲",
+ SAT: "鍛ㄥ叚",
+ SUN: "鍛ㄦ棩",
+ };
+ return detail.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]);
+};
+
+const openDialog = (row) => {
+ dialogVisitable.value = true;
+ detailData.value = { ...row };
+ fileList.value = [];
+
+ if (row.taskId) {
+ getLedgerById(row.taskId).then(res => {
+ if (res.code === 200 && res.data) {
+ fileList.value = res.data.storageBlobVOs || [];
+ }
+ });
+ }
+};
+
+const cancel = () => {
+ dialogVisitable.value = false;
+};
+
+defineExpose({ openDialog });
+</script>
+
+<style scoped>
+.image-section {
+ margin-top: 20px;
+}
+.image-title {
+ font-weight: bold;
+ margin-bottom: 10px;
+ color: #606266;
+}
+</style>
diff --git a/src/views/equipmentManagement/upkeep/Form/formDia.vue b/src/views/equipmentManagement/upkeep/Form/formDia.vue
index 6856ae1..60dda54 100644
--- a/src/views/equipmentManagement/upkeep/Form/formDia.vue
+++ b/src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -70,8 +70,8 @@
<el-form-item label="淇濆吇椤圭洰" prop="machineryCategory">
<el-input
v-model.trim="form.machineryCategory"
+ type="textarea"
placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
- maxlength="100"
clearable
/>
</el-form-item>
@@ -101,7 +101,7 @@
<el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType">
<el-form-item label="鏃ユ湡" prop="frequencyDetail">
<el-time-picker v-model="form.frequencyDetail" placeholder="閫夋嫨鏃堕棿" format="HH:mm"
- value-format="HH:mm" />
+ value-format="HH:mm" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
@@ -116,7 +116,7 @@
<el-option label="鍛ㄦ棩" value="SUN"/>
</el-select>
<el-time-picker v-model="form.time" placeholder="閫夋嫨鏃堕棿" format="HH:mm"
- value-format="HH:mm" style="width: 50%"/>
+ value-format="HH:mm" style="width: 50%"/>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
@@ -141,6 +141,23 @@
format="MM,DD,HH:mm"
value-format="MM,DD,HH:mm"
/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="瀹氭椂浠诲姟">
+ <el-switch
+ v-model="form.isActive"
+ :active-value="1"
+ :inactive-value="0"
+ active-text="寮�鍚�"
+ inactive-text="鍏抽棴"
+ inline-prompt
+ />
+ <span style="margin-left: 12px; color: #909399; font-size: 12px;">
+ {{ form.isActive === 1 ? '浠诲姟灏嗘寜璁″垝鎵ц' : '浠诲姟鏆傚仠鎵ц' }}
+ </span>
</el-form-item>
</el-col>
</el-row>
@@ -184,7 +201,8 @@
time: '',
deviceModel: undefined, // 瑙勬牸鍨嬪彿
registrationDate: '',
- maintenancePerson: '' // 淇濆吇浜�
+ maintenancePerson: '', // 淇濆吇浜�
+ isActive: 0 // 瀹氭椂浠诲姟寮�鍏筹細0=鍏抽棴锛�1=寮�鍚�
},
rules: {
taskId: [{ required: true, message: "璇烽�夋嫨璁惧", trigger: "change" },],
@@ -271,7 +289,8 @@
time: '',
deviceModel: undefined,
registrationDate: '',
- maintenancePerson: ''
+ maintenancePerson: '',
+ isActive: 0
}
}
@@ -294,21 +313,21 @@
}
delete payload.inspector
delete payload.inspectorIds
-
+ delete payload.active
+
if (payload.frequencyType === 'WEEKLY') {
let frequencyDetail = ''
frequencyDetail = payload.week + ',' + payload.time
payload.frequencyDetail = frequencyDetail
}
-
+
// 褰曞叆鏃ユ湡锛氱洿鎺ヤ娇鐢ㄨ〃鍗曢噷鐨� registrationDate 瀛楁
// 涓�浜涢粯璁ょ姸鎬佸瓧娈�
if (payload.status === undefined || payload.status === null || payload.status === '') {
payload.status = '0' // 榛樿鐘舵�侊紝鍙寜瀹為檯鏋氫妇璋冩暣
}
- payload.active = true
payload.deleted = 0
-
+
if (operationType.value === 'edit') {
await deviceMaintenanceTaskEdit(payload)
} else {
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 245a162..cd1adff 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -63,6 +63,12 @@
}"
@selection-change="handleScheduledSelectionChange"
@pagination="changeScheduledPage">
+ <template #isActiveRef="{ row }">
+ <el-tag v-if="row.isActive === 1"
+ type="success">寮�鍚�</el-tag>
+ <el-tag v-else
+ type="info">鍏抽棴</el-tag>
+ </template>
<template #statusRef="{ row }">
<el-tag v-if="row.status === 1"
type="success">鍚敤</el-tag>
@@ -70,6 +76,11 @@
type="danger">鍋滅敤</el-tag>
</template>
<template #operation="{ row }">
+ <el-button type="primary"
+ link
+ @click="handleDetail(row)">
+ 璇︽儏
+ </el-button>
<el-button type="primary"
link
@click="editScheduledTask(row)">
@@ -171,6 +182,11 @@
type="warning">寰呬繚鍏�</el-tag>
</template>
<template #operation="{ row }">
+ <el-button type="primary"
+ link
+ @click="handleRecordDetail(row)">
+ 璇︽儏
+ </el-button>
<!-- 杩欎釜鍔熻兘璺熸柊澧炰繚鍏诲姛鑳戒竴妯′竴鏍凤紝鏈夊暐鎰忎箟锛� -->
<!-- <el-button
type="primary"
@@ -213,6 +229,8 @@
@ok="getTableData" />
<FormDia ref="formDiaRef"
@closeDia="getScheduledTableData" />
+ <DetailDia ref="detailDiaRef" />
+ <RecordDetailDia ref="recordDetailDiaRef" />
<FileList v-if="fileDialogVisible"
v-model:visible="fileDialogVisible"
:record-type="'device_maintenance'"
@@ -235,6 +253,8 @@
import PlanModal from "./Form/PlanModal.vue";
import MaintenanceModal from "./Form/MaintenanceModal.vue";
import FormDia from "./Form/formDia.vue";
+ import DetailDia from "./Form/detailDia.vue";
+ import RecordDetailDia from "./Form/RecordDetailDia.vue";
import {
getUpkeepPage,
delUpkeep,
@@ -257,6 +277,10 @@
const maintainModalRef = ref();
// 瀹氭椂浠诲姟寮圭獥鎺у埗鍣�
const formDiaRef = ref();
+ // 瀹氭椂浠诲姟璇︽儏寮圭獥鎺у埗鍣�
+ const detailDiaRef = ref();
+ // 淇濆吇璁板綍璇︽儏寮圭獥鎺у埗鍣�
+ const recordDetailDiaRef = ref();
// 闄勪欢寮圭獥
const fileListDialogRef = ref(null);
const fileDialogVisible = ref(false);
@@ -308,7 +332,7 @@
{
prop: "frequencyType",
label: "棰戞",
- minWidth: 150,
+ minWidth: 80,
// PIMTable 浣跨敤鐨勬槸 formatData锛岃�屼笉鏄� Element-Plus 鐨� formatter
formatData: cell =>
({
@@ -321,7 +345,7 @@
{
prop: "frequencyDetail",
label: "寮�濮嬫棩鏈熶笌鏃堕棿",
- minWidth: 150,
+ minWidth: 130,
// 鍚屾牱鏀圭敤 formatData锛孭IMTable 鍐呴儴浼氭妸鍗曞厓鏍煎�间紶杩涙潵
formatData: cell => {
if (typeof cell !== "string") return "";
@@ -342,6 +366,14 @@
);
},
},
+ {
+ prop: "isActive",
+ label: "瀹氭椂浠诲姟",
+ dataType: "slot",
+ slot: "isActiveRef",
+ align: "center",
+ minWidth: 100,
+ },
{ prop: "maintenancePerson", label: "淇濆吇浜�", minWidth: 100 },
{ prop: "registrant", label: "鐧昏浜�", minWidth: 100 },
{
@@ -349,7 +381,7 @@
label: "鐧昏鏃ユ湡",
minWidth: 100,
formatData: cell =>
- cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-",
+ cell ? dayjs(cell).format("YYYY-MM-DD") : "-",
},
{
fixed: "right",
@@ -357,7 +389,7 @@
dataType: "slot",
slot: "operation",
align: "center",
- width: "200px",
+ width: "160px",
},
]);
@@ -409,7 +441,7 @@
align: "center",
prop: "maintenanceActuallyTime",
formatData: cell =>
- cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-",
+ cell ? dayjs(cell).format("YYYY-MM-DD") : "-",
},
{
label: "淇濆吇缁撴灉",
@@ -431,7 +463,7 @@
dataType: "slot",
slot: "operation",
align: "center",
- width: "350px",
+ width: "250px",
},
]);
@@ -489,6 +521,14 @@
if (row) {
nextTick(() => {
formDiaRef.value?.openDialog("edit", row);
+ });
+ }
+ };
+
+ const handleDetail = row => {
+ if (row) {
+ nextTick(() => {
+ detailDiaRef.value?.openDialog(row);
});
}
};
@@ -564,6 +604,14 @@
maintainModalRef.value.open(row.id, row);
};
+ const handleRecordDetail = row => {
+ if (row) {
+ nextTick(() => {
+ recordDetailDiaRef.value?.openDialog(row);
+ });
+ }
+ };
+
const addPlan = () => {
planModalRef.value.openModal();
};
diff --git a/src/views/financialManagement/assets/fixedAssets.vue b/src/views/financialManagement/assets/fixedAssets.vue
index 95eb017..24b4cc3 100644
--- a/src/views/financialManagement/assets/fixedAssets.vue
+++ b/src/views/financialManagement/assets/fixedAssets.vue
@@ -82,7 +82,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="璧勪骇缂栧彿" prop="assetCode">
- <el-input v-model="form.assetCode" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
+ <el-input v-model="form.assetCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -175,13 +175,6 @@
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
- <el-date-picker v-model="createTimeDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
- </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>
@@ -196,7 +189,6 @@
<script setup>
import { ref, reactive, onMounted, computed } from "vue";
-import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
@@ -266,17 +258,10 @@
keeper: "",
status: "in_use",
remark: "",
- createTime: "",
});
const form = reactive({
...createDefaultForm(),
-});
-const createTimeDate = computed({
- get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
- set: (value) => {
- form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
const rules = {
@@ -371,14 +356,16 @@
getTableData();
};
+const buildAssetCode = () => `GD${Date.now().toString().slice(-10)}`;
+
const add = () => {
isEdit.value = false;
isView.value = false;
currentId.value = null;
dialogTitle.value = "鏂板鍥哄畾璧勪骇";
Object.assign(form, createDefaultForm(), {
+ assetCode: buildAssetCode(),
purchaseDate: new Date().toISOString().split('T')[0],
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
dialogVisible.value = true;
};
diff --git a/src/views/financialManagement/assets/intangibleAssets.vue b/src/views/financialManagement/assets/intangibleAssets.vue
index b2c13b1..4642166 100644
--- a/src/views/financialManagement/assets/intangibleAssets.vue
+++ b/src/views/financialManagement/assets/intangibleAssets.vue
@@ -72,7 +72,7 @@
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
- <el-button v-if="row.status !== 'amortized'" type="primary" link @click="edit(row)">缂栬緫</el-button>
+ <el-button type="primary" link @click="edit(row)">缂栬緫</el-button>
<el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
@@ -83,7 +83,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="璧勪骇缂栧彿" prop="assetCode">
- <el-input v-model="form.assetCode" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
+ <el-input v-model="form.assetCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -160,15 +160,8 @@
<el-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��" style="width: 100%;">
<el-option label="鍦ㄧ敤" value="in_use" />
<el-option label="闂茬疆" value="idle" />
- <el-option v-if="isView" label="宸叉憡閿�瀹屾瘯" value="amortized" />
+ <el-option label="宸叉憡閿�瀹屾瘯" value="amortized" />
</el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
- <el-date-picker v-model="createTimeDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
</el-form-item>
</el-col>
</el-row>
@@ -189,7 +182,6 @@
<script setup>
import { ref, reactive, onMounted, computed } from "vue";
-import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
@@ -244,7 +236,6 @@
);
const createDefaultForm = () => ({
- id: null,
assetCode: "",
assetName: "",
category: "",
@@ -259,17 +250,10 @@
status: "in_use",
description: "",
remark: "",
- createTime: "",
});
const form = reactive({
...createDefaultForm(),
-});
-const createTimeDate = computed({
- get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
- set: (value) => {
- form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
const rules = {
@@ -370,14 +354,16 @@
getTableData();
};
+const buildAssetCode = () => `WX${Date.now().toString().slice(-10)}`;
+
const add = () => {
isEdit.value = false;
isView.value = false;
currentId.value = null;
dialogTitle.value = "鏂板鏃犲舰璧勪骇";
Object.assign(form, createDefaultForm(), {
+ assetCode: buildAssetCode(),
acquisitionDate: new Date().toISOString().split('T')[0],
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
dialogVisible.value = true;
};
diff --git a/src/views/financialManagement/payable/input-invoice.vue b/src/views/financialManagement/payable/input-invoice.vue
index ae40709..86ebd09 100644
--- a/src/views/financialManagement/payable/input-invoice.vue
+++ b/src/views/financialManagement/payable/input-invoice.vue
@@ -51,8 +51,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -375,26 +373,6 @@
invoiceType: [{ required: true, message: "璇烽�夋嫨鍙戠エ绫诲瀷", trigger: "change" }],
taxRate: [{ required: true, message: "璇烽�夋嫨绋庣巼", trigger: "change" }],
amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
-};
-
-const summaryProps = ["amount", "taxAmount", "totalAmount"];
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (summaryProps.includes(col.property)) {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur[col.property]);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = Number(total.toFixed(2)).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- } else {
- sums[index] = "";
- }
- });
- return sums;
};
const formatMoney = (value) => {
diff --git a/src/views/financialManagement/payable/payment.vue b/src/views/financialManagement/payable/payment.vue
index dd386d8..18e7941 100644
--- a/src/views/financialManagement/payable/payment.vue
+++ b/src/views/financialManagement/payable/payment.vue
@@ -65,8 +65,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -151,25 +149,7 @@
dataList.value.reduce((sum, item) => sum + Number(item.amount ?? 0), 0)
);
- const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "amount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.amount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- } else {
- sums[index] = "";
- }
- });
- return sums;
-};
-
-const formatMoney = value => {
+ const formatMoney = value => {
if (value === undefined || value === null) return "0.00";
return Number(value)
.toFixed(2)
diff --git a/src/views/financialManagement/payable/paymentApply.vue b/src/views/financialManagement/payable/paymentApply.vue
index 309d6d3..3937e96 100644
--- a/src/views/financialManagement/payable/paymentApply.vue
+++ b/src/views/financialManagement/payable/paymentApply.vue
@@ -52,8 +52,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -99,7 +97,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="鐢宠鍗曞彿" prop="invoiceApplicationNo">
- <el-input v-model="form.invoiceApplicationNo" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
+ <el-input v-model="form.invoiceApplicationNo" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -160,18 +158,6 @@
</el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
- <el-date-picker
- v-model="formCreateTimeDate"
- 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="paymentAmount">
<el-input-number
v-model="form.paymentAmount"
@@ -231,7 +217,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="浠樻鍗曞彿" prop="paymentNumber">
- <el-input v-model="paymentForm.paymentNumber" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
+ <el-input v-model="paymentForm.paymentNumber" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -259,17 +245,6 @@
</el-col>
</el-row>
<el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
- <el-date-picker
- v-model="paymentFormCreateTimeDate"
- 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="paymentAmount">
<el-input-number
@@ -355,7 +330,6 @@
<script setup>
import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from "vue";
-import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
@@ -433,7 +407,6 @@
bankAccount: "",
bankName: "",
remark: "",
- createTime: "",
});
const paymentRules = {
@@ -456,19 +429,6 @@
stockInRecordIds: [],
inboundBatches: "",
status: 0,
- createTime: "",
-});
-const formCreateTimeDate = computed({
- get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
- set: (value) => {
- form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
-});
-const paymentFormCreateTimeDate = computed({
- get: () => (paymentForm.createTime ? String(paymentForm.createTime).split(" ")[0] : ""),
- set: (value) => {
- paymentForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
const rules = {
@@ -477,24 +437,6 @@
paymentAmount: [{ required: true, message: "璇疯緭鍏ヤ粯娆鹃噾棰�", trigger: "blur" }],
paymentMethod: [{ required: true, message: "璇烽�夋嫨浠樻鏂瑰紡", trigger: "change" }],
applyDate: [{ required: true, message: "璇烽�夋嫨鐢宠鏃ユ湡", trigger: "change" }],
-};
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "amount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.amount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- } else {
- sums[index] = "";
- }
- });
- return sums;
};
const formatMoney = (value) => {
@@ -621,7 +563,6 @@
stockInRecordIds,
inboundBatches: formatInboundBatches(row.inboundBatches),
status: normalizeStatus(row.status),
- createTime: row.createTime ?? "",
});
};
@@ -639,7 +580,6 @@
remark: row.remark ?? "",
status: statusOverride !== undefined ? statusOverride : normalizeStatus(row.status),
paymentAmount: Number(row.paymentAmount ?? row.amount ?? 0),
- createTime: row.createTime,
});
const buildSubmitPayload = (forUpdate = false) => {
@@ -653,7 +593,6 @@
remark: form.remark || "",
status: 0,
paymentAmount: form.paymentAmount,
- createTime: form.createTime,
};
if (forUpdate) {
payload.id = currentId.value;
@@ -764,7 +703,6 @@
stockInRecordIds: [],
inboundBatches: "",
status: 0,
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
inboundBatchList.value = [];
inboundBatchOptions.value = [];
@@ -843,7 +781,6 @@
bankAccount: row.bankAccountNum ?? row.bankAccount ?? "",
bankName: row.bankAccountName ?? row.bankName ?? "",
remark: "",
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
paymentDialogVisible.value = true;
nextTick(() => {
@@ -863,7 +800,6 @@
paymentAmount: paymentForm.paymentAmount,
paymentNumber: paymentForm.paymentNumber || "",
remark: paymentForm.remark || "",
- createTime: paymentForm.createTime,
})
.then((res) => {
if (res.code === 200) {
diff --git a/src/views/financialManagement/payable/purchaseIn.vue b/src/views/financialManagement/payable/purchaseIn.vue
index b105859..fcb768f 100644
--- a/src/views/financialManagement/payable/purchaseIn.vue
+++ b/src/views/financialManagement/payable/purchaseIn.vue
@@ -49,8 +49,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -100,7 +98,7 @@
slot: "inboundDate",
},
{ label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
- { label: "瑙勬牸鍨嬪彿", prop: "specificationModel", minWidth: "140" },
+ { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
{
label: "閲戦",
prop: "inboundAmount",
@@ -191,25 +189,7 @@
getTableData();
};
- const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "inboundAmount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.inboundAmount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- } else {
- sums[index] = "";
- }
- });
- return sums;
-};
-
-const handleOut = () => {
+ const handleOut = () => {
proxy.download(
"/accountPurchase/exportAccountPurchaseInbound",
buildFilterParams(),
diff --git a/src/views/financialManagement/payable/purchaseReturn.vue b/src/views/financialManagement/payable/purchaseReturn.vue
index 5c274ac..eeec383 100644
--- a/src/views/financialManagement/payable/purchaseReturn.vue
+++ b/src/views/financialManagement/payable/purchaseReturn.vue
@@ -44,8 +44,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -85,30 +83,6 @@
{ label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: "150" },
{ label: "渚涘簲鍟�", prop: "supplierName", minWidth: "180" },
{ label: "鍏宠仈鍏ュ簱鍗曞彿", prop: "inboundBatches", minWidth: "150" },
- {
- label: "鍙戣揣绫诲瀷",
- prop: "shippingType",
- minWidth: "110",
- formatData: (val) => ({ 1: "璐ц溅", 2: "蹇��" }[String(val)] || "--"),
- },
- {
- label: "鍙戣揣杞︾墝鍙�",
- prop: "truckPlateNo",
- minWidth: "140",
- formatData: (_val, row) => (String(row?.shippingType) === "1" ? row?.truckPlateNo || "--" : "--"),
- },
- {
- label: "蹇�掑叕鍙�",
- prop: "expressCompany",
- minWidth: "140",
- formatData: (_val, row) => (String(row?.shippingType) === "2" ? row?.expressCompany || "--" : "--"),
- },
- {
- label: "蹇�掑崟鍙�",
- prop: "expressNo",
- minWidth: "150",
- formatData: (_val, row) => (String(row?.shippingType) === "2" ? row?.expressNo || "--" : "--"),
- },
{ label: "閫�璐ф棩鏈�", prop: "preparedAt", minWidth: "170" },
{
label: "閫�娆炬�婚",
@@ -199,24 +173,6 @@
pagination.currentPage = page;
pagination.pageSize = limit;
getTableData();
-};
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "totalAmount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.totalAmount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- } else {
- sums[index] = "";
- }
- });
- return sums;
};
const handleOut = () => {
diff --git a/src/views/financialManagement/payable/reconciliation.vue b/src/views/financialManagement/payable/reconciliation.vue
index a3b8495..e749e56 100644
--- a/src/views/financialManagement/payable/reconciliation.vue
+++ b/src/views/financialManagement/payable/reconciliation.vue
@@ -35,8 +35,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -406,26 +404,6 @@
closingBalance: generateForm.closingBalance,
accountStatementDetails: selectedPurchases.value.map(buildDetailSubmitItem),
});
-
-const summaryProps = ["openingBalance", "currentPlan", "currentActually", "closingBalance"];
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (summaryProps.includes(col.property)) {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur[col.property]);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = Number(total.toFixed(2)).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- } else {
- sums[index] = "";
- }
- });
- return sums;
-};
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
diff --git a/src/views/financialManagement/receivable/invoiceApply.vue b/src/views/financialManagement/receivable/invoiceApply.vue
index 21b5f0e..14fdd67 100644
--- a/src/views/financialManagement/receivable/invoiceApply.vue
+++ b/src/views/financialManagement/receivable/invoiceApply.vue
@@ -48,8 +48,6 @@
v-loading="tableLoading"
:column="columns"
:tableData="dataList"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -100,7 +98,7 @@
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="鐢宠鍗曞彿" prop="applyCode">
- <el-input v-model="form.applyCode" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
+ <el-input v-model="form.applyCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
</el-row>
@@ -191,20 +189,6 @@
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
- <el-date-picker
- v-model="formCreateTimeDate"
- 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="璇疯緭鍏ュ彂绁ㄥ唴瀹�" :disabled="isView" />
</el-form-item>
@@ -269,7 +253,6 @@
<script setup>
import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance, defineAsyncComponent } from "vue";
-import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { listCustomer } from "@/api/basicData/customer.js";
@@ -541,13 +524,6 @@
applyDate: "",
content: "",
remark: "",
- createTime: "",
-});
-const formCreateTimeDate = computed({
- get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
- set: (value) => {
- form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
const rules = {
@@ -650,27 +626,6 @@
proxy.download("/accountInvoiceApplication/exportAccountInvoiceApplication", params, filename);
};
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "amount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.amount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
- } else {
- sums[index] = "";
- }
- });
- return sums;
-};
-
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
@@ -751,7 +706,6 @@
status: normalizeStatus(row.status ?? row.auditStatus),
outboundBatchNos,
outboundBatches: formatOutboundBatches(row.outboundBatches),
- createTime: row.createTime ?? "",
});
};
@@ -760,7 +714,7 @@
isView.value = false;
dialogTitle.value = "鏂板寮�绁ㄧ敵璇�";
Object.assign(form, {
- applyCode: "",
+ applyCode: "KP" + Date.now().toString().slice(-8),
customerId: "",
outboundBatchNos: [],
outboundBatches: "",
@@ -770,7 +724,6 @@
applyDate: new Date().toISOString().split("T")[0],
content: "",
remark: "",
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
outboundBatchList.value = [];
outboundBatchOptions.value = [];
@@ -799,7 +752,6 @@
invoiceAmount: form.amount,
taxRate: form.taxRate,
status: 0,
- createTime: form.createTime,
};
if (forUpdate) {
payload.id = currentId.value;
@@ -814,7 +766,6 @@
dialogTitle.value = "缂栬緫寮�绁ㄧ敵璇�";
fillFormFromRow(row);
dialogVisible.value = true;
- loadOutboundBatches(form.customerId, true);
};
const view = (row) => {
diff --git a/src/views/financialManagement/receivable/outputInvoice.vue b/src/views/financialManagement/receivable/outputInvoice.vue
index effb0af..d746aea 100644
--- a/src/views/financialManagement/receivable/outputInvoice.vue
+++ b/src/views/financialManagement/receivable/outputInvoice.vue
@@ -37,7 +37,7 @@
<div class="actions">
<div></div>
<div>
- <el-button type="primary" @click="add" icon="Plus">褰曞叆鍙戠エ</el-button>
+ <!-- <el-button type="primary" @click="add" icon="Plus">褰曞叆鍙戠エ</el-button> -->
<el-button type="success" @click="handleExport" icon="Download">瀵煎嚭</el-button>
</div>
</div>
@@ -46,8 +46,6 @@
v-loading="tableLoading"
:column="columns"
:tableData="dataList"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -93,7 +91,7 @@
@confirm="submitForm"
@cancel="closeDialog"
>
- <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
+ <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="鐘舵��">
@@ -111,25 +109,13 @@
</el-col>
<el-col :span="12">
<el-form-item label="瀹㈡埛" prop="customerId">
- <el-select @change="checkCustomer" v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" :disabled="isView">
+ <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-row>
<el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍏宠仈寮�绁ㄧ敵璇�" prop="accountInvoiceApplicationId">
- <el-select v-model="form.accountInvoiceApplicationId"
- placeholder="璇峰厛閫夋嫨瀹㈡埛"
- readonly
- @change="selectionApply"
- :disabled="!form.customerId || isView"
- class="outbound-batch-select">
- <el-option v-for="(item,index) in applyList" :key="index" :label="item.invoiceApplicationNo" :value="item.id"></el-option>
- </el-select>
- </el-form-item>
- </el-col>
<el-col :span="12">
<el-form-item label="寮�绁ㄦ棩鏈�" prop="invoiceDate">
<el-date-picker
@@ -142,15 +128,14 @@
/>
</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%;"
- :disabled="isView"
+ v-model="form.invoiceType"
+ placeholder="璇烽�夋嫨鍙戠エ绫诲瀷"
+ style="width: 100%;"
+ :disabled="isView"
+ @change="handleInvoiceTypeChange"
>
<el-option label="澧炲�肩◣涓撶敤鍙戠エ" value="澧炲�肩◣涓撶敤鍙戠エ" />
<el-option label="澧炲�肩◣鏅�氬彂绁�" value="澧炲�肩◣鏅�氬彂绁�" />
@@ -158,6 +143,8 @@
</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
@@ -165,7 +152,7 @@
placeholder="璇烽�夋嫨绋庣巼"
style="width: 100%;"
:disabled="isView"
- @change="handleTaxRateChange"
+ @change="calculateTax"
>
<el-option
v-for="dict in tax_rate"
@@ -178,7 +165,7 @@
</el-col>
</el-row>
<el-row :gutter="20">
- <el-col :span="10">
+ <el-col :span="8">
<el-form-item label="閲戦(涓嶅惈绋�)" prop="amount">
<el-input-number
v-model="form.amount"
@@ -186,18 +173,18 @@
:precision="2"
style="width: 100%;"
:disabled="isView"
- @change="handleTaxRateChange"
+ @change="calculateTax"
/>
</el-form-item>
</el-col>
- <el-col :span="7">
+ <el-col :span="8">
<el-form-item label="绋庨">
- <el-input v-model="form.taxAmount" style="width: 100%;" disabled />
+ <el-input v-model="form.taxAmount" disabled />
</el-form-item>
</el-col>
- <el-col :span="7">
+ <el-col :span="8">
<el-form-item label="浠风◣鍚堣">
- <el-input v-model="form.totalAmount" style="width: 100%;" disabled />
+ <el-input v-model="form.totalAmount" disabled />
</el-form-item>
</el-col>
</el-row>
@@ -235,7 +222,6 @@
cancelAccountSalesInvoice,
deleteAccountSalesInvoice,
} from "@/api/financialManagement/accountSalesInvoice.js";
-import {getAccountInvoiceApplicationList} from "@/api/financialManagement/invoiceApply.js";
const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
@@ -283,9 +269,6 @@
const fileDialogVisible = ref(false);
const currentRecordId = ref(0);
-const applySelectVisible = ref(false);
-const applyList = ref([]);
-
const openFileDialog = (row) => {
if (!row.accountInvoiceApplicationId) {
ElMessage.warning("鏈叧鑱斿紑绁ㄧ敵璇凤紝鏃犳硶鏌ョ湅闄勪欢");
@@ -328,14 +311,12 @@
totalAmount: 0,
content: "",
remark: "",
- deptId: undefined,
accountInvoiceApplicationId: undefined,
storageAttachmentId: undefined,
});
const rules = {
invoiceNo: [{ required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿鐮�", trigger: "blur" }],
- accountInvoiceApplicationId: [{ required: true, message: "璇烽�夋嫨寮�绁ㄧ敵璇�", trigger: "change" }],
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
invoiceDate: [{ required: true, message: "璇烽�夋嫨寮�绁ㄦ棩鏈�", trigger: "change" }],
invoiceType: [{ required: true, message: "璇烽�夋嫨鍙戠エ绫诲瀷", trigger: "change" }],
@@ -343,99 +324,18 @@
amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
};
-// 閫夋嫨瀹㈡埛
-const checkCustomer = (val) =>{
- loadApplyList(val);
-}
-
-//鏌ヨ寮�绁ㄧ敵璇峰垪琛�
-const loadApplyList = (customerId) => {
- if (!customerId) {
- applyList.value = [];
- return Promise.resolve();
- }
- return getAccountInvoiceApplicationList({ customerId })
- .then(res => {
- if (res.code === 200) {
- const list = res.data?.records ?? res.data ?? [];
- applyList.value = Array.isArray(list) ? list : [];
- } else {
- applyList.value = [];
- }
- })
- .catch(() => {
- applyList.value = [];
- })
+const formatMoney = (value) => {
+ if (value === undefined || value === null) return "0.00";
+ return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
-const selectionApply = (val)=>{
- const applyObj = applyList.value.find(item=>item.id === val);
- if(!applyObj){
- ElMessage.warning("璇烽�夋嫨鍏宠仈鐨勫紑绁ㄧ敵璇�");
- return;
- }
- form.remark = applyObj.remark;
- form.content = applyObj.invoiceContent;
- form.invoiceDate = applyObj.applyDate;
- form.invoiceType = applyObj.invoiceType;
- form.deptId = applyObj.deptId;
- form.taxRate = applyObj.taxRate;
- form.totalAmount = applyObj.invoiceAmount
- handleTaxRateChange();
-}
-
-/** 浠风◣鍚堣鍙樻洿锛氭寜绋庣巼鍙嶇畻涓嶅惈绋庨噾棰濄�佺◣棰� */
-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 calculateTaxFromExclusive = () => {
+const calculateTax = () => {
form.taxAmount = Number((form.amount * form.taxRate / 100).toFixed(2));
form.totalAmount = Number((form.amount + form.taxAmount).toFixed(2));
};
-const handleTaxRateChange = () => {
- if (form.totalAmount > 0) {
- calculateTaxFromInclusive(form.totalAmount);
- } else {
- calculateTaxFromExclusive();
- }
-};
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "amount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.amount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
- } else {
- sums[index] = "";
- }
- });
- return sums;
-};
-
-const formatMoney = (value) => {
- if (value === undefined || value === null) return "0.00";
- return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+const handleInvoiceTypeChange = () => {
+ calculateTax();
};
const normalizeTableRow = (row) => ({
@@ -583,8 +483,6 @@
const closeDialog = () => {
dialogVisible.value = false;
- applySelectVisible.value = false;
- isView.value = false;
isView.value = false;
};
diff --git a/src/views/financialManagement/receivable/receipt.vue b/src/views/financialManagement/receivable/receipt.vue
index 29194e7..6ddb3fe 100644
--- a/src/views/financialManagement/receivable/receipt.vue
+++ b/src/views/financialManagement/receivable/receipt.vue
@@ -111,7 +111,7 @@
<el-form-item label="鏀舵鍗曞彿"
prop="receiptCode">
<el-input v-model="form.receiptCode"
- placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�"
+ placeholder="绯荤粺鑷姩鐢熸垚"
disabled />
</el-form-item>
</el-col>
@@ -171,10 +171,10 @@
prop="amount">
<el-input-number v-model="form.amount"
:min="0"
- :max="collectionAmountInputMax"
:precision="2"
style="width: 100%;"
- :disabled="isView" />
+ :disabled="isView"
+ placeholder="鏍规嵁鍏宠仈鍗曟嵁鑷姩姹囨�伙紝鍙慨鏀�" />
</el-form-item>
</el-col>
</el-row>
@@ -191,17 +191,6 @@
:label="item.label"
:value="item.value" />
</el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿"
- prop="createTime">
- <el-date-picker v-model="formCreateTimeDate"
- type="date"
- placeholder="閫夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- style="width: 100%;"
- :disabled="isView" />
</el-form-item>
</el-col>
</el-row>
@@ -274,12 +263,6 @@
align="right">
<template #default="{ row }">楼{{ formatMoney(row.outboundAmount) }}</template>
</el-table-column>
- <el-table-column prop="amountReceived"
- label="宸叉敹娆鹃噾棰�"
- width="110"
- align="right">
- <template #default="{ row }">楼{{ formatMoney(row.amountReceived) }}</template>
- </el-table-column>
<el-table-column prop="taxRate"
label="绋庣巼"
width="80"
@@ -305,7 +288,6 @@
nextTick,
getCurrentInstance,
} from "vue";
- import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { listCustomer } from "@/api/basicData/customer.js";
@@ -368,7 +350,6 @@
const isEdit = ref(false);
const isView = ref(false);
const currentId = ref(null);
- const originalReceiptAmount = ref(0);
const submitLoading = ref(false);
const customerList = ref([]);
@@ -398,54 +379,7 @@
stockOutRecordIds: [],
outboundBatches: "",
remark: "",
- createTime: "",
});
- const formCreateTimeDate = computed({
- get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
- set: (value) => {
- form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
- });
-
- const maxCollectionAmount = computed(() => {
- const selected = form.stockOutRecordIds || [];
- const editAmount = isEdit.value ? Number(originalReceiptAmount.value) || 0 : 0;
- if (!selected.length) return isEdit.value ? editAmount : undefined;
- const selectedValueSet = new Set(selected.map(id => String(id)));
- const selectedOptions = outboundBatchOptions.value.filter(
- opt => opt.amountLimitAvailable && selectedValueSet.has(String(opt.value))
- );
- if (selectedOptions.length !== selectedValueSet.size) {
- return isEdit.value ? Number(editAmount.toFixed(2)) : undefined;
- }
- const sum = selectedOptions.reduce(
- (acc, opt) => acc + (Number(opt.outboundAmount) || 0),
- 0
- );
- return Number((sum + editAmount).toFixed(2));
- });
-
- const collectionAmountInputMax = computed(
- () => maxCollectionAmount.value ?? Number.MAX_SAFE_INTEGER
- );
-
- const validateCollectionAmount = (rule, value, callback) => {
- if (value === undefined || value === null || value === "") {
- callback();
- return;
- }
- const amount = Number(value);
- if (Number.isNaN(amount)) {
- callback(new Error("璇疯緭鍏ユ敹娆鹃噾棰�"));
- return;
- }
- const max = maxCollectionAmount.value;
- if (max !== undefined && amount - max > 0.000001) {
- callback(new Error(`鏀舵閲戦涓嶈兘瓒呰繃${max.toFixed(2)}`));
- return;
- }
- callback();
- };
const rules = {
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
@@ -461,10 +395,7 @@
receiptDate: [
{ required: true, message: "璇烽�夋嫨鏀舵鏃ユ湡", trigger: "change" },
],
- amount: [
- { required: true, message: "璇疯緭鍏ユ敹娆鹃噾棰�", trigger: "blur" },
- { validator: validateCollectionAmount, trigger: ["blur", "change"] },
- ],
+ amount: [{ required: true, message: "璇疯緭鍏ユ敹娆鹃噾棰�", trigger: "blur" }],
receiptMethod: [
{ required: true, message: "璇烽�夋嫨鏀舵鏂瑰紡", trigger: "change" },
],
@@ -524,12 +455,7 @@
return list.map((item, index) => {
if (typeof item === "string" || typeof item === "number") {
const text = String(item);
- return {
- label: text,
- value: text,
- outboundAmount: 0,
- amountLimitAvailable: false,
- };
+ return { label: text, value: text, outboundAmount: 0 };
}
const label =
item.outboundBatches ??
@@ -539,15 +465,10 @@
item.label ??
`鍑哄簱鍗�${index + 1}`;
const value = item.id ?? item.stockOutRecordId ?? label;
- const outboundAmount = Number(item.outboundAmount) || 0;
- const amountReceived = Number(item.amountReceived) || 0;
- const availableAmount = outboundAmount - amountReceived;
return {
label: String(label),
value,
- outboundAmount:
- availableAmount > 0 ? Number(availableAmount.toFixed(2)) : 0,
- amountLimitAvailable: true,
+ outboundAmount: Number(item.outboundAmount) || 0,
};
});
};
@@ -595,7 +516,6 @@
label: String(id),
value: id,
outboundAmount: 0,
- amountLimitAvailable: false,
});
});
};
@@ -698,7 +618,6 @@
outboundSelectVisible.value = false;
syncCollectionAmount();
formRef.value?.validateField("stockOutRecordIds");
- formRef.value?.validateField("amount");
};
const handleOutboundDialogClosed = () => {
@@ -739,7 +658,6 @@
collectionNumber: form.receiptCode || "",
remark: form.remark || "",
stockOutRecordIds: (form.stockOutRecordIds || []).join(","),
- createTime: form.createTime,
};
if (forUpdate) {
payload.id = currentId.value;
@@ -760,7 +678,6 @@
stockOutRecordIds,
outboundBatches: formatOutboundBatches(row.outboundBatches),
remark: row.remark ?? "",
- createTime: row.createTime ?? "",
});
};
@@ -769,7 +686,6 @@
outboundSelectVisible.value = false;
isView.value = false;
isEdit.value = false;
- originalReceiptAmount.value = 0;
};
const handleExport = () => {
@@ -829,9 +745,8 @@
isEdit.value = false;
isView.value = false;
dialogTitle.value = "鏂板鏀舵";
- originalReceiptAmount.value = 0;
Object.assign(form, {
- receiptCode: "",
+ receiptCode: "SK" + Date.now().toString().slice(-8),
customerId: "",
receiptDate: new Date().toISOString().split("T")[0],
amount: 0,
@@ -839,7 +754,6 @@
stockOutRecordIds: [],
outboundBatches: "",
remark: "",
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
outboundBatchList.value = [];
outboundBatchOptions.value = [];
@@ -852,16 +766,13 @@
currentId.value = row.id;
dialogTitle.value = "缂栬緫鏀舵";
fillFormFromRow(row);
- originalReceiptAmount.value = Number(form.amount || 0);
dialogVisible.value = true;
- loadOutboundBatches(form.customerId, true);
};
const view = row => {
isView.value = true;
isEdit.value = false;
dialogTitle.value = "鏌ョ湅鏀舵";
- originalReceiptAmount.value = 0;
fillFormFromRow(row);
dialogVisible.value = true;
};
diff --git a/src/views/financialManagement/receivable/reconciliation.vue b/src/views/financialManagement/receivable/reconciliation.vue
index 03400ef..b1bff0e 100644
--- a/src/views/financialManagement/receivable/reconciliation.vue
+++ b/src/views/financialManagement/receivable/reconciliation.vue
@@ -30,8 +30,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -389,29 +387,6 @@
closingBalance: generateForm.closingBalance,
accountStatementDetails: selectedSales.value.map(buildDetailSubmitItem),
});
-
-const summaryProps = ["openingBalance", "currentPlan", "currentActually", "closingBalance"];
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (summaryProps.includes(col.property)) {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur[col.property]);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = Number(total.toFixed(2)).toLocaleString("zh-CN", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
- } else {
- sums[index] = "";
- }
- });
- return sums;
-};
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
diff --git a/src/views/financialManagement/receivable/salesOut.vue b/src/views/financialManagement/receivable/salesOut.vue
index f6205d8..297a82c 100644
--- a/src/views/financialManagement/receivable/salesOut.vue
+++ b/src/views/financialManagement/receivable/salesOut.vue
@@ -1,33 +1,27 @@
<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.outboundBatches"
- placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�"
- clearable
- style="width: 200px;" />
+ <el-input v-model="filters.outboundBatches" placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�" clearable style="width: 200px;" />
</el-form-item>
<el-form-item label="瀹㈡埛鍚嶇О:">
- <el-input v-model="filters.customerName"
- placeholder="璇疯緭鍏ュ鎴峰悕绉�"
- clearable
- style="width: 200px;" />
+ <el-input v-model="filters.customerName" placeholder="璇疯緭鍏ュ鎴峰悕绉�" clearable style="width: 200px;" />
</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>
@@ -35,168 +29,141 @@
<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"
- isShowSummary
- :summaryMethod="getSummaries"
- :page="{
+ <PIMTable
+ rowKey="id"
+ :column="columns"
+ :tableData="dataList"
+ :tableLoading="tableLoading"
+ :page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @pagination="changePage" />
+ @pagination="changePage"
+ />
</div>
</div>
</template>
<script setup>
- import { ref, reactive, onMounted, getCurrentInstance } from "vue";
- import { ElMessage } from "element-plus";
- import { listPageAccountSales } from "@/api/financialManagement/accountSales";
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ElMessage } from "element-plus";
+import { listPageAccountSales } from "@/api/financialManagement/accountSales";
- defineOptions({
- name: "閿�鍞嚭搴�",
- });
+defineOptions({
+ name: "閿�鍞嚭搴�",
+});
- const { proxy } = getCurrentInstance();
+const { proxy } = getCurrentInstance();
- const filters = reactive({
- outboundBatches: "",
- customerName: "",
- dateRange: [],
- });
+const filters = reactive({
+ outboundBatches: "",
+ customerName: "",
+ dateRange: [],
+});
- const pagination = reactive({
- currentPage: 1,
- pageSize: 10,
- total: 0,
- });
+const pagination = reactive({
+ currentPage: 1,
+ pageSize: 10,
+ total: 0,
+});
- const columns = [
- { label: "鍑哄簱鍗曞彿", prop: "outboundBatches", minWidth: "150" },
- { label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: "180" },
- { label: "鍑哄簱鏃ユ湡", prop: "shippingDate", width: "170" },
- { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
- { label: "瑙勬牸鍨嬪彿", prop: "specificationModel", minWidth: "140" },
- {
- label: "閲戦",
- prop: "outboundAmount",
- minWidth: "120",
- formatData: val =>
- val === null || val === undefined || val === ""
- ? ""
- : Number(val).toLocaleString("zh-CN", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- }),
- },
- { label: "鍙戣揣缂栧彿", prop: "shippingNo", minWidth: "140" },
- { label: "閿�鍞鍗曞彿", prop: "salesContractNo", minWidth: "150" },
- ];
+const columns = [
+ { label: "鍑哄簱鍗曞彿", prop: "outboundBatches", minWidth: "150" },
+ { label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: "180" },
+ { label: "鍑哄簱鏃ユ湡", prop: "shippingDate", width: "170" },
+ { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
+ { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
+ {
+ label: "閲戦",
+ prop: "outboundAmount",
+ minWidth: "120",
+ align: "right",
+ formatData: (val) => (val === null || val === undefined || val === "" ? "" : Number(val).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 })),
+ },
+ { label: "鍙戣揣缂栧彿", prop: "shippingNo", minWidth: "140" },
+ { label: "閿�鍞鍗曞彿", prop: "salesContractNo", minWidth: "150" },
+];
- const dataList = ref([]);
- const tableLoading = ref(false);
+const dataList = ref([]);
+const tableLoading = ref(false);
- function buildFilterParams() {
- const params = {
- outboundBatches: filters.outboundBatches || undefined,
- customerName: filters.customerName || undefined,
- };
- if (filters.dateRange && filters.dateRange.length === 2) {
- params.startDate = filters.dateRange[0];
- params.endDate = filters.dateRange[1];
- }
- return params;
+function buildFilterParams() {
+ const params = {
+ outboundBatches: filters.outboundBatches || undefined,
+ customerName: filters.customerName || undefined,
+ };
+ 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 onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
+};
- const getTableData = () => {
- tableLoading.value = true;
- listPageAccountSales({
- ...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 = [];
- }
- })
- .catch(() => {
- dataList.value = [];
- })
- .finally(() => {
- tableLoading.value = false;
- });
- };
-
- const resetFilters = () => {
- filters.outboundBatches = "";
- filters.customerName = "";
- filters.dateRange = [];
- pagination.currentPage = 1;
- getTableData();
- };
-
- const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- getTableData();
- };
-
- const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "outboundAmount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.outboundAmount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
+const getTableData = () => {
+ tableLoading.value = true;
+ listPageAccountSales({
+ ...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 {
- sums[index] = "";
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
}
+ })
+ .catch(() => {
+ dataList.value = [];
+ })
+ .finally(() => {
+ tableLoading.value = false;
});
- return sums;
- };
+};
- const handleOut = () => {
- proxy.download(
- "/accountSales/exportAccountSalesOutbound",
- buildFilterParams(),
- `閿�鍞嚭搴揰${new Date().getTime()}.xlsx`
- );
- };
+const resetFilters = () => {
+ filters.outboundBatches = "";
+ filters.customerName = "";
+ filters.dateRange = [];
+ pagination.currentPage = 1;
+ getTableData();
+};
- onMounted(() => {
- getTableData();
- });
+const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
+ getTableData();
+};
+
+const handleOut = () => {
+ proxy.download(
+ "/accountSales/exportAccountSalesOutbound",
+ buildFilterParams(),
+ `閿�鍞嚭搴揰${new Date().getTime()}.xlsx`
+ );
+};
+
+onMounted(() => {
+ 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/receivable/salesReturn.vue b/src/views/financialManagement/receivable/salesReturn.vue
index 85153bf..c58d330 100644
--- a/src/views/financialManagement/receivable/salesReturn.vue
+++ b/src/views/financialManagement/receivable/salesReturn.vue
@@ -37,8 +37,6 @@
:column="columns"
:tableData="dataList"
:tableLoading="tableLoading"
- isShowSummary
- :summaryMethod="getSummaries"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -77,35 +75,12 @@
{ label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: "150" },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: "180" },
{ label: "鍏宠仈鍙戣揣鍗曞彿", prop: "shippingNo", minWidth: "150" },
- {
- label: "鍙戣揣绫诲瀷",
- prop: "shippingType",
- minWidth: "110",
- formatData: (val) => ({ 1: "璐ц溅", 2: "蹇��" }[String(val)] || "--"),
- },
- {
- label: "鍙戣揣杞︾墝鍙�",
- prop: "truckPlateNo",
- minWidth: "140",
- formatData: (_val, row) => (String(row?.shippingType) === "1" ? row?.truckPlateNo || "--" : "--"),
- },
- {
- label: "蹇�掑叕鍙�",
- prop: "expressCompany",
- minWidth: "140",
- formatData: (_val, row) => (String(row?.shippingType) === "2" ? row?.expressCompany || "--" : "--"),
- },
- {
- label: "蹇�掑崟鍙�",
- prop: "expressNo",
- minWidth: "150",
- formatData: (_val, row) => (String(row?.shippingType) === "2" ? row?.expressNo || "--" : "--"),
- },
{ label: "閫�璐ф棩鏈�", prop: "makeTime", minWidth: "170" },
{
label: "閫�娆炬�婚",
prop: "refundAmount",
minWidth: "120",
+ align: "right",
formatData: (val) =>
val === null || val === undefined || val === ""
? ""
@@ -172,27 +147,6 @@
pagination.currentPage = page;
pagination.pageSize = limit;
getTableData();
-};
-
-const getSummaries = ({ columns, data }) => {
- const sums = [];
- columns.forEach((col, index) => {
- if (index === 0) {
- sums[index] = "鍚堣";
- } else if (col.property === "refundAmount") {
- const total = data.reduce((prev, cur) => {
- const v = Number(cur.refundAmount);
- return prev + (isNaN(v) ? 0 : v);
- }, 0);
- sums[index] = total.toLocaleString("zh-CN", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
- } else {
- sums[index] = "";
- }
- });
- return sums;
};
const handleOut = () => {
diff --git a/src/views/financialManagement/voucher/index.vue b/src/views/financialManagement/voucher/index.vue
index 0c02d51..1aa6f69 100644
--- a/src/views/financialManagement/voucher/index.vue
+++ b/src/views/financialManagement/voucher/index.vue
@@ -25,7 +25,7 @@
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="onSearch">鎼滅储</el-button>
+ <el-button type="primary" @click="getTableData">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -453,11 +453,6 @@
return map[key] || "";
};
-const onSearch = () => {
- pagination.currentPage = 1;
- getTableData();
-};
-
// 鑱旇皟绾﹀畾锛氬垎椤靛弬鏁颁娇鐢� current/size锛屾棩鏈熻寖鍥存媶鍒嗕负 startDate/endDate
const getTableData = async () => {
try {
@@ -523,9 +518,9 @@
getTableData();
};
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
+const changePage = ({ current, size }) => {
+ pagination.currentPage = current;
+ pagination.pageSize = size;
getTableData();
};
diff --git a/src/views/index.vue b/src/views/index.vue
index 5a76883..c6fa35e 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -117,38 +117,36 @@
<el-radio-button :value="'waiting'">寰呭紑濮�({{ orderProgressMeta.waitingCount }})</el-radio-button>
<el-radio-button :value="'inProgress'">杩涜涓�({{ orderProgressMeta.inProgressCount }})</el-radio-button>
<el-radio-button :value="'completed'">宸插畬鎴�({{ orderProgressMeta.completedCount }})</el-radio-button>
- <el-radio-button :value="'end'">宸茬粨鏉�({{ orderProgressMeta.endCount }})</el-radio-button>
+ <el-radio-button :value="'paused'">宸叉殏鍋�({{ orderProgressMeta.pausedCount }})</el-radio-button>
</el-radio-group>
</div>
- <div class="order-table-wrap">
- <el-table :data="filteredOrders" stripe max-height="440">
- <el-table-column prop="orderNo" label="璁㈠崟缂栧彿" min-width="150" />
- <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="120" />
- <el-table-column prop="planQty" label="璁″垝鏁伴噺" min-width="90" />
- <el-table-column prop="completedQty" label="宸插畬鎴�" min-width="90" />
- <el-table-column label="瀹屾垚鐜�" min-width="180">
- <template #default="{ row }">
- <div class="table-progress">
- <el-progress
- :stroke-width="8"
- :percentage="row.completionRate"
- :show-text="false"
- status="success"
- />
- <span>{{ row.completionRate }}%</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="deliveryDate" label="浜ゆ湡" min-width="110" />
- <el-table-column label="鐘舵��" min-width="90">
- <template #default="{ row }">
- <el-tag :type="getOrderStatusType(row.status)" effect="light">
- {{ row.statusLabel || getOrderStatusText(row.status) }}
- </el-tag>
- </template>
- </el-table-column>
- </el-table>
- </div>
+ <el-table :data="filteredOrders" stripe>
+ <el-table-column prop="orderNo" label="璁㈠崟缂栧彿" min-width="150" />
+ <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="120" />
+ <el-table-column prop="planQty" label="璁″垝鏁伴噺" min-width="90" />
+ <el-table-column prop="completedQty" label="宸插畬鎴�" min-width="90" />
+ <el-table-column label="瀹屾垚鐜�" min-width="180">
+ <template #default="{ row }">
+ <div class="table-progress">
+ <el-progress
+ :stroke-width="8"
+ :percentage="row.completionRate"
+ :show-text="false"
+ status="success"
+ />
+ <span>{{ row.completionRate }}%</span>
+ </div>
+ </template>
+ </el-table-column>
+ <el-table-column prop="deliveryDate" label="浜ゆ湡" min-width="110" />
+ <el-table-column label="鐘舵��" min-width="90">
+ <template #default="{ row }">
+ <el-tag :type="getOrderStatusType(row.status)" effect="light">
+ {{ row.statusLabel || getOrderStatusText(row.status) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
</div>
<div v-if="visiblePanels.contract" class="cockpit-panel contract-panel">
@@ -216,7 +214,7 @@
<div v-if="visiblePanels.todo" class="cockpit-panel todo-panel">
<div class="panel-title-row">
<div class="panel-title">寰呭姙浜嬮」</div>
- <span class="panel-more" @click="openTodoDialog">鏇村</span>
+ <span class="panel-more" @click="goToApprovalProcess">鏇村</span>
</div>
<ul class="todo-list" v-if="todoList.length > 0">
<li v-for="item in todoList" :key="item.id" class="todo-item">
@@ -234,6 +232,7 @@
<div v-if="visiblePanels.realtime" class="cockpit-panel realtime-panel">
<div class="panel-title-row">
<div class="panel-title">鐢熶骇瀹炴椂鐪嬫澘</div>
+ <span class="panel-more" @click="goToProductionOrder">鏇村</span>
</div>
<div class="realtime-grid">
<div class="realtime-item" v-for="item in realtimeBoard" :key="item.key">
@@ -279,7 +278,7 @@
<div v-if="visiblePanels.plan" class="cockpit-panel plan-panel">
<div class="panel-title-row">
<div class="panel-title">浠婃棩鐢熶骇璁″垝</div>
- <span class="panel-more">{{ todayPlanTotal }}椤�</span>
+ <span class="panel-more" @click="goToProductionPlan">{{ todayPlanTotal }}椤�</span>
</div>
<ul class="plan-list">
<li v-for="item in todayPlanList" :key="item.orderNo" class="plan-item">
@@ -333,18 +332,6 @@
<el-button type="primary" @click="handleProcessDialogConfirm">纭</el-button>
</span>
</template>
- </el-dialog>
-
- <el-dialog v-model="todoDialogVisible" title="鍏ㄩ儴寰呭姙浜嬮」" width="900px" append-to-body destroy-on-close>
- <div v-loading="todoDialogLoading" class="todo-dialog-body">
- <el-table :data="todoDialogList" stripe max-height="520">
- <el-table-column prop="approveId" label="寰呭姙缂栧彿" min-width="160" />
- <el-table-column prop="approveDeptName" label="閮ㄩ棬/妯℃澘" min-width="160" />
- <el-table-column prop="approveReason" label="浜嬬敱" min-width="240" show-overflow-tooltip />
- <el-table-column prop="approveUserName" label="鍙戣捣浜�" min-width="120" />
- <el-table-column prop="approveTime" label="鏃堕棿" min-width="170" />
- </el-table>
- </div>
</el-dialog>
</div>
</template>
@@ -462,7 +449,6 @@
});
const realtimeBoardData = ref({
- deviceOee: { value: 0, compareYesterday: 0 },
orderAchievementRate: { value: 0, compareYesterday: 0 },
defectRate: { value: 0, compareYesterday: 0 },
});
@@ -477,14 +463,11 @@
waitingCount: 0,
inProgressCount: 0,
completedCount: 0,
- endCount: 0,
+ pausedCount: 0,
});
const todayPlanList = ref([]);
const todayPlanTotal = ref(0);
-const todoDialogVisible = ref(false);
-const todoDialogLoading = ref(false);
-const todoDialogList = ref([]);
const sum = ref(0);
const yny = ref(0);
@@ -852,12 +835,12 @@
const productionOrders = ref([]);
-const orderFilterOptions = ["all", "waiting", "inProgress", "completed", "end"];
+const orderFilterOptions = ["all", "waiting", "inProgress", "completed", "paused"];
const orderFilterAliasMap = {
1: "waiting",
2: "inProgress",
3: "completed",
- 5: "end",
+ 4: "paused",
};
const orderFilter = ref("all");
const filteredOrders = computed(() => productionOrders.value);
@@ -899,22 +882,11 @@
};
const realtimeBoard = computed(() => {
- const oee = Number(realtimeBoardData.value.deviceOee?.value || 0);
const orderAchievement = Number(realtimeBoardData.value.orderAchievementRate?.value || 0);
const defectRate = Number(realtimeBoardData.value.defectRate?.value || 0);
- const oeeCompare = Number(realtimeBoardData.value.deviceOee?.compareYesterday || 0);
const orderCompare = Number(realtimeBoardData.value.orderAchievementRate?.compareYesterday || 0);
const defectCompare = Number(realtimeBoardData.value.defectRate?.compareYesterday || 0);
return [
- {
- key: "oee",
- label: "璁惧 OEE",
- percent: clampPercent(oee),
- display: `${oee.toFixed(2)}%`,
- delta: getCompareText(oeeCompare),
- trend: getCompareTrend(oeeCompare),
- color: "#2d8cff",
- },
{
key: "order",
label: "璁㈠崟杈炬垚鐜�",
@@ -922,7 +894,7 @@
display: `${orderAchievement.toFixed(2)}%`,
delta: getCompareText(orderCompare),
trend: getCompareTrend(orderCompare),
- color: "#31d2ff",
+ color: "#2d8cff",
},
{
key: "defect",
@@ -1031,8 +1003,8 @@
pathPrefixes: ["/inventorymanagement"],
},
production: {
- titles: ["鐢熶骇绠℃帶"],
- pathPrefixes: ["/productionManagement", "/productionPlan"],
+ titles: ["鐢熶骇绠$悊", "涓荤敓浜ц鍒�", "鐢熶骇璁㈠崟", "鐢熶骇鎶ュ伐"],
+ pathPrefixes: ["/productionmanagement", "/productionplan"],
},
quality: {
titles: ["璐ㄩ噺绠$悊"],
@@ -1086,7 +1058,7 @@
realtime: visibleModules.value.production,
quick: quickEntries.value.length > 0,
plan: visibleModules.value.production,
- receipt: visibleModules.value.finance,
+ receipt: visibleModules.value.sales || visibleModules.value.finance,
}));
const hasLeftPanels = computed(
@@ -1157,7 +1129,7 @@
1: "寰呭紑濮�",
2: "杩涜涓�",
3: "宸插畬鎴�",
- 5: "宸茬粨鏉�",
+ 4: "宸叉殏鍋�",
};
return mapping[status] || "鏈煡";
};
@@ -1221,10 +1193,6 @@
const res = await productionRealtimeBoard();
const data = res?.data || {};
realtimeBoardData.value = {
- deviceOee: {
- value: Number(data.deviceOee?.value || 0),
- compareYesterday: Number(data.deviceOee?.compareYesterday || 0),
- },
orderAchievementRate: {
value: Number(data.orderAchievementRate?.value || 0),
compareYesterday: Number(data.orderAchievementRate?.compareYesterday || 0),
@@ -1236,7 +1204,6 @@
};
} catch {
realtimeBoardData.value = {
- deviceOee: { value: 0, compareYesterday: 0 },
orderAchievementRate: { value: 0, compareYesterday: 0 },
defectRate: { value: 0, compareYesterday: 0 },
};
@@ -1248,8 +1215,8 @@
const res = await productionOrderProgress({
status: orderFilter.value,
tab: orderFilter.value,
- pageNum: -1,
- pageSize: -1,
+ pageNum: 1,
+ pageSize: 10,
});
const data = res?.data || {};
const statusValue = normalizeOrderFilter(data.status, orderFilter.value);
@@ -1264,7 +1231,7 @@
waitingCount: resolveProgressCount(data.waitingCount, statusValue, "waiting", total),
inProgressCount: resolveProgressCount(data.inProgressCount, statusValue, "inProgress", total),
completedCount: resolveProgressCount(data.completedCount, statusValue, "completed", total),
- endCount: resolveProgressCount(data.endCount, statusValue, "end", total),
+ pausedCount: resolveProgressCount(data.pausedCount, statusValue, "paused", total),
};
productionOrders.value = (data.records || []).map(mapOrderProgressRecord);
} catch {
@@ -1278,7 +1245,7 @@
waitingCount: 0,
inProgressCount: 0,
completedCount: 0,
- endCount: 0,
+ pausedCount: 0,
};
productionOrders.value = [];
}
@@ -1287,7 +1254,7 @@
const refreshTodayProductionPlan = async () => {
try {
const res = await todayProductionPlan({
- limit: 1000,
+ limit: 4,
planDate: nowDate.value,
});
const data = res?.data || {};
@@ -1319,19 +1286,6 @@
const todoInfoS = async () => {
const res = await homeTodos();
todoList.value = res.data || [];
-};
-
-const openTodoDialog = async () => {
- todoDialogVisible.value = true;
- todoDialogLoading.value = true;
- try {
- const res = await homeTodos();
- todoDialogList.value = res.data || [];
- } catch {
- todoDialogList.value = [];
- } finally {
- todoDialogLoading.value = false;
- }
};
const statisticsReceivable = async () => {
@@ -1425,6 +1379,18 @@
const goToQuick = (path) => {
if (!path) return;
router.push(path).catch(() => {});
+};
+
+const goToProductionOrder = () => {
+ router.push('/productionManagement/productionOrder').catch(() => {});
+};
+
+const goToApprovalProcess = () => {
+ router.push('/collaborativeApproval/approvalProcess').catch(() => {});
+};
+
+const goToProductionPlan = () => {
+ router.push('/productionManagement/productionPlan').catch(() => {});
};
watch(orderFilter, () => {
@@ -1584,12 +1550,9 @@
}
.stats-grid {
- display: flex;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 14px;
-}
-
-.stats-grid .stat-card {
- flex: 1;
}
.stat-card {
@@ -1771,34 +1734,6 @@
font-size: 14px;
color: #2563eb;
cursor: pointer;
-}
-
-.todo-dialog-body {
- min-height: 220px;
-}
-
-.plan-panel {
- overflow: hidden;
-}
-
-.plan-list {
- margin: 10px 0 0;
- padding: 0 4px 0 0;
- list-style: none;
- display: flex;
- flex-direction: column;
- gap: 8px;
- max-height: 300px;
- overflow-y: auto;
-}
-
-.plan-list::-webkit-scrollbar {
- width: 6px;
-}
-
-.plan-list::-webkit-scrollbar-thumb {
- border-radius: 999px;
- background: rgba(37, 99, 235, 0.28);
}
.todo-list {
@@ -2154,7 +2089,7 @@
.realtime-grid {
margin-top: 10px;
display: grid;
- grid-template-columns: repeat(3, minmax(0, 1fr));
+ grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
}
@@ -2162,12 +2097,12 @@
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 12px;
background: #f8fbff;
- padding: 10px 8px;
+ padding: 16px 12px;
text-align: center;
}
.realtime-value {
- font-size: 26px;
+ font-size: 32px;
color: #0f172a;
font-weight: 700;
}
@@ -2254,13 +2189,6 @@
.order-panel {
min-height: 0;
- display: flex;
- flex-direction: column;
-}
-
-.order-table-wrap {
- flex: 1;
- min-height: 0;
}
.quick-panel {
@@ -2300,12 +2228,25 @@
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
+.plan-panel {
+ min-height: 236px;
+}
+
.quality-panel {
min-height: 0;
}
.receipt-panel {
min-height: 340px;
+}
+
+.plan-list {
+ margin: 10px 0 0;
+ padding: 0;
+ list-style: none;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
}
.plan-item {
@@ -2460,6 +2401,10 @@
.main-grid {
grid-template-columns: minmax(0, 1fr) 340px;
}
+
+ .stats-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
}
@media (max-width: 1200px) {
@@ -2482,7 +2427,7 @@
}
.realtime-grid {
- grid-template-columns: repeat(3, minmax(0, 1fr));
+ grid-template-columns: repeat(2, minmax(0, 1fr));
}
.quality-cards {
@@ -2505,6 +2450,10 @@
justify-content: flex-start;
}
+ .stats-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+
.right-column {
grid-template-columns: 1fr;
}
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index 5a056d6..c7d53ab 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -1,70 +1,71 @@
<template>
<div>
- <div class="search_form"
- style="margin-bottom: 10px">
- <el-form ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline">
+ <div class="search_form" style="margin-bottom: 10px">
+ <el-form
+ ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline"
+ >
<el-row :gutter="20">
<el-col :span="4">
- <el-form-item label="鍑哄簱鏃ユ湡"
- prop="timeStr">
+ <el-form-item label="鍑哄簱鏃ユ湡" prop="timeStr">
<el-date-picker v-model="searchForm.timeStr"
type="date"
placeholder="璇烽�夋嫨鏃ユ湡"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="浜у搧澶х被"
- prop="productName">
+ <el-form-item label="浜у搧澶х被" prop="productName">
<el-input v-model="searchForm.productName"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
+
<el-col :span="4">
- <el-form-item label="瑙勬牸鍨嬪彿"
- prop="model">
+ <el-form-item label="浜у搧瑙勬牸" prop="model">
<el-input v-model="searchForm.model"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎵瑰彿"
- prop="batchNo">
+ <el-form-item label="鎵瑰彿" prop="batchNo">
<el-input v-model="searchForm.batchNo"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鏉ユ簮"
- prop="recordType">
- <el-select v-model="searchForm.recordType"
- style="width: 240px"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option v-for="item in stockRecordTypeOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value" />
+ <el-form-item label="鏉ユ簮" prop="recordType">
+ <el-select
+ v-model="searchForm.recordType"
+ style="width: 240px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ >
+ <el-option
+ v-for="item in stockRecordTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
</el-select>
</el-form-item>
</el-col>
<!-- 鎸夐挳 -->
<el-col :span="4">
<el-form-item>
- <el-button type="primary"
- @click="getList">
+ <el-button type="primary" @click="getList">
鎼滅储
</el-button>
+
<el-button @click="resetSearch">
閲嶇疆
</el-button>
@@ -74,837 +75,799 @@
</el-form>
</div>
<div class="actions">
- <el-button type="primary"
- @click="handleBatchApprove">瀹℃壒</el-button>
- <el-button :disabled="!canReverseApprove"
- @click="handleReverseApprove">鍙嶅</el-button>
+ <!-- <el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button> -->
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎</el-button>
- <el-button type="primary"
- plain
- @click="handlePrint">鎵撳嵃</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
</div>
<div class="table_list">
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- style="width: 100%"
- 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="outboundBatches"
- min-width="100"
- show-overflow-tooltip />
- <el-table-column label="鍑哄簱鏃ユ湡"
- prop="createTime"
- show-overflow-tooltip />
- <el-table-column label="浜у搧澶х被"
- prop="productName"
- show-overflow-tooltip />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="model"
- show-overflow-tooltip />
- <el-table-column label="鎵瑰彿"
- prop="batchNo"
- show-overflow-tooltip />
- <el-table-column label="鍗曚綅"
- prop="unit"
- show-overflow-tooltip />
- <el-table-column label="鍑哄簱鏁伴噺"
- prop="stockOutNum"
- show-overflow-tooltip />
- <el-table-column label="鍑哄簱浜�"
- prop="createBy"
- show-overflow-tooltip />
- <el-table-column label="鏉ユ簮"
- prop="recordType"
- show-overflow-tooltip>
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ style="width: 100%"
+ 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="outboundBatches"
+ min-width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鍑哄簱鏃ユ湡"
+ prop="createTime"
+ width="120"
+ show-overflow-tooltip
+ >
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="浜у搧澶х被"
+ prop="productName"
+ show-overflow-tooltip
+ />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
+ <el-table-column label="鎵瑰彿" prop="batchNo" width="150" show-overflow-tooltip />
+ <el-table-column label="鍗曚綅" prop="unit" width="80" show-overflow-tooltip />
+ <el-table-column
+ label="鍑哄簱鏁伴噺"
+ prop="stockOutNum"
+ width="80"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鍑哄簱浜�" prop="createBy" width="100" show-overflow-tooltip />
+ <el-table-column label="鏉ユ簮" prop="recordType" show-overflow-tooltip>
<template #default="scope">
{{ getRecordType(scope.row.recordType) }}
</template>
</el-table-column>
- <el-table-column label="瀹℃壒鐘舵��"
- prop="approvalStatus"
- show-overflow-tooltip>
+ <!-- <el-table-column
+ label="瀹℃壒鐘舵��"
+ prop="approvalStatus"
+ show-overflow-tooltip
+ >
<template #default="scope">
- <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)"
- size="small">
+ <el-tag
+ :type="getApprovalStatusTagType(scope.row.approvalStatus)"
+ size="small"
+ >
{{ getApprovalStatusLabel(scope.row.approvalStatus) }}
</el-tag>
</template>
- </el-table-column>
+ </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" />
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
+ />
</div>
</div>
</template>
<script setup>
- import pagination from "@/components/PIMTable/Pagination.vue";
- import { ref } from "vue";
- import { ElMessageBox } from "element-plus";
- import useUserStore from "@/store/modules/user";
- import { getCurrentDate } from "@/utils/index.js";
- import {
- getStockOutPage,
- delPendingStockOut,
- batchApproveStockOutRecords,
- batchUnapproveStockOutRecords,
- } from "@/api/inventoryManagement/stockOut.js";
- import {
- findAllQualifiedStockOutRecordTypeOptions,
- findAllUnQualifiedStockOutRecordTypeOptions,
- } from "@/api/basicData/enum.js";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref } from "vue";
+import { ElMessageBox } from "element-plus";
+import useUserStore from "@/store/modules/user";
+import { getCurrentDate } from "@/utils/index.js";
+import {
+ getStockOutPage,
+ delPendingStockOut,
+ batchApproveStockOutRecords,
+} from "@/api/inventoryManagement/stockOut.js";
+import {
+ findAllQualifiedStockOutRecordTypeOptions,
+ findAllUnQualifiedStockOutRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+import { parseTime } from "@/utils/ruoyi";
- const userStore = useUserStore();
- const { proxy } = getCurrentInstance();
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- // 鏉ユ簮绫诲瀷閫夐」
- const stockRecordTypeOptions = ref([]);
- const page = reactive({
- current: 1,
- size: 100,
- });
- const total = ref(0);
+const userStore = useUserStore();
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
- const props = defineProps({
- type: {
- type: String,
- required: true,
- default: "0",
- },
- topParentProductId: {
- type: [String, Number],
- default: undefined,
- },
- });
+const props = defineProps({
+ type: {
+ type: String,
+ required: true,
+ default: "0",
+ },
+ topParentProductId: {
+ type: [String, Number],
+ default: undefined,
+ },
+});
- // 鎵撳嵃鐩稿叧
- const printPreviewVisible = ref(false);
- const printData = ref([]);
+// 鎵撳嵃鐩稿叧
+const printPreviewVisible = ref(false);
+const printData = ref([]);
- // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
- const data = reactive({
- searchForm: {
- supplierName: "",
- timeStr: "",
- recordType: "",
- },
- });
- const { searchForm } = toRefs(data);
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const data = reactive({
+ searchForm: {
+ supplierName: "",
+ timeStr: "",
+ recordType: "",
+ },
+});
+const { searchForm } = toRefs(data);
- const searchFormRef = ref(null);
+const searchFormRef = ref(null);
- const resetSearch = () => {
- searchFormRef.value?.resetFields();
- page.current = 1;
- getList();
- };
+const resetSearch = () => {
+ searchFormRef.value?.resetFields();
+ page.current = 1;
+ getList();
+}
- const paginationChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- getStockOutPage({
- ...searchForm.value,
- ...page,
- topParentProductId: props.topParentProductId,
+const paginationChange = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ getStockOutPage({
+ ...searchForm.value,
+ ...page,
+ topParentProductId: props.topParentProductId,
+ })
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ tableData.value.map((item) => {
+ item.children = [];
+ });
+ total.value = res.data.total;
})
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- tableData.value.map(item => {
- item.children = [];
- });
- total.value = res.data.total;
- })
- .catch(() => {
- tableLoading.value = false;
- });
- };
+ .catch(() => {
+ tableLoading.value = false;
+ });
+};
- const getRecordType = recordType => {
- return (
- stockRecordTypeOptions.value.find(item => item.value === recordType)
- ?.label || ""
- );
- };
+const getRecordType = (recordType) => {
+ return (
+ stockRecordTypeOptions.value.find((item) => item.value === recordType)
+ ?.label || ""
+ );
+};
- const approvalStatusLabelMap = {
- 0: "寰呭鎵�",
- 1: "閫氳繃",
- 2: "椹冲洖",
- 3: "寰呯‘璁�",
- pending: "寰呭鎵�",
- approved: "閫氳繃",
- rejected: "椹冲洖",
- PENDING: "寰呭鎵�",
- APPROVED: "閫氳繃",
- REJECTED: "椹冲洖",
- };
+const approvalStatusLabelMap = {
+ 0: "寰呭鎵�",
+ 1: "閫氳繃",
+ 2: "椹冲洖",
+ 3: "寰呯‘璁�",
+ pending: "寰呭鎵�",
+ approved: "閫氳繃",
+ rejected: "椹冲洖",
+ PENDING: "寰呭鎵�",
+ APPROVED: "閫氳繃",
+ REJECTED: "椹冲洖",
+};
- const getApprovalStatusLabel = status => {
- if (status === null || status === undefined || status === "") {
- return "寰呭鎵�";
- }
- return approvalStatusLabelMap[status] || "寰呭鎵�";
- };
+const getApprovalStatusLabel = (status) => {
+ if (status === null || status === undefined || status === "") {
+ return "寰呭鎵�";
+ }
+ return approvalStatusLabelMap[status] || "寰呭鎵�";
+};
- // 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
- const getApprovalStatusTagType = status => {
- if (
- status === 1 ||
- status === "1" ||
- status === "approved" ||
- status === "APPROVED"
- )
- return "success";
- if (
- status === 2 ||
- status === "2" ||
- status === "rejected" ||
- status === "REJECTED"
- )
- return "danger";
- return "warning";
- };
+// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
+const getApprovalStatusTagType = (status) => {
+ if (
+ status === 1 ||
+ status === "1" ||
+ status === "approved" ||
+ status === "APPROVED"
+ )
+ return "success";
+ if (
+ status === 2 ||
+ status === "2" ||
+ status === "rejected" ||
+ status === "REJECTED"
+ )
+ return "danger";
+ return "warning";
+};
- // 鑾峰彇鏉ユ簮绫诲瀷閫夐」
- const fetchStockRecordTypeOptions = () => {
- if (props.type === "0") {
- findAllQualifiedStockOutRecordTypeOptions().then(res => {
- stockRecordTypeOptions.value = res.data;
- });
- return;
- }
- findAllUnQualifiedStockOutRecordTypeOptions().then(res => {
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+ if (props.type === "0") {
+ findAllQualifiedStockOutRecordTypeOptions().then((res) => {
stockRecordTypeOptions.value = res.data;
});
- };
-
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter(item => item.id);
- console.log("selection", selectedRows.value);
- };
-
- const isRejectedApproval = status => {
- return status === 2 || status === "2" || status === "rejected" || status === "REJECTED";
- };
-
- const canReverseApprove = computed(() => {
- return (
- selectedRows.value.length > 0 &&
- selectedRows.value.every(row => isRejectedApproval(row.approvalStatus))
- );
+ return;
+ }
+ findAllUnQualifiedStockOutRecordTypeOptions().then((res) => {
+ stockRecordTypeOptions.value = res.data;
});
+};
- const handleReverseApprove = () => {
- if (!canReverseApprove.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨椹冲洖鐘舵�佺殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("鍙嶅鍚庤褰曞皢鎭㈠涓哄緟瀹℃壒鐘舵�侊紝鏄惁纭鍙嶅锛�", "鍙嶅", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- batchUnapproveStockOutRecords({ ids })
- .then(() => {
- proxy.$modal.msgSuccess("鍙嶅鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鍙嶅澶辫触");
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter((item) => item.id);
+ console.log("selection", selectedRows.value);
+};
+const expandedRowKeys = ref([]);
- const expandedRowKeys = ref([]);
-
- const handleBatchApprove = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
- type: "warning",
- distinguishCancelAndClose: true,
- })
- .then(() => {
- batchApproveStockOutRecords({ ids, approvalStatus: 1 })
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
- });
- })
- .catch(action => {
- if (action === "cancel") {
- batchApproveStockOutRecords({ ids, approvalStatus: 2 })
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
- });
- return;
- }
- proxy.$modal.msg("宸插彇娑�");
- });
- };
-
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(
- "/stockOutRecord/exportStockOutRecord",
- { type: props.type },
- props.type === "0" ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx"
- );
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
-
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map(item => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delPendingStockOut(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+const handleBatchApprove = () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map((item) => item.id);
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
+ confirmButtonText: "閫氳繃",
+ cancelButtonText: "椹冲洖",
+ type: "warning",
+ distinguishCancelAndClose: true,
+ })
+ .then(() => {
+ batchApproveStockOutRecords({ ids, approvalStatus: 1 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
});
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ })
+ .catch((action) => {
+ if (action === "cancel") {
+ batchApproveStockOutRecords({ ids, approvalStatus: 2 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ });
+ return;
+ }
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/stockOutRecord/exportStockOutRecord",
+ { type: props.type },
+ props.type === "0" ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delPendingStockOut(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
});
- };
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
- // 鎵撳嵃鍔熻兘
- const handlePrint = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
- return;
- }
- printData.value = [...selectedRows.value];
- console.log("鎵撳嵃鏁版嵁:", printData.value);
- printPreviewVisible.value = true;
- };
+// 鎵撳嵃鍔熻兘
+const handlePrint = () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+ printData.value = [...selectedRows.value];
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
+ printPreviewVisible.value = true;
+};
- // 鎵ц鎵撳嵃
- const executePrint = () => {
- console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
- console.log("鎵撳嵃鏁版嵁:", printData.value);
+// 鎵ц鎵撳嵃
+const executePrint = () => {
+ console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
- // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
- const printWindow = window.open("", "_blank", "width=800,height=600");
+ // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+ const printWindow = window.open("", "_blank", "width=800,height=600");
- // 鏋勫缓鎵撳嵃鍐呭
- let printContent = `
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>鎵撳嵃棰勮</title>
- <style>
+ // 鏋勫缓鎵撳嵃鍐呭
+ let printContent = `
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8">
+ <title>鎵撳嵃棰勮</title>
+ <style>
+ body {
+ margin: 0;
+ padding: 0;
+ font-family: "SimSun", serif;
+ background: white;
+ }
+ .print-page {
+ width: 200mm;
+ height: 75mm;
+ padding: 10mm;
+ padding-left: 20mm;
+ background: white;
+ box-sizing: border-box;
+ page-break-after: always;
+ page-break-inside: avoid;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+ .delivery-note {
+ width: 100%;
+ height: 100%;
+ font-size: 12px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+ color: #000;
+ }
+ .header {
+ text-align: center;
+ margin-bottom: 8px;
+ }
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+ .info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ .info-row {
+ line-height: 20px;
+ }
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 12px;
+ }
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 12px;
+ }
+ .table-section {
+ margin-bottom: 40px;
+ // flex: 0.6;
+ }
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+ }
+ .product-table th, .product-table td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 12px;
+ line-height: 1.4;
+ }
+ .product-table th {
+ font-weight: bold;
+ }
+ .total-value {
+ font-weight: bold;
+ }
+ .footer-section {
+ margin-top: auto;
+ }
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 22px;
+ justify-content: space-between;
+ }
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+ }
+ .footer-item .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 12px;
+ }
+ .footer-item .value {
+ min-width: 80px;
+ font-size: 12px;
+ }
+ .address-item .address-value {
+ min-width: 200px;
+ }
+ @media print {
body {
margin: 0;
padding: 0;
- font-family: "SimSun", serif;
- background: white;
}
- .print-page {
- width: 200mm;
- height: 75mm;
- padding: 10mm;
- padding-left: 20mm;
- background: white;
- box-sizing: border-box;
- page-break-after: always;
- page-break-inside: avoid;
- }
+ .print-page {
+ margin: 0;
+ padding: 10mm;
+ /* padding-left: 20mm; */
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
.print-page:last-child {
page-break-after: avoid;
}
- .delivery-note {
- width: 100%;
- height: 100%;
- font-size: 12px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
- color: #000;
- }
- .header {
- text-align: center;
- margin-bottom: 8px;
- }
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
- .info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .info-row {
- line-height: 20px;
- }
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 12px;
- }
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 12px;
- }
- .table-section {
- margin-bottom: 40px;
- // flex: 0.6;
- }
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
- }
- .product-table th, .product-table td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 12px;
- line-height: 1.4;
- }
- .product-table th {
- font-weight: bold;
- }
- .total-value {
- font-weight: bold;
- }
- .footer-section {
- margin-top: auto;
- }
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 22px;
- justify-content: space-between;
- }
- .footer-item {
- display: flex;
- margin-right: 20px;
- }
- .footer-item .label {
- font-weight: bold;
- width: 80px;
- font-size: 12px;
- }
- .footer-item .value {
- min-width: 80px;
- font-size: 12px;
- }
- .address-item .address-value {
- min-width: 200px;
- }
- @media print {
- body {
- margin: 0;
- padding: 0;
- }
- .print-page {
- margin: 0;
- padding: 10mm;
- /* padding-left: 20mm; */
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
- }
- </style>
- </head>
- <body>
- `;
+ }
+ </style>
+ </head>
+ <body>
+ `;
- // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
- printData.value.forEach((item, index) => {
- printContent += `
- <div class="print-page">
- <div class="delivery-note">
- <div class="header">
- <div class="document-title">闆跺敭鍙戣揣鍗�</div>
- </div>
-
- <div class="info-section">
- <div class="info-row">
- <div>
- <span class="label">鍙戣揣鏃ユ湡锛�</span>
- <span class="value">${formatDate(item.createTime)}</span>
- </div>
- <div>
- <span class="label">瀹㈡埛鍚嶇О锛�</span>
- <span class="value">${item.supplierName}</span>
- </div>
+ // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+ printData.value.forEach((item, index) => {
+ printContent += `
+ <div class="print-page">
+ <div class="delivery-note">
+ <div class="header">
+ <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+ </div>
+
+ <div class="info-section">
+ <div class="info-row">
+ <div>
+ <span class="label">鍙戣揣鏃ユ湡锛�</span>
+ <span class="value">${formatDate(item.createTime)}</span>
</div>
- <div class="info-row">
- <span class="label">鍗曞彿锛�</span>
- <span class="value">${item.code || ""}</span>
+ <div>
+ <span class="label">瀹㈡埛鍚嶇О锛�</span>
+ <span class="value">${item.supplierName}</span>
</div>
</div>
-
- <div class="table-section">
- <table class="product-table">
- <thead>
- <tr>
- <th>浜у搧鍚嶇О</th>
- <th>瑙勬牸鍨嬪彿</th>
- <th>鍗曚綅</th>
- <th>鍗曚环</th>
- <th>闆跺敭鏁伴噺</th>
- <th>闆跺敭閲戦</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>${item.productName || "鐮傜伆鐮�"}</td>
- <td>${item.model || "鏍囧噯"}</td>
- <td>${item.unit || "鍧�"}</td>
- <td>${item.taxInclusiveUnitPrice || "0"}</td>
- <td>${item.inboundNum || "2000"}</td>
- <td>${item.taxInclusiveTotalPrice || "0"}</td>
- </tr>
- </tbody>
- <tfoot>
- <tr>
- <td class="label">鍚堣</td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value">${item.inboundNum || "2000"}</td>
- <td class="total-value">${
- item.taxInclusiveTotalPrice || "0"
- }</td>
- </tr>
- </tfoot>
- </table>
+ <div class="info-row">
+ <span class="label">鍗曞彿锛�</span>
+ <span class="value">${item.code || ""}</span>
</div>
+ </div>
- <div class="footer-section">
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鏀惰揣鐢佃瘽锛�</span>
- <span class="value"></span>
- </div>
- <div class="footer-item">
- <span class="label">鏀惰揣浜猴細</span>
- <span class="value"></span>
- </div>
- <div class="footer-item address-item">
- <span class="label">鏀惰揣鍦板潃锛�</span>
- <span class="value address-value"></span>
- </div>
+ <div class="table-section">
+ <table class="product-table">
+ <thead>
+ <tr>
+ <th>浜у搧鍚嶇О</th>
+ <th>瑙勬牸鍨嬪彿</th>
+ <th>鍗曚綅</th>
+ <th>鍗曚环</th>
+ <th>闆跺敭鏁伴噺</th>
+ <th>闆跺敭閲戦</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>${item.productName || "鐮傜伆鐮�"}</td>
+ <td>${item.model || "鏍囧噯"}</td>
+ <td>${item.unit || "鍧�"}</td>
+ <td>${item.taxInclusiveUnitPrice || "0"}</td>
+ <td>${item.inboundNum || "2000"}</td>
+ <td>${item.taxInclusiveTotalPrice || "0"}</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="label">鍚堣</td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value">${item.inboundNum || "2000"}</td>
+ <td class="total-value">${
+ item.taxInclusiveTotalPrice || "0"
+ }</td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div class="footer-section">
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鏀惰揣鐢佃瘽锛�</span>
+ <span class="value"></span>
</div>
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">${userStore.nickName || "鎾曞紑鍓�"}</span>
- </div>
- <div class="footer-item">
- <span class="label">鎵撳嵃鏃ユ湡锛�</span>
- <span class="value">${formatDateTime(new Date())}</span>
- </div>
+ <div class="footer-item">
+ <span class="label">鏀惰揣浜猴細</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item address-item">
+ <span class="label">鏀惰揣鍦板潃锛�</span>
+ <span class="value address-value"></span>
+ </div>
+ </div>
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鎿嶄綔鍛橈細</span>
+ <span class="value">${userStore.nickName || "鎾曞紑鍓�"}</span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+ <span class="value">${formatDateTime(new Date())}</span>
</div>
</div>
</div>
</div>
- `;
- });
-
- printContent += `
- </body>
- </html>
+ </div>
`;
-
- // 鍐欏叆鍐呭鍒版柊绐楀彛
- printWindow.document.write(printContent);
- printWindow.document.close();
-
- // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
- printWindow.onload = () => {
- setTimeout(() => {
- printWindow.print();
- printWindow.close();
- printPreviewVisible.value = false;
- }, 500);
- };
- };
-
- // 鏍煎紡鍖栨棩鏈�
- const formatDate = dateString => {
- if (!dateString) return getCurrentDate();
- const date = new Date(dateString);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- return `${year}/${month}/${day}`;
- };
-
- // 鏍煎紡鍖栨棩鏈熸椂闂�
- const formatDateTime = date => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const seconds = String(date.getSeconds()).padStart(2, "0");
- return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
- };
- onMounted(() => {
- getList();
- fetchStockRecordTypeOptions();
});
- watch(
- () => props.topParentProductId,
- () => {
- page.current = 1;
- getList();
- }
- );
+ printContent += `
+ </body>
+ </html>
+ `;
+
+ // 鍐欏叆鍐呭鍒版柊绐楀彛
+ printWindow.document.write(printContent);
+ printWindow.document.close();
+
+ // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+ printWindow.onload = () => {
+ setTimeout(() => {
+ printWindow.print();
+ printWindow.close();
+ printPreviewVisible.value = false;
+ }, 500);
+ };
+};
+
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+ if (!dateString) return getCurrentDate();
+ const date = new Date(dateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ return `${year}/${month}/${day}`;
+};
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (date) => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ const seconds = String(date.getSeconds()).padStart(2, "0");
+ return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+};
+onMounted(() => {
+ getList();
+ fetchStockRecordTypeOptions();
+});
+
+watch(
+ () => props.topParentProductId,
+ () => {
+ page.current = 1;
+ getList();
+ }
+);
</script>
<style scoped lang="scss">
- .print-preview-dialog {
- .el-dialog__body {
- padding: 0;
- max-height: 80vh;
- overflow-y: auto;
- }
+.print-preview-dialog {
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
}
+}
- .print-preview-container {
- .print-preview-header {
- padding: 15px;
- border-bottom: 1px solid #e4e7ed;
- text-align: center;
-
- .el-button {
- margin: 0 10px;
- }
- }
-
- .print-preview-content {
- padding: 20px;
- background-color: #f5f5f5;
- min-height: 400px;
- }
- }
-
- .print-page {
- width: 220mm;
- height: 90mm;
- padding: 10mm;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin-bottom: 10px;
- box-sizing: border-box;
- }
-
- .delivery-note {
- width: 100%;
- height: 100%;
- font-family: "SimSun", serif;
- font-size: 10px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
- }
-
- .header {
+.print-preview-container {
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
text-align: center;
- margin-bottom: 8px;
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
-
- .document-title {
- font-size: 16px;
- font-weight: bold;
+ .el-button {
+ margin: 0 10px;
}
}
- .info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
+}
- .info-row {
- line-height: 20px;
+.print-page {
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
+}
+
+.delivery-note {
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+}
+
+.header {
+ text-align: center;
+ margin-bottom: 8px;
+
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+}
+
+.info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .info-row {
+ line-height: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 14px;
+ }
+
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 14px;
+ }
+ }
+}
+
+.table-section {
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th,
+ td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
+}
+
+.footer-section {
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
.label {
font-weight: bold;
- width: 60px;
+ width: 80px;
font-size: 14px;
}
.value {
- margin-right: 20px;
min-width: 80px;
font-size: 14px;
}
- }
- }
- .table-section {
- margin-bottom: 4px;
- flex: 1;
-
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
-
- th,
- td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 14px;
- line-height: 1.4;
- }
-
- th {
- font-weight: bold;
- }
-
- .total-label {
- text-align: right;
- font-weight: bold;
- }
-
- .total-value {
- font-weight: bold;
- }
- }
- }
-
- .footer-section {
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 20px;
- justify-content: space-between;
-
- .footer-item {
- display: flex;
- margin-right: 20px;
-
- .label {
- font-weight: bold;
- width: 80px;
- font-size: 14px;
- }
-
- .value {
- min-width: 80px;
- font-size: 14px;
- }
-
- &.address-item {
- .address-value {
- min-width: 200px;
- }
+ &.address-item {
+ .address-value {
+ min-width: 200px;
}
}
}
}
+}
- @media print {
- .app-container {
- display: none;
- }
-
- .print-page {
- box-shadow: none;
- margin: 0;
- padding: 10mm;
- padding-left: 20mm;
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
+@media print {
+ .app-container {
+ display: none;
}
- .actions {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 10px;
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
}
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+}
+
+.actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+}
</style>
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 0a01def..2fe86a2 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -1,52 +1,49 @@
<template>
<div>
- <div class="search_form"
- style="margin-bottom: 10px;">
- <el-form ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline">
+ <div class="search_form" style="margin-bottom: 10px;">
+ <el-form
+ ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline"
+ >
<el-row :gutter="20">
<el-col :span="4">
- <el-form-item label="鍏ュ簱鏃ユ湡"
- prop="timeStr">
+ <el-form-item label="鍏ュ簱鏃ユ湡" prop="timeStr">
<el-date-picker v-model="searchForm.timeStr"
type="date"
placeholder="璇烽�夋嫨鏃ユ湡"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="浜у搧澶х被"
- prop="productName">
+ <el-form-item label="浜у搧澶х被" prop="productName">
<el-input v-model="searchForm.productName"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
+
<el-col :span="4">
- <el-form-item label="瑙勬牸鍨嬪彿"
- prop="model">
+ <el-form-item label="浜у搧瑙勬牸" prop="model">
<el-input v-model="searchForm.model"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎵瑰彿"
- prop="batchNo">
+ <el-form-item label="鎵瑰彿" prop="batchNo">
<el-input v-model="searchForm.batchNo"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鏉ユ簮"
- prop="recordType">
+ <el-form-item label="鏉ユ簮" prop="recordType">
<el-select v-model="searchForm.recordType"
style="width: 240px"
placeholder="璇烽�夋嫨"
@@ -54,17 +51,17 @@
<el-option v-for="item in stockRecordTypeOptions"
:key="item.value"
:label="item.label"
- :value="item.value" />
+ :value="item.value"/>
</el-select>
</el-form-item>
</el-col>
<!-- 鎸夐挳 -->
<el-col :span="4">
<el-form-item>
- <el-button type="primary"
- @click="getList">
+ <el-button type="primary" @click="getList">
鎼滅储
</el-button>
+
<el-button @click="resetSearch">
閲嶇疆
</el-button>
@@ -74,11 +71,11 @@
</el-form>
</div>
<div class="actions">
- <el-button type="primary"
+ <!-- <el-button type="primary"
:disabled="!canBatchApprove"
@click="handleBatchApprove">瀹℃壒</el-button>
<el-button :disabled="!canReverseApprove"
- @click="handleReverseApprove">鍙嶅</el-button>
+ @click="handleReverseApprove">鍙嶅</el-button> -->
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger"
plain
@@ -98,36 +95,42 @@
<el-table-column align="center"
type="selection"
:selectable="isRowSelectable"
- width="55" />
+ width="55"/>
<el-table-column align="center"
label="搴忓彿"
type="index"
- width="60" />
+ width="60"/>
<el-table-column label="鍏ュ簱鎵规"
prop="inboundBatches"
- width="200"
- show-overflow-tooltip />
+ width="150"
+ show-overflow-tooltip/>
<el-table-column label="鍏ュ簱鏃堕棿"
prop="createTime"
- show-overflow-tooltip />
+ width="120"
+ show-overflow-tooltip>
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
<el-table-column label="浜у搧澶х被"
prop="productName"
- show-overflow-tooltip />
+ show-overflow-tooltip/>
<el-table-column label="瑙勬牸鍨嬪彿"
prop="model"
- show-overflow-tooltip />
+ show-overflow-tooltip/>
<el-table-column label="鎵瑰彿"
prop="batchNo"
- show-overflow-tooltip />
+ width="180"
+ show-overflow-tooltip/>
<el-table-column label="鍗曚綅"
prop="unit"
- show-overflow-tooltip />
+ show-overflow-tooltip/>
<el-table-column label="鍏ュ簱鏁伴噺"
prop="stockInNum"
- show-overflow-tooltip />
+ show-overflow-tooltip/>
<el-table-column label="鍏ュ簱浜�"
prop="createBy"
- show-overflow-tooltip />
+ show-overflow-tooltip/>
<el-table-column label="鏉ユ簮"
prop="recordType"
show-overflow-tooltip>
@@ -135,380 +138,331 @@
{{ getRecordType(scope.row.recordType) }}
</template>
</el-table-column>
- <el-table-column v-if="showSourceOrderNoColumn"
- label="婧愬崟鍙�"
- width="150"
- prop="sourceOrderNo"
- show-overflow-tooltip>
+ <el-table-column
+ v-if="showSourceOrderNoColumn"
+ label="婧愬崟鍙�"
+ width="150"
+ prop="sourceOrderNo"
+ show-overflow-tooltip>
<template #default="scope">
{{ formatSourceOrderNo(scope.row?.sourceOrderNo) }}
</template>
</el-table-column>
- <el-table-column label="瀹℃壒鐘舵��"
+ <!-- <el-table-column label="瀹℃壒鐘舵��"
prop="approvalStatus"
show-overflow-tooltip>
<template #default="scope">
- <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)"
- size="small">
+ <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" size="small">
{{ getApprovalStatusLabel(scope.row.approvalStatus) }}
</el-tag>
</template>
- </el-table-column>
+ </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="pageProductChange" />
+ @pagination="pageProductChange"/>
</div>
</div>
</template>
<script setup>
- import pagination from "@/components/PIMTable/Pagination.vue";
- import {
- ref,
- reactive,
- toRefs,
- computed,
- onMounted,
- getCurrentInstance,
- } from "vue";
- import { ElMessageBox } from "element-plus";
- import {
- getStockInRecordListPage,
- batchDeletePendingStockInRecords,
- batchApproveStockInRecords,
- batchUnapproveStockInRecords,
- } from "@/api/inventoryManagement/stockInRecord.js";
- import {
- findAllQualifiedStockInRecordTypeOptions,
- // findAllUnQualifiedStockInRecordTypeOptions,
- } from "@/api/basicData/enum.js";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import {
+ ref,
+ reactive,
+ toRefs,
+ computed,
+ onMounted,
+ getCurrentInstance,
+} from "vue";
+import {ElMessageBox} from "element-plus";
+import {
+ getStockInRecordListPage,
+ batchDeletePendingStockInRecords,
+ batchApproveStockInRecords,
+ batchUnapproveStockInRecords,
+} from "@/api/inventoryManagement/stockInRecord.js";
+import {
+ findAllQualifiedStockInRecordTypeOptions,
+ // findAllUnQualifiedStockInRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+import { parseTime } from "@/utils/ruoyi";
- const { proxy } = getCurrentInstance();
+const {proxy} = getCurrentInstance();
- const props = defineProps({
- type: {
- type: String,
- required: true,
- default: "0",
- },
- topParentProductId: {
- type: [String, Number],
- default: undefined,
- },
- });
+const props = defineProps({
+ type: {
+ type: String,
+ required: true,
+ default: '0'
+ },
+ topParentProductId: {
+ type: [String, Number],
+ default: undefined
+ }
+})
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- // 鏉ユ簮绫诲瀷閫夐」
- const stockRecordTypeOptions = ref([]);
- const page = reactive({
- current: 1,
- size: 10,
- });
- const total = ref(0);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+ current: 1,
+ size: 10,
+});
+const total = ref(0);
- const data = reactive({
- searchForm: {
- productName: "",
- batchNo: "",
- model: "",
- timeStr: "",
- recordType: "",
- },
- });
- const { searchForm } = toRefs(data);
- const searchFormRef = ref(null);
+const data = reactive({
+ searchForm: {
+ productName: "",
+ batchNo: "",
+ model: "",
+ timeStr: "",
+ recordType: "",
+ },
+});
+const {searchForm} = toRefs(data);
+const searchFormRef = ref(null);
- const resetSearch = () => {
- searchFormRef.value?.resetFields();
- page.current = 1;
- getList();
- };
+const resetSearch = () => {
+ searchFormRef.value?.resetFields();
+ page.current = 1;
+ getList();
+}
- const getRecordType = recordType => {
- return (
- stockRecordTypeOptions.value.find(item => item.value === recordType)
- ?.label || ""
- );
- };
+const getRecordType = (recordType) => {
+ return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
- const approvalStatusLabelMap = {
- 0: "寰呭鎵�",
- 1: "閫氳繃",
- 2: "椹冲洖",
- pending: "寰呭鎵�",
- approved: "閫氳繃",
- rejected: "椹冲洖",
- PENDING: "寰呭鎵�",
- APPROVED: "閫氳繃",
- REJECTED: "椹冲洖",
- };
- approvalStatusLabelMap[3] = "寰呯‘璁�";
+const approvalStatusLabelMap = {
+ 0: "寰呭鎵�",
+ 1: "閫氳繃",
+ 2: "椹冲洖",
+ pending: "寰呭鎵�",
+ approved: "閫氳繃",
+ rejected: "椹冲洖",
+ PENDING: "寰呭鎵�",
+ APPROVED: "閫氳繃",
+ REJECTED: "椹冲洖",
+};
+approvalStatusLabelMap[3] = "寰呯‘璁�";
- const getApprovalStatusLabel = status => {
- if (status === null || status === undefined || status === "") {
- return "寰呭鎵�";
- }
- return approvalStatusLabelMap[status] || "寰呭鎵�";
- };
+const getApprovalStatusLabel = (status) => {
+ if (status === null || status === undefined || status === "") {
+ return "寰呭鎵�";
+ }
+ return approvalStatusLabelMap[status] || "寰呭鎵�";
+};
- // 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
- const getApprovalStatusTagType = status => {
- if (
- status === 1 ||
- status === "1" ||
- status === "approved" ||
- status === "APPROVED"
- )
- return "success";
- if (
- status === 2 ||
- status === "2" ||
- status === "rejected" ||
- status === "REJECTED"
- )
- return "danger";
- return "warning";
- };
+// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
+const getApprovalStatusTagType = (status) => {
+ if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success";
+ if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger";
+ return "warning";
+};
- const isPendingApproval = status => {
- return (
- status === 0 ||
- status === "0" ||
- status === "pending" ||
- status === "PENDING" ||
- status === null ||
- status === undefined ||
- status === ""
- );
- };
+const isPendingApproval = status => {
+ return status === 0 || status === "0" || status === "pending" || status === "PENDING" || status === null || status === undefined || status === "";
+};
- const isRejectedApproval = status => {
- return (
- status === 2 ||
- status === "2" ||
- status === "rejected" ||
- status === "REJECTED"
- );
- };
+const isRejectedApproval = status => {
+ return status === 2 || status === "2" || status === "rejected" || status === "REJECTED";
+};
- const isRowSelectable = row => {
- return (
- isPendingApproval(row?.approvalStatus) ||
- isRejectedApproval(row?.approvalStatus)
- );
- };
+const isRowSelectable = row => {
+ return isPendingApproval(row?.approvalStatus) || isRejectedApproval(row?.approvalStatus);
+};
- const canBatchApprove = computed(() => {
- return (
- selectedRows.value.length > 0 &&
- selectedRows.value.every(row => isPendingApproval(row.approvalStatus))
- );
- });
+const canBatchApprove = computed(() => {
+ return selectedRows.value.length > 0
+ && selectedRows.value.every(row => isPendingApproval(row.approvalStatus));
+});
- const canReverseApprove = computed(() => {
- return (
- selectedRows.value.length > 0 &&
- selectedRows.value.every(row => isRejectedApproval(row.approvalStatus))
- );
- });
+const canReverseApprove = computed(() => {
+ return selectedRows.value.length > 0
+ && selectedRows.value.every(row => isRejectedApproval(row.approvalStatus));
+});
- const canDelete = computed(() => canBatchApprove.value);
- const showSourceOrderNoColumn = computed(() => {
- const topParentProductId = Number(props.topParentProductId);
- return topParentProductId === 276 || topParentProductId === 278;
- });
+const canDelete = computed(() => canBatchApprove.value);
+const showSourceOrderNoColumn = computed(() => {
+ const topParentProductId = Number(props.topParentProductId);
+ return topParentProductId === 1 || topParentProductId === 3;
+});
- const formatSourceOrderNo = value => {
- const text = String(value ?? "").trim();
- return text || "--";
- };
+const formatSourceOrderNo = (value) => {
+ const text = String(value ?? "").trim();
+ return text || "--";
+};
- const pageProductChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
+const pageProductChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
- const getList = () => {
- tableLoading.value = true;
- getStockInRecordListPage(
- Object.assign(
- {},
- {
- ...searchForm.value,
- ...page,
- topParentProductId: props.topParentProductId,
- }
- )
- )
+const getList = () => {
+ tableLoading.value = true;
+ getStockInRecordListPage(Object.assign({}, {...searchForm.value, ...page, topParentProductId: props.topParentProductId}))
.then(res => {
tableData.value = res.data.records;
total.value = res.data.total || 0;
- })
- .finally(() => {
- tableLoading.value = false;
- });
- };
+ }).finally(() => {
+ tableLoading.value = false;
+ })
+};
- // 鑾峰彇鏉ユ簮绫诲瀷閫夐」
- const fetchStockRecordTypeOptions = () => {
- if (props.type === "0") {
- findAllQualifiedStockInRecordTypeOptions().then(res => {
- stockRecordTypeOptions.value = res.data;
- });
- return;
- }
- // findAllUnQualifiedStockInRecordTypeOptions()
- // .then(res => {
- // stockRecordTypeOptions.value = res.data;
- // })
- };
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+ if (props.type === '0') {
+ findAllQualifiedStockInRecordTypeOptions()
+ .then(res => {
+ stockRecordTypeOptions.value = res.data;
+ })
+ return
+ }
+ // findAllUnQualifiedStockInRecordTypeOptions()
+ // .then(res => {
+ // stockRecordTypeOptions.value = res.data;
+ // })
+}
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection.filter(
- item => item.id && isRowSelectable(item)
- );
- };
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = selection => {
+ selectedRows.value = selection.filter(item => item.id && isRowSelectable(item));
+};
- const expandedRowKeys = ref([]);
+const expandedRowKeys = ref([]);
- const handleReverseApprove = () => {
- if (!canReverseApprove.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨宸查┏鍥炵殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("鍙嶅鍚庤褰曞皢鎭㈠涓哄緟瀹℃壒鐘舵�侊紝鏄惁纭鍙嶅锛�", "鍙嶅", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+const handleReverseApprove = () => {
+ if (!canReverseApprove.value) {
+ proxy.$modal.msgWarning("璇烽�夋嫨宸查┏鍥炵殑鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+ ElMessageBox.confirm("鍙嶅鍚庤褰曞皢鎭㈠涓哄緟瀹℃壒鐘舵�侊紝鏄惁纭鍙嶅锛�", "鍙嶅", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- batchUnapproveStockInRecords({ ids })
- .then(() => {
- proxy.$modal.msgSuccess("鍙嶅鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鍙嶅澶辫触");
- });
+ batchUnapproveStockInRecords({ids})
+ .then(() => {
+ proxy.$modal.msgSuccess("鍙嶅鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鍙嶅澶辫触");
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+};
- const handleBatchApprove = () => {
- if (!canBatchApprove.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
- type: "warning",
- distinguishCancelAndClose: true,
- })
+const handleBatchApprove = () => {
+ if (!canBatchApprove.value) {
+ proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
+ confirmButtonText: "閫氳繃",
+ cancelButtonText: "椹冲洖",
+ type: "warning",
+ distinguishCancelAndClose: true,
+ })
.then(() => {
- batchApproveStockInRecords({ ids, approvalStatus: 1 })
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
- });
- })
- .catch(action => {
- if (action === "cancel") {
- batchApproveStockInRecords({ ids, approvalStatus: 2 })
+ batchApproveStockInRecords({ids, approvalStatus: 1})
.then(() => {
- proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
getList();
})
.catch(() => {
- proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
});
+ })
+ .catch((action) => {
+ if (action === "cancel") {
+ batchApproveStockInRecords({ids, approvalStatus: 2})
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ });
return;
}
proxy.$modal.msg("宸插彇娑�");
});
- };
+};
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
// 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
- proxy.download(
- "/stockInRecord/exportStockInRecord",
- { type: props.type },
- props.type === "0" ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx"
- );
+ proxy.download("/stockInRecord/exportStockInRecord", {type: props.type}, props.type === '0' ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+};
- // 鍒犻櫎
- const handleDelete = () => {
- if (!canDelete.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
+// 鍒犻櫎
+const handleDelete = () => {
+ if (!canDelete.value) {
+ proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
batchDeletePendingStockInRecords(ids)
- .then(() => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鍒犻櫎澶辫触");
- });
+ .then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鍒犻櫎澶辫触");
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+};
- onMounted(() => {
+onMounted(() => {
+ getList();
+ fetchStockRecordTypeOptions();
+});
+
+watch(
+ () => props.topParentProductId,
+ () => {
+ page.current = 1;
getList();
- fetchStockRecordTypeOptions();
- });
-
- watch(
- () => props.topParentProductId,
- () => {
- page.current = 1;
- getList();
- }
- );
+ }
+);
</script>
<style scoped lang="scss">
- .actions {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 10px;
- }
+.actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+}
</style>
diff --git a/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue b/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
index a835ef4..639b7bd 100644
--- a/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
+++ b/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
@@ -29,12 +29,12 @@
prop="qualifiedQuantity"
show-overflow-tooltip
/>
- <el-table-column
+ <!-- <el-table-column
label="涓嶅悎鏍煎簱瀛樻暟閲�"
prop="unQualifiedQuantity"
show-overflow-tooltip
- />
- <el-table-column
+ /> -->
+ <!-- <el-table-column
label="鍚堟牸鍐荤粨鏁伴噺"
prop="qualifiedLockedQuantity"
show-overflow-tooltip
@@ -43,7 +43,7 @@
label="涓嶅悎鏍煎喕缁撴暟閲�"
prop="unQualifiedLockedQuantity"
show-overflow-tooltip
- />
+ /> -->
<el-table-column
label="搴撳瓨棰勮鏁伴噺"
prop="warnNum"
@@ -55,7 +55,7 @@
prop="updateTime"
show-overflow-tooltip
/>
- <el-table-column fixed="right" label="鎿嶄綔" min-width="180" align="center">
+ <el-table-column fixed="right" label="鎿嶄綔" min-width="100" align="center">
<template #default="scope">
<el-button
link
@@ -71,7 +71,7 @@
"
>棰嗙敤</el-button
>
- <el-button
+ <!-- <el-button
link
type="primary"
v-if="
@@ -80,7 +80,7 @@
"
@click="handleFrozen(scope.row)"
>鍐荤粨</el-button
- >
+ > -->
<el-button
link
type="primary"
diff --git a/src/views/inventoryManagement/stockManagement/New.vue b/src/views/inventoryManagement/stockManagement/New.vue
index e55de75..3d4b398 100644
--- a/src/views/inventoryManagement/stockManagement/New.vue
+++ b/src/views/inventoryManagement/stockManagement/New.vue
@@ -45,16 +45,15 @@
placeholder="璇烽�夋嫨搴撳瓨绫诲瀷">
<el-option label="鍚堟牸搴撳瓨"
value="qualified" />
- <el-option label="涓嶅悎鏍煎簱瀛�"
- value="unqualified" />
+ <!-- <el-option label="涓嶅悎鏍煎簱瀛�"
+ value="unqualified" /> -->
</el-select>
</el-form-item>
<el-form-item label="搴撳瓨鏁伴噺"
prop="qualitity">
<el-input-number v-model="formState.qualitity"
- :step="0.01"
- :min="0.01"
- :precision="2"
+ :step="1"
+ :min="1"
style="width: 100%" />
</el-form-item>
<el-form-item label="鎵瑰彿"
@@ -66,10 +65,9 @@
label="搴撳瓨棰勮鏁伴噺"
prop="warnNum">
<el-input-number v-model="formState.warnNum"
- :step="0.01"
+ :step="1"
:min="0"
:max="formState.qualitity"
- :precision="2"
style="width: 100%" />
</el-form-item>
<el-form-item label="澶囨敞"
diff --git a/src/views/inventoryManagement/stockManagement/Record.vue b/src/views/inventoryManagement/stockManagement/Record.vue
index 9ee214c..f036a9a 100644
--- a/src/views/inventoryManagement/stockManagement/Record.vue
+++ b/src/views/inventoryManagement/stockManagement/Record.vue
@@ -1,359 +1,384 @@
<template>
<div>
<div class="search_form mb10">
- <el-form ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline">
+ <el-form
+ ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline"
+ >
<el-row :gutter="20">
<el-col :span="4">
- <el-form-item label="浜у搧澶х被"
- prop="productName">
+ <el-form-item label="浜у搧澶х被" prop="productName">
<el-input v-model="searchForm.productName"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
+
<el-col :span="4">
- <el-form-item label="瑙勬牸鍨嬪彿"
- prop="model">
+ <el-form-item label="浜у搧瑙勬牸" prop="model">
<el-input v-model="searchForm.model"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎵瑰彿"
- prop="batchNo">
+ <el-form-item label="鎵瑰彿" prop="batchNo">
<el-input v-model="searchForm.batchNo"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable />
+ clearable/>
</el-form-item>
</el-col>
- <!-- 鎸夐挳 -->
- <el-col :span="4">
+ <el-col :span="24" :sm="24" :md="12" :lg="12">
<el-form-item>
- <el-button type="primary"
- @click="getList">
- 鎼滅储
- </el-button>
- <el-button @click="resetSearch">
- 閲嶇疆
- </el-button>
+ <div style="display: flex; align-items: center; gap: 4px; width: 100%; flex-wrap: wrap;">
+ <el-button type="primary" @click="getList">
+ 鎼滅储
+ </el-button>
+
+ <el-button @click="resetSearch">
+ 閲嶇疆
+ </el-button>
+ <div style="display: flex; gap: 4px; margin-left: auto;">
+ <el-button type="primary" @click="isShowNewModal = true">
+ 鏂板搴撳瓨
+ </el-button>
+ <el-button
+ type="info"
+ plain
+ icon="Upload"
+ @click="isShowImportModal = true"
+ >
+ 瀵煎叆搴撳瓨
+ </el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ </div>
+ </div>
</el-form-item>
</el-col>
</el-row>
</el-form>
- <div style="display: flex; gap: 10px; flex-wrap: nowrap;">
- <el-button type="primary"
- @click="isShowNewModal = true">鏂板搴撳瓨</el-button>
- <el-button type="info"
- plain
- icon="Upload"
- @click="isShowImportModal = true">
- 瀵煎叆搴撳瓨
- </el-button>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- </div>
</div>
<div class="table_list">
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row, index) => index"
- style="width: 100%"
- :row-class-name="tableRowClassName"
- 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="productName"
- show-overflow-tooltip />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="model"
- show-overflow-tooltip />
- <el-table-column label="鍗曚綅"
- prop="unit"
- show-overflow-tooltip />
- <el-table-column label="鎵瑰彿"
- prop="batchNo"
- show-overflow-tooltip />
- <el-table-column label="鍚堟牸搴撳瓨鏁伴噺"
- prop="qualifiedQuantity"
- show-overflow-tooltip />
- <el-table-column label="涓嶅悎鏍煎簱瀛樻暟閲�"
- prop="unQualifiedQuantity"
- show-overflow-tooltip />
- <el-table-column label="鍚堟牸鍐荤粨鏁伴噺"
- prop="qualifiedLockedQuantity"
- show-overflow-tooltip />
- <el-table-column label="涓嶅悎鏍煎喕缁撴暟閲�"
- prop="unQualifiedLockedQuantity"
- show-overflow-tooltip />
- <el-table-column label="搴撳瓨棰勮鏁伴噺"
- prop="warnNum"
- show-overflow-tooltip />
- <el-table-column label="澶囨敞"
- prop="remark"
- show-overflow-tooltip />
- <el-table-column label="鏈�杩戞洿鏂版椂闂�"
- prop="updateTime"
- show-overflow-tooltip />
- <el-table-column fixed="right"
- label="鎿嶄綔"
- min-width="80"
- align="center">
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row, index) => index"
+ style="width: 100%"
+ :row-class-name="tableRowClassName"
+ 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="productName"
+ show-overflow-tooltip
+ />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
+ <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
+ <!-- <el-table-column label="鎵瑰彿" prop="batchNo" show-overflow-tooltip /> -->
+ <el-table-column
+ label="鍚堟牸搴撳瓨鏁伴噺"
+ prop="qualifiedQuantity"
+ show-overflow-tooltip
+ />
+ <!-- <el-table-column
+ label="涓嶅悎鏍煎簱瀛樻暟閲�"
+ prop="unQualifiedQuantity"
+ show-overflow-tooltip
+ /> -->
+ <!-- <el-table-column
+ label="鍚堟牸鍐荤粨鏁伴噺"
+ prop="qualifiedLockedQuantity"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="涓嶅悎鏍煎喕缁撴暟閲�"
+ prop="unQualifiedLockedQuantity"
+ show-overflow-tooltip
+ /> -->
+ <el-table-column
+ label="搴撳瓨棰勮鏁伴噺"
+ prop="warnNum"
+ show-overflow-tooltip
+ />
+ <el-table-column label="澶囨敞" prop="remark" show-overflow-tooltip />
+ <el-table-column
+ label="鏈�杩戞洿鏂版椂闂�"
+ prop="updateTime"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ fixed="right"
+ label="鎿嶄綔"
+ min-width="80"
+ align="center"
+ >
<template #default="scope">
- <el-button link
- type="primary"
- @click="showDetailModal(scope.row)">璇︽儏</el-button>
+ <el-button
+ link
+ type="primary"
+ @click="showDetailModal(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" />
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
+ />
</div>
- <batch-no-qty-detail v-if="isShowDetailModal"
- v-model:visible="isShowDetailModal"
- :record="record"
- @subtract="handleDetailSubtract"
- @frozen="handleDetailFrozen"
- @thaw="handleDetailThaw" />
- <new-stock-inventory v-if="isShowNewModal"
- v-model:visible="isShowNewModal"
- :top-product-parent-id="props.productId"
- @completed="handleQuery" />
- <subtract-stock-inventory v-if="isShowSubtractModal"
- v-model:visible="isShowSubtractModal"
- :record="record"
- :type="record.stockType"
- @completed="handleQuery" />
+ <batch-no-qty-detail
+ v-if="isShowDetailModal"
+ v-model:visible="isShowDetailModal"
+ :record="record"
+ @subtract="handleDetailSubtract"
+ @frozen="handleDetailFrozen"
+ @thaw="handleDetailThaw"
+ />
+ <new-stock-inventory
+ v-if="isShowNewModal"
+ v-model:visible="isShowNewModal"
+ :top-product-parent-id="props.productId"
+ @completed="handleQuery"
+ />
+
+ <subtract-stock-inventory
+ v-if="isShowSubtractModal"
+ v-model:visible="isShowSubtractModal"
+ :record="record"
+ :type="record.stockType"
+ @completed="handleQuery"
+ />
<!-- 瀵煎叆搴撳瓨-->
- <import-stock-inventory v-if="isShowImportModal"
- v-model:visible="isShowImportModal"
- type="qualified"
- @uploadSuccess="handleQuery" />
+ <import-stock-inventory
+ v-if="isShowImportModal"
+ v-model:visible="isShowImportModal"
+ type="qualified"
+ @uploadSuccess="handleQuery"
+ />
<!-- 鍐荤粨/瑙e喕搴撳瓨-->
- <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal"
- v-model:visible="isShowFrozenAndThawModal"
- :record="record"
- :operation-type="operationType"
- :type="record.stockType"
- @completed="handleQuery" />
+ <frozen-and-thaw-stock-inventory
+ v-if="isShowFrozenAndThawModal"
+ v-model:visible="isShowFrozenAndThawModal"
+ :record="record"
+ :operation-type="operationType"
+ :type="record.stockType"
+ @completed="handleQuery"
+ />
</div>
</template>
<script setup>
- import pagination from "@/components/PIMTable/Pagination.vue";
- import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
- import { ElMessage, ElMessageBox } from "element-plus";
- import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js";
- const props = defineProps({
- productId: {
- type: Number,
- required: true,
- default: 0,
- },
- });
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js";
+const props = defineProps({
+ productId: {
+ type: Number,
+ required: true,
+ default: 0,
+ },
+});
- const NewStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/New.vue")
- );
- const SubtractStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/Subtract.vue")
- );
- const ImportStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/Import.vue")
- );
- const FrozenAndThawStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue")
- );
- const BatchNoQtyDetail = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue")
- );
- const { proxy } = getCurrentInstance();
- const tableData = ref([]);
- const selectedRows = ref([]);
- const record = ref({});
- const tableLoading = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- });
- const total = ref(0);
- // 鏄惁鏄剧ず鏂板寮规
- const isShowNewModal = ref(false);
- // 鏄惁鏄剧ず棰嗙敤寮规
- const isShowSubtractModal = ref(false);
- // 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
- const isShowFrozenAndThawModal = ref(false);
- // 鏄惁鏄剧ず璇︽儏寮规
- const isShowDetailModal = ref(false);
- // 鎿嶄綔绫诲瀷
- const operationType = ref("frozen");
- // 鏄惁鏄剧ず瀵煎叆寮规
- const isShowImportModal = ref(false);
- const data = reactive({
- searchForm: {
- productName: "",
- model: "",
- batchNo: "",
- topParentProductId: props.productId,
- },
- });
- const { searchForm } = toRefs(data);
- const searchFormRef = ref(null);
+const NewStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/New.vue")
+);
+const SubtractStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/Subtract.vue")
+);
+const ImportStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/Import.vue")
+);
+const FrozenAndThawStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue")
+);
+const BatchNoQtyDetail = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue")
+);
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const selectedRows = ref([]);
+const record = ref({});
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
+// 鏄惁鏄剧ず鏂板寮规
+const isShowNewModal = ref(false);
+// 鏄惁鏄剧ず棰嗙敤寮规
+const isShowSubtractModal = ref(false);
+// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
+const isShowFrozenAndThawModal = ref(false);
+// 鏄惁鏄剧ず璇︽儏寮规
+const isShowDetailModal = ref(false);
+// 鎿嶄綔绫诲瀷
+const operationType = ref("frozen");
+// 鏄惁鏄剧ず瀵煎叆寮规
+const isShowImportModal = ref(false);
+const data = reactive({
+ searchForm: {
+ productName: "",
+ model: "",
+ batchNo: "",
+ topParentProductId: props.productId,
+ },
+});
+const { searchForm } = toRefs(data);
+const searchFormRef = ref(null);
- const resetSearch = () => {
- searchFormRef.value?.resetFields();
- page.current = 1;
- getList();
- };
+const resetSearch = () => {
+ searchFormRef.value?.resetFields();
+ page.current = 1;
+ getList();
+}
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
- const paginationChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- getStockInventoryListPageCombined({ ...searchForm.value, ...page })
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- total.value = res.data.total;
- // 鏁版嵁鍔犺浇瀹屾垚鍚庢鏌ュ簱瀛�
- // checkStockAndCreatePurchase();
- })
- .catch(() => {
- tableLoading.value = false;
- });
- };
-
- const handleFileSuccess = response => {
- const { code, msg } = response;
- if (code == 200) {
- ElMessage({ message: "瀵煎叆鎴愬姛", type: "success" });
- upload.open = false;
- emits("uploadSuccess");
- } else {
- ElMessage({ message: msg, type: "error" });
- }
- };
-
- // 鐐瑰嚮棰嗙敤
- const showSubtractModal = row => {
- record.value = row;
- isShowSubtractModal.value = true;
- };
-
- // 鐐瑰嚮璇︽儏
- const showDetailModal = row => {
- if (!row?.productId || !row?.productModelId) {
- proxy.$modal.msgError("褰撳墠鏁版嵁缂哄皯浜у搧ID鎴栬鏍煎瀷鍙稩D");
- return;
- }
- record.value = row;
- isShowDetailModal.value = true;
- };
-
- const handleDetailSubtract = row => {
- isShowDetailModal.value = false;
- showSubtractModal(row);
- };
-
- const handleDetailFrozen = row => {
- isShowDetailModal.value = false;
- showFrozenModal(row);
- };
-
- const handleDetailThaw = row => {
- isShowDetailModal.value = false;
- showThawModal(row);
- };
-
- // 鐐瑰嚮鍐荤粨
- const showFrozenModal = row => {
- record.value = row;
- isShowFrozenAndThawModal.value = true;
- operationType.value = "frozen";
- };
-
- // 鐐瑰嚮瑙e喕
- const showThawModal = row => {
- record.value = row;
- isShowFrozenAndThawModal.value = true;
- operationType.value = "thaw";
- };
-
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter(item => item.id);
- console.log("selection", selectedRows.value);
- };
- const expandedRowKeys = ref([]);
-
- // 琛ㄦ牸琛岀被鍚�
- const tableRowClassName = ({ row }) => {
- const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
- const warn = Number(row?.warnNum ?? 0);
- if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
- return "";
- }
- return stock < warn ? "row-low-stock" : "";
- };
-
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const paginationChange = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ getStockInventoryListPageCombined({ ...searchForm.value, ...page })
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ // 鏁版嵁鍔犺浇瀹屾垚鍚庢鏌ュ簱瀛�
+ // checkStockAndCreatePurchase();
})
- .then(() => {
- proxy.download(
- "/stockInventory/exportStockInventory",
- { topParentProductId: props.productId },
- "搴撳瓨淇℃伅.xlsx"
- );
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
+ .catch(() => {
+ tableLoading.value = false;
+ });
+};
- onMounted(() => {
- getList();
- });
+const handleFileSuccess = (response) => {
+ const { code, msg } = response;
+ if (code == 200) {
+ ElMessage({ message: "瀵煎叆鎴愬姛", type: "success" });
+ upload.open = false;
+ emits("uploadSuccess");
+ } else {
+ ElMessage({ message: msg, type: "error" });
+ }
+};
+
+// 鐐瑰嚮棰嗙敤
+const showSubtractModal = (row) => {
+ record.value = row;
+ isShowSubtractModal.value = true;
+};
+
+// 鐐瑰嚮璇︽儏
+const showDetailModal = (row) => {
+ if (!row?.productId || !row?.productModelId) {
+ proxy.$modal.msgError("褰撳墠鏁版嵁缂哄皯浜у搧ID鎴栬鏍煎瀷鍙稩D");
+ return;
+ }
+ record.value = row;
+ isShowDetailModal.value = true;
+};
+
+const handleDetailSubtract = (row) => {
+ isShowDetailModal.value = false;
+ showSubtractModal(row);
+};
+
+const handleDetailFrozen = (row) => {
+ isShowDetailModal.value = false;
+ showFrozenModal(row);
+};
+
+const handleDetailThaw = (row) => {
+ isShowDetailModal.value = false;
+ showThawModal(row);
+};
+
+// 鐐瑰嚮鍐荤粨
+const showFrozenModal = (row) => {
+ record.value = row;
+ isShowFrozenAndThawModal.value = true;
+ operationType.value = "frozen";
+};
+
+// 鐐瑰嚮瑙e喕
+const showThawModal = (row) => {
+ record.value = row;
+ isShowFrozenAndThawModal.value = true;
+ operationType.value = "thaw";
+};
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter((item) => item.id);
+ console.log("selection", selectedRows.value);
+};
+const expandedRowKeys = ref([]);
+
+// 琛ㄦ牸琛岀被鍚�
+const tableRowClassName = ({ row }) => {
+ const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
+ const warn = Number(row?.warnNum ?? 0);
+ if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
+ return "";
+ }
+ return stock < warn ? "row-low-stock" : "";
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/stockInventory/exportStockInventory",
+ { topParentProductId: props.productId },
+ "搴撳瓨淇℃伅.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+onMounted(() => {
+ getList();
+});
</script>
<style scoped lang="scss">
- :deep(.row-low-stock td) {
- background-color: #fde2e2;
- color: #c45656;
- }
+:deep(.row-low-stock td) {
+ background-color: #fde2e2;
+ color: #c45656;
+}
- :deep(.row-low-stock:hover > td) {
- background-color: #fcd4d4;
- }
+:deep(.row-low-stock:hover > td) {
+ background-color: #fcd4d4;
+}
</style>
diff --git a/src/views/login.vue b/src/views/login.vue
index d044465..c7db15a 100644
--- a/src/views/login.vue
+++ b/src/views/login.vue
@@ -2,16 +2,16 @@
<div class="login-page">
<main class="page">
<section class="factory">
-<!-- <div class="brand hero-brand">-->
-<!-- <div class="logo hero-logo">-->
-<!-- <img-->
-<!-- :src="brandLogoUrl"-->
-<!-- :alt="`${companyName} logo`"-->
-<!-- class="logo-image hero-logo-image"-->
-<!-- @error="handleLogoError"-->
-<!-- />-->
-<!-- </div>-->
-<!-- </div>-->
+ <div class="brand hero-brand">
+ <div class="logo hero-logo">
+ <img
+ :src="brandLogoUrl"
+ :alt="`${companyName} logo`"
+ class="logo-image hero-logo-image"
+ @error="handleLogoError"
+ />
+ </div>
+ </div>
<div class="hero">
<div class="chip">鏁板瓧宸ュ巶 路 鏅鸿兘鎺掍骇 路 璁惧浜掕仈 路 璐ㄩ噺杩芥函</div>
diff --git a/src/views/monitor/operlog/index.vue b/src/views/monitor/operlog/index.vue
index 92f9c35..53979da 100644
--- a/src/views/monitor/operlog/index.vue
+++ b/src/views/monitor/operlog/index.vue
@@ -125,7 +125,7 @@
</el-table-column>
<el-table-column label="鎿嶄綔鏃ユ湡" align="center" prop="operTime" width="180" sortable="custom" :sort-orders="['descending', 'ascending']">
<template #default="scope">
- <span>{{ parseTime(scope.row.operTime) }}</span>
+ <span>{{ parseTime(scope.row.operTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="娑堣�楁椂闂�" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
@@ -165,10 +165,10 @@
<el-col :span="24">
<el-form-item label="鎿嶄綔鏂规硶锛�">{{ form.method }}</el-form-item>
</el-col>
- <el-col :span="24">
+ <el-col :span="24" v-if="form.status === 1">
<el-form-item label="璇锋眰鍙傛暟锛�">{{ form.operParam }}</el-form-item>
</el-col>
- <el-col :span="24">
+ <el-col :span="24" v-if="form.status === 1">
<el-form-item label="杩斿洖鍙傛暟锛�">{{ form.jsonResult }}</el-form-item>
</el-col>
<el-col :span="8">
@@ -181,7 +181,7 @@
<el-form-item label="娑堣�楁椂闂达細">{{ form.costTime }}姣</el-form-item>
</el-col>
<el-col :span="8">
- <el-form-item label="鎿嶄綔鏃堕棿锛�">{{ parseTime(form.operTime) }}</el-form-item>
+ <el-form-item label="鎿嶄綔鏃堕棿锛�">{{ parseTime(form.operTime, '{y}-{m}-{d}') }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="寮傚父淇℃伅锛�" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
diff --git a/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue b/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue
index 0ddea67..b17b234 100644
--- a/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue
+++ b/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue
@@ -37,17 +37,11 @@
<el-option v-for="item in shifts_list"
:key="item.value"
:label="item.label"
- :value="item.value"
- :disabled="
- operationType === 'add' &&
- (String(item.label || '').includes('鍋�') ||
- String(item.label || '').includes('浼�'))
- " />
+ :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="鎵撳崱鑼冨洿(m)"
- prop="radius"
- v-show="!hideClockFields">
+ prop="radius">
<el-input-number v-model="form.radius"
:min="10"
:max="1000"
@@ -57,8 +51,7 @@
</el-form-item>
<!-- 楂樺痉鍦板浘閫夋嫨 -->
<el-form-item label="鎵撳崱浣嶇疆"
- prop="longitude"
- v-show="!hideClockFields">
+ prop="longitude">
<div class="map-container">
<div class="map-header"
style="margin-bottom: 10px">
@@ -89,16 +82,14 @@
</div>
</el-form-item>
<el-form-item label="鍦扮偣鍚嶇О"
- prop="locationName"
- v-show="!hideClockFields">
+ prop="locationName">
<el-input v-model="form.locationName"
:disabled="operationType === 'view'"
placeholder="璇疯緭鍏ュ湴鐐瑰悕绉�" />
</el-form-item>
<!-- 涓婁笅鐝椂闂� -->
<el-form-item label="涓婄彮鏃堕棿"
- prop="startAt"
- v-show="!hideClockFields">
+ prop="startAt">
<el-time-picker v-model="form.startAt"
format="HH:mm"
value-format="HH:mm"
@@ -106,8 +97,7 @@
:disabled="operationType === 'view'" />
</el-form-item>
<el-form-item label="涓嬬彮鏃堕棿"
- prop="endAt"
- v-show="!hideClockFields">
+ prop="endAt">
<el-time-picker v-model="form.endAt"
format="HH:mm"
value-format="HH:mm"
@@ -120,9 +110,7 @@
</el-form>
<template #footer>
<span class="dialog-footer">
- <el-button type="primary"
- @click="submitForm"
- v-if="operationType !== 'view'">纭畾</el-button>
+ <el-button type="primary" @click="submitForm" v-if="operationType !== 'view'">纭畾</el-button>
<el-button @click="dialogVisible = false">鍙栨秷</el-button>
</span>
</template>
@@ -169,21 +157,6 @@
// 鑾峰彇鐝瀛楀吀鍊�
const { shifts_list } = useDict("shifts_list");
- const selectedShiftLabel = computed(() => {
- const item = shifts_list.value?.find(
- s => String(s.value) === String(form.shift)
- );
- return item?.label || "";
- });
-
- const hideClockFields = computed(() => {
- if (props.operationType === "view") return false;
- return (
- selectedShiftLabel.value.includes("鍋�") ||
- selectedShiftLabel.value.includes("浼�")
- );
- });
-
// 琛ㄥ崟鏁版嵁
const formRef = ref();
const form = reactive({
@@ -199,53 +172,39 @@
});
// 琛ㄥ崟楠岃瘉瑙勫垯
- const rules = computed(() => {
- const base = {
- sysDeptId: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
- shift: [{ required: true, message: "璇烽�夋嫨鐝", trigger: "change" }],
- };
-
- if (hideClockFields.value) {
- return base;
- }
-
- return {
- ...base,
- locationName: [
- { required: true, message: "璇疯緭鍏ュ湴鐐瑰悕绉�", trigger: "blur" },
- ],
- longitude: [{ required: true, message: "璇烽�夋嫨鎵撳崱浣嶇疆", trigger: "blur" }],
- latitude: [{ required: true, message: "璇烽�夋嫨鎵撳崱浣嶇疆", trigger: "blur" }],
- radius: [{ required: true, message: "璇疯緭鍏ユ墦鍗¤寖鍥�", trigger: "blur" }],
- startAt: [{ required: true, message: "璇烽�夋嫨涓婄彮鏃堕棿", trigger: "change" }],
- endAt: [
- { required: true, message: "璇烽�夋嫨涓嬬彮鏃堕棿", trigger: "change" },
- {
- validator: (rule, value, callback) => {
- if (form.shift && ["澶滅彮", "澶�"].includes(form.shift)) {
- callback();
- return;
- }
- if (form.startAt && value) {
- const startParts = form.startAt.split(":");
- const endParts = value.split(":");
- const startTime =
- parseInt(startParts[0]) * 60 + parseInt(startParts[1]);
- const endTime = parseInt(endParts[0]) * 60 + parseInt(endParts[1]);
- if (endTime <= startTime) {
- callback(new Error("涓嬬彮鏃堕棿涓嶈兘鏃╀簬涓婄彮鏃堕棿"));
- } else {
- callback();
- }
+ const rules = {
+ sysDeptId: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
+ locationName: [
+ { required: true, message: "璇疯緭鍏ュ湴鐐瑰悕绉�", trigger: "blur" },
+ ],
+ longitude: [{ required: true, message: "璇烽�夋嫨鎵撳崱浣嶇疆", trigger: "blur" }],
+ latitude: [{ required: true, message: "璇烽�夋嫨鎵撳崱浣嶇疆", trigger: "blur" }],
+ shift: [{ required: true, message: "璇烽�夋嫨鐝", trigger: "change" }],
+ radius: [{ required: true, message: "璇疯緭鍏ユ墦鍗¤寖鍥�", trigger: "blur" }],
+ startAt: [{ required: true, message: "璇烽�夋嫨涓婄彮鏃堕棿", trigger: "change" }],
+ endAt: [
+ { required: true, message: "璇烽�夋嫨涓嬬彮鏃堕棿", trigger: "change" },
+ {
+ validator: (rule, value, callback) => {
+ if (form.startAt && value) {
+ const startParts = form.startAt.split(":");
+ const endParts = value.split(":");
+ const startTime =
+ parseInt(startParts[0]) * 60 + parseInt(startParts[1]);
+ const endTime = parseInt(endParts[0]) * 60 + parseInt(endParts[1]);
+ if (endTime <= startTime) {
+ callback(new Error("涓嬬彮鏃堕棿涓嶈兘鏃╀簬涓婄彮鏃堕棿"));
} else {
callback();
}
- },
- trigger: "change",
+ } else {
+ callback();
+ }
},
- ],
- };
- });
+ trigger: "change",
+ },
+ ],
+ };
// 閮ㄩ棬閫夐」
const deptOptions = ref([]);
@@ -429,8 +388,8 @@
watch(
() => form.radius,
newValue => {
- if (circle && newValue != null && newValue !== "") {
- circle.setRadius(Number(newValue));
+ if (circle) {
+ circle.setRadius(newValue);
}
}
);
@@ -441,29 +400,6 @@
() => {
if (formRef.value && form.endAt) {
formRef.value.validateField("endAt");
- }
- }
- );
-
- watch(
- () => hideClockFields.value,
- val => {
- if (!val) return;
- form.radius = null;
- form.longitude = "";
- form.latitude = "";
- form.locationName = "";
- form.startAt = "";
- form.endAt = "";
- if (formRef.value) {
- formRef.value.clearValidate([
- "radius",
- "longitude",
- "latitude",
- "locationName",
- "startAt",
- "endAt",
- ]);
}
}
);
@@ -501,9 +437,7 @@
// 鍒濆鍖栧湴鍥�
setTimeout(() => {
- if (!hideClockFields.value) {
- initMap();
- }
+ initMap();
}, 100);
}
}
@@ -574,4 +508,4 @@
.mt8 {
margin-top: 8px;
}
-</style>
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue b/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue
index 9658b1f..c47dd2e 100644
--- a/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue
+++ b/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue
@@ -13,37 +13,30 @@
</el-button>
</div>
</div>
- <el-form :model="searchForm"
+ <!-- 鏌ヨ鏉′欢 -->
+ <!-- <el-form :model="searchForm"
:inline="true"
class="search-form mb16">
<el-form-item label="閮ㄩ棬锛�"
- prop="sysDeptId">
- <el-tree-select v-model="searchForm.sysDeptId"
+ prop="countId">
+ <el-tree-select v-model="searchForm.countId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="id"
placeholder="璇烽�夋嫨閮ㄩ棬"
check-strictly
- clearable
style="width: 200px" />
</el-form-item>
- <el-form-item label="鐝锛�"
- prop="shift">
- <el-select v-model="searchForm.shift"
- placeholder="璇烽�夋嫨鐝"
- clearable
- style="width: 200px">
- <el-option
- v-for="item in shifts_list"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
+ <el-form-item label="鍦扮偣锛�"
+ prop="locationName">
+ <el-input v-model="searchForm.locationName"
+ placeholder="璇疯緭鍏ュ湴鐐瑰悕绉�"
+ clearable
+ style="width: 200px" />
</el-form-item>
<el-form-item>
<el-button type="primary"
- @click="handleSearch">
+ @click="fetchData">
<el-icon>
<Search />
</el-icon>
@@ -56,7 +49,7 @@
閲嶇疆
</el-button>
</el-form-item>
- </el-form>
+ </el-form> -->
<!-- 鐝鍒楄〃 -->
<el-card shadow="never"
class="mb16">
@@ -81,39 +74,23 @@
</template>
</el-table-column>
<el-table-column prop="locationName"
- label="鍦扮偣鍚嶇О">
- <template #default="scope">
- {{ scope.row.locationName || "-" }}
- </template>
- </el-table-column>
+ label="鍦扮偣鍚嶇О" />
<el-table-column prop="longitude"
- label="缁忓害">
- <template #default="scope">
- {{ scope.row.longitude ?? "-" }}
- </template>
- </el-table-column>
+ label="缁忓害" />
<el-table-column prop="latitude"
- label="绾害">
- <template #default="scope">
- {{ scope.row.latitude ?? "-" }}
- </template>
- </el-table-column>
+ label="绾害" />
<el-table-column prop="radius"
- label="鎵撳崱鑼冨洿(m)">
- <template #default="scope">
- {{ scope.row.radius ?? "-" }}
- </template>
- </el-table-column>
+ label="鎵撳崱鑼冨洿(m)" />
<el-table-column prop="startAt"
label="涓婄彮鏃堕棿">
<template #default="scope">
- {{ scope.row.startAt || "-" }}
+ {{ scope.row.startAt }}
</template>
</el-table-column>
<el-table-column prop="endAt"
label="涓嬬彮鏃堕棿">
<template #default="scope">
- {{ scope.row.endAt || "-" }}
+ {{ scope.row.endAt }}
</template>
</el-table-column>
<el-table-column label="鎿嶄綔"
@@ -123,11 +100,9 @@
<template #default="scope">
<el-button type="primary"
link
- :disabled="isRuleLocked(scope.row)"
@click="openForm('edit', scope.row)">缂栬緫</el-button>
<el-button type="danger"
link
- :disabled="isRuleLocked(scope.row)"
@click="handleDelete(scope.row.id)">鍒犻櫎</el-button>
</template>
</el-table-column>
@@ -149,7 +124,7 @@
</template>
<script setup>
- import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+ import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
Plus,
@@ -183,8 +158,8 @@
// 鏌ヨ琛ㄥ崟
const searchForm = reactive({
- sysDeptId: "",
- shift: "",
+ countId: "",
+ locationName: "",
});
// 閮ㄩ棬閫夐」
@@ -212,10 +187,6 @@
if (!value) return "";
const shift = shifts_list.value.find(item => item.value === value);
return shift ? shift.label : value;
- };
-
- const isRuleLocked = row => {
- return Boolean(row?.usageLocked || row?.canEdit === false || row?.canDelete === false);
};
// 鑾峰彇閮ㄩ棬鍒楄〃
@@ -261,18 +232,12 @@
tableLoading.value = true;
getAttendanceRules({ ...page, ...searchForm })
.then(res => {
- const records = Array.isArray(res?.data?.records) ? res.data.records : [];
- tableData.value = records.filter(r => String(r?.id) !== "999");
+ tableData.value = res.data.records;
page.total = res.data.total;
})
.finally(() => {
tableLoading.value = false;
});
- };
-
- const handleSearch = () => {
- page.current = 1;
- fetchData();
};
// 鍒嗛〉鍙樻洿
@@ -284,18 +249,13 @@
// 閲嶇疆鎼滅储
const resetSearch = () => {
- searchForm.sysDeptId = "";
- searchForm.shift = "";
- page.current = 1;
+ searchForm.countId = "";
+ searchForm.locationName = "";
fetchData();
};
// 鎵撳紑琛ㄥ崟
const openForm = (type, row = {}) => {
- if (type === "edit" && isRuleLocked(row)) {
- ElMessage.warning("璇ョ彮娆¢厤缃凡琚帓鐝苟浜х敓鎵撳崱璁板綍锛屼笉鑳界紪杈�");
- return;
- }
operationType.value = type;
currentRow.value = row;
dialogVisible.value = true;
@@ -303,11 +263,6 @@
// 鍒犻櫎鐝
const handleDelete = id => {
- const row = tableData.value.find(item => String(item.id) === String(id));
- if (isRuleLocked(row)) {
- ElMessage.warning("瀛樺湪宸叉帓鐝笖宸叉湁鎵撳崱璁板綍鐨勭彮娆¢厤缃紝涓嶈兘鍒犻櫎");
- return;
- }
ElMessageBox.confirm("纭畾瑕佸垹闄よ繖鏉$彮娆″悧锛�", "鍒犻櫎纭", {
confirmButtonText: "纭畾",
cancelButtonText: "鍙栨秷",
diff --git a/src/views/personnelManagement/classsSheduling/index.vue b/src/views/personnelManagement/classsSheduling/index.vue
index 59e65b4..140ffba 100644
--- a/src/views/personnelManagement/classsSheduling/index.vue
+++ b/src/views/personnelManagement/classsSheduling/index.vue
@@ -142,20 +142,19 @@
:key="'d' + i">
<el-dropdown trigger="click"
placement="bottom"
- :disabled="isCellBlockedByLeaveDate(item, m)"
- @command="(e) => handleCommand(e, item, m)"
+ @command="(e) => handleCommand(e, m)"
class="shift-dropdown">
<div class="shift-box"
:class="{
'shift-box-early': m.shift === '鏃╃彮',
'shift-box-mid': m.shift === '涓彮',
'shift-box-night': m.shift === '澶滅彮',
- 'shift-box-rest': !m.shift || m.shift === '浼戞伅',
+ 'shift-box-rest': m.shift === '浼戞伅',
'shift-box-leave': m.shift === '璇峰亣',
'shift-box-other': m.shift === '澶�11',
'shift-box-business': m.shift === '澶�12',
}">
- <span class="shift-text">{{ getShiftNameByValue(m.shift) || '浼戞伅' }}</span>
+ <span class="shift-text">{{ getShiftNameByValue(m.shift) || '鈥�' }}</span>
</div>
<template #dropdown>
<el-dropdown-menu>
@@ -200,7 +199,7 @@
</div> -->
<div class="user-total">
<span class="total-label">鍚堣鍑哄嫟:</span>
- <span class="total-value">{{ item.year.totalYearAttendance }}澶�</span>
+ <span class="total-value">{{ item.work_time }}澶�</span>
</div>
</div>
</div>
@@ -272,23 +271,6 @@
<div class="search_thing">
<div class="search_label"
style="width: 90px">
- <span style="color: red; margin-right: 4px">*</span>閮ㄩ棬锛�
- </div>
- <div class="search_input">
- <el-tree-select v-model="schedulingQuery.deptId"
- :data="deptOptions"
- :props="{ value: 'id', label: 'label', children: 'children' }"
- value-key="id"
- placeholder="璇烽�夋嫨閮ㄩ棬"
- check-strictly
- clearable
- @change="onSchedulingDeptChange"
- style="width: 100%" />
- </div>
- </div>
- <div class="search_thing">
- <div class="search_label"
- style="width: 90px">
<span style="color: red; margin-right: 4px">*</span>浜哄憳鍚嶇О锛�
</div>
<div class="search_input">
@@ -297,8 +279,7 @@
style="width: 100%"
multiple
clearable
- collapse-tags
- :disabled="!schedulingQuery.deptId">
+ collapse-tags>
<el-option v-for="item in personList"
:key="item.id"
:label="item.staffName"
@@ -315,9 +296,8 @@
<div class="search_input">
<el-select v-model="schedulingQuery.shift"
placeholder="璇烽�夋嫨"
- style="width: 100%"
- :disabled="!schedulingQuery.deptId">
- <el-option v-for="item in schedulingClassType"
+ style="width: 100%">
+ <el-option v-for="item in classType"
:key="item.id"
:label="getShiftNameByValue(item.shift)"
:value="item.id">
@@ -338,14 +318,7 @@
</template>
<script setup>
- import {
- ref,
- reactive,
- computed,
- watch,
- onMounted,
- getCurrentInstance,
- } from "vue";
+ import { ref, reactive, onMounted, getCurrentInstance } from "vue";
import { useRouter } from "vue-router";
import {
page,
@@ -355,7 +328,6 @@
update,
staffOnJobListPage,
} from "@/api/personnelManagement/class";
- import { findStaffLeaveListPage } from "@/api/personnelManagement/staffLeave.js";
import { deptTreeSelect } from "@/api/system/user.js";
import { getAttendanceRules } from "@/api/personnelManagement/attendanceRules.js";
import { useDict } from "@/utils/dict";
@@ -404,8 +376,6 @@
// 浜哄憳鍒楄〃
const personList = ref([]);
- const personListAll = ref([]);
- const leaveDateMap = ref({});
// 鍔犺浇鐘舵��
const loading = ref(false);
@@ -413,18 +383,8 @@
// 鎺掔彮鏌ヨ鏉′欢
const schedulingQuery = reactive({
week: "",
- deptId: "",
userId: null,
shift: "",
- });
-
- const schedulingClassType = computed(() => {
- if (!schedulingQuery.deptId) return classType.value || [];
- return (classType.value || []).filter(item => {
- if (["998", "999"].includes(String(item?.id))) return true;
- const itemDeptId = item.deptId ?? item.sysDeptId ?? item.dept_id;
- return String(itemDeptId) === String(schedulingQuery.deptId);
- });
});
// 鍒楄〃鏁版嵁
@@ -633,10 +593,6 @@
proxy.$modal.msgError("璇烽�夋嫨鍛ㄦ");
return;
}
- if (!schedulingQuery.deptId) {
- proxy.$modal.msgError("璇烽�夋嫨閮ㄩ棬");
- return;
- }
let time = schedulingQuery.week.getTime();
// 鏍煎紡鍖栨棩鏈熶负 YYYY-MM-DD 鏍煎紡
@@ -660,15 +616,6 @@
proxy.$modal.msgError("璇烽�夋嫨鐝");
return;
}
- const blockedEmployees = (personList.value || []).filter(item => {
- const leaveDate = getEmployeeLeaveDate(item?.id);
- const weekEndDate = getSchedulingWeekEndDate();
- return leaveDate && weekEndDate && weekEndDate.getTime() > leaveDate.getTime();
- });
- if (blockedEmployees.length) {
- proxy.$modal.msgError("瀛樺湪宸茶秴杩囩鑱屾棩鏈熺殑浜哄憳锛屼笉鑳界户缁帓鐝�");
- return;
- }
loading.value = true;
add({
startWeek,
@@ -681,10 +628,8 @@
proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
schedulingVisible.value = false;
schedulingQuery.week = "";
- schedulingQuery.deptId = "";
schedulingQuery.userId = null;
schedulingQuery.shift = "";
- personList.value = [];
refresh();
})
.catch(err => {
@@ -738,20 +683,17 @@
}
proxy.$download.saveAs(blob, fileName + ".xlsx");
})
- .catch(err => {})
+ .catch(err => {
+ })
.finally(() => {
downLoading.value = false;
});
};
// 澶勭悊鍛戒护
- const handleCommand = (e, row, cell) => {
- if (isCellBlockedByLeaveDate(row, cell)) {
- proxy.$modal.msgError("璇ュ憳宸ュ凡瓒呭嚭绂昏亴鏃ユ湡锛屼笉鑳界户缁帓鐝�");
- return;
- }
+ const handleCommand = (e, m) => {
// if (e != m.shift) {
update({
- id: cell.id,
+ id: m.id,
personalAttendanceLocationConfigId: e,
}).then(res => {
proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
@@ -767,18 +709,7 @@
// 鏌ヨ瑙勫垯鍒楄〃
const fetchData = () => {
getAttendanceRules({ current: -1, size: -1 }).then(res => {
- const records = Array.isArray(res?.data?.records) ? res.data.records : [];
- const appendList = [
- { id: 998, shift: "浼戞伅" },
- { id: 999, shift: "璇峰亣" },
- ];
- const exists = new Set(records.map(r => String(r?.id)));
- appendList.forEach(item => {
- if (!exists.has(String(item.id))) {
- records.push(item);
- }
- });
- classType.value = records;
+ classType.value = res.data.records;
});
};
// 鑾峰彇鐢ㄦ埛
@@ -793,139 +724,8 @@
staffState: 1,
}).then(res => {
let arr = res.data.records;
- personListAll.value = arr;
- updatePersonListByDept();
+ personList.value = arr;
});
- };
-
- const getLeaveDates = () => {
- findStaffLeaveListPage({
- current: -1,
- size: -1,
- }).then(res => {
- const records = Array.isArray(res?.data?.records) ? res.data.records : [];
- const map = {};
- records.forEach(item => {
- const staffId = item?.staffOnJobId ?? item?.staff_on_job_id;
- const leaveDate = item?.leaveDate ?? item?.leave_date;
- if (!staffId || !leaveDate) return;
- const key = String(staffId);
- const prev = map[key];
- if (!prev || String(leaveDate) > String(prev)) {
- map[key] = leaveDate;
- }
- });
- leaveDateMap.value = map;
- updatePersonListByDept();
- syncPersonListSelection();
- });
- };
-
- const findDeptNodeById = (deptId, deptList = deptOptions.value) => {
- const list = Array.isArray(deptList) ? deptList : [];
- for (const node of list) {
- if (String(node.id) === String(deptId)) return node;
- if (node.children && node.children.length) {
- const found = findDeptNodeById(deptId, node.children);
- if (found) return found;
- }
- }
- return null;
- };
-
- const collectDeptIds = node => {
- const ids = [];
- if (!node) return ids;
- ids.push(String(node.id));
- if (node.children && node.children.length) {
- node.children.forEach(child => {
- ids.push(...collectDeptIds(child));
- });
- }
- return ids;
- };
-
- const updatePersonListByDept = () => {
- if (!schedulingQuery.deptId) {
- personList.value = [];
- return;
- }
- const node = findDeptNodeById(schedulingQuery.deptId);
- const deptIds = new Set(collectDeptIds(node));
- personList.value = (personListAll.value || []).filter(item => {
- const itemDeptId = item.deptId ?? item.sysDeptId ?? item.dept_id;
- return deptIds.has(String(itemDeptId)) && !isEmployeeBlockedByLeaveDate(item);
- });
- };
-
- const parseDateOnly = value => {
- if (!value) return null;
- if (value instanceof Date) {
- const d = new Date(value);
- d.setHours(0, 0, 0, 0);
- return d;
- }
- const normalized = String(value).trim().slice(0, 10);
- if (!normalized) return null;
- const d = new Date(normalized.replace(/-/g, "/"));
- if (Number.isNaN(d.getTime())) return null;
- d.setHours(0, 0, 0, 0);
- return d;
- };
-
- const getSchedulingWeekEndDate = () => {
- if (!schedulingQuery.week) return null;
- const start = new Date(schedulingQuery.week);
- start.setHours(0, 0, 0, 0);
- return new Date(start.getTime() + 24 * 60 * 60 * 1000 * 5);
- };
-
- const getCellDate = cell => parseDateOnly(cell?.time);
-
- const getEmployeeLeaveDate = staffId => {
- const leaveDate = leaveDateMap.value[String(staffId)];
- return parseDateOnly(leaveDate);
- };
-
- const isEmployeeBlockedByLeaveDate = item => {
- const leaveDate = getEmployeeLeaveDate(item?.id);
- if (!leaveDate) return false;
- const weekEndDate = getSchedulingWeekEndDate();
- if (!weekEndDate) return false;
- return weekEndDate.getTime() > leaveDate.getTime();
- };
-
- const isCellBlockedByLeaveDate = (row, cell) => {
- const staffId = row?.userId ?? row?.user_id ?? row?.id;
- const leaveDate = getEmployeeLeaveDate(staffId);
- const cellDate = getCellDate(cell);
- if (!leaveDate || !cellDate) return false;
- return cellDate.getTime() > leaveDate.getTime();
- };
-
- const syncPersonListSelection = () => {
- if (!Array.isArray(schedulingQuery.userId) || !schedulingQuery.userId.length) return;
- const validIds = new Set((personList.value || []).map(item => String(item.id)));
- const nextIds = schedulingQuery.userId.filter(id => validIds.has(String(id)));
- if (nextIds.length !== schedulingQuery.userId.length) {
- schedulingQuery.userId = nextIds;
- proxy.$modal.msgWarning("宸茶嚜鍔ㄥ墧闄よ秴鍑虹鑱屾棩鏈熺殑浜哄憳");
- }
- };
-
- const setDefaultShiftByDept = () => {
- if (!schedulingQuery.deptId) {
- schedulingQuery.shift = "";
- return;
- }
- const first = schedulingClassType.value?.[0];
- schedulingQuery.shift = first ? first.id : "";
- };
-
- const onSchedulingDeptChange = () => {
- schedulingQuery.userId = null;
- updatePersonListByDept();
- setDefaultShiftByDept();
};
// 鏍规嵁瀛楀吀鑾峰彇鏃ユ湡
@@ -949,7 +749,6 @@
onMounted(() => {
fetchData();
getUsers();
- getLeaveDates();
fetchDeptOptions();
if (query.month) {
init();
@@ -962,45 +761,6 @@
}
monthList.value.reverse();
});
-
- watch(
- () => classType.value,
- () => {
- if (schedulingVisible.value && schedulingQuery.deptId) {
- setDefaultShiftByDept();
- }
- }
- );
-
- watch(
- () => schedulingQuery.week,
- () => {
- if (!schedulingVisible.value) return;
- updatePersonListByDept();
- syncPersonListSelection();
- }
- );
-
- watch(
- () => schedulingQuery.deptId,
- () => {
- if (!schedulingVisible.value) return;
- updatePersonListByDept();
- syncPersonListSelection();
- }
- );
-
- watch(
- () => schedulingVisible.value,
- val => {
- if (!val) return;
- schedulingQuery.week = "";
- schedulingQuery.deptId = "";
- schedulingQuery.userId = null;
- schedulingQuery.shift = "";
- personList.value = [];
- }
- );
</script>
<style scoped>
@@ -1213,7 +973,7 @@
.user-stats {
/* display: flex; */
/* flex-wrap: wrap;
- gap: 10px; */
+ gap: 10px; */
margin-bottom: 4px;
}
diff --git a/src/views/personnelManagement/contractManagement/components/formDia.vue b/src/views/personnelManagement/contractManagement/components/formDia.vue
index 3db1bee..54b2ef9 100644
--- a/src/views/personnelManagement/contractManagement/components/formDia.vue
+++ b/src/views/personnelManagement/contractManagement/components/formDia.vue
@@ -1,93 +1,96 @@
<template>
<div>
- <el-dialog v-model="dialogFormVisible"
- title="璇︽儏"
- width="70%"
- @close="closeDia">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :tableLoading="tableLoading"
- height="600"></PIMTable>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="璇︽儏"
+ width="70%"
+ @close="closeDia"
+ >
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="600"
+ ></PIMTable>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
</el-dialog>
- <FileList v-if="fileDialogVisible"
- v-model:visible="fileDialogVisible"
- :record-type="'staff_contract'"
- :record-id="recordId" />
+ <Files ref="filesDia"></Files>
</div>
</template>
<script setup>
- import { ref, defineAsyncComponent, getCurrentInstance } from "vue";
- import { findStaffContractListPage } from "@/api/personnelManagement/staffContract.js";
- const FileList = defineAsyncComponent(() =>
- import("@/components/Dialog/FileList.vue")
- );
- const { proxy } = getCurrentInstance();
- const emit = defineEmits(["close"]);
- const fileDialogVisible = ref(false);
- const recordId = ref(0);
- const dialogFormVisible = ref(false);
- const operationType = ref("");
- const tableColumn = ref([
- {
- label: "鍚堝悓骞撮檺",
- prop: "contractTerm",
- },
- {
- label: "鍚堝悓寮�濮嬫棩鏈�",
- prop: "contractStartTime",
- },
- {
- label: "鍚堝悓缁撴潫鏃ユ湡",
- prop: "contractEndTime",
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 120,
- operation: [
- {
- name: "闄勪欢",
- type: "text",
- clickFun: row => {
- recordId.value = row.id;
- fileDialogVisible.value = true;
- },
+import {ref} from "vue";
+import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js";
+const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue"));
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+const filesDia = ref()
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const tableColumn = ref([
+ {
+ label: "鍚堝悓骞撮檺",
+ prop: "contractTerm",
+ },
+ {
+ label: "鍚堝悓寮�濮嬫棩鏈�",
+ prop: "contractStartTime",
+ },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractEndTime",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ width: 120,
+ operation: [
+ {
+ name: "涓婁紶闄勪欢",
+ type: "text",
+ clickFun: (row) => {
+ filesDia.value.openDialog( row,'鍚堝悓')
},
- ],
- },
- ]);
- const tableData = ref([]);
- const tableLoading = ref(false);
+ }
+ ],
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
- // 鎵撳紑寮规
- const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- if (operationType.value === "edit") {
- findStaffContractListPage({ staffOnJobId: row.id }).then(res => {
- tableData.value = res.data.records;
- });
- }
- };
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === 'edit') {
+ findStaffContractListPage({staffOnJobId: row.id}).then(res => {
+ tableData.value = res.data.records
+ })
+ }
+}
- // 鍏抽棴寮规
- const closeDia = () => {
- dialogFormVisible.value = false;
- emit("close");
- };
- defineExpose({
- openDialog,
- });
+const openUploadFile = (row) => {
+ filesDia.value.open = true
+ filesDia.value.row = row
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit('close')
+};
+defineExpose({
+ openDialog,
+});
</script>
<style scoped>
+
</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/contractManagement/index.vue b/src/views/personnelManagement/contractManagement/index.vue
index bde498a..074b9ac 100644
--- a/src/views/personnelManagement/contractManagement/index.vue
+++ b/src/views/personnelManagement/contractManagement/index.vue
@@ -3,64 +3,52 @@
<div class="search_form mb20">
<div>
<span class="search_title">濮撳悕锛�</span>
- <el-input v-model="searchForm.staffName"
- style="width: 240px"
- placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search" />
- <span style="margin-left: 10px"
- class="search_title">鍚堝悓缁撴潫鏃ユ湡锛�</span>
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
- <el-button type="primary"
- @click="handleQuery"
- style="margin-left: 10px">鎼滅储</el-button>
+ <el-input v-model="searchForm.staffName" style="width: 240px" placeholder="璇疯緭鍏ュ鍚嶆悳绱�" @change="handleQuery"
+ clearable :prefix-icon="Search" />
+ <span style="margin-left: 10px" class="search_title">鍚堝悓缁撴潫鏃ユ湡锛�</span>
+ <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+ placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
</div>
<div>
<!-- <el-button type="primary" @click="openForm('add')">鏂板鍏ヨ亴</el-button>-->
- <!-- <el-button type="info" @click="handleImport">瀵煎叆</el-button>-->
+<!-- <el-button type="info" @click="handleImport">瀵煎叆</el-button>-->
<el-button @click="handleOut">瀵煎嚭</el-button>
<!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
</div>
</div>
<div class="table_list">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"></PIMTable>
+ <PIMTable rowKey="id" :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true"
+ @selection-change="handleSelectionChange" :tableLoading="tableLoading" @pagination="pagination"
+ :total="page.total"></PIMTable>
</div>
- <form-dia ref="formDia"
- @close="handleQuery"></form-dia>
- <renew-contract v-if="isShowRenewContractModal"
- v-model:visible="isShowRenewContractModal"
- :id="id"
- @completed="handleQuery" />
+ <form-dia ref="formDia" @close="handleQuery"></form-dia>
+ <renew-contract
+ v-if="isShowRenewContractModal"
+ v-model:visible="isShowRenewContractModal"
+ :id="id"
+ @completed="handleQuery"
+ />
+
<!-- 鍚堝悓瀵煎叆瀵硅瘽妗� -->
- <el-dialog :title="upload.title"
- v-model="upload.open"
- width="400px"
- append-to-body>
- <el-upload ref="uploadRef"
- :limit="1"
- accept=".xlsx, .xls"
- :headers="upload.headers"
- :action="upload.url + '?updateSupport=' + upload.updateSupport"
- :disabled="upload.isUploading"
- :on-progress="handleFileUploadProgress"
- :on-success="handleFileSuccess"
- :auto-upload="false"
- drag>
+ <el-dialog
+ :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body
+ >
+ <el-upload
+ ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :auto-upload="false"
+ drag
+ >
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
<template #tip>
@@ -78,8 +66,7 @@
</el-upload>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
<el-button @click="upload.open = false">鍙� 娑�</el-button>
</div>
</template>
@@ -89,259 +76,258 @@
</template>
<script setup>
- import { Search } from "@element-plus/icons-vue";
- import { onMounted, ref, defineAsyncComponent } from "vue";
- import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue";
- const RenewContract = defineAsyncComponent(() =>
- import(
- "@/views/personnelManagement/employeeRecord/components/RenewContract.vue"
- )
- );
- import { ElMessageBox } from "element-plus";
- import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
- import dayjs from "dayjs";
- import { getToken } from "@/utils/auth.js";
- import FilesDia from "./filesDia.vue";
- const data = reactive({
- searchForm: {
- staffName: "",
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
+import { Search } from "@element-plus/icons-vue";
+import { onMounted, ref, defineAsyncComponent } from "vue";
+import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue";
+const RenewContract = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/RenewContract.vue"));
+import { ElMessageBox } from "element-plus";
+import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
+import dayjs from "dayjs";
+import { getToken } from "@/utils/auth.js";
+import FilesDia from "./filesDia.vue";
+const data = reactive({
+ searchForm: {
+ staffName: "",
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "staffState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == 0) {
+ return "绂昏亴";
+ } else if (params == 1) {
+ return "鍦ㄨ亴";
+ } else {
+ return null;
+ }
},
- });
- const { searchForm } = toRefs(data);
- const tableColumn = ref([
- {
- label: "鐘舵��",
- prop: "staffState",
- dataType: "tag",
- formatData: params => {
- if (params == 0) {
- return "绂昏亴";
- } else if (params == 1) {
- return "鍦ㄨ亴";
- } else {
- return null;
- }
- },
- formatType: params => {
- if (params == 0) {
- return "danger";
- } else if (params == 1) {
- return "primary";
- } else {
- return null;
- }
- },
+ formatType: (params) => {
+ if (params == 0) {
+ return "danger";
+ } else if (params == 1) {
+ return "primary";
+ } else {
+ return null;
+ }
},
- {
- label: "鍛樺伐缂栧彿",
- prop: "staffNo",
- },
- {
- label: "濮撳悕",
- prop: "staffName",
- },
- {
- label: "鎬у埆",
- prop: "sex",
- },
- {
- label: "宀椾綅",
- prop: "postName",
- },
- {
- label: "绗竴瀛﹀巻",
- prop: "firstStudy",
- },
- {
- label: "涓撲笟",
- prop: "profession",
- width: 100,
- },
- {
- label: "骞撮緞",
- prop: "age",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "phone",
- width: 150,
- },
- {
- label: "绱ф�ヨ仈绯讳汉",
- prop: "emergencyContact",
- width: 120,
- },
- {
- label: "绱ф�ヨ仈绯讳汉鐢佃瘽",
- prop: "emergencyContactPhone",
- width: 150,
- },
- // {
- // label: "鍚堝悓骞撮檺",
- // prop: "contractTerm",
- // },
- // {
- // label: "鍚堝悓寮�濮嬫棩鏈�",
- // prop: "contractStartTime",
- // width: 120
- // },
- {
- label: "鍚堝悓缁撴潫鏃ユ湡",
- prop: "contractExpireTime",
- width: 120,
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 160,
- operation: [
- {
- name: "璇︽儏",
- type: "text",
- clickFun: row => {
- openForm("edit", row);
- },
+ },
+ {
+ label: "鍛樺伐缂栧彿",
+ prop: "staffNo",
+ },
+ {
+ label: "濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "鎬у埆",
+ prop: "sex",
+ },
+ {
+ label: "鎴风睄浣忓潃",
+ prop: "nativePlace",
+ },
+ {
+ label: "宀椾綅",
+ prop: "postJob",
+ },
+ {
+ label: "鐜颁綇鍧�",
+ prop: "adress",
+ width: 200
+ },
+ {
+ label: "绗竴瀛﹀巻",
+ prop: "firstStudy",
+ },
+ {
+ label: "涓撲笟",
+ prop: "profession",
+ width: 100
+ },
+ {
+ label: "骞撮緞",
+ prop: "age",
+ },
+ {
+ label: "鑱旂郴鐢佃瘽",
+ prop: "phone",
+ width: 150
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉",
+ prop: "emergencyContact",
+ width: 120
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉鐢佃瘽",
+ prop: "emergencyContactPhone",
+ width: 150
+ },
+ // {
+ // label: "鍚堝悓骞撮檺",
+ // prop: "contractTerm",
+ // },
+ // {
+ // label: "鍚堝悓寮�濮嬫棩鏈�",
+ // prop: "contractStartTime",
+ // width: 120
+ // },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractExpireTime",
+ width: 120
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ width: 160,
+ operation: [
+ {
+ name: "璇︽儏",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
},
- {
- name: "缁鍚堝悓",
- type: "text",
- showHide: row => row.staffState === 1,
- clickFun: row => {
- isShowRenewContractModal.value = true;
- id.value = row.id;
- },
+ },
+ {
+ name: "缁鍚堝悓",
+ type: "text",
+ showHide: row => row.staffState === 1,
+ clickFun: (row) => {
+ isShowRenewContractModal.value = true;
+ id.value = row.id;
},
- ],
- },
- ]);
- const filesDia = ref();
- const isShowRenewContractModal = ref(false);
- const id = ref(0);
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
- const formDia = ref();
- const { proxy } = getCurrentInstance();
+ }
+ ],
+ },
+]);
+const filesDia = ref()
+const isShowRenewContractModal = ref(false);
+const id = ref(0);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+const formDia = ref()
+const { proxy } = getCurrentInstance()
- const changeDaterange = value => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- }
- getList();
- };
- // 鎵撳紑闄勪欢寮规
- const openFilesFormDia = row => {
- console.log(row);
- nextTick(() => {
- filesDia.value?.openDialog(row, "鍚堝悓");
- });
- };
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined;
- params.staffState = 1;
- staffOnJobListPage(params)
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- page.total = res.data.total;
- })
- .catch(err => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
+const changeDaterange = (value) => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
+ getList();
+};
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (row) => {
+ console.log(row)
+ nextTick(() => {
+ filesDia.value?.openDialog( row,'鍚堝悓')
+ })
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined
+ params.staffState = 1
+ staffOnJobListPage(params).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records
+ page.total = res.data.total;
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
- // 鎵撳紑寮规
- const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row);
- });
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row)
+ })
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍚堝悓绠$悊.xlsx");
})
- .then(() => {
- proxy.download(
- "/staff/staffOnJob/export",
- { staffState: 1 },
- "鍚堝悓绠$悊.xlsx"
- );
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
- const upload = reactive({
- // 鏄惁鏄剧ず寮瑰嚭灞傦紙鍚堝悓瀵煎叆锛�
- open: false,
- // 寮瑰嚭灞傛爣棰橈紙鍚堝悓瀵煎叆锛�
- title: "",
- // 鏄惁绂佺敤涓婁紶
- isUploading: false,
- // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
- updateSupport: 1,
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import",
- });
- /** 瀵煎叆鎸夐挳鎿嶄綔 */
- function handleImport() {
- upload.title = "鍚堝悓瀵煎叆";
- upload.open = true;
- }
- /** 鎻愪氦涓婁紶鏂囦欢 */
- function submitFileForm() {
- console.log(upload.url + "?updateSupport=" + upload.updateSupport);
- proxy.$refs["uploadRef"].submit();
- }
- /**鏂囦欢涓婁紶涓鐞� */
- const handleFileUploadProgress = (event, file, fileList) => {
- upload.isUploading = true;
- };
- /** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
- const handleFileSuccess = (response, file, fileList) => {
- upload.open = false;
- upload.isUploading = false;
- proxy.$refs["uploadRef"].handleRemove(file);
- getList();
- };
- onMounted(() => {
- getList();
- });
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙鍚堝悓瀵煎叆锛�
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙鍚堝悓瀵煎叆锛�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import",
+});
+/** 瀵煎叆鎸夐挳鎿嶄綔 */
+function handleImport() {
+ upload.title = "鍚堝悓瀵煎叆";
+ upload.open = true;
+}
+/** 鎻愪氦涓婁紶鏂囦欢 */
+function submitFileForm() {
+ console.log(upload.url + '?updateSupport=' + upload.updateSupport)
+ proxy.$refs["uploadRef"].submit();
+}
+/**鏂囦欢涓婁紶涓鐞� */
+const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+};
+/** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+const handleFileSuccess = (response, file, fileList) => {
+ upload.open = false;
+ upload.isUploading = false;
+ proxy.$refs["uploadRef"].handleRemove(file);
+ getList();
+};
+onMounted(() => {
+ getList();
+});
</script>
<style scoped></style>
diff --git a/src/views/personnelManagement/dimission/components/formDia.vue b/src/views/personnelManagement/dimission/components/formDia.vue
index 20c1794..86c59ce 100644
--- a/src/views/personnelManagement/dimission/components/formDia.vue
+++ b/src/views/personnelManagement/dimission/components/formDia.vue
@@ -1,31 +1,29 @@
<template>
<div>
- <el-dialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板绂昏亴' : '缂栬緫绂昏亴'"
- width="70%"
- @close="closeDia">
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板绂昏亴' : '缂栬緫绂昏亴'"
+ width="70%"
+ @close="closeDia"
+ >
<!-- 鍛樺伐淇℃伅灞曠ず鍖哄煙 -->
<div class="info-section">
<div class="info-title">鍛樺伐淇℃伅</div>
- <el-form :model="form"
- label-width="200px"
- label-position="left"
- :rules="rules"
- ref="formRef"
- style="margin-top: 20px">
+ <el-form :model="form" label-width="200px" label-position="left" :rules="rules" ref="formRef" style="margin-top: 20px">
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="濮撳悕锛�"
- prop="staffOnJobId">
+ <el-form-item label="濮撳悕锛�" prop="staffOnJobId">
<el-select v-model="form.staffOnJobId"
placeholder="璇烽�夋嫨浜哄憳"
style="width: 100%"
:disabled="operationType === 'edit'"
@change="handleSelect">
- <el-option v-for="item in personList"
- :key="item.id"
- :label="item.staffName"
- :value="item.id" />
+ <el-option
+ v-for="item in personList"
+ :key="item.id"
+ :label="item.staffName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
@@ -41,11 +39,21 @@
{{ currentStaffRecord.sex || '-' }}
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="鎴风睄浣忓潃锛�">
+ {{ currentStaffRecord.nativePlace || '-' }}
+ </el-form-item>
+ </el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="宀椾綅锛�">
{{ currentStaffRecord.postName || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐜颁綇鍧�锛�">
+ {{ currentStaffRecord.adress || '-' }}
</el-form-item>
</el-col>
</el-row>
@@ -89,74 +97,74 @@
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="绂昏亴鏃ユ湡锛�"
- prop="leaveDate">
- <el-date-picker v-model="form.leaveDate"
- type="date"
- :disabled="operationType === 'edit'"
- :disabled-date="disabledFutureDate"
- placeholder="璇烽�夋嫨绂昏亴鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- style="width: 100%" />
+ <el-form-item label="绂昏亴鏃ユ湡锛�" prop="leaveDate">
+ <el-date-picker
+ v-model="form.leaveDate"
+ type="date"
+ :disabled="operationType === 'edit'"
+ :disabled-date="disabledFutureDate"
+ placeholder="璇烽�夋嫨绂昏亴鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绂昏亴鍘熷洜锛�"
- prop="reason">
- <el-select v-model="form.reason"
- placeholder="璇烽�夋嫨绂昏亴鍘熷洜"
- style="width: 100%"
- @change="handleSelectDimissionReason">
- <el-option v-for="(item, index) in dimissionReasonOptions"
- :key="index"
- :label="item.label"
- :value="item.value" />
+ <el-form-item label="绂昏亴鍘熷洜锛�" prop="reason">
+ <el-select v-model="form.reason" placeholder="璇烽�夋嫨绂昏亴鍘熷洜" style="width: 100%" @change="handleSelectDimissionReason">
+ <el-option
+ v-for="(item, index) in dimissionReasonOptions"
+ :key="index"
+ :label="item.label"
+ :value="item.value"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="澶囨敞锛�"
- prop="remark"
- v-if="form.reason === 'other'">
- <el-input v-model="form.remark"
- type="textarea"
- :rows="3"
- placeholder="澶囨敞"
- maxlength="500"
- show-word-limit />
+ <el-form-item label="澶囨敞锛�" prop="remark" v-if="form.reason === 'other'">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="澶囨敞"
+ maxlength="500"
+ show-word-limit
+ />
</el-form-item>
</el-col>
</el-row>
</el-form>
- <!-- <el-row :gutter="30">-->
- <!-- <el-col :span="12">-->
- <!-- <div class="info-item">-->
- <!-- <span class="info-label">绂昏亴鍘熷洜锛�</span>-->
- <!-- <el-select v-model="form.reason" placeholder="璇烽�夋嫨浜哄憳" style="width: 100%" @change="handleSelect">-->
- <!-- <el-option-->
- <!-- v-for="(item, index) in dimissionReasonOptions"-->
- <!-- :key="index"-->
- <!-- :label="item.label"-->
- <!-- :value="item.value"-->
- <!-- />-->
- <!-- </el-select>-->
- <!-- </div>-->
- <!-- </el-col>-->
- <!-- <el-col :span="12">-->
- <!-- <div class="info-item">-->
- <!-- <span class="info-label">鍛樺伐缂栧彿锛�</span>-->
- <!-- <span class="info-value">{{ form.staffNo || '-' }}</span>-->
- <!-- </div>-->
- <!-- </el-col>-->
- <!-- </el-row>-->
+
+<!-- <el-row :gutter="30">-->
+<!-- <el-col :span="12">-->
+<!-- <div class="info-item">-->
+<!-- <span class="info-label">绂昏亴鍘熷洜锛�</span>-->
+<!-- <el-select v-model="form.reason" placeholder="璇烽�夋嫨浜哄憳" style="width: 100%" @change="handleSelect">-->
+<!-- <el-option-->
+<!-- v-for="(item, index) in dimissionReasonOptions"-->
+<!-- :key="index"-->
+<!-- :label="item.label"-->
+<!-- :value="item.value"-->
+<!-- />-->
+<!-- </el-select>-->
+<!-- </div>-->
+<!-- </el-col>-->
+<!-- <el-col :span="12">-->
+<!-- <div class="info-item">-->
+<!-- <span class="info-label">鍛樺伐缂栧彿锛�</span>-->
+<!-- <span class="info-value">{{ form.staffNo || '-' }}</span>-->
+<!-- </div>-->
+<!-- </el-col>-->
+<!-- </el-row>-->
</div>
+
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
+ <el-button type="primary" @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
@@ -165,180 +173,175 @@
</template>
<script setup>
- import { ref, reactive, toRefs, getCurrentInstance } from "vue";
- import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
- import {
- createStaffLeave,
- updateStaffLeave,
- } from "@/api/personnelManagement/staffLeave.js";
- const { proxy } = getCurrentInstance();
- const emit = defineEmits(["close"]);
+import {ref, reactive, toRefs, getCurrentInstance} from "vue";
+import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
+import {createStaffLeave, updateStaffLeave} from "@/api/personnelManagement/staffLeave.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
- const dialogFormVisible = ref(false);
- const operationType = ref("");
- const getTodayDate = () => {
- const now = new Date();
- const year = now.getFullYear();
- const month = `${now.getMonth() + 1}`.padStart(2, "0");
- const day = `${now.getDate()}`.padStart(2, "0");
- return `${year}-${month}-${day}`;
- };
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const getTodayDate = () => {
+ const now = new Date();
+ const year = now.getFullYear();
+ const month = `${now.getMonth() + 1}`.padStart(2, '0');
+ const day = `${now.getDate()}`.padStart(2, '0');
+ return `${year}-${month}-${day}`;
+};
- const disabledFutureDate = time => {
- const todayEnd = new Date();
- todayEnd.setHours(23, 59, 59, 999);
- return time.getTime() > todayEnd.getTime();
- };
- const data = reactive({
- form: {
- staffOnJobId: undefined,
- leaveDate: "",
- reason: "",
- remark: "",
- },
- rules: {
- staffName: [{ required: true, message: "璇烽�夋嫨浜哄憳" }],
- leaveDate: [
- { required: true, message: "璇烽�夋嫨绂昏亴鏃ユ湡", trigger: "change" },
- ],
- reason: [{ required: true, message: "璇烽�夋嫨绂昏亴鍘熷洜" }],
- },
- dimissionReasonOptions: [
- { label: "钖祫寰呴亣", value: "salary" },
- { label: "鑱屼笟鍙戝睍", value: "career_development" },
- { label: "宸ヤ綔鐜", value: "work_environment" },
- { label: "涓汉鍘熷洜", value: "personal_reason" },
- { label: "鍏朵粬", value: "other" },
- ],
- currentStaffRecord: {},
- });
- const { form, rules, dimissionReasonOptions, currentStaffRecord } =
- toRefs(data);
+const disabledFutureDate = (time) => {
+ const todayEnd = new Date();
+ todayEnd.setHours(23, 59, 59, 999);
+ return time.getTime() > todayEnd.getTime();
+};
+const data = reactive({
+ form: {
+ staffOnJobId: undefined,
+ leaveDate: "",
+ reason: "",
+ remark: "",
+ },
+ rules: {
+ staffName: [{ required: true, message: "璇烽�夋嫨浜哄憳" }],
+ leaveDate: [{ required: true, message: "璇烽�夋嫨绂昏亴鏃ユ湡", trigger: "change" }],
+ reason: [{ required: true, message: "璇烽�夋嫨绂昏亴鍘熷洜"}],
+ },
+ dimissionReasonOptions: [
+ {label: '钖祫寰呴亣', value: 'salary'},
+ {label: '鑱屼笟鍙戝睍', value: 'career_development'},
+ {label: '宸ヤ綔鐜', value: 'work_environment'},
+ {label: '涓汉鍘熷洜', value: 'personal_reason'},
+ {label: '鍏朵粬', value: 'other'},
+ ],
+ currentStaffRecord: {},
+});
+const { form, rules, dimissionReasonOptions, currentStaffRecord } = toRefs(data);
- // 鎵撳紑寮规
- const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- if (operationType.value === "edit") {
- currentStaffRecord.value = row;
- form.value.staffOnJobId = row.staffOnJobId;
- form.value.leaveDate = row.leaveDate;
- form.value.reason = row.reason;
- form.value.remark = row.remark;
- personList.value = [
- {
- staffName: row.staffName,
- id: row.staffOnJobId,
- },
- ];
- } else {
- form.value.leaveDate = getTodayDate();
- getList();
- }
- };
-
- const handleSelectDimissionReason = val => {
- if (val === "other") {
- form.value.remark = "";
- }
- };
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitForm = () => {
- form.value.staffState = 0;
- if (form.value.reason !== "other") {
- form.value.remark = "";
- }
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- if (operationType.value === "add") {
- createStaffLeave(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- } else {
- updateStaffLeave(currentStaffRecord.value.id, form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- }
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === 'edit') {
+ currentStaffRecord.value = row
+ form.value.staffOnJobId = row.staffOnJobId
+ form.value.leaveDate = row.leaveDate
+ form.value.reason = row.reason
+ form.value.remark = row.remark
+ personList.value = [
+ {
+ staffName: row.staffName,
+ id: row.staffOnJobId,
}
- });
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- // 琛ㄥ崟宸叉敞閲婏紝鎵嬪姩閲嶇疆琛ㄥ崟鏁版嵁
- form.value = {
- staffOnJobId: undefined,
- leaveDate: "",
- reason: "",
- remark: "",
- };
- dialogFormVisible.value = false;
- emit("close");
- };
+ ]
+ } else {
+ form.value.leaveDate = getTodayDate()
+ getList()
+ }
+}
- const personList = ref([]);
-
- /**
- * 鑾峰彇褰撳墠鍦ㄨ亴浜哄憳鍒楄〃
- */
- const getList = () => {
- staffOnJobListPage({
- current: -1,
- size: -1,
- staffState: 1,
- }).then(res => {
- personList.value = res.data.records || [];
- });
- };
-
- const handleSelect = val => {
- let obj = personList.value.find(item => item.id === val);
- currentStaffRecord.value = {};
- if (obj) {
- // 淇濈暀绂昏亴鏃ユ湡鍜岀鑱屽師鍥狅紝鍙洿鏂板憳宸ヤ俊鎭�
- currentStaffRecord.value = obj;
+const handleSelectDimissionReason = (val) => {
+ if (val === 'other') {
+ form.value.remark = ''
+ }
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+ form.value.staffState = 0
+ if (form.value.reason !== 'other') {
+ form.value.remark = ''
+ }
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "add") {
+ createStaffLeave(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ } else {
+ updateStaffLeave(currentStaffRecord.value.id, form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ }
}
+ })
+
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ // 琛ㄥ崟宸叉敞閲婏紝鎵嬪姩閲嶇疆琛ㄥ崟鏁版嵁
+ form.value = {
+ staffOnJobId: undefined,
+ leaveDate: "",
+ reason: "",
+ remark: "",
};
- defineExpose({
- openDialog,
- });
+ dialogFormVisible.value = false;
+ emit('close')
+};
+
+const personList = ref([]);
+
+/**
+ * 鑾峰彇褰撳墠鍦ㄨ亴浜哄憳鍒楄〃
+ */
+const getList = () => {
+ staffOnJobListPage({
+ current: -1,
+ size: -1,
+ staffState: 1
+ }).then(res => {
+ personList.value = res.data.records || []
+ })
+};
+
+const handleSelect = (val) => {
+ let obj = personList.value.find(item => item.id === val)
+ currentStaffRecord.value = {}
+ if (obj) {
+ // 淇濈暀绂昏亴鏃ユ湡鍜岀鑱屽師鍥狅紝鍙洿鏂板憳宸ヤ俊鎭�
+ currentStaffRecord.value = obj
+ }
+}
+defineExpose({
+ openDialog,
+});
</script>
<style scoped>
- .info-section {
- background: #f5f7fa;
- padding: 20px;
- border-radius: 8px;
- margin-bottom: 20px;
- }
+.info-section {
+ background: #f5f7fa;
+ padding: 20px;
+ border-radius: 8px;
+ margin-bottom: 20px;
+}
- .info-title {
- font-size: 16px;
- font-weight: 600;
- color: #303133;
- margin-bottom: 20px;
- padding-bottom: 10px;
- border-bottom: 1px solid #e4e7ed;
- }
+.info-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 20px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #e4e7ed;
+}
- .info-item {
- display: flex;
- align-items: center;
- margin-bottom: 16px;
- min-height: 32px;
- }
+.info-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 16px;
+ min-height: 32px;
+}
- .info-label {
- min-width: 140px;
- color: #606266;
- font-size: 14px;
- font-weight: 500;
- }
+.info-label {
+ min-width: 140px;
+ color: #606266;
+ font-size: 14px;
+ font-weight: 500;
+}
- .info-value {
- flex: 1;
- color: #303133;
- font-size: 14px;
- }
+.info-value {
+ flex: 1;
+ color: #303133;
+ font-size: 14px;
+}
</style>
diff --git a/src/views/personnelManagement/dimission/index.vue b/src/views/personnelManagement/dimission/index.vue
index 4a37ae3..c2b8c3e 100644
--- a/src/views/personnelManagement/dimission/index.vue
+++ b/src/views/personnelManagement/dimission/index.vue
@@ -3,209 +3,216 @@
<div class="search_form mb20">
<div>
<span class="search_title">濮撳悕锛�</span>
- <el-input v-model="searchForm.staffName"
- 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.staffName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
</div>
<div>
- <el-button type="primary"
- @click="openForm('add')">鏂板绂昏亴</el-button>
+ <el-button type="primary" @click="openForm('add')">鏂板绂昏亴</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button> -->
</div>
</div>
<div class="table_list">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"></PIMTable>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"
+ ></PIMTable>
</div>
- <form-dia ref="formDia"
- @close="handleQuery"></form-dia>
+ <form-dia ref="formDia" @close="handleQuery"></form-dia>
</div>
</template>
<script setup>
- import { Search } from "@element-plus/icons-vue";
- import { onMounted, ref } from "vue";
- import FormDia from "@/views/personnelManagement/dimission/components/formDia.vue";
- import {
- findStaffLeaveListPage,
- batchDeleteStaffLeaves,
- } from "@/api/personnelManagement/staffLeave.js";
- import { ElMessageBox } from "element-plus";
+import { Search } from "@element-plus/icons-vue";
+import {onMounted, ref} from "vue";
+import FormDia from "@/views/personnelManagement/dimission/components/formDia.vue";
+import {findStaffLeaveListPage, batchDeleteStaffLeaves} from "@/api/personnelManagement/staffLeave.js";
+import {ElMessageBox} from "element-plus";
- const data = reactive({
- searchForm: {
- staffName: "",
+const data = reactive({
+ searchForm: {
+ staffName: "",
+ },
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "staffState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == 0) {
+ return "绂昏亴";
+ } else if (params == 1) {
+ return "鍦ㄨ亴";
+ } else {
+ return null;
+ }
},
- });
- const { searchForm } = toRefs(data);
- const tableColumn = ref([
- {
- label: "鐘舵��",
- prop: "staffState",
- dataType: "tag",
- formatData: params => {
- if (params == 0) {
- return "绂昏亴";
- } else if (params == 1) {
- return "鍦ㄨ亴";
- } else {
- return null;
- }
- },
- formatType: params => {
- if (params == 0) {
- return "danger";
- } else if (params == 1) {
- return "primary";
- } else {
- return null;
- }
- },
+ formatType: (params) => {
+ if (params == 0) {
+ return "danger";
+ } else if (params == 1) {
+ return "primary";
+ } else {
+ return null;
+ }
},
- {
- label: "绂昏亴鏃ユ湡",
- prop: "leaveDate",
- },
- {
- label: "鍛樺伐缂栧彿",
- prop: "staffNo",
- },
- {
- label: "濮撳悕",
- prop: "staffName",
- },
- {
- label: "鎬у埆",
- prop: "sex",
- },
- {
- label: "閮ㄩ棬",
- prop: "deptName",
- },
- {
- label: "宀椾綅",
- prop: "postName",
- },
- {
- label: "绗竴瀛﹀巻",
- prop: "firstStudy",
- },
- {
- label: "涓撲笟",
- prop: "profession",
- width: 100,
- },
- {
- label: "骞撮緞",
- prop: "age",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "phone",
- width: 150,
- },
- {
- label: "绱ф�ヨ仈绯讳汉",
- prop: "emergencyContact",
- width: 120,
- },
- {
- label: "绱ф�ヨ仈绯讳汉鐢佃瘽",
- prop: "emergencyContactPhone",
- width: 150,
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: row => {
- openForm("edit", row);
- },
+ },
+ {
+ label: "绂昏亴鏃ユ湡",
+ prop: "leaveDate",
+ },
+ {
+ label: "鍛樺伐缂栧彿",
+ prop: "staffNo",
+ },
+ {
+ label: "濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "鎬у埆",
+ prop: "sex",
+ },
+ {
+ label: "鎴风睄浣忓潃",
+ prop: "nativePlace",
+ },
+ {
+ label: "閮ㄩ棬",
+ prop: "deptName",
+ },
+ {
+ label: "宀椾綅",
+ prop: "postName",
+ },
+ {
+ label: "鐜颁綇鍧�",
+ prop: "adress",
+ width:200
+ },
+ {
+ label: "绗竴瀛﹀巻",
+ prop: "firstStudy",
+ },
+ {
+ label: "涓撲笟",
+ prop: "profession",
+ width:100
+ },
+ {
+ label: "骞撮緞",
+ prop: "age",
+ },
+ {
+ label: "鑱旂郴鐢佃瘽",
+ prop: "phone",
+ width:150
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉",
+ prop: "emergencyContact",
+ width: 120
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉鐢佃瘽",
+ prop: "emergencyContactPhone",
+ width:150
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
},
- ],
- },
- ]);
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
- const formDia = ref();
- const { proxy } = getCurrentInstance();
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+const formDia = ref()
+const { proxy } = getCurrentInstance()
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- findStaffLeaveListPage({ ...page, ...searchForm.value })
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- page.total = res.data.total;
- })
- .catch(err => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
- // 鎵撳紑寮规
- const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row);
- });
- };
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ findStaffLeaveListPage({...page, ...searchForm.value}).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records
+ page.total = res.data.total;
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map(item => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row)
+ })
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- batchDeleteStaffLeaves(ids).then(res => {
+ batchDeleteStaffLeaves(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -213,24 +220,24 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
proxy.download("/staff/staffLeave/export", {}, "浜哄憳绂昏亴.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
- onMounted(() => {
- getList();
- });
+};
+onMounted(() => {
+ getList();
+});
</script>
<style scoped></style>
diff --git a/src/views/personnelManagement/employeeRecord/index.vue b/src/views/personnelManagement/employeeRecord/index.vue
index b8496e3..a0699b0 100644
--- a/src/views/personnelManagement/employeeRecord/index.vue
+++ b/src/views/personnelManagement/employeeRecord/index.vue
@@ -145,10 +145,6 @@
prop: "staffNo",
},
{
- label: "閮ㄩ棬",
- prop: "deptName",
- },
- {
label: "濮撳悕",
prop: "staffName",
},
diff --git a/src/views/personnelManagement/monthlyStatistics/components/auditDia.vue b/src/views/personnelManagement/monthlyStatistics/components/auditDia.vue
index e615402..48a41f0 100644
--- a/src/views/personnelManagement/monthlyStatistics/components/auditDia.vue
+++ b/src/views/personnelManagement/monthlyStatistics/components/auditDia.vue
@@ -86,7 +86,7 @@
<script setup>
import { ref, computed, reactive, toRefs, getCurrentInstance, watch } from "vue";
import { ElMessage } from "element-plus";
-import useUserStore from "@/store/modules/user";
+import Cookies from "js-cookie";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { staffSalaryMainUpdate } from "@/api/personnelManagement/staffSalaryMain.js";
@@ -98,7 +98,6 @@
});
const { proxy } = getCurrentInstance();
-const userStore = useUserStore();
const dialogVisible = computed({
get: () => props.modelValue,
@@ -177,21 +176,15 @@
return;
}
- const username = userStore.name || "";
- const currentUserId = Number(userStore.id);
- const assignedAuditUserId = Number(row?.auditUserId);
-
- // 鏉冮檺楠岃瘉锛氬彧鏈夋寚瀹氱殑瀹℃牳浜烘墠鑳借繘琛屽鏍�
- if (!currentUserId || currentUserId !== assignedAuditUserId) {
- ElMessage.warning("鎮ㄤ笉鏄寚瀹氱殑瀹℃牳浜猴紝鏃犳硶杩涜瀹℃牳鎿嶄綔");
- return;
- }
+ const username = Cookies.get("username") || "";
+ const userIdRaw = Cookies.get("userId");
+ const auditUserId = userIdRaw ? Number(userIdRaw) : undefined;
// 鏋勫缓瀹℃牳鏁版嵁
const submitData = {
id: row.id,
status: Number(auditResult.value) === 2 ? 2 : 4, // 2=涓嶉�氳繃 4=閫氳繃(寰呭彂鏀�)
- auditUserId: currentUserId,
+ auditUserId,
auditUserName: username,
};
loading.value = true;
diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
index 46515ed..36c2ec3 100644
--- a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
+++ b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
@@ -1,520 +1,505 @@
<template>
- <FormDialog v-model="dialogVisible"
- :title="operationType === 'add' ? '鏂板缓宸ヨ祫琛�' : '缂栬緫宸ヨ祫琛�'"
- width="90%"
- @close="closeDia">
+ <FormDialog
+ v-model="dialogVisible"
+ :title="operationType === 'add' ? '鏂板缓宸ヨ祫琛�' : '缂栬緫宸ヨ祫琛�'"
+ width="90%"
+ @close="closeDia"
+ >
<template #footer>
- <el-button type="info"
- @click="saveDraft">淇濆瓨鑽夌</el-button>
- <el-button type="primary"
- @click="submitForm">纭鎻愪氦</el-button>
+ <el-button type="info" @click="saveDraft">淇濆瓨鑽夌</el-button>
+ <el-button type="primary" @click="submitForm">纭鎻愪氦</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</template>
<div class="form-dia-body">
<!-- 鍩虹璧勬枡 -->
- <el-card class="form-card"
- shadow="never">
+ <el-card class="form-card" shadow="never">
<template #header>
<span class="card-title"><span class="card-title-line">|</span> 鍩虹璧勬枡</span>
- <el-icon class="card-collapse">
- <ArrowUp />
- </el-icon>
+ <el-icon class="card-collapse"><ArrowUp /></el-icon>
</template>
- <el-form ref="formRef"
- :model="form"
- :rules="rules"
- label-position="top">
+ <el-form ref="formRef" :model="form" :rules="rules" label-position="top">
<el-row :gutter="24">
<el-col :span="6">
- <el-form-item label="宸ヨ祫涓婚"
- prop="salaryTitle">
- <el-input v-model="form.salaryTitle"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="20"
- show-word-limit />
+ <el-form-item label="宸ヨ祫涓婚" prop="salaryTitle">
+ <el-input
+ v-model="form.salaryTitle"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
</el-form-item>
</el-col>
<el-col :span="6">
- <el-form-item label="閫夋嫨宸ヨ祫鏈堜唤"
- prop="salaryMonth">
- <el-date-picker v-model="form.salaryMonth"
- type="month"
- value-format="YYYY-MM"
- format="YYYY-MM"
- placeholder="璇烽�夋嫨宸ヨ祫鏈堜唤"
- style="width: 100%"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="閫夋嫨閮ㄩ棬"
- prop="deptIds">
- <el-select v-model="form.deptIds"
- placeholder="璇烽�夋嫨"
- clearable
- multiple
- collapse-tags-tooltip
- style="width: 100%">
- <el-option v-for="item in deptOptions"
- :key="item.deptId"
- :label="item.deptName"
- :value="item.deptId"
- :disabled="isDeptDisabled(item.deptId)" />
+ <el-form-item label="閫夋嫨閮ㄩ棬" prop="deptIds">
+ <el-select
+ v-model="form.deptIds"
+ placeholder="璇烽�夋嫨"
+ clearable
+ multiple
+ collapse-tags-tooltip
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in deptOptions"
+ :key="item.deptId"
+ :label="item.deptName"
+ :value="item.deptId"
+ />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
- <el-form-item label="澶囨敞"
- prop="remark">
- <el-input v-model="form.remark"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="閫夋嫨宸ヨ祫鏈堜唤" prop="salaryMonth">
+ <el-date-picker
+ v-model="form.salaryMonth"
+ type="month"
+ value-format="YYYY-MM"
+ format="YYYY-MM"
+ placeholder="璇烽�夋嫨宸ヨ祫鏈堜唤"
+ style="width: 100%"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input
+ v-model="form.remark"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="6">
- <el-form-item label="鏀粯閾惰"
- prop="payBank">
- <el-select v-model="form.payBank"
- placeholder="璇烽�夋嫨"
- clearable
- filterable
- style="width: 100%">
- <el-option v-for="b in bankOptions"
- :key="b"
- :label="b"
- :value="b" />
+ <el-form-item label="鏀粯閾惰" prop="payBank">
+ <el-select
+ v-model="form.payBank"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="b in bankOptions"
+ :key="b"
+ :label="b"
+ :value="b"
+ />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
- <el-form-item label="瀹℃牳浜�"
- prop="auditUserId">
- <el-select v-model="form.auditUserId"
- placeholder="璇烽�夋嫨瀹℃牳浜�"
- clearable
- filterable
- style="width: 100%">
- <el-option v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId" />
+ <el-form-item label="瀹℃牳浜�" prop="auditUserId">
+ <el-select
+ v-model="form.auditUserId"
+ placeholder="璇烽�夋嫨瀹℃牳浜�"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
+
<!-- 鎿嶄綔鎸夐挳 -->
<div class="toolbar">
- <el-button type="primary"
- @click="handleGenerate">鐢熸垚宸ヨ祫琛�</el-button>
+ <el-button type="primary" @click="handleGenerate">鐢熸垚宸ヨ祫琛�</el-button>
<el-button @click="handleClear">娓呯┖</el-button>
<el-button @click="handleBatchDelete">鍒犻櫎</el-button>
<el-button @click="handleTaxForm">涓◣琛�</el-button>
</div>
+
<!-- 鍛樺伐宸ヨ祫璇︽儏琛ㄦ牸 -->
<div class="employee-table-wrap">
- <el-table ref="employeeTableRef"
- :data="employeeList"
- border
- max-height="400"
- @selection-change="onEmployeeSelectionChange">
- <el-table-column type="selection"
- width="55"
- align="center" />
- <el-table-column label="鍛樺伐濮撳悕"
- prop="staffName"
- minWidth="100" />
- <el-table-column label="閮ㄩ棬"
- prop="deptName"
- minWidth="100" />
- <el-table-column label="鍩烘湰宸ヨ祫"
- minWidth="110">
+ <el-table
+ ref="employeeTableRef"
+ :data="employeeList"
+ border
+ max-height="400"
+ @selection-change="onEmployeeSelectionChange"
+ >
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="鍛樺伐濮撳悕" prop="staffName" minWidth="100" />
+ <el-table-column label="閮ㄩ棬" prop="deptName" minWidth="100" />
+ <el-table-column label="鍩烘湰宸ヨ祫" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.basicSalary"
- type="number"
- placeholder="0"
- size="small"
- @input="handleSalaryInput(row)" />
+ <el-input
+ v-model.number="row.basicSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.basicSalary = parseNum(row.basicSalary)"
+ />
</template>
</el-table-column>
- <el-table-column label="璁′欢宸ヨ祫"
- minWidth="110">
+ <el-table-column label="璁′欢宸ヨ祫" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.pieceSalary"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.pieceSalary = parseNum(row.pieceSalary)" />
+ <el-input
+ v-model.number="row.pieceSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.pieceSalary = parseNum(row.pieceSalary)"
+ />
</template>
</el-table-column>
- <el-table-column label="璁℃椂宸ヨ祫"
- minWidth="110">
+ <el-table-column label="璁℃椂宸ヨ祫" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.hourlySalary"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.hourlySalary = parseNum(row.hourlySalary)" />
+ <el-input
+ v-model.number="row.hourlySalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.hourlySalary = parseNum(row.hourlySalary)"
+ />
</template>
</el-table-column>
- <el-table-column label="鍏朵粬鏀跺叆"
- minWidth="110">
+ <el-table-column label="鍏朵粬鏀跺叆" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.otherIncome"
- type="number"
- placeholder="0"
- size="small"
- @input="handleSalaryInput(row)" />
+ <el-input
+ v-model.number="row.otherIncome"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.otherIncome = parseNum(row.otherIncome)"
+ />
</template>
</el-table-column>
- <el-table-column label="绀句繚涓汉"
- minWidth="110">
+ <el-table-column label="绀句繚涓汉" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.socialPersonal"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.socialPersonal = parseNum(row.socialPersonal)" />
+ <el-input
+ v-model.number="row.socialPersonal"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.socialPersonal = parseNum(row.socialPersonal)"
+ />
</template>
</el-table-column>
- <el-table-column label="鍏Н閲戜釜浜�"
- minWidth="120">
+ <el-table-column label="鍏Н閲戜釜浜�" minWidth="120">
<template #default="{ row }">
- <el-input v-model.number="row.fundPersonal"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.fundPersonal = parseNum(row.fundPersonal)" />
+ <el-input
+ v-model.number="row.fundPersonal"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.fundPersonal = parseNum(row.fundPersonal)"
+ />
</template>
</el-table-column>
- <el-table-column label="鍏朵粬鏀嚭"
- minWidth="110">
+ <el-table-column label="鍏朵粬鏀嚭" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.otherDeduct"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.otherDeduct = parseNum(row.otherDeduct)" />
+ <el-input
+ v-model.number="row.otherDeduct"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.otherDeduct = parseNum(row.otherDeduct)"
+ />
</template>
</el-table-column>
- <el-table-column label="绀句繚琛ョ即"
- minWidth="120">
+ <el-table-column label="宸ヨ祫涓◣" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.socialSupplementAmount"
- type="number"
- placeholder="0"
- size="small"
- @input="handleSalaryInput(row)" />
+ <el-input
+ v-model.number="row.salaryTax"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.salaryTax = parseNum(row.salaryTax)"
+ />
</template>
</el-table-column>
- <el-table-column label="宸ヨ祫涓◣"
- minWidth="110">
+ <el-table-column label="搴斿彂宸ヨ祫" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.salaryTax"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.salaryTax = parseNum(row.salaryTax)" />
+ <el-input
+ v-model.number="row.grossSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.grossSalary = parseNum(row.grossSalary)"
+ />
</template>
</el-table-column>
- <el-table-column label="搴斿彂宸ヨ祫"
- minWidth="110">
+ <el-table-column label="搴旀墸宸ヨ祫" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.grossSalary"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.grossSalary = parseNum(row.grossSalary)" />
+ <el-input
+ v-model.number="row.deductSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.deductSalary = parseNum(row.deductSalary)"
+ />
</template>
</el-table-column>
- <el-table-column label="搴旀墸宸ヨ祫"
- minWidth="110">
+ <el-table-column label="瀹炲彂宸ヨ祫" minWidth="110">
<template #default="{ row }">
- <el-input v-model.number="row.deductSalary"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.deductSalary = parseNum(row.deductSalary)" />
+ <el-input
+ v-model.number="row.netSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.netSalary = parseNum(row.netSalary)"
+ />
</template>
</el-table-column>
- <el-table-column label="瀹炲彂宸ヨ祫"
- minWidth="110">
+ <el-table-column label="澶囨敞" minWidth="120">
<template #default="{ row }">
- <el-input v-model.number="row.netSalary"
- type="number"
- placeholder="0"
- size="small"
- disabled
- @input="row.netSalary = parseNum(row.netSalary)" />
+ <el-input
+ v-model="row.remark"
+ placeholder="璇疯緭鍏�"
+ size="small"
+ />
</template>
</el-table-column>
- <el-table-column label="澶囨敞"
- minWidth="120">
+ <el-table-column label="鎿嶄綔" width="80" align="center" fixed="right">
<template #default="{ row }">
- <el-input v-model="row.remark"
- placeholder="璇疯緭鍏�"
- size="small" />
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔"
- width="80"
- align="center"
- fixed="right">
- <template #default="{ row }">
- <el-button type="primary"
- link
- @click="removeEmployee(row)">鍒犻櫎</el-button>
+ <el-button type="primary" link @click="removeEmployee(row)">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
- <div v-if="!employeeList.length"
- class="table-empty">鏆傛棤鏁版嵁</div>
- <div v-else
- class="salary-total">
+ <div v-if="!employeeList.length" class="table-empty">鏆傛棤鏁版嵁</div>
+ <div v-else class="salary-total">
<span class="total-label">宸ヨ祫鎬婚锛�</span>
<span class="total-value">楼 {{ totalSalary.toFixed(2) }}</span>
</div>
</div>
</div>
+
+
+
<!-- 鏂板浜哄憳寮圭獥 -->
- <el-dialog v-model="addPersonVisible"
- title="鏂板浜哄憳"
- width="400px"
- append-to-body
- @close="addPersonClose">
+ <el-dialog
+ v-model="addPersonVisible"
+ title="鏂板浜哄憳"
+ width="400px"
+ append-to-body
+ @close="addPersonClose"
+ >
<div class="add-person-tree">
- <el-tree ref="personTreeRef"
- :data="deptStaffTree"
- show-checkbox
- node-key="id"
- :props="{ label: 'label', children: 'children' }"
- default-expand-all />
+ <el-tree
+ ref="personTreeRef"
+ :data="deptStaffTree"
+ show-checkbox
+ node-key="id"
+ :props="{ label: 'label', children: 'children' }"
+ default-expand-all
+ />
</div>
<template #footer>
<el-button @click="addPersonVisible = false">鍙栨秷</el-button>
- <el-button type="primary"
- @click="confirmAddPerson">纭畾</el-button>
+ <el-button type="primary" @click="confirmAddPerson">纭畾</el-button>
</template>
</el-dialog>
+
<!-- 涓◣琛ㄥ脊绐� -->
- <el-dialog v-model="taxDialogVisible"
- title="涓◣琛�"
- width="700px"
- append-to-body>
+ <el-dialog
+ v-model="taxDialogVisible"
+ title="涓◣琛�"
+ width="700px"
+ append-to-body
+ >
<div class="tax-desc">涓汉鎵�寰楃◣鍏嶅緛棰濓細5000鍏�</div>
- <el-table :data="taxTableData"
- border
- style="width: 100%;margin-bottom: 20px;">
- <el-table-column prop="level"
- label="绾ф暟"
- width="80"
- align="center" />
- <el-table-column prop="range"
- label="鍏ㄥ勾搴旂撼绋庢墍寰楅/鍏�"
- min-width="220" />
- <el-table-column prop="rate"
- label="绋庣巼(%)"
- width="100"
- align="center" />
- <el-table-column prop="quickDeduction"
- label="閫熺畻鎵i櫎鏁�/鍏�"
- width="160"
- align="center" />
+ <el-table :data="taxTableData" border style="width: 100%;margin-bottom: 20px;">
+ <el-table-column prop="level" label="绾ф暟" width="80" align="center" />
+ <el-table-column
+ prop="range"
+ label="鍏ㄥ勾搴旂撼绋庢墍寰楅/鍏�"
+ min-width="220"
+ />
+ <el-table-column
+ prop="rate"
+ label="绋庣巼(%)"
+ width="100"
+ align="center"
+ />
+ <el-table-column
+ prop="quickDeduction"
+ label="閫熺畻鎵i櫎鏁�/鍏�"
+ width="160"
+ align="center"
+ />
</el-table>
</el-dialog>
</FormDialog>
</template>
<script setup>
- import {
- ref,
- reactive,
- toRefs,
- computed,
- getCurrentInstance,
- nextTick,
- watch,
- } from "vue";
- import { ArrowUp } from "@element-plus/icons-vue";
- import FormDialog from "@/components/Dialog/FormDialog.vue";
- import { listDept } from "@/api/system/dept.js";
- import { staffOnJobList } from "@/api/personnelManagement/monthlyStatistics.js";
+import { ref, reactive, toRefs, computed, getCurrentInstance, nextTick } from "vue";
+import { ArrowUp } from "@element-plus/icons-vue";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { listDept } from "@/api/system/dept.js";
+import { staffOnJobList } from "@/api/personnelManagement/monthlyStatistics.js";
import { bankList } from "@/api/personnelManagement/bank.js";
import {
staffSalaryMainAdd,
staffSalaryMainUpdate,
staffSalaryMainCalculateSalary,
- staffSalaryMainCalculateByEmployeeId,
- staffSalaryMainAvailableDepts,
} from "@/api/personnelManagement/staffSalaryMain.js";
- import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
- const emit = defineEmits(["update:modelValue", "close"]);
- const props = defineProps({
- modelValue: { type: Boolean, default: false },
- operationType: { type: String, default: "add" },
- row: { type: Object, default: () => ({}) },
- });
- const { proxy } = getCurrentInstance();
+const emit = defineEmits(["update:modelValue", "close"]);
+const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ operationType: { type: String, default: "add" },
+ row: { type: Object, default: () => ({}) },
+});
- const dialogVisible = computed({
- get: () => props.modelValue,
- set: val => emit("update:modelValue", val),
- });
+const { proxy } = getCurrentInstance();
- const formRef = ref(null);
- const employeeTableRef = ref(null);
- const personTreeRef = ref(null);
- const addPersonVisible = ref(false);
- const taxDialogVisible = ref(false);
- const deptOptions = ref([]);
- const availableDeptIds = ref(new Set());
- const deptStaffTree = ref([]);
- const employeeList = ref([]);
- const selectedEmployees = ref([]);
- const bankOptions = ref([]);
- const userList = ref([]);
- const recalcTimers = new Map();
- const recalcVersions = new Map();
- const taxTableData = ref([
- { level: 1, range: "涓嶈秴杩�36000鍏�", rate: 3, quickDeduction: 0 },
- { level: 2, range: "瓒呰繃36000-144000鍏�", rate: 10, quickDeduction: 2520 },
- { level: 3, range: "瓒呰繃144000-300000鍏�", rate: 20, quickDeduction: 16920 },
- { level: 4, range: "瓒呰繃300000-420000鍏�", rate: 25, quickDeduction: 31920 },
- { level: 5, range: "瓒呰繃420000-660000鍏�", rate: 30, quickDeduction: 52920 },
- { level: 6, range: "瓒呰繃660000-960000鍏�", rate: 35, quickDeduction: 85920 },
- { level: 7, range: "瓒呰繃960000鍏�", rate: 45, quickDeduction: 181920 },
- ]);
+const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: (val) => emit("update:modelValue", val),
+});
- function parseNum(v) {
- if (v === "" || v == null) return 0;
- const n = Number(v);
- return isNaN(n) ? 0 : n;
- }
+const formRef = ref(null);
+const employeeTableRef = ref(null);
+const personTreeRef = ref(null);
+const addPersonVisible = ref(false);
+const taxDialogVisible = ref(false);
+const deptOptions = ref([]);
+const deptStaffTree = ref([]);
+const employeeList = ref([]);
+const selectedEmployees = ref([]);
+const bankOptions = ref([]);
+const userList = ref([]);
+const taxTableData = ref([
+ { level: 1, range: "涓嶈秴杩�36000鍏�", rate: 3, quickDeduction: 0 },
+ { level: 2, range: "瓒呰繃36000-144000鍏�", rate: 10, quickDeduction: 2520 },
+ { level: 3, range: "瓒呰繃144000-300000鍏�", rate: 20, quickDeduction: 16920 },
+ { level: 4, range: "瓒呰繃300000-420000鍏�", rate: 25, quickDeduction: 31920 },
+ { level: 5, range: "瓒呰繃420000-660000鍏�", rate: 30, quickDeduction: 52920 },
+ { level: 6, range: "瓒呰繃660000-960000鍏�", rate: 35, quickDeduction: 85920 },
+ { level: 7, range: "瓒呰繃960000鍏�", rate: 45, quickDeduction: 181920 },
+]);
- function parseNullableNum(v) {
- if (v === "" || v == null) return null;
- const n = Number(v);
- return isNaN(n) ? null : n;
- }
+function parseNum(v) {
+ if (v === "" || v == null) return 0;
+ const n = Number(v);
+ return isNaN(n) ? 0 : n;
+}
- const createEmployeeRow = () => ({
- staffOnJobId: undefined,
+// 鍩虹璧勬枡琛ㄥ崟
+const data = reactive({
+ form: {
id: undefined,
- staffName: "",
- postName: "",
- deptName: "",
- basicSalary: 0,
- pieceSalary: 0,
- hourlySalary: 0,
- otherIncome: 0,
- socialPersonal: 0,
- fundPersonal: 0,
- otherDeduct: 0,
- socialSupplementAmount: null,
- salaryTax: 0,
- grossSalary: 0,
- deductSalary: 0,
- netSalary: 0,
+ salaryTitle: "",
+ deptIds: [],
+ salaryMonth: "",
remark: "",
+ payBank: "",
+ auditUserId: undefined,
+ },
+ rules: {
+ salaryTitle: [{ required: true, message: "璇疯緭鍏ュ伐璧勪富棰�", trigger: "blur" }],
+ deptIds: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
+ salaryMonth: [{ required: true, message: "璇烽�夋嫨宸ヨ祫鏈堜唤", trigger: "change" }],
+ auditUserId: [{ required: true, message: "璇烽�夋嫨瀹℃牳浜�", trigger: "change" }],
+ },
+});
+const { form, rules } = toRefs(data);
+
+// 璁$畻宸ヨ祫鎬婚锛堟墍鏈夊憳宸ュ疄鍙戝伐璧勪箣鍜岋級
+const totalSalary = computed(() => {
+ return employeeList.value.reduce((sum, e) => sum + parseNum(e.netSalary), 0);
+});
+
+// 鏍规嵁瀹℃牳浜篒D鑾峰彇瀹℃牳浜哄悕绉�
+const auditUserName = computed(() => {
+ if (!form.value.auditUserId) return "";
+ const user = userList.value.find(u => u.userId === form.value.auditUserId);
+ return user ? user.nickName : "";
+});
+
+const loadBankOptions = () => {
+ return bankList().then((res) => {
+ const list = Array.isArray(res?.data) ? res.data : [];
+ bankOptions.value = list
+ .map((b) => (b?.bankName == null ? "" : String(b.bankName).trim()))
+ .filter((v) => v !== "");
});
+};
- const normalizeEmployeeRow = (source, fallback = {}) => ({
- ...createEmployeeRow(),
- ...fallback,
- ...source,
- staffOnJobId: source?.staffOnJobId ?? source?.staffId ?? source?.id ?? fallback.staffOnJobId ?? fallback.id,
- id: source?.staffOnJobId ?? source?.staffId ?? source?.id ?? fallback.staffOnJobId ?? fallback.id,
- staffName: source?.staffName ?? fallback.staffName ?? "",
- postName: source?.postName ?? fallback.postName ?? "",
- deptName: source?.deptName ?? fallback.deptName ?? "",
- basicSalary: parseNum(source?.basicSalary ?? fallback.basicSalary),
- pieceSalary: parseNum(source?.pieceSalary ?? fallback.pieceSalary),
- hourlySalary: parseNum(source?.hourlySalary ?? fallback.hourlySalary),
- otherIncome: parseNum(source?.otherIncome ?? fallback.otherIncome),
- socialPersonal: parseNum(source?.socialPersonal ?? fallback.socialPersonal),
- fundPersonal: parseNum(source?.fundPersonal ?? fallback.fundPersonal),
- otherDeduct: parseNum(source?.otherDeduct ?? fallback.otherDeduct),
- socialSupplementAmount:
- source?.socialSupplementAmount ?? fallback.socialSupplementAmount ?? null,
- salaryTax: parseNum(source?.salaryTax ?? fallback.salaryTax),
- grossSalary: parseNum(source?.grossSalary ?? fallback.grossSalary),
- deductSalary: parseNum(source?.deductSalary ?? fallback.deductSalary),
- netSalary: parseNum(source?.netSalary ?? fallback.netSalary),
- remark: source?.remark ?? fallback.remark ?? "",
+const loadUserList = () => {
+ return userListNoPageByTenantId().then((res) => {
+ userList.value = res.data || [];
});
+};
- const applyBackendRow = (targetRow, sourceRow) => {
- Object.assign(targetRow, normalizeEmployeeRow(sourceRow, targetRow));
- };
+// 鎵佸钩鍖栭儴闂ㄦ爲渚涗笅鎷変娇鐢�
+function flattenDept(tree, list = []) {
+ if (!tree?.length) return list;
+ tree.forEach((node) => {
+ list.push({ deptId: node.deptId, deptName: node.deptName });
+ if (node.children?.length) flattenDept(node.children, list);
+ });
+ return list;
+}
- const clearRowRecalcState = row => {
- const key = String(row?.staffOnJobId ?? row?.id ?? "");
- if (!key) return;
- clearTimeout(recalcTimers.get(key));
- recalcTimers.delete(key);
- recalcVersions.delete(key);
- };
+const loadDeptOptions = () => {
+ listDept().then((res) => {
+ const tree = res.data ?? [];
+ deptOptions.value = flattenDept(tree);
+ });
+};
- const resetRecalcState = () => {
- recalcTimers.forEach(timer => clearTimeout(timer));
- recalcTimers.clear();
- recalcVersions.clear();
- };
-
- const requestEmployeeRecalculate = row => {
- const key = String(row?.staffOnJobId ?? row?.id ?? "");
- if (!key || !form.value.salaryMonth) return;
- const version = (recalcVersions.get(key) || 0) + 1;
- recalcVersions.set(key, version);
- clearTimeout(recalcTimers.get(key));
- const payload = {
- staffOnJobId: row.staffOnJobId ?? row.id,
- salaryMonth: form.value.salaryMonth,
- staffName: row.staffName ?? "",
- postName: row.postName ?? "",
- deptName: row.deptName ?? "",
- basicSalary: parseNum(row.basicSalary),
- pieceSalary: parseNum(row.pieceSalary),
- hourlySalary: parseNum(row.hourlySalary),
- otherIncome: parseNum(row.otherIncome),
- otherDeduct: parseNum(row.otherDeduct),
- socialSupplementAmount: parseNullableNum(row.socialSupplementAmount),
- remark: row.remark ?? "",
- };
- recalcTimers.set(
- key,
- setTimeout(() => {
- staffSalaryMainCalculateByEmployeeId(payload).then(res => {
- if (recalcVersions.get(key) !== version) return;
- applyBackendRow(row, res?.data || {});
+// 鏋勫缓 閮ㄩ棬-浜哄憳 鏍戯紙鐢ㄤ簬鏂板浜哄憳寮圭獥锛�
+const loadDeptStaffTree = () => {
+ Promise.all([listDept(), staffOnJobList()]).then(([deptRes, staffRes]) => {
+ const tree = deptRes.data ?? [];
+ const staffList = staffRes.data ?? [];
+ const deptMap = new Map();
+ function walk(nodes) {
+ nodes.forEach((node) => {
+ deptMap.set(node.deptId, {
+ id: "dept_" + node.deptId,
+ deptId: node.deptId,
+ label: node.deptName,
+ type: "dept",
+ children: [],
});
- }, 250)
+ if (node.children?.length) walk(node.children);
+ });
+ }
+ walk(tree);
+ staffList.forEach((s) => {
+ const deptId = s.deptId ?? s.dept_id;
+ const node = deptMap.get(deptId);
+ if (node) {
+ node.children.push({
+ id: s.id ?? s.staffId,
+ staffId: s.id ?? s.staffId,
+ label: s.staffName ?? s.name,
+ type: "staff",
+ ...s,
+ });
+ }
+ });
+ deptStaffTree.value = Array.from(deptMap.values()).filter(
+ (n) => n.children && n.children.length > 0
);
- };
+ });
+};
- const handleSalaryInput = row => {
- row.basicSalary = parseNum(row.basicSalary);
- row.otherIncome = parseNum(row.otherIncome);
- requestEmployeeRecalculate(row);
- };
-
- // 鍩虹璧勬枡琛ㄥ崟
- const data = reactive({
- form: {
+const openDialog = (type, row) => {
+ nextTick(() => {
+ loadDeptOptions();
+ loadBankOptions();
+ loadUserList();
+ employeeList.value = [];
+ Object.assign(form.value, {
id: undefined,
salaryTitle: "",
deptIds: [],
@@ -522,413 +507,298 @@
remark: "",
payBank: "",
auditUserId: undefined,
- },
- rules: {
- salaryTitle: [
- { required: true, message: "璇疯緭鍏ュ伐璧勪富棰�", trigger: "blur" },
- ],
- deptIds: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
- salaryMonth: [
- { required: true, message: "璇烽�夋嫨宸ヨ祫鏈堜唤", trigger: "change" },
- ],
- auditUserId: [
- { required: true, message: "璇烽�夋嫨瀹℃牳浜�", trigger: "change" },
- ],
- },
- });
- const { form, rules } = toRefs(data);
-
- // 璁$畻宸ヨ祫鎬婚锛堟墍鏈夊憳宸ュ疄鍙戝伐璧勪箣鍜岋級
- const totalSalary = computed(() => {
- return employeeList.value.reduce((sum, e) => sum + parseNum(e.netSalary), 0);
- });
-
- // 鏍规嵁瀹℃牳浜篒D鑾峰彇瀹℃牳浜哄悕绉�
- const auditUserName = computed(() => {
- if (!form.value.auditUserId) return "";
- const user = userList.value.find(u => u.userId === form.value.auditUserId);
- return user ? user.nickName : "";
- });
-
- const loadBankOptions = () => {
- return bankList().then(res => {
- const list = Array.isArray(res?.data) ? res.data : [];
- bankOptions.value = list
- .map(b => (b?.bankName == null ? "" : String(b.bankName).trim()))
- .filter(v => v !== "");
});
- };
-
- const loadUserList = () => {
- return userListNoPageByTenantId().then(res => {
- userList.value = res.data || [];
- });
- };
-
- // 鎵佸钩鍖栭儴闂ㄦ爲渚涗笅鎷変娇鐢�
- function flattenDept(tree, list = []) {
- if (!tree?.length) return list;
- tree.forEach(node => {
- list.push({ deptId: node.deptId, deptName: node.deptName });
- if (node.children?.length) flattenDept(node.children, list);
- });
- return list;
- }
-
- // 鍔犺浇鎵�鏈夐儴闂�
- const loadAllDeptOptions = () => {
- listDept().then(res => {
- const tree = res.data ?? [];
- deptOptions.value = flattenDept(tree);
- });
- };
-
- // 鍔犺浇鍙敤閮ㄩ棬鍒楄〃锛堢敤浜庡垽鏂儴闂ㄦ槸鍚﹀彲閫夛級
- const loadAvailableDepts = (salaryMonth) => {
- if (!salaryMonth) {
- availableDeptIds.value = new Set();
- return;
- }
- staffSalaryMainAvailableDepts(salaryMonth).then(res => {
- const availableDepts = Array.isArray(res.data) ? res.data : [];
- availableDeptIds.value = new Set(availableDepts.map(d => d.deptId));
- });
- };
-
- // 鍒ゆ柇閮ㄩ棬鏄惁绂佺敤
- const isDeptDisabled = (deptId) => {
- // 濡傛灉娌℃湁閫夋嫨鏈堜唤锛屾墍鏈夐儴闂ㄩ兘鍙��
- if (!form.value.salaryMonth) return false;
- // 濡傛灉宸查�夋嫨鏈堜唤锛屽彧鏈夊湪鍙敤閮ㄩ棬鍒楄〃涓殑閮ㄩ棬鎵嶅彲閫�
- return !availableDeptIds.value.has(deptId);
- };
-
- // 鏋勫缓 閮ㄩ棬-浜哄憳 鏍戯紙鐢ㄤ簬鏂板浜哄憳寮圭獥锛�
- const loadDeptStaffTree = () => {
- Promise.all([listDept(), staffOnJobList()]).then(([deptRes, staffRes]) => {
- const tree = deptRes.data ?? [];
- const staffList = staffRes.data ?? [];
- const deptMap = new Map();
- function walk(nodes) {
- nodes.forEach(node => {
- deptMap.set(node.deptId, {
- id: "dept_" + node.deptId,
- deptId: node.deptId,
- label: node.deptName,
- type: "dept",
- children: [],
- });
- if (node.children?.length) walk(node.children);
- });
+ // 缂栬緫锛氬垪琛ㄩ〉宸茶繑鍥炰富琛ㄥ瓧娈碉紱杩欓噷鍙仛鍥炴樉锛堟槑缁嗙敱鈥滅敓鎴愬伐璧勮〃/璁$畻宸ヨ祫鈥濆緱鍒帮級
+ if (type === "edit" && row?.id) {
+ form.value.id = row.id;
+ form.value.salaryTitle = row.salaryTitle ?? "";
+ // deptIds 鍚庣鏄瓧绗︿覆锛堝涓敤閫楀彿鍒嗛殧锛夛紱褰撳墠琛ㄥ崟浠嶆槸鍗曢�� deptId
+ form.value.deptIds = row.deptIds
+ ? String(row.deptIds).split(",").map((id) => Number(id.trim())).filter(Boolean)
+ : [];
+ form.value.salaryMonth = row.salaryMonth ?? "";
+ form.value.remark = row.remark ?? "";
+ form.value.payBank = row.payBank ?? "";
+ form.value.auditUserId = row.auditUserId ?? undefined;
+
+ // 濡傛灉鏈夊憳宸ユ槑缁嗘暟鎹紝鐩存帴鍙嶆樉
+ if (row.staffSalaryDetailList && row.staffSalaryDetailList.length > 0) {
+ employeeList.value = row.staffSalaryDetailList.map((e) => ({
+ staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+ id: e.staffOnJobId ?? e.staffId ?? e.id,
+ staffName: e.staffName ?? "",
+ postName: e.postName ?? "",
+ deptName: e.deptName ?? "",
+ basicSalary: parseNum(e.basicSalary),
+ pieceSalary: parseNum(e.pieceSalary),
+ hourlySalary: parseNum(e.hourlySalary),
+ otherIncome: parseNum(e.otherIncome),
+ socialPersonal: parseNum(e.socialPersonal),
+ fundPersonal: parseNum(e.fundPersonal),
+ otherDeduct: parseNum(e.otherDeduct),
+ salaryTax: parseNum(e.salaryTax),
+ grossSalary: parseNum(e.grossSalary),
+ deductSalary: parseNum(e.deductSalary),
+ netSalary: parseNum(e.netSalary),
+ remark: e.remark ?? "",
+ }));
}
- walk(tree);
- staffList.forEach(s => {
- const deptId = s.deptId ?? s.dept_id;
- const node = deptMap.get(deptId);
- if (node) {
- node.children.push({
- id: s.id ?? s.staffId,
- staffId: s.id ?? s.staffId,
- label: s.staffName ?? s.name,
- type: "staff",
- ...s,
- });
- }
- });
- deptStaffTree.value = Array.from(deptMap.values()).filter(
- n => n.children && n.children.length > 0
- );
- });
- };
-
- const openDialog = (type, row) => {
- nextTick(() => {
- resetRecalcState();
- loadBankOptions();
- loadUserList();
- loadAllDeptOptions();
- employeeList.value = [];
- Object.assign(form.value, {
- id: undefined,
- salaryTitle: "",
- deptIds: [],
- salaryMonth: "",
- remark: "",
- payBank: "",
- auditUserId: undefined,
- });
- // 缂栬緫锛氬垪琛ㄩ〉宸茶繑鍥炰富琛ㄥ瓧娈碉紱杩欓噷鍙仛鍥炴樉锛堟槑缁嗙敱鈥滅敓鎴愬伐璧勮〃/璁$畻宸ヨ祫鈥濆緱鍒帮級
- if (type === "edit" && row?.id) {
- form.value.id = row.id;
- form.value.salaryTitle = row.salaryTitle ?? "";
- // deptIds 鍚庣鏄瓧绗︿覆锛堝涓敤閫楀彿鍒嗛殧锛夛紱褰撳墠琛ㄥ崟浠嶆槸鍗曢�� deptId
- form.value.deptIds = row.deptIds
- ? String(row.deptIds)
- .split(",")
- .map(id => Number(id.trim()))
- .filter(Boolean)
- : [];
- form.value.salaryMonth = row.salaryMonth ?? "";
- form.value.remark = row.remark ?? "";
- form.value.payBank = row.payBank ?? "";
- form.value.auditUserId = row.auditUserId ?? undefined;
-
- // 濡傛灉鏈夊憳宸ユ槑缁嗘暟鎹紝鐩存帴鍙嶆樉
- if (row.staffSalaryDetailList && row.staffSalaryDetailList.length > 0) {
- employeeList.value = row.staffSalaryDetailList.map(e => normalizeEmployeeRow(e));
- }
- }
- // 缂栬緫鐘舵�佷笖鏈夋湀浠芥椂锛屽姞杞藉彲鐢ㄩ儴闂ㄥ垪琛�
- if (type === "edit" && form.value.salaryMonth) {
- loadAvailableDepts(form.value.salaryMonth);
- }
- });
- };
-
- // 鐩戝惉宸ヨ祫鏈堜唤鍙樺寲锛屾竻绌洪儴闂ㄩ�夋嫨骞跺姞杞藉彲鐢ㄩ儴闂ㄥ垪琛�
- watch(() => form.value.salaryMonth, (newMonth, oldMonth) => {
- // 鍒囨崲鏈堜唤鏃舵竻绌哄凡閫夋嫨鐨勯儴闂�
- if (newMonth !== oldMonth) {
- form.value.deptIds = [];
}
- loadAvailableDepts(newMonth);
});
+};
- const openAddPerson = () => {
- loadDeptStaffTree();
- addPersonVisible.value = true;
- nextTick(() => {
- personTreeRef.value?.setCheckedKeys([]);
- });
- };
+const openAddPerson = () => {
+ loadDeptStaffTree();
+ addPersonVisible.value = true;
+ nextTick(() => {
+ personTreeRef.value?.setCheckedKeys([]);
+ });
+};
- const addPersonClose = () => {};
+const addPersonClose = () => {};
- const confirmAddPerson = () => {
- const tree = personTreeRef.value;
- if (!tree) {
- addPersonVisible.value = false;
- return;
- }
- const checked = tree.getCheckedNodes();
- const staffNodes = checked.filter(n => n.type === "staff");
- const existIds = new Set(employeeList.value.map(e => e.staffId || e.id));
- staffNodes.forEach(node => {
- const id = node.staffId ?? node.id;
- if (existIds.has(id)) return;
- existIds.add(id);
- const newRow = normalizeEmployeeRow({
- staffOnJobId: id,
- id,
- staffName: node.label,
- postName: node.postName ?? node.post ?? "",
- deptName: node.deptName ?? "",
- remark: "",
- socialSupplementAmount: null,
- });
- employeeList.value.push(newRow);
- requestEmployeeRecalculate(newRow);
- });
+const confirmAddPerson = () => {
+ const tree = personTreeRef.value;
+ if (!tree) {
addPersonVisible.value = false;
- };
+ return;
+ }
+ const checked = tree.getCheckedNodes();
+ const staffNodes = checked.filter((n) => n.type === "staff");
+ const existIds = new Set(employeeList.value.map((e) => e.staffId || e.id));
+ staffNodes.forEach((node) => {
+ const id = node.staffId ?? node.id;
+ if (existIds.has(id)) return;
+ existIds.add(id);
+ employeeList.value.push({
+ staffOnJobId: id,
+ id,
+ staffName: node.label,
+ postName: node.postName ?? node.post ?? "",
+ deptName: node.deptName ?? "",
+ basicSalary: 0,
+ pieceSalary: 0,
+ hourlySalary: 0,
+ otherIncome: 0,
+ socialPersonal: 0,
+ fundPersonal: 0,
+ otherDeduct: 0,
+ salaryTax: 0,
+ grossSalary: 0,
+ deductSalary: 0,
+ netSalary: 0,
+ remark: "",
+ });
+ });
+ addPersonVisible.value = false;
+};
- const removeEmployee = row => {
- clearRowRecalcState(row);
- employeeList.value = employeeList.value.filter(
- e => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
- );
- };
+const removeEmployee = (row) => {
+ employeeList.value = employeeList.value.filter(
+ (e) => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
+ );
+};
- const onEmployeeSelectionChange = selection => {
- selectedEmployees.value = selection;
- };
+const onEmployeeSelectionChange = (selection) => {
+ selectedEmployees.value = selection;
+};
- const handleBatchDelete = () => {
- if (!selectedEmployees.value?.length) {
- proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍒犻櫎鐨勫憳宸�");
+const handleBatchDelete = () => {
+ if (!selectedEmployees.value?.length) {
+ proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍒犻櫎鐨勫憳宸�");
+ return;
+ }
+ const ids = new Set(selectedEmployees.value.map((e) => e.staffOnJobId || e.id));
+ employeeList.value = employeeList.value.filter(
+ (e) => !ids.has(e.staffOnJobId || e.id)
+ );
+};
+
+const handleGenerate = () => {
+ if (!form.value.deptIds?.length) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨閮ㄩ棬");
+ return;
+ }
+ if (!form.value.salaryMonth) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨宸ヨ祫鏈堜唤");
+ return;
+ }
+ const payload = {
+ ids: form.value.deptIds,
+ date: form.value.salaryMonth,
+ };
+ staffSalaryMainCalculateSalary(payload).then((res) => {
+ const list = Array.isArray(res?.data) ? res.data : [];
+ if (!list.length) {
+ proxy.$modal.msgWarning("鏈绠楀埌宸ヨ祫鏁版嵁");
return;
}
- const ids = new Set(selectedEmployees.value.map(e => e.staffOnJobId || e.id));
- selectedEmployees.value.forEach(item => clearRowRecalcState(item));
- employeeList.value = employeeList.value.filter(
- e => !ids.has(e.staffOnJobId || e.id)
- );
- };
+ employeeList.value = list.map((e) => ({
+ ...e,
+ staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+ staffName: e.staffName,
+ postName: e.postName,
+ deptName: e.deptName,
+ basicSalary: parseNum(e.basicSalary),
+ pieceSalary: parseNum(e.pieceSalary),
+ hourlySalary: parseNum(e.hourlySalary),
+ otherIncome: parseNum(e.otherIncome),
+ socialPersonal: parseNum(e.socialPersonal),
+ fundPersonal: parseNum(e.fundPersonal),
+ otherDeduct: parseNum(e.otherDeduct),
+ salaryTax: parseNum(e.salaryTax),
+ grossSalary: parseNum(e.grossSalary),
+ deductSalary: parseNum(e.deductSalary),
+ netSalary: parseNum(e.netSalary),
+ remark: e.remark ?? "",
+ }));
+ proxy.$modal.msgSuccess("鐢熸垚鎴愬姛");
+ });
+};
- const handleGenerate = () => {
- if (!form.value.deptIds?.length) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨閮ㄩ棬");
- return;
- }
- if (!form.value.salaryMonth) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨宸ヨ祫鏈堜唤");
- return;
- }
- const payload = {
- ids: form.value.deptIds,
- date: form.value.salaryMonth,
- };
- staffSalaryMainCalculateSalary(payload).then(res => {
- const list = Array.isArray(res?.data) ? res.data : [];
- if (!list.length) {
- proxy.$modal.msgWarning("鏈绠楀埌宸ヨ祫鏁版嵁");
- return;
- }
- resetRecalcState();
- employeeList.value = list.map(e => normalizeEmployeeRow(e));
- proxy.$modal.msgSuccess("鐢熸垚鎴愬姛");
+const handleClear = () => {
+ proxy.$modal.confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵").then(() => {
+ employeeList.value = [];
+ }).catch(() => {});
+};
+
+const handleTaxForm = () => {
+ taxDialogVisible.value = true;
+};
+
+const submitForm = () => {
+ formRef.value?.validate((valid) => {
+ if (!valid) return;
+ saveData(3); // 纭鎻愪氦锛岀姸鎬佷负3锛堝緟瀹℃牳锛�
+ });
+};
+
+const saveDraft = () => {
+ formRef.value?.validate((valid) => {
+ if (!valid) return;
+ saveData(1); // 淇濆瓨鑽夌锛岀姸鎬佷负1锛堣崏绋匡級
+ });
+};
+
+const saveData = (status) => {
+ const payload = {
+ id: form.value.id,
+ salaryTitle: form.value.salaryTitle,
+ deptIds: form.value.deptIds?.length ? form.value.deptIds.join(",") : "",
+ salaryMonth: form.value.salaryMonth,
+ remark: form.value.remark,
+ payBank: form.value.payBank,
+ auditUserId: form.value.auditUserId,
+ auditUserName: auditUserName.value,
+ totalSalary: totalSalary.value,
+ staffSalaryDetailList: employeeList.value.map((e) => ({
+ staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+ staffName: e.staffName,
+ postName: e.postName ?? "",
+ deptName: e.deptName ?? "",
+ basicSalary: parseNum(e.basicSalary),
+ pieceSalary: parseNum(e.pieceSalary),
+ hourlySalary: parseNum(e.hourlySalary),
+ otherIncome: parseNum(e.otherIncome),
+ socialPersonal: parseNum(e.socialPersonal),
+ fundPersonal: parseNum(e.fundPersonal),
+ otherDeduct: parseNum(e.otherDeduct),
+ salaryTax: parseNum(e.salaryTax),
+ grossSalary: parseNum(e.grossSalary),
+ deductSalary: parseNum(e.deductSalary),
+ netSalary: parseNum(e.netSalary),
+ remark: e.remark ?? "",
+ })),
+ };
+ if (props.operationType === "add") {
+ staffSalaryMainAdd({ ...payload, status }).then(() => {
+ proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
+ closeDia();
});
- };
-
- const handleClear = () => {
- proxy.$modal
- .confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵")
- .then(() => {
- resetRecalcState();
- employeeList.value = [];
- })
- .catch(() => {});
- };
-
- const handleTaxForm = () => {
- taxDialogVisible.value = true;
- };
-
- const submitForm = () => {
- formRef.value?.validate(valid => {
- if (!valid) return;
- saveData(3); // 纭鎻愪氦锛岀姸鎬佷负3锛堝緟瀹℃牳锛�
+ } else {
+ staffSalaryMainUpdate({ ...payload, status }).then(() => {
+ proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
+ closeDia();
});
- };
+ }
+};
- const saveDraft = () => {
- formRef.value?.validate(valid => {
- if (!valid) return;
- saveData(1); // 淇濆瓨鑽夌锛岀姸鎬佷负1锛堣崏绋匡級
- });
- };
+const closeDia = () => {
+ dialogVisible.value = false;
+ emit("close");
+};
- const saveData = status => {
- const payload = {
- id: form.value.id,
- salaryTitle: form.value.salaryTitle,
- deptIds: form.value.deptIds?.length ? form.value.deptIds.join(",") : "",
- salaryMonth: form.value.salaryMonth,
- remark: form.value.remark,
- payBank: form.value.payBank,
- auditUserId: form.value.auditUserId,
- auditUserName: auditUserName.value,
- totalSalary: totalSalary.value,
- staffSalaryDetailList: employeeList.value.map(e => ({
- staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
- staffName: e.staffName,
- postName: e.postName ?? "",
- deptName: e.deptName ?? "",
- basicSalary: parseNum(e.basicSalary),
- pieceSalary: parseNum(e.pieceSalary),
- hourlySalary: parseNum(e.hourlySalary),
- otherIncome: parseNum(e.otherIncome),
- socialPersonal: parseNum(e.socialPersonal),
- fundPersonal: parseNum(e.fundPersonal),
- otherDeduct: parseNum(e.otherDeduct),
- socialSupplementAmount: parseNum(e.socialSupplementAmount),
- salaryTax: parseNum(e.salaryTax),
- grossSalary: parseNum(e.grossSalary),
- deductSalary: parseNum(e.deductSalary),
- netSalary: parseNum(e.netSalary),
- remark: e.remark ?? "",
- })),
- };
- if (props.operationType === "add") {
- staffSalaryMainAdd({ ...payload, status }).then(() => {
- proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
- closeDia();
- });
- } else {
- staffSalaryMainUpdate({ ...payload, status }).then(() => {
- proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
- closeDia();
- });
- }
- };
-
- const closeDia = () => {
- resetRecalcState();
- dialogVisible.value = false;
- emit("close");
- };
-
- defineExpose({ openDialog });
+defineExpose({ openDialog });
</script>
<style scoped>
- .form-dia-body {
- padding: 0;
- }
- .card-title-line {
- color: #f56c6c;
- margin-right: 4px;
- }
- .form-card {
- margin-bottom: 16px;
- }
- .form-card :deep(.el-card__header) {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 12px 16px;
- }
- .card-title {
- font-weight: 500;
- }
- .card-collapse {
- color: #999;
- cursor: pointer;
- }
- .toolbar {
- margin-bottom: 16px;
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- }
- .employee-table-wrap {
- position: relative;
- min-height: 120px;
- }
- .table-empty {
- text-align: center;
- padding: 24px;
- color: #999;
- font-size: 14px;
- }
- .add-person-tree {
- max-height: 360px;
- overflow-y: auto;
- padding: 8px 0;
- }
- .tax-desc {
- margin-bottom: 12px;
- font-size: 14px;
- color: #606266;
- }
- .dialog-footer {
- text-align: right;
- }
- .salary-total {
- margin-top: 16px;
- padding: 12px 16px;
- background-color: #f5f7fa;
- border-radius: 4px;
- text-align: right;
- font-size: 16px;
- }
- .salary-total .total-label {
- color: #606266;
- margin-right: 8px;
- }
- .salary-total .total-value {
- color: #f56c6c;
- font-weight: bold;
- font-size: 18px;
- }
+.form-dia-body {
+ padding: 0;
+}
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+.form-card {
+ margin-bottom: 16px;
+}
+.form-card :deep(.el-card__header) {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+}
+.card-title {
+ font-weight: 500;
+}
+.card-collapse {
+ color: #999;
+ cursor: pointer;
+}
+.toolbar {
+ margin-bottom: 16px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.employee-table-wrap {
+ position: relative;
+ min-height: 120px;
+}
+.table-empty {
+ text-align: center;
+ padding: 24px;
+ color: #999;
+ font-size: 14px;
+}
+.add-person-tree {
+ max-height: 360px;
+ overflow-y: auto;
+ padding: 8px 0;
+}
+.tax-desc {
+ margin-bottom: 12px;
+ font-size: 14px;
+ color: #606266;
+}
+.dialog-footer {
+ text-align: right;
+}
+.salary-total {
+ margin-top: 16px;
+ padding: 12px 16px;
+ background-color: #f5f7fa;
+ border-radius: 4px;
+ text-align: right;
+ font-size: 16px;
+}
+.salary-total .total-label {
+ color: #606266;
+ margin-right: 8px;
+}
+.salary-total .total-value {
+ color: #f56c6c;
+ font-weight: bold;
+ font-size: 18px;
+}
</style>
diff --git a/src/views/personnelManagement/monthlyStatistics/index.vue b/src/views/personnelManagement/monthlyStatistics/index.vue
index f581070..4ac9e97 100644
--- a/src/views/personnelManagement/monthlyStatistics/index.vue
+++ b/src/views/personnelManagement/monthlyStatistics/index.vue
@@ -107,7 +107,7 @@
nextTick,
} from "vue";
import { ElMessageBox } from "element-plus";
-import useUserStore from "@/store/modules/user";
+import Cookies from "js-cookie";
import FormDia from "./components/formDia.vue";
import BankSettingDia from "./components/bankSettingDia.vue";
import AuditDia from "./components/auditDia.vue";
@@ -167,12 +167,7 @@
{
name: "瀹℃牳",
type: "text",
- disabled: (row) => {
- const currentUserId = Number(userStore.id);
- const auditUserId = Number(row?.auditUserId);
- // 鐘舵�佷笉鏄緟瀹℃牳 鎴� 褰撳墠鐢ㄦ埛涓嶆槸鎸囧畾鐨勫鏍镐汉锛屽垯绂佺敤瀹℃牳鎸夐挳
- return Number(row?.status) !== 3 || !currentUserId || currentUserId !== auditUserId;
- },
+ disabled: (row) => Number(row?.status) !== 3,
clickFun: (row) => openAudit(row),
},
{
@@ -198,7 +193,6 @@
const operationType = ref("add");
const currentRow = ref({});
const { proxy } = getCurrentInstance();
-const userStore = useUserStore();
const bankSetting = ref({});
const bankDialogVisible = ref(false);
const bankDiaRef = ref(null);
@@ -384,8 +378,8 @@
const handleExport = () => {
proxy.download(
- "/staffSalaryMain/export",
- { ...searchForm.value },
+ "/compensationPerformance/export",
+ { ...searchForm.value, current: page.current, size: page.size },
"宸ヨ祫琛�.xlsx"
);
};
@@ -410,4 +404,4 @@
.table_list {
margin-top: 20px;
}
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/personnelManagement/socialSecuritySet/components/formDia.vue b/src/views/personnelManagement/socialSecuritySet/components/formDia.vue
index a8cba91..71f5e61 100644
--- a/src/views/personnelManagement/socialSecuritySet/components/formDia.vue
+++ b/src/views/personnelManagement/socialSecuritySet/components/formDia.vue
@@ -1,31 +1,34 @@
<template>
<div>
- <FormDialog v-model="dialogFormVisible"
- :operation-type="operationType"
- :title="dialogTitle"
- width="80%"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia">
- <el-form ref="formRef"
- :model="form"
- :rules="rules"
- label-position="top">
+ <FormDialog
+ v-model="dialogFormVisible"
+ :operation-type="operationType"
+ :title="dialogTitle"
+ width="80%"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia"
+ >
+ <el-form ref="formRef" :model="form" :rules="rules" label-position="top">
<el-row :gutter="24">
<!-- 宸︿晶锛氶�傜敤浜哄憳 -->
<el-col :span="8">
- <el-form-item label="閫傜敤浜哄憳锛�"
- prop="deptIds">
+ <el-form-item label="閫傜敤浜哄憳锛�" prop="deptIds">
<div class="dept-checkbox-wrap">
- <el-checkbox-group v-model="form.deptIds"
- :disabled="isDetail">
- <div v-for="dept in deptList"
- :key="dept.deptId"
- class="dept-checkbox-item">
+ <el-checkbox-group
+ v-model="form.deptIds"
+ :disabled="isDetail"
+ >
+ <div
+ v-for="dept in deptList"
+ :key="dept.deptId"
+ class="dept-checkbox-item"
+ >
<el-checkbox :value="dept.deptId">
{{ dept.deptName }}
- <span v-if="dept.personCount != null"
- class="dept-count">{{ dept.personCount }}浜�</span>
+ <span v-if="dept.personCount != null" class="dept-count"
+ >{{ dept.personCount }}浜�</span
+ >
</el-checkbox>
</div>
</el-checkbox-group>
@@ -35,117 +38,124 @@
<!-- 鍙充晶锛氬熀纭�淇℃伅 + 淇濋櫓绫诲瀷 -->
<el-col :span="16">
<!-- 鍩虹淇℃伅 -->
- <el-card class="form-card"
- shadow="never">
+ <el-card class="form-card" shadow="never">
<template #header>
<span class="card-title"><span class="card-title-line">|</span> 鍩虹淇℃伅</span>
- <el-icon class="card-collapse">
- <ArrowUp />
- </el-icon>
+ <el-icon class="card-collapse"><ArrowUp /></el-icon>
</template>
- <el-form-item label="鏂规鏍囬锛�"
- prop="title">
- <el-input v-model="form.title"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="isDetail" />
+ <el-form-item label="鏂规鏍囬锛�" prop="title">
+ <el-input
+ v-model="form.title"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="isDetail"
+ />
</el-form-item>
- <el-form-item label="澶囨敞锛�"
- prop="remark">
- <el-input v-model="form.remark"
- type="textarea"
- :rows="2"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="isDetail" />
+ <el-form-item label="澶囨敞锛�" prop="remark">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="isDetail"
+ />
</el-form-item>
</el-card>
+
<!-- 淇濋櫓绫诲瀷 -->
- <el-card class="form-card"
- shadow="never">
+ <el-card class="form-card" shadow="never">
<template #header>
<span class="card-title"><span class="card-title-line">|</span> 淇濋櫓绫诲瀷</span>
- <el-button v-if="!isDetail"
- type="primary"
- size="small"
- @click="addInsuranceBenefit">
+ <el-button
+ v-if="!isDetail"
+ type="primary"
+ size="small"
+ @click="addInsuranceBenefit"
+ >
娣诲姞淇濋櫓绂忓埄
</el-button>
</template>
<el-row :gutter="16">
- <el-col v-for="(item, index) in form.insuranceBenefits"
- :key="item._key"
- :span="12">
+ <el-col
+ v-for="(item, index) in form.insuranceBenefits"
+ :key="item._key"
+ :span="12"
+ >
<div class="insurance-benefit-card">
<div class="insurance-benefit-title">
淇濋櫓绂忓埄{{ index + 1 }}
- <el-button v-if="!isDetail && form.insuranceBenefits.length > 1"
- type="danger"
- link
- size="small"
- class="card-delete-btn"
- @click="removeInsuranceBenefit(index)">
+ <el-button
+ v-if="!isDetail && form.insuranceBenefits.length > 1"
+ type="danger"
+ link
+ size="small"
+ class="card-delete-btn"
+ @click="removeInsuranceBenefit(index)"
+ >
鍒犻櫎
</el-button>
</div>
- <el-form-item :prop="'insuranceBenefits.' + index + '.insuranceType'"
- label="淇濋櫓绫诲瀷锛�"
- label-width="100px"
- :rules="[{ required: true, message: '璇烽�夋嫨淇濋櫓绫诲瀷', trigger: 'blur' }]"
+ <el-form-item
+ :prop="'insuranceBenefits.' + index + '.insuranceType'"
+ label="淇濋櫓绫诲瀷锛�"
+ label-width="100px"
>
- <el-select v-model="item.insuranceType"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%"
- :disabled="isDetail">
- <el-option v-for="opt in insuranceTypeOptions"
- :key="opt.value"
- :label="opt.label"
- :value="opt.value" />
+ <el-select
+ v-model="item.insuranceType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ :disabled="isDetail"
+ >
+ <el-option
+ v-for="opt in insuranceTypeOptions"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
</el-select>
</el-form-item>
- <el-form-item label="缂磋垂鍩烘暟锛�"
- label-width="100px"
- :prop="'insuranceBenefits.' + index + '.paymentBase'"
- :rules="[{ validator: validatePaymentBase, trigger: 'blur' }]">
+ <el-form-item label="缂磋垂鍩烘暟锛�" label-width="100px">
<div class="base-salary-wrap">
- <el-input v-model="item.paymentBase"
- placeholder="鏍规嵁鍩烘湰宸ヨ祫缂寸撼"
- clearable
- style="width: 120px"
- type="number"
- :disabled="isDetail || item.useBasicSalary"
- @input="handlePaymentBaseInput(item)" />
- <el-checkbox v-model="item.useBasicSalary"
- @change="(val) => handleUseBasicSalaryChange(item, index)"
- :disabled="isDetail">
+ <el-input
+ v-model="item.paymentBase"
+ placeholder="鏍规嵁鍩烘湰宸ヨ祫缂寸撼"
+ clearable
+ style="width: 120px"
+ type="number"
+ :disabled="isDetail || item.useBasicSalary"
+ @input="handlePaymentBaseInput(item)"
+ />
+ <el-checkbox
+ v-model="item.useBasicSalary"
+ @change="handleUseBasicSalaryChange(item)"
+ :disabled="isDetail"
+ >
璋冪敤鍩烘湰宸ヨ祫
</el-checkbox>
</div>
</el-form-item>
- <el-form-item label="涓汉缂磋垂姣斾緥锛�"
- label-width="100px"
- :prop="'insuranceBenefits.' + index + '.personalRatio'"
- :rules="[{ required: true, message: '璇疯緭鍏ヤ釜浜虹即璐规瘮渚�', trigger: 'blur' }]">
+ <el-form-item label="涓汉缂磋垂姣斾緥锛�" label-width="100px">
<div class="personal-ratio-wrap">
- <el-input v-model="item.personalRatio"
- placeholder="璇疯緭鍏�"
- clearable
- style="width: 100px"
- type="number"
- :disabled="isDetail"
- :min="0"
- @input="handlePersonalRatioInput(item)" />
+ <el-input
+ v-model="item.personalRatio"
+ placeholder="璇疯緭鍏�"
+ clearable
+ style="width: 100px"
+ type="number"
+ :disabled="isDetail"
+ />
<span class="ratio-unit">(%)</span>
<span class="ratio-plus">+</span>
- <el-input v-model="item.personalFixed"
- placeholder="璇疯緭鍏�"
- clearable
- style="width: 100px"
- type="number"
- :disabled="isDetail"
- :min="0"
- @input="handlePersonalFixedInput(item)" />
+ <el-input
+ v-model="item.personalFixed"
+ placeholder="璇疯緭鍏�"
+ clearable
+ style="width: 100px"
+ type="number"
+ :disabled="isDetail"
+ />
</div>
</el-form-item>
</div>
@@ -160,345 +170,301 @@
</template>
<script setup>
- import {
- ref,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
- computed,
- } from "vue";
- import FormDialog from "@/components/Dialog/FormDialog.vue";
- import { ArrowUp } from "@element-plus/icons-vue";
- import { listDept } from "@/api/system/dept.js";
- import {
- socialSecurityAdd,
- socialSecurityUpdate,
- } from "@/api/personnelManagement/socialSecuritySet.js";
+import { ref, reactive, toRefs, getCurrentInstance, nextTick, computed } from "vue";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ArrowUp } from "@element-plus/icons-vue";
+import { listDept } from "@/api/system/dept.js";
+import { socialSecurityAdd, socialSecurityUpdate } from "@/api/personnelManagement/socialSecuritySet.js";
- const emit = defineEmits(["close"]);
- const { proxy } = getCurrentInstance();
+const emit = defineEmits(["close"]);
+const { proxy } = getCurrentInstance();
- const dialogFormVisible = ref(false);
- const operationType = ref("add");
- const formRef = ref(null);
- const deptList = ref([]);
+const dialogFormVisible = ref(false);
+const operationType = ref("add");
+const formRef = ref(null);
+const deptList = ref([]);
- const isDetail = computed(() => operationType.value === "detail");
+const isDetail = computed(() => operationType.value === "detail");
- const dialogTitle = () =>
- operationType.value === "add"
- ? "鏂板鏂规"
- : operationType.value === "edit"
- ? "缂栬緫鏂规"
- : "鏂规璇︽儏";
+const dialogTitle = () =>
+ operationType.value === "add"
+ ? "鏂板鏂规"
+ : operationType.value === "edit"
+ ? "缂栬緫鏂规"
+ : "鏂规璇︽儏";
- // 淇濋櫓绫诲瀷閫夐」锛堝彲鎸夊瓧鍏告浛鎹級
- const insuranceTypeOptions = [
- { label: "鍏昏�佷繚闄�", value: "鍏昏�佷繚闄�" },
- { label: "鍖荤枟淇濋櫓", value: "鍖荤枟淇濋櫓" },
- { label: "澶变笟淇濋櫓", value: "澶变笟淇濋櫓" },
- { label: "宸ヤ激淇濋櫓", value: "宸ヤ激淇濋櫓" },
- { label: "鐢熻偛淇濋櫓", value: "鐢熻偛淇濋櫓" },
- { label: "鍏Н閲�", value: "鍏Н閲�" },
- ];
+// 淇濋櫓绫诲瀷閫夐」锛堝彲鎸夊瓧鍏告浛鎹級
+const insuranceTypeOptions = [
+ { label: "鍏昏�佷繚闄�", value: "鍏昏�佷繚闄�" },
+ { label: "鍖荤枟淇濋櫓", value: "鍖荤枟淇濋櫓" },
+ { label: "澶变笟淇濋櫓", value: "澶变笟淇濋櫓" },
+ { label: "宸ヤ激淇濋櫓", value: "宸ヤ激淇濋櫓" },
+ { label: "鐢熻偛淇濋櫓", value: "鐢熻偛淇濋櫓" },
+ { label: "鍏Н閲�", value: "鍏Н閲�" },
+];
- const defaultBenefit = () => ({
- _key: Math.random().toString(36).slice(2),
- insuranceType: "",
- paymentBase: "",
- useBasicSalary: false,
- personalRatio: "",
- personalFixed: "",
- });
+const defaultBenefit = () => ({
+ _key: Math.random().toString(36).slice(2),
+ insuranceType: "",
+ paymentBase: "",
+ useBasicSalary: false,
+ personalRatio: "",
+ personalFixed: "",
+});
- const data = reactive({
- form: {
- id: undefined,
- title: "",
- remark: "",
- deptIds: [],
- insuranceBenefits: [defaultBenefit()],
- },
- rules: {
- title: [{ required: true, message: "璇疯緭鍏ユ柟妗堟爣棰�", trigger: "blur" }],
- deptIds: [
- {
- required: true,
- type: "array",
- min: 1,
- message: "璇疯嚦灏戦�夋嫨涓�涓�傜敤閮ㄩ棬",
- trigger: "change",
- },
- ],
- },
- });
- const { form, rules } = toRefs(data);
+const data = reactive({
+ form: {
+ id: undefined,
+ title: "",
+ remark: "",
+ deptIds: [],
+ insuranceBenefits: [defaultBenefit()],
+ },
+ rules: {
+ title: [{ required: true, message: "璇疯緭鍏ユ柟妗堟爣棰�", trigger: "blur" }],
+ deptIds: [
+ {
+ required: true,
+ type: "array",
+ min: 1,
+ message: "璇疯嚦灏戦�夋嫨涓�涓�傜敤閮ㄩ棬",
+ trigger: "change",
+ },
+ ],
+ },
+});
+const { form, rules } = toRefs(data);
- function flattenDept(tree, list = []) {
- if (!tree || !tree.length) return list;
- tree.forEach(node => {
- list.push({
- deptId: node.deptId,
- deptName: node.deptName,
- personCount: node.personCount ?? null,
- });
- if (node.children && node.children.length) {
- flattenDept(node.children, list);
- }
+function flattenDept(tree, list = []) {
+ if (!tree || !tree.length) return list;
+ tree.forEach((node) => {
+ list.push({
+ deptId: node.deptId,
+ deptName: node.deptName,
+ personCount: node.personCount ?? null,
});
- return list;
+ if (node.children && node.children.length) {
+ flattenDept(node.children, list);
+ }
+ });
+ return list;
+}
+
+const loadDeptList = () => {
+ listDept().then((res) => {
+ const tree = res.data ?? [];
+ deptList.value = flattenDept(tree);
+ });
+};
+
+const addInsuranceBenefit = () => {
+ form.value.insuranceBenefits.push(defaultBenefit());
+};
+
+const removeInsuranceBenefit = (index) => {
+ form.value.insuranceBenefits.splice(index, 1);
+};
+
+const handleUseBasicSalaryChange = (item) => {
+ if (item.useBasicSalary) {
+ item.paymentBase = "";
}
+};
- const loadDeptList = () => {
- listDept().then(res => {
- const tree = res.data ?? [];
- deptList.value = flattenDept(tree);
- });
+const handlePaymentBaseInput = (item) => {
+ if (item.paymentBase !== "" && item.paymentBase != null) {
+ item.useBasicSalary = false;
+ }
+};
+
+const resetForm = () => {
+ form.value = {
+ id: undefined,
+ title: "",
+ remark: "",
+ deptIds: [],
+ insuranceBenefits: [defaultBenefit()],
};
+};
- const addInsuranceBenefit = () => {
- form.value.insuranceBenefits.push(defaultBenefit());
- };
-
- const removeInsuranceBenefit = index => {
- form.value.insuranceBenefits.splice(index, 1);
- };
-
- const handleUseBasicSalaryChange = (item, index) => {
- if (item.useBasicSalary) {
- item.paymentBase = "";
- }
- nextTick(() => {
- formRef.value?.validateField(`insuranceBenefits.${index}.paymentBase`);
- });
- };
-
- const handlePaymentBaseInput = item => {
- if (item.paymentBase !== "" && item.paymentBase != null) {
- item.useBasicSalary = false;
- }
- };
-
- const handlePersonalRatioInput = item => {
- if (item.personalRatio !== "" && item.personalRatio != null) {
- const value = Number(item.personalRatio);
- if (value < 0) {
- item.personalRatio = "";
- }
- }
- };
-
- const handlePersonalFixedInput = item => {
- if (item.personalFixed !== "" && item.personalFixed != null) {
- const value = Number(item.personalFixed);
- if (value < 0) {
- item.personalFixed = "";
- }
- }
- };
-
- const validatePaymentBase = (rule, value, callback) => {
- const match = rule.field.match(/insuranceBenefits\.(\d+)\.paymentBase/);
- if (match) {
- const index = parseInt(match[1], 10);
- const item = form.value.insuranceBenefits[index];
- if (item && !item.useBasicSalary && (!value || value === "")) {
- callback(new Error("璇疯緭鍏ョ即璐瑰熀鏁�"));
- } else {
- callback();
- }
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ loadDeptList();
+ resetForm();
+ if ((type === "edit" || type === "detail") && row) {
+ const d = row || {};
+ form.value.id = d.id;
+ form.value.title = d.title;
+ form.value.remark = d.remark ?? "";
+ // deptIds 鍚庣鍙兘鏄�楀彿鍒嗛殧瀛楃涓叉垨鏁扮粍锛岃繖閲岀粺涓�杞负鏁扮粍骞跺敖閲忚繕鍘熸暟鍊肩被鍨�
+ if (d.deptIds) {
+ form.value.deptIds = String(d.deptIds)
+ .split(",")
+ .filter((v) => v !== "")
+ .map((v) => {
+ const num = Number(v);
+ return Number.isNaN(num) ? v : num;
+ });
} else {
- callback();
+ form.value.deptIds = [];
}
- };
+ const detailList = d.schemeInsuranceDetailList || [];
+ form.value.insuranceBenefits =
+ detailList.length > 0
+ ? detailList.map((b) => ({
+ _key: Math.random().toString(36).slice(2),
+ insuranceType: b.insuranceType || "",
+ paymentBase: b.paymentBase ?? "",
+ useBasicSalary: b.useBasicSalary === 2,
+ personalRatio: b.personalRatio ?? "",
+ personalFixed: b.personalFixed ?? "",
+ }))
+ : [defaultBenefit()];
+ }
+};
- const resetForm = () => {
- form.value = {
- id: undefined,
- title: "",
- remark: "",
- deptIds: [],
- insuranceBenefits: [defaultBenefit()],
- };
- };
-
- const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- loadDeptList();
- resetForm();
- if ((type === "edit" || type === "detail") && row) {
- const d = row || {};
- form.value.id = d.id;
- form.value.title = d.title;
- form.value.remark = d.remark ?? "";
- // deptIds 鍚庣鍙兘鏄�楀彿鍒嗛殧瀛楃涓叉垨鏁扮粍锛岃繖閲岀粺涓�杞负鏁扮粍骞跺敖閲忚繕鍘熸暟鍊肩被鍨�
- if (d.deptIds) {
- form.value.deptIds = String(d.deptIds)
- .split(",")
- .filter(v => v !== "")
- .map(v => {
- const num = Number(v);
- return Number.isNaN(num) ? v : num;
- });
- } else {
- form.value.deptIds = [];
- }
- const detailList = d.schemeInsuranceDetailList || [];
- form.value.insuranceBenefits =
- detailList.length > 0
- ? detailList.map(b => ({
- _key: Math.random().toString(36).slice(2),
- insuranceType: b.insuranceType || "",
- paymentBase: b.paymentBase ?? "",
- useBasicSalary: b.useBasicSalary === 2,
- personalRatio: b.personalRatio ?? "",
- personalFixed: b.personalFixed ?? "",
- }))
- : [defaultBenefit()];
- }
- };
-
- const submitForm = () => {
- // 璇︽儏妯″紡涓嬩笉鎻愪氦锛屽彧鍏抽棴寮圭獥
- if (operationType.value === "detail") {
- closeDia();
- return;
- }
- formRef.value?.validate(valid => {
- if (!valid) return;
- const deptIds =
- Array.isArray(form.value.deptIds) && form.value.deptIds.length
- ? form.value.deptIds.join(",")
- : "";
- const schemeInsuranceDetailList = (form.value.insuranceBenefits || []).map(
- ({ _key, ...rest }) => ({
- ...rest,
- useBasicSalary: rest.useBasicSalary ? 2 : 1,
- })
- );
- const insuranceTypes = schemeInsuranceDetailList
- .map(item => item.insuranceType)
- .filter(v => v)
- .join(",");
- // 閮ㄩ棬鍚嶇О锛屽涓娇鐢ㄩ�楀彿闅斿紑锛堟牴鎹�変腑鐨� deptIds 涓� deptList 璁$畻锛�
- const deptNames = (deptList.value || [])
- .filter(d =>
- (form.value.deptIds || []).some(id => String(id) === String(d.deptId))
+const submitForm = () => {
+ // 璇︽儏妯″紡涓嬩笉鎻愪氦锛屽彧鍏抽棴寮圭獥
+ if (operationType.value === "detail") {
+ closeDia();
+ return;
+ }
+ formRef.value?.validate((valid) => {
+ if (!valid) return;
+ const deptIds =
+ Array.isArray(form.value.deptIds) && form.value.deptIds.length
+ ? form.value.deptIds.join(",")
+ : "";
+ const schemeInsuranceDetailList = (form.value.insuranceBenefits || []).map(
+ ({ _key, ...rest }) => ({
+ ...rest,
+ useBasicSalary: rest.useBasicSalary ? 2 : 1,
+ })
+ );
+ const insuranceTypes = schemeInsuranceDetailList
+ .map((item) => item.insuranceType)
+ .filter((v) => v)
+ .join(",");
+ // 閮ㄩ棬鍚嶇О锛屽涓娇鐢ㄩ�楀彿闅斿紑锛堟牴鎹�変腑鐨� deptIds 涓� deptList 璁$畻锛�
+ const deptNames = (deptList.value || [])
+ .filter((d) =>
+ (form.value.deptIds || []).some(
+ (id) => String(id) === String(d.deptId)
)
- .map(d => d.deptName)
- .join(",");
- const submitData = {
- id: form.value.id,
- title: form.value.title,
- remark: form.value.remark ?? "",
- deptIds,
- insuranceTypes,
- deptNames,
- schemeInsuranceDetailList,
- };
- if (operationType.value === "add") {
- socialSecurityAdd(submitData).then(() => {
- proxy.$modal.msgSuccess("鏂板鎴愬姛");
- closeDia();
- });
- } else {
- socialSecurityUpdate(submitData).then(() => {
- proxy.$modal.msgSuccess("淇敼鎴愬姛");
- closeDia();
- });
- }
- });
- };
+ )
+ .map((d) => d.deptName)
+ .join(",");
+ const submitData = {
+ id: form.value.id,
+ title: form.value.title,
+ remark: form.value.remark ?? "",
+ deptIds,
+ insuranceTypes,
+ deptNames,
+ schemeInsuranceDetailList,
+ };
+ if (operationType.value === "add") {
+ socialSecurityAdd(submitData).then(() => {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛");
+ closeDia();
+ });
+ } else {
+ socialSecurityUpdate(submitData).then(() => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛");
+ closeDia();
+ });
+ }
+ });
+};
- const closeDia = () => {
- proxy.resetForm?.("formRef");
- dialogFormVisible.value = false;
- emit("close");
- };
+const closeDia = () => {
+ proxy.resetForm?.("formRef");
+ dialogFormVisible.value = false;
+ emit("close");
+};
- defineExpose({ openDialog });
+defineExpose({ openDialog });
</script>
<style scoped>
- .card-title-line {
- color: #f56c6c;
- margin-right: 4px;
- }
- .form-card {
- margin-bottom: 16px;
- }
- .form-card :deep(.el-card__header) {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 12px 16px;
- }
- .card-title {
- font-weight: 500;
- }
- .card-collapse {
- color: #999;
- cursor: pointer;
- }
- .dept-checkbox-wrap {
- max-height: 320px;
- overflow-y: auto;
- padding: 8px 0;
- border: 1px solid var(--el-border-color);
- border-radius: 4px;
- background: #fff;
- }
- .dept-checkbox-item {
- padding: 6px 12px;
- }
- .dept-count {
- color: #909399;
- font-size: 12px;
- margin-left: 4px;
- }
- .insurance-benefit-card {
- border: 1px solid var(--el-border-color-lighter);
- border-radius: 4px;
- padding: 12px 16px;
- margin-bottom: 12px;
- background: #fafafa;
- }
- .insurance-benefit-title {
- font-size: 14px;
- margin-bottom: 12px;
- font-weight: 500;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- .card-delete-btn {
- margin-left: auto;
- }
- .checkbox-group-inline {
- display: flex;
- flex-wrap: wrap;
- gap: 16px;
- }
- .base-salary-wrap {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- gap: 8px;
- }
- .base-salary-text {
- color: #606266;
- font-size: 14px;
- }
- .personal-ratio-wrap {
- display: flex;
- align-items: center;
- gap: 8px;
- }
- .ratio-unit,
- .ratio-plus {
- color: #606266;
- font-size: 14px;
- }
-</style>
\ No newline at end of file
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+.form-card {
+ margin-bottom: 16px;
+}
+.form-card :deep(.el-card__header) {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+}
+.card-title {
+ font-weight: 500;
+}
+.card-collapse {
+ color: #999;
+ cursor: pointer;
+}
+.dept-checkbox-wrap {
+ max-height: 320px;
+ overflow-y: auto;
+ padding: 8px 0;
+ border: 1px solid var(--el-border-color);
+ border-radius: 4px;
+ background: #fff;
+}
+.dept-checkbox-item {
+ padding: 6px 12px;
+}
+.dept-count {
+ color: #909399;
+ font-size: 12px;
+ margin-left: 4px;
+}
+.insurance-benefit-card {
+ border: 1px solid var(--el-border-color-lighter);
+ border-radius: 4px;
+ padding: 12px 16px;
+ margin-bottom: 12px;
+ background: #fafafa;
+}
+.insurance-benefit-title {
+ font-size: 14px;
+ margin-bottom: 12px;
+ font-weight: 500;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.card-delete-btn {
+ margin-left: auto;
+}
+.checkbox-group-inline {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+}
+.base-salary-wrap {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 8px;
+}
+.base-salary-text {
+ color: #606266;
+ font-size: 14px;
+}
+.personal-ratio-wrap {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.ratio-unit,
+.ratio-plus {
+ color: #606266;
+ font-size: 14px;
+}
+</style>
diff --git a/src/views/procurementManagement/paymentLedger/index.vue b/src/views/procurementManagement/paymentLedger/index.vue
index 7fba9cb..b913032 100644
--- a/src/views/procurementManagement/paymentLedger/index.vue
+++ b/src/views/procurementManagement/paymentLedger/index.vue
@@ -42,20 +42,16 @@
prop="contractAmounts"
show-overflow-tooltip
:formatter="formattedNumber" />
- <el-table-column label="浠樻閲戦(鍏�)"
- prop="paymentAmount"
+ <el-table-column label="宸插叆搴撻噾棰�(鍏�)"
+ prop="shippedAmount"
show-overflow-tooltip
:formatter="formattedNumber" />
- <el-table-column label="閫�璐ч噾棰�(鍏�)"
- prop="returnAmount"
- show-overflow-tooltip
- :formatter="formattedNumber" />
- <el-table-column label="搴斾粯閲戦(鍏�)"
- prop="payableAmount"
+ <el-table-column label="鏈叆搴撻噾棰�(鍏�)"
+ prop="unshippedAmount"
show-overflow-tooltip>
<template #default="{ row, column }">
<el-text type="danger">
- {{ formattedNumber(row, column, row.payableAmount) }}
+ {{ formattedNumber(row, column, row.unshippedAmount) }}
</el-text>
</template>
</el-table-column>
@@ -83,7 +79,7 @@
@pagination="sonPaginationSearch">
<template #payableAmountSlot="{ row }">
<el-text type="danger">
- {{ parseFloat(row.payableAmount).toFixed(2) }}
+ {{ formatDecimal(row.unshippedAmount) }}
</el-text>
</template>
</PIMTable>
@@ -94,13 +90,14 @@
</template>
<script setup>
- import { ref, toRefs } from "vue";
+ import { ref, toRefs, reactive, getCurrentInstance } 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 { tableAmountFormatter, formatDecimal, buildAmountSummaryFormat } from "@/utils/numberFormat";
const tableData = ref([]);
const tableLoading = ref(false);
@@ -144,31 +141,19 @@
label: "鍚堝悓閲戦(鍏�)",
prop: "contractAmount",
width: 200,
- formatData: params => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
+ formatData: params => formatDecimal(params),
},
{
- label: "浠樻閲戦(鍏�)",
- prop: "paymentAmount",
+ label: "宸插叆搴撻噾棰�(鍏�)",
+ prop: "shippedAmount",
width: 200,
- formatData: params => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
+ formatData: params => formatDecimal(params),
},
{
- label: "閫�璐ч噾棰�(鍏�)",
- prop: "returnAmount",
- width: 200,
- formatData: params => {
- return params ? parseFloat(params).toFixed(2) : 0;
- },
- },
- {
- label: "搴斾粯閲戦(鍏�)",
+ label: "鏈叆搴撻噾棰�(鍏�)",
dataType: "slot",
width: 200,
- prop: "payableAmount",
+ prop: "unshippedAmount",
slot: "payableAmountSlot",
},
]);
@@ -182,31 +167,29 @@
const summarizeMainTable = param => {
return proxy.summarizeTable(
param,
- ["contractAmounts", "paymentAmount", "returnAmount", "payableAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
+ ["contractAmounts", "shippedAmount", "unshippedAmount"],
+ buildAmountSummaryFormat(
+ ["contractAmounts", "shippedAmount", "unshippedAmount"],
+ {
+ ticketsNum: { noDecimal: true },
+ futureTickets: { noDecimal: true },
+ }
+ )
);
};
// 瀛愯〃鍚堣鏂规硶
const summarizeMainTable1 = param => {
let summarizeTable = proxy.summarizeTable(
param,
- ["contractAmount", "invoiceAmount", "paymentAmount", "returnAmount"],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
+ ["contractAmount", "shippedAmount", "unshippedAmount"],
+ buildAmountSummaryFormat(
+ ["contractAmount", "shippedAmount", "unshippedAmount"],
+ {
+ 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;
};
/** 鎼滅储鎸夐挳鎿嶄綔 */
@@ -277,13 +260,7 @@
sonPage.size = pagination.limit;
getPaymenRecordtList(currentSupplierId.value);
};
- const formattedNumber = (row, column, cellValue) => {
- if (column.property !== "supplierName") {
- return parseFloat(cellValue).toFixed(2);
- } else {
- return cellValue;
- }
- };
+ const formattedNumber = tableAmountFormatter;
getList();
</script>
diff --git a/src/views/procurementManagement/procurementLedger/detail.vue b/src/views/procurementManagement/procurementLedger/detail.vue
new file mode 100644
index 0000000..80aa42b
--- /dev/null
+++ b/src/views/procurementManagement/procurementLedger/detail.vue
@@ -0,0 +1,246 @@
+<template>
+ <FormDialog v-model="visible" title="閲囪喘鍙拌处璇︽儏" width="70%" operation-type="detail" @close="handleClose">
+ <el-form :model="form" label-width="140px" label-position="top">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閲囪喘鍚堝悓鍙凤細">
+ <span class="readonly-text">{{ form.purchaseContractNumber || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ <el-col v-if="showSalesContractBinding" :span="12">
+ <el-form-item label="閿�鍞悎鍚屽彿锛�">
+ <span class="readonly-text">{{ form.salesContractNo || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細">
+ <span class="readonly-text">{{ form.supplierName || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="椤圭洰鍚嶇О锛�">
+ <span class="readonly-text">{{ form.projectName || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡锛�">
+ <span class="readonly-text">{{ form.paymentMethod || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绛捐鏃ユ湡锛�">
+ <span class="readonly-text">{{ form.executionDate || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="褰曞叆浜猴細">
+ <span class="readonly-text">{{ form.recorderName || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="褰曞叆鏃ユ湡锛�">
+ <span class="readonly-text">{{ form.entryDate || '--' }}</span>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <div style="font-weight: bold; margin: 10px 0; color: #f56c6c">
+ * 浜у搧淇℃伅锛�
+ </div>
+ <el-table :data="productData" border>
+ <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="鏁伴噺" prop="quantity" />
+ <el-table-column label="搴撳瓨棰勭暀鏁伴噺" prop="stockReservedQuantity" />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" />
+ <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" width="150" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" width="150" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" width="150" />
+ <template #append>
+ <div class="summary-row" v-if="productData.length > 0">
+ <div class="summary-label">鍚堣</div>
+ <div class="summary-value" style="width: 150px">
+ {{ formattedNumber(null, null, sumTaxInclusiveUnitPrice) }}
+ </div>
+ <div class="summary-value" style="width: 150px">
+ {{ formattedNumber(null, null, sumTaxInclusiveTotalPrice) }}
+ </div>
+ <div class="summary-value" style="width: 150px">
+ {{ formattedNumber(null, null, sumTaxExclusiveTotalPrice) }}
+ </div>
+ </div>
+ </template>
+ </el-table>
+
+ <el-row :gutter="30" style="margin-top: 20px;">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�">
+ <div class="readonly-text-area">{{ form.remarks || '--' }}</div>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="闄勪欢鏉愭枡锛�">
+ <div class="table-container" style="width: 100%;">
+ <el-table :data="fileList" border class="attachment-table" style="width: 100%;"
+ :height="fileList.length > 0 ? 'auto' : '120px'">
+ <el-table-column label="闄勪欢鍚嶇О" prop="originalFilename" show-overflow-tooltip min-width="200">
+ <template #default="scope">
+ {{ scope.row.name || scope.row.originalFilename || ('闄勪欢' + (scope.$index + 1)) }}
+ </template>
+ </el-table-column>
+ <el-table-column fixed="right" label="鎿嶄綔" :width="150" align="center">
+ <template #default="scope">
+ <el-button link type="primary" size="small" class="download-link"
+ @click="previewFile(scope.row.previewURL || scope.row.url)">
+ 棰勮
+ </el-button>
+ <el-button link type="primary" size="small" class="download-link"
+ @click="downloadFile(scope.row.downloadURL || scope.row.url)">
+ 涓嬭浇
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ </FormDialog>
+ <filePreview ref="filePreviewRef" />
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { ElMessage } from 'element-plus'
+import FormDialog from "@/components/Dialog/FormDialog.vue"
+import filePreview from '@/components/filePreview/index.vue'
+import { getPurchaseById } from "@/api/procurementManagement/procurementLedger"
+import { tableAmountFormatter } from '@/utils/numberFormat'
+
+const visible = ref(false)
+// 鏄惁鏄剧ず閿�鍞悎鍚屽彿缁戝畾
+const showSalesContractBinding = false
+const form = ref({})
+const productData = ref([])
+const fileList = ref([])
+const filePreviewRef = ref()
+
+const open = (id) => {
+ visible.value = true
+ getPurchaseById({ id: id, type: 2 }).then(res => {
+ form.value = res.data ? res.data : res || {}
+ productData.value = form.value.purchaseLedgerProductList || form.value.productData || []
+ fileList.value = form.value.storageBlobVOS || []
+ })
+}
+
+// 鏆撮湶 open 鏂规硶缁欑埗缁勪欢璋冪敤
+defineExpose({
+ open
+})
+
+const handleClose = () => {
+ visible.value = false
+ form.value = {}
+ productData.value = []
+ fileList.value = []
+}
+
+const formattedNumber = tableAmountFormatter
+
+const sumTaxInclusiveUnitPrice = computed(() => {
+ return productData.value.reduce((sum, item) => {
+ return sum + (Number(item.taxInclusiveUnitPrice) || 0)
+ }, 0)
+})
+
+const sumTaxInclusiveTotalPrice = computed(() => {
+ return productData.value.reduce((sum, item) => {
+ return sum + (Number(item.taxInclusiveTotalPrice) || 0)
+ }, 0)
+})
+
+const sumTaxExclusiveTotalPrice = computed(() => {
+ return productData.value.reduce((sum, item) => {
+ return sum + (Number(item.taxExclusiveTotalPrice) || 0)
+ }, 0)
+})
+
+const previewFile = (url) => {
+ if (url) {
+ filePreviewRef.value.open(url)
+ } else {
+ ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曢瑙�')
+ }
+}
+
+const downloadFile = (url) => {
+ window.open(url, "_blank")
+}
+</script>
+
+<style scoped>
+.readonly-text {
+ width: 100%;
+ padding: 0 12px;
+ background-color: #f5f7fa;
+ color: #606266;
+ border-radius: 4px;
+ border: 1px solid #e4e7ed;
+ box-sizing: border-box;
+ min-height: 32px;
+ line-height: 32px;
+ display: inline-block;
+}
+
+.readonly-text-area {
+ width: 100%;
+ padding: 8px 12px;
+ background-color: #f5f7fa;
+ color: #606266;
+ border-radius: 4px;
+ border: 1px solid #e4e7ed;
+ box-sizing: border-box;
+ min-height: 64px;
+ line-height: 1.5;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+.summary-row {
+ display: flex;
+ background-color: #f5f7fa;
+ font-weight: bold;
+ border-top: 1px solid #ebeef5;
+}
+
+.summary-label {
+ flex: 1;
+ text-align: right;
+ padding: 12px;
+ color: #606266;
+}
+
+.summary-value {
+ padding: 12px;
+ color: #606266;
+ border-left: 1px solid #ebeef5;
+}
+
+.table-container {
+ overflow-y: auto;
+ box-sizing: border-box;
+}
+</style>
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 7e1576b..6167e6c 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -2,63 +2,37 @@
<div class="app-container">
<div class="search_form">
<div>
- <el-form :model="searchForm"
- :inline="true">
+ <el-form :model="searchForm" :inline="true">
<el-form-item label="渚涘簲鍟嗗悕绉帮細">
- <el-input v-model="searchForm.supplierName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery" />
+ <el-input v-model="searchForm.supplierName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="閲囪喘鍚堝悓鍙凤細">
- <el-input v-model="searchForm.purchaseContractNumber"
- style="width: 240px"
- placeholder="璇疯緭鍏�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search" />
+ <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.salesContractNo"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery" />
+ <el-form-item v-if="showSalesContractBinding" label="閿�鍞悎鍚屽彿锛�">
+ <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="椤圭洰鍚嶇О锛�">
- <el-input v-model="searchForm.projectName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery" />
+ <el-input v-model="searchForm.projectName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
+ <el-date-picker v-model="searchForm.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="searchForm.stockInStatus"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 240px"
- @change="handleQuery">
- <el-option label="寰呭叆搴�"
- value="寰呭叆搴�" />
- <el-option label="鍏ュ簱涓�"
- value="鍏ュ簱涓�" />
- <el-option label="瀹屽叏鍏ュ簱"
- value="瀹屽叏鍏ュ簱" />
+ <el-select v-model="searchForm.stockInStatus" placeholder="璇烽�夋嫨" clearable style="width: 240px"
+ @change="handleQuery">
+ <el-option label="寰呭叆搴�" value="寰呭叆搴�" />
+ <el-option label="鍏ュ簱涓�" value="鍏ュ簱涓�" />
+ <el-option label="瀹屽叏鍏ュ簱" value="瀹屽叏鍏ュ簱" />
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary"
- @click="handleQuery"> 鎼滅储
+ <el-button type="primary" @click="handleQuery"> 鎼滅储
</el-button>
</el-form-item>
</el-form>
@@ -66,427 +40,213 @@
</div>
<div class="table_list">
<div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
- <el-button type="success"
- plain
- @click="handleBatchGenerate">鎵归噺鐢熸垚鏁版嵁</el-button>
- <el-button type="primary"
- @click="openForm('add')">鏂板鍙拌处</el-button>
- <el-button type="primary"
- plain
- @click="handleImport">瀵煎叆</el-button>
+ <el-button type="primary" @click="openForm('add')">鏂板鍙拌处</el-button>
+ <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎
</el-button>
+ <el-button type="warning" plain @click="handlePrint">鎵撳嵃鍗曟嵁</el-button>
</div>
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- show-summary
- :summary-method="summarizeMainTable"
- @expand-change="expandChange"
- height="calc(100vh - 21.5em)">
- <el-table-column align="center"
- type="selection"
- width="55" />
+ <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary :summary-method="summarizeMainTable"
+ @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="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel" />
- <el-table-column label="鍗曚綅"
- prop="unit" />
- <el-table-column label="鍏ュ簱瀹℃牳鐘舵��"
- prop="stockInApprovalStatus"
- width="120">
+ <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" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="鍏ュ簱瀹℃牳鐘舵��" prop="stockInApprovalStatus" width="120">
<template #default="scope">
- <el-tag :type="getStockInApprovalStatusType(scope.row.stockInApprovalStatus)"
- size="small">
+ <el-tag :type="getStockInApprovalStatusType(scope.row.stockInApprovalStatus)" size="small">
{{ scope.row.stockInApprovalStatus || '--' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column label="鏁伴噺"
- prop="quantity" />
- <el-table-column label="閿�鍞彂璐ф暟閲�"
- prop="shippedQuantity" />
- <el-table-column label="鍙敤鏁伴噺"
- prop="availableQuality" />
- <el-table-column label="閫�璐ф暟閲�"
- prop="returnQuantity" />
- <el-table-column label="绋庣巼(%)"
- prop="taxRate" />
- <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="quantity" />
+ <el-table-column label="鍙敤鏁伴噺" prop="availableQuality" />
+ <el-table-column label="閫�璐ф暟閲�" prop="returnQuality" />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" />
+ <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>
</template>
</el-table-column>
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="閲囪喘鍚堝悓鍙�"
- prop="purchaseContractNumber"
- width="160"
- show-overflow-tooltip />
- <el-table-column label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- width="160"
- show-overflow-tooltip />
- <el-table-column label="渚涘簲鍟嗗悕绉�"
- prop="supplierName"
- width="160"
- show-overflow-tooltip />
- <el-table-column label="椤圭洰鍚嶇О"
- prop="projectName"
- width="320"
- show-overflow-tooltip />
- <el-table-column label="瀹℃壒鐘舵��"
- prop="approvalStatus"
- width="100"
- show-overflow-tooltip>
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column label="閲囪喘鍚堝悓鍙�" prop="purchaseContractNumber" width="160" show-overflow-tooltip />
+ <el-table-column v-if="showSalesContractBinding" label="閿�鍞悎鍚屽彿" prop="salesContractNo" width="160" show-overflow-tooltip />
+ <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" width="160" show-overflow-tooltip />
+ <el-table-column label="椤圭洰鍚嶇О" prop="projectName" width="320" show-overflow-tooltip />
+ <el-table-column label="瀹℃壒鐘舵��" prop="approvalStatus" width="100" show-overflow-tooltip>
<template #default="scope">
- <el-tag :type="getApprovalStatusType(scope.row.approvalStatus)"
- size="small">
+ <el-tag :type="getApprovalStatusType(scope.row.approvalStatus)" size="small">
{{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column label="鍏ュ簱鐘舵��"
- prop="stockInStatus"
- width="100"
- show-overflow-tooltip>
+ <el-table-column label="鍏ュ簱鐘舵��" prop="stockInStatus" width="100" show-overflow-tooltip>
<template #default="scope">
- <el-tag :type="getStockInStatusType(scope.row.stockInStatus)"
- size="small">
+ <el-tag :type="getStockInStatusType(scope.row.stockInStatus)" size="small">
{{ scope.row.stockInStatus || '--' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column label="绛捐鏃ユ湡"
- prop="executionDate"
- width="100"
- show-overflow-tooltip />
- <el-table-column label="浠樻鏂瑰紡"
- width="100"
- prop="paymentMethod"
- show-overflow-tooltip />
- <el-table-column label="鍚堝悓閲戦(鍏�)"
- prop="contractAmount"
- width="200"
- show-overflow-tooltip
- :formatter="formattedNumber" />
- <el-table-column label="瀹為檯鍚堝悓閲戦(鍏�)"
- prop="netContractAmount"
- width="200"
- show-overflow-tooltip
- :formatter="(_, __, cellValue) => formatMoney(cellValue)" />
- <el-table-column label="褰曞叆浜�"
- prop="recorderName"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="褰曞叆鏃ユ湡"
- prop="entryDate"
- width="100"
- show-overflow-tooltip />
- <el-table-column label="澶囨敞"
- prop="remarks"
- width="200"
- show-overflow-tooltip />
- <el-table-column fixed="right"
- label="鎿嶄綔"
- width="120"
- align="center">
+ <el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="100" show-overflow-tooltip />
+ <el-table-column label="浠樻鏂瑰紡" width="100" prop="paymentMethod" show-overflow-tooltip />
+ <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" width="200" show-overflow-tooltip
+ :formatter="formattedNumber" />
+ <el-table-column label="褰曞叆浜�" prop="recorderName" width="120" show-overflow-tooltip />
+ <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="100" show-overflow-tooltip />
+ <el-table-column label="澶囨敞" prop="remarks" width="200" show-overflow-tooltip />
+ <el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
<template #default="scope">
- <el-button link
- type="primary"
- @click="openForm('edit', scope.row)"
- :disabled="scope.row.approvalStatus === 3">缂栬緫
+ <el-button link type="primary" @click="openForm('detail', scope.row)">璇︽儏
</el-button>
- <el-button link
- type="primary"
- @click="openFileDialog(scope.row)">闄勪欢</el-button>
+ <el-button link type="primary" @click="openForm('edit', scope.row)"
+ :disabled="scope.row.stockInStatus === '瀹屽叏鍏ュ簱'">缂栬緫
+ </el-button>
+ <el-button link type="primary" @click="openFileDialog(scope.row)">闄勪欢</el-button> <!--downloadOrder(scope.row.id) 涓嬭浇-->
</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" />
+ <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="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
- :width="'70%'"
- :operation-type="operationType"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
+ :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : operationType === 'edit' ? '缂栬緫閲囪喘鍙拌处椤甸潰' : '閲囪喘鍙拌处璇︽儏'" :width="'70%'"
+ :operation-type="operationType" @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="purchaseContractNumber">
- <el-input v-model="form.purchaseContractNumber"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="閲囪喘鍚堝悓鍙凤細" prop="purchaseContractNumber">
+ <el-input v-model="form.purchaseContractNumber" placeholder="璇疯緭鍏�" clearable />
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�"
- prop="salesLedgerId">
- <el-select v-model="form.salesLedgerId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- @change="salesLedgerChange">
- <el-option v-for="item in salesContractList"
- :key="item.id"
- :label="item.salesContractNo"
- :value="item.id" />
+ <el-col v-if="showSalesContractBinding" :span="12">
+ <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesLedgerId">
+ <el-select v-model="form.salesLedgerId" placeholder="璇烽�夋嫨" filterable clearable @change="salesLedgerChange">
+ <el-option v-for="item in salesContractList" :key="item.id" :label="item.salesContractNo" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="渚涘簲鍟嗗悕绉帮細"
- prop="supplierId">
- <el-select v-model="form.supplierId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable>
- <el-option v-for="item in supplierList"
- :key="item.id"
- :label="item.supplierName"
- :value="item.id">{{ item.supplierName + '---' + item.supplierType }}
- </el-option>
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierId">
+ <el-select v-model="form.supplierId" placeholder="璇烽�夋嫨" filterable clearable>
+ <el-option v-for="item in supplierList" :key="item.id" :label="item.supplierName" :value="item.id">{{ item.supplierType ? item.supplierName + '---' + item.supplierType : item.supplierName }}</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="椤圭洰鍚嶇О"
- prop="projectName">
- <el-input v-model="form.projectName"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="椤圭洰鍚嶇О" prop="projectName">
+ <el-input v-model="form.projectName" placeholder="璇疯緭鍏�" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绛捐鏃ユ湡锛�"
- prop="executionDate">
- <el-date-picker style="width: 100%"
- v-model="form.executionDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable />
+ <el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
+ <el-date-picker style="width: 100%" v-model="form.executionDate" 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="12">
- <el-form-item label="褰曞叆浜猴細"
- prop="recorderId">
- <el-select v-model="form.recorderId"
- placeholder="璇烽�夋嫨"
- clearable
- filterable>
- <el-option v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId" />
+ <el-form-item label="褰曞叆浜猴細" prop="recorderId">
+ <el-select v-model="form.recorderId" placeholder="璇烽�夋嫨" clearable filterable disabled>
+ <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select>
</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"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable />
+ <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
+ <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row>
- <el-form-item label="浜у搧淇℃伅锛�"
- prop="entryDate">
- <el-button type="primary"
- @click="openProductForm('add')">娣诲姞
- </el-button>
- <el-button plain
- type="danger"
- @click="deleteProduct">鍒犻櫎
- </el-button>
+ <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
+ <el-button type="primary" @click="openProductForm('add')">娣诲姞</el-button>
+ <el-button plain type="danger" @click="deleteProduct">鍒犻櫎</el-button>
</el-form-item>
- <div class="select-button-group"
- style="width: 500px; margin: 20px 0;"
- v-if="operationType === 'add'">
- <el-select filterable
- allow-create
- :reserve-keyword="true"
- :default-first-option="false"
- clearable
- v-model="templateName"
- :input-value="filterInputValue"
- @filter-change="onTemplateFilterChange"
- @change="onTemplateChange"
- @focus="getTemplateList"
- style="width: 500px;"
- placeholder="璇烽�夋嫨妯$増鎴栬�呰緭鍏ユ柊鐨勬ā鐗堝悕绉板悗閫夋嫨"
- class="no-arrow-select">
- <el-option v-for="item in templateList"
- :key="item.id || item.value"
- :label="item.templateName"
- :value="item.templateName">
+ <div class="select-button-group" style="width: 500px; margin: 20px 0;" v-if="operationType === 'add'">
+ <el-select filterable allow-create :reserve-keyword="true" :default-first-option="false" clearable
+ v-model="templateName" :input-value="filterInputValue" @filter-change="onTemplateFilterChange"
+ @change="onTemplateChange" @focus="getTemplateList" style="width: 500px;" placeholder="璇烽�夋嫨妯$増鎴栬�呰緭鍏ユ柊鐨勬ā鐗堝悕绉板悗閫夋嫨"
+ class="no-arrow-select">
+ <el-option v-for="item in templateList" :key="item.id || item.value" :label="item.templateName"
+ :value="item.templateName">
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>{{ item.templateName }}</span>
- <el-icon v-if="item.id"
- class="delete-icon"
- @click.stop="handleDeleteTemplate(item)"
- style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;">
+ <el-icon v-if="item.id" class="delete-icon" @click.stop="handleDeleteTemplate(item)"
+ style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;">
<Delete />
</el-icon>
</div>
</el-option>
</el-select>
<!-- 鎸夐挳锛氫笌 Select 楂樺害鍖归厤锛屽幓鎺夊乏渚ц竟妗嗭紝鏃犵紳琛旀帴 -->
- <el-button size="small"
- style="height: 32px;margin-left: 8px;"
- @click="handleButtonClick"
- :disabled="!templateName || templateName.trim() === '' || (!currentTemplateId && isTemplateNameDuplicate)">
+ <el-button size="small" style="height: 32px;margin-left: 8px;" @click="handleButtonClick"
+ :disabled="!templateName || templateName.trim() === '' || (!currentTemplateId && isTemplateNameDuplicate)">
淇濆瓨
</el-button>
</div>
</el-row>
- <el-table :data="productData"
- border
- @selection-change="productSelected"
- show-summary
- :summary-method="summarizeProTable">
- <el-table-column align="center"
- type="selection"
- width="55" />
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="浜у搧澶х被"
- prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel" />
- <el-table-column label="鍗曚綅"
- prop="unit"
- width="70" />
- <el-table-column label="鏁伴噺"
- prop="quantity"
- width="70" />
- <el-table-column label="搴撳瓨棰勮鏁伴噺"
- prop="warnNum"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="绋庣巼(%)"
- prop="taxRate"
- width="80" />
- <el-table-column label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber"
- width="150" />
- <el-table-column label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber"
- width="150" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber"
- width="150" />
- <el-table-column label="鏄惁璐ㄦ"
- prop="isChecked"
- width="150">
+ <el-table :data="productData" border @selection-change="productSelected" show-summary
+ :summary-method="summarizeProTable">
+ <el-table-column align="center" type="selection" width="55" />
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" width="70" />
+ <el-table-column label="鏁伴噺" prop="quantity" width="70" />
+<!-- <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" width="120" show-overflow-tooltip />-->
+ <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
+ <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" width="150" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" width="150" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" width="150" />
+ <el-table-column label="鏄惁璐ㄦ" prop="isChecked" width="150">
<template #default="scope">
<el-tag :type="scope.row.isChecked ? 'success' : 'info'">
{{ scope.row.isChecked ? '鏄�' : '鍚�' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column label="鍏ュ簱瀹℃牳鐘舵��"
- prop="stockInApprovalStatus"
- width="120">
+ <el-table-column label="鍏ュ簱瀹℃牳鐘舵��" prop="stockInApprovalStatus" width="120">
<template #default="scope">
- <el-tag :type="getStockInApprovalStatusType(scope.row.stockInApprovalStatus)"
- size="small">
+ <el-tag :type="getStockInApprovalStatusType(scope.row.stockInApprovalStatus)" size="small">
{{ scope.row.stockInApprovalStatus || '--' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column fixed="right"
- label="鎿嶄綔"
- min-width="60"
- align="center">
+ <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
<template #default="scope">
- <el-button link
- type="primary"
- @click="openProductForm('edit', scope.row, scope.$index)"
- :disabled="scope.row.stockInApprovalStatus === '瀹屽叏鍏ュ簱'">缂栬緫
+ <el-button link type="primary"
+ @click="openProductForm('edit', scope.row, scope.$index)"
+ :disabled="scope.row.stockInApprovalStatus === '瀹屽叏鍏ュ簱'">缂栬緫
</el-button>
</template>
</el-table-column>
</el-table>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="澶囨敞路锛�"
- prop="remarks">
- <el-input v-model="form.remarks"
- placeholder="璇疯緭鍏�"
- clearable
- type="textarea"
- :rows="2" />
+ <el-form-item label="澶囨敞路锛�" prop="remarks">
+ <el-input v-model="form.remarks" placeholder="璇疯緭鍏�" clearable type="textarea" :rows="2" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�"
- prop="purchaseLedgerFiles">
+ <el-form-item label="闄勪欢鏉愭枡锛�" prop="purchaseLedgerFiles">
<FileUpload v-model:file-list="fileList" />
</el-form-item>
</el-col>
@@ -494,24 +254,12 @@
</el-form>
</FormDialog>
<!-- 瀵煎叆寮圭獥 -->
- <FormDialog v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false">
- <el-upload ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag>
+ <FormDialog v-model="importUpload.open" :title="importUpload.title" :width="'600px'"
+ @close="importUpload.open = false" @confirm="submitImportFile" @cancel="importUpload.open = false">
+ <el-upload ref="importUploadRef" :limit="1" accept=".xlsx,.xls" :action="importUpload.url"
+ :headers="importUpload.headers" :before-upload="importUpload.beforeUpload" :on-success="importUpload.onSuccess"
+ :on-error="importUpload.onError" :on-progress="importUpload.onProgress" :on-change="importUpload.onChange"
+ :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
@@ -519,1548 +267,1576 @@
<template #tip>
<div class="el-upload__tip">
浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link
- type="primary"
- @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
+ <el-button link type="primary" @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
</div>
</template>
</el-upload>
</FormDialog>
- <FormDialog v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
- <el-form :model="productForm"
- label-width="140px"
- label-position="top"
- :rules="productRules"
- ref="productFormRef">
+ <FormDialog v-model="productFormVisible" :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'" :width="'40%'"
+ :operation-type="productOperationType" @close="closeProductDia" @confirm="submitProduct"
+ @cancel="closeProductDia">
+ <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
<el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="浜у搧澶х被锛�"
- prop="productId">
- <el-tree-select v-model="productForm.productId"
- placeholder="璇烽�夋嫨"
- clearable
- filterable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%" />
+ <el-col :span="12">
+ <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
+ <el-input v-model="productForm.productCategory"
+ placeholder="鐐瑰嚮閫夋嫨"
+ readonly
+ @click="showProductSelectDialog = true"
+ style="cursor:pointer" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-input v-model="productForm.specificationModel"
+ placeholder="鐐瑰嚮閫夋嫨"
+ readonly
+ @click="showProductSelectDialog = true"
+ style="cursor:pointer" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="瑙勬牸鍨嬪彿锛�"
- prop="productModelId">
- <el-select v-model="productForm.productModelId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- @change="getProductModel">
- <el-option v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id" />
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input v-model="productForm.unit" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绋庣巼(%)锛�" prop="taxRate">
+ <el-select v-model="productForm.taxRate" placeholder="璇烽�夋嫨" clearable @change="mathNum">
+ <el-option v-for="dict in tax_rate" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍗曚綅锛�"
- prop="unit">
- <el-input v-model="productForm.unit"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
+ <el-input-number v-model="productForm.taxInclusiveUnitPrice" :precision="6" :step="0.000001" :min="0" clearable
+ style="width: 100%" @change="mathNum" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绋庣巼(%)锛�"
- prop="taxRate">
- <el-select v-model="productForm.taxRate"
- placeholder="璇烽�夋嫨"
- clearable
- @change="mathNum">
- <el-option v-for="dict in tax_rate"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value" />
+ <el-form-item label="鏁伴噺锛�" prop="quantity">
+ <el-input-number :step="0.1" clearable :precision="2" :min="0" style="width: 100%"
+ v-model="productForm.quantity" placeholder="璇疯緭鍏�" @change="mathNum" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+ <el-input-number v-model="productForm.taxInclusiveTotalPrice" :precision="6" :step="0.000001" :min="0"
+ clearable style="width: 100%" @change="reverseMathNum('taxInclusiveTotalPrice')" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice">
+ <el-input-number v-model="productForm.taxExclusiveTotalPrice" :precision="6" :step="0.000001" :min="0"
+ clearable style="width: 100%" @change="reverseMathNum('taxExclusiveTotalPrice')" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
+ <el-select v-model="productForm.invoiceType" placeholder="璇烽�夋嫨" clearable>
+ <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
+ <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
</el-select>
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="30">
+<!-- <el-col :span="12">-->
+<!-- <el-form-item label="搴撳瓨棰勮鏁伴噺锛�" prop="warnNum">-->
+<!-- <el-input-number v-model="productForm.warnNum" :precision="2" :step="0.1" :min="0" clearable-->
+<!-- style="width: 100%" />-->
+<!-- </el-form-item>-->
+<!-- </el-col>-->
<el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
- prop="taxInclusiveUnitPrice">
- <el-input-number v-model="productForm.taxInclusiveUnitPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="mathNum" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏁伴噺锛�"
- prop="quantity">
- <el-input-number :step="0.1"
- clearable
- :precision="2"
- :min="0"
- style="width: 100%"
- v-model="productForm.quantity"
- placeholder="璇疯緭鍏�"
- @change="mathNum" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚◣鎬讳环(鍏�)锛�"
- prop="taxInclusiveTotalPrice">
- <el-input-number v-model="productForm.taxInclusiveTotalPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="reverseMathNum('taxInclusiveTotalPrice')" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
- prop="taxExclusiveTotalPrice">
- <el-input-number v-model="productForm.taxExclusiveTotalPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="reverseMathNum('taxExclusiveTotalPrice')" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷锛�"
- prop="invoiceType">
- <el-select v-model="productForm.invoiceType"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option label="澧炴櫘绁�"
- value="澧炴櫘绁�" />
- <el-option label="澧炰笓绁�"
- value="澧炰笓绁�" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="搴撳瓨棰勮鏁伴噺锛�"
- prop="warnNum">
- <el-input-number v-model="productForm.warnNum"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鏄惁璐ㄦ锛�"
- prop="isChecked">
+ <el-form-item label="鏄惁璐ㄦ锛�" prop="isChecked">
<el-radio-group v-model="productForm.isChecked">
- <el-radio label="鏄�"
- :value="true" />
- <el-radio label="鍚�"
- :value="false" />
+ <el-radio label="鏄�" :value="true" />
+ <el-radio label="鍚�" :value="false" />
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
+<!-- <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏄惁璐ㄦ锛�" prop="isChecked">
+ <el-radio-group v-model="productForm.isChecked">
+ <el-radio label="鏄�" :value="true" />
+ <el-radio label="鍚�" :value="false" />
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ </el-row>-->
</el-form>
</FormDialog>
- <FileList v-if="fileListDialogVisible"
- v-model:visible="fileListDialogVisible"
- record-type="purchase_ledger"
- :record-id="recordId" />
+ <ProductSelectDialog v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single />
+ <FileList v-if="fileListDialogVisible" v-model:visible="fileListDialogVisible" record-type="purchase_ledger"
+ :record-id="recordId" />
+ <Detail ref="detailRef" />
</div>
</template>
<script setup>
- import FormDialog from "@/components/Dialog/FormDialog.vue";
- import FileListDialog from "@/components/Dialog/FileListDialog.vue";
- import { getToken } from "@/utils/auth";
- import pagination from "@/components/PIMTable/Pagination.vue";
- import {
- ref,
- onMounted,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import { Search, Delete } from "@element-plus/icons-vue";
- import { ElMessageBox, ElMessage } from "element-plus";
- import { userListNoPage } from "@/api/system/user.js";
- import {
- addOrUpdateSalesLedgerProduct,
- delProduct,
- delLedgerFile,
- getProductInfoByContractNo,
- } from "@/api/salesManagement/salesLedger.js";
- import {
- addOrEditPurchase,
- addPurchaseTemplate,
- updatePurchaseTemplate,
- createPurchaseNo,
- delPurchase,
- getSalesNo,
- purchaseListPage,
- productList,
- getPurchaseById,
- getOptions,
- getPurchaseTemplateList,
- delPurchaseTemplate,
- batchGeneratePurchaseInboundSteps,
- } from "@/api/procurementManagement/procurementLedger.js";
- import useFormData from "@/hooks/useFormData.js";
- const FileList = defineAsyncComponent(() =>
- import("@/components/Dialog/FileList.vue")
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import FileListDialog from "@/components/Dialog/FileListDialog.vue";
+import Detail from "./detail.vue";
+import { getToken } from "@/utils/auth";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import {
+ ref,
+ onMounted,
+ reactive,
+ toRefs,
+ getCurrentInstance,
+ nextTick,
+} from "vue";
+import { Search, Delete } from "@element-plus/icons-vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import {
+ addOrUpdateSalesLedgerProduct,
+ delProduct,
+ delLedgerFile,
+ getProductInfoByContractNo,
+} from "@/api/salesManagement/salesLedger.js";
+import {
+ addOrEditPurchase,
+ addPurchaseTemplate,
+ updatePurchaseTemplate,
+ createPurchaseNo,
+ delPurchase,
+ getSalesNo,
+ purchaseListPage,
+ productList,
+ getPurchaseById,
+ getOptions,
+ getPrintData,
+ getPurchaseTemplateList,
+ delPurchaseTemplate,
+} from "@/api/procurementManagement/procurementLedger.js";
+import useFormData from "@/hooks/useFormData.js";
+const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+);
+
+const detailRef = ref(null);
+
+const { proxy } = getCurrentInstance();
+const { tax_rate } = proxy.useDict("tax_rate");
+const tableData = ref([]);
+const productData = ref([]);
+const selectedRows = ref([]);
+const productSelectedRows = ref([]);
+const modelOptions = ref([]);
+const userList = ref([]);
+const productOptions = ref([]);
+const salesContractList = ref([]);
+const supplierList = ref([]);
+const tableLoading = ref(false);
+const recordId = ref();
+const fileListDialogVisible = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
+const fileList = ref([]);
+import useUserStore from "@/store/modules/user";
+import { modelList, productTreeList } from "@/api/basicData/product.js";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+import dayjs from "dayjs";
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+import { tableAmountFormatter, formatDecimal, buildAmountSummaryFormat } from '@/utils/numberFormat';
+import { downloadPurchaseJpg, printPurchaseMulti } from "@/utils/documentPrint.js";
+
+const userStore = useUserStore();
+
+// 鏄惁鏄剧ず閿�鍞悎鍚屽彿缁戝畾
+const showSalesContractBinding = false;
+
+// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+const approvalStatusText = {
+ 1: "寰呭鏍�",
+ 2: "瀹℃壒涓�",
+ 3: "瀹℃壒閫氳繃",
+ 4: "瀹℃壒澶辫触",
+};
+
+// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
+const getApprovalStatusType = status => {
+ const typeMap = {
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ };
+ return typeMap[status] || "";
+};
+
+// 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
+const getStockInStatusType = status => {
+ const typeMap = {
+ "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
+ "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
+ "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+ };
+ return typeMap[status] || "";
+};
+
+// 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
+const getStockInApprovalStatusType = status => {
+ const typeMap = {
+ "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
+ "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
+ "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+ };
+ return typeMap[status] || "";
+};
+
+const templateName = ref("");
+const filterInputValue = ref("");
+const templateList = ref([]);
+const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
+// 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
+const currentTemplateId = ref(null);
+
+// 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
+const checkTemplateNameDuplicate = name => {
+ if (!name || name.trim() === "") {
+ isTemplateNameDuplicate.value = false;
+ return false;
+ }
+ const isDuplicate = templateList.value.some(
+ item => item.templateName === name.trim()
);
+ isTemplateNameDuplicate.value = isDuplicate;
+ return isDuplicate;
+};
- const { proxy } = getCurrentInstance();
- const { tax_rate } = proxy.useDict("tax_rate");
- const tableData = ref([]);
- const productData = ref([]);
- const selectedRows = ref([]);
- const productSelectedRows = ref([]);
- const modelOptions = ref([]);
- const userList = ref([]);
- const productOptions = ref([]);
- const salesContractList = ref([]);
- const supplierList = ref([]);
- const tableLoading = ref(false);
- const recordId = ref();
- const fileListDialogVisible = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- });
- const total = ref(0);
- const fileList = ref([]);
- import useUserStore from "@/store/modules/user";
- import { modelList, productTreeList } from "@/api/basicData/product.js";
- import dayjs from "dayjs";
- import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+// 鍒ゆ柇鏂囦欢鏄惁涓哄浘鐗�
+const isImage = (filename) => {
+ if (!filename) return false;
+ const ext = filename.substring(filename.lastIndexOf('.')).toLowerCase();
+ return ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'].includes(ext);
+};
- const userStore = useUserStore();
-
- // 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
- const approvalStatusText = {
- 1: "寰呭鏍�",
- 2: "瀹℃壒涓�",
- 3: "瀹℃壒閫氳繃",
- 4: "瀹℃壒澶辫触",
- };
-
- // 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
- const getApprovalStatusType = status => {
- const typeMap = {
- 1: "info", // 寰呭鏍� - 鐏拌壊
- 2: "warning", // 瀹℃壒涓� - 姗欒壊
- 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
- 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
- };
- return typeMap[status] || "";
- };
-
- // 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
- const getStockInStatusType = status => {
- const typeMap = {
- 寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
- 鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
- 瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
- };
- return typeMap[status] || "";
- };
-
- // 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
- const getStockInApprovalStatusType = status => {
- const typeMap = {
- 寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
- 鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
- 瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
- };
- return typeMap[status] || "";
- };
-
- const templateName = ref("");
- const filterInputValue = ref("");
- const templateList = ref([]);
- const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
- // 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
- const currentTemplateId = ref(null);
-
- // 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
- const checkTemplateNameDuplicate = name => {
- if (!name || name.trim() === "") {
- isTemplateNameDuplicate.value = false;
- return false;
- }
- const isDuplicate = templateList.value.some(
- item => item.templateName === name.trim()
- );
- isTemplateNameDuplicate.value = isDuplicate;
- return isDuplicate;
- };
-
- // 闃叉姈瀹氭椂鍣�
- let duplicateCheckTimer = null;
- const onTemplateFilterChange = val => {
- filterInputValue.value = val ?? "";
- // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
- if (duplicateCheckTimer) {
- clearTimeout(duplicateCheckTimer);
- }
- // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
- if (val && val.trim()) {
- duplicateCheckTimer = setTimeout(() => {
- const isDuplicate = checkTemplateNameDuplicate(val);
- if (isDuplicate) {
- ElMessage({
- message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
- type: "warning",
- duration: 2000,
- });
- }
- }, 300); // 300ms 闃叉姈
- } else {
- isTemplateNameDuplicate.value = false;
- }
- };
-
- // allow-create 鏃讹紝杈撳叆涓嶅瓨鍦ㄧ殑鍐呭浼氫綔涓� string 鍊艰繑鍥烇紱杩欓噷鍚屾鍥炶緭鍏ユ浠ョ‘淇濇枃瀛椾笉涓�
- const onTemplateChange = async val => {
- if (typeof val === "string") {
- filterInputValue.value = val;
- // 閫夋嫨鎴栬緭鍏ユ椂妫�鏌ラ噸澶�
- checkTemplateNameDuplicate(val);
- }
-
- // 杩囨护鏁版嵁锛屾煡鎵惧尮閰嶇殑妯℃澘
- const matchedTemplate = templateList.value.find(
- item => item.templateName === val
- );
-
- if (matchedTemplate?.id) {
- // 璁板綍褰撳墠閫変腑鐨勬ā鏉縄D锛屽悗缁繚瀛樻椂杩涜鏇存柊鎿嶄綔
- currentTemplateId.value = matchedTemplate.id;
- // 閫変腑宸叉湁妯℃澘鏃讹紝涓嶅簲瑙嗕负鈥滄ā鏉垮悕绉伴噸澶嶅鑷翠笉鍙繚瀛樷��
- isTemplateNameDuplicate.value = false;
- // 濡傛灉鎵惧埌妯℃澘锛屽彧璧嬪�间緵搴斿晢銆侀」鐩悕绉般�佷粯娆炬柟寮忓拰浜у搧淇℃伅
- if (matchedTemplate.supplierId) {
- form.value.supplierId = matchedTemplate.supplierId;
- }
- if (matchedTemplate.supplierName) {
- form.value.supplierName = matchedTemplate.supplierName;
- }
- if (matchedTemplate.projectName) {
- form.value.projectName = matchedTemplate.projectName;
- }
- if (matchedTemplate.paymentMethod) {
- form.value.paymentMethod = matchedTemplate.paymentMethod;
- }
- // 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
- productData.value =
- matchedTemplate.productList || matchedTemplate.productData || [];
- } else {
- // 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
- currentTemplateId.value = null;
- // 濡傛灉娌℃湁鎵惧埌妯℃澘锛岄噸缃〃鍗曪紙淇濇寔褰撳墠琛ㄥ崟鐘舵�侊級
- const currentFormData = { ...form.value };
- const currentProductData = [...productData.value];
-
- // 濡傛灉瀵硅瘽妗嗘湭鎵撳紑锛屽厛鎵撳紑
- if (!dialogFormVisible.value) {
- operationType.value = "add";
- dialogFormVisible.value = true;
- }
-
- // 绛夊緟涓嬩竴涓� tick 鍚庢仮澶嶆暟鎹�
- await nextTick();
- form.value = {
- ...form.value,
- ...currentFormData,
- };
- productData.value = currentProductData;
- }
- };
-
- // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
- const operationType = ref("");
- const dialogFormVisible = ref(false);
- const data = reactive({
- searchForm: {
- supplierName: "", // 渚涘簲鍟嗗悕绉�
- purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
- salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
- projectName: "", // 椤圭洰鍚嶇О
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- form: {
- purchaseContractNumber: "",
- salesLedgerId: "",
- projectName: "",
- recorderId: "",
- entryDate: "",
- productData: [],
- supplierName: "",
- supplierId: "",
- paymentMethod: "",
- executionDate: "",
- isChecked: false,
- },
- rules: {
- purchaseContractNumber: [
- { required: false, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- projectName: [
- { required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" },
- ],
- supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
- });
- const { form, rules } = toRefs(data);
- const { form: searchForm } = useFormData({
- ...data.searchForm,
- // 璁剧疆褰曞叆鏃ユ湡鑼冨洿涓哄綋澶�
- entryDate: [
- dayjs().startOf("day").format("YYYY-MM-DD"),
- dayjs().endOf("day").format("YYYY-MM-DD"),
- ],
- entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"),
- entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"),
- });
-
- // 浜у搧琛ㄥ崟寮规鏁版嵁
- const productFormVisible = ref(false);
- const productOperationType = ref("");
- const productOperationIndex = ref("");
- const currentId = ref("");
- const productFormData = reactive({
- productForm: {
- productId: "",
- productCategory: "",
- productModelId: "",
- specificationModel: "",
- unit: "",
- quantity: "",
- taxInclusiveUnitPrice: "",
- taxRate: "",
- taxInclusiveTotalPrice: "",
- taxExclusiveTotalPrice: "",
- invoiceType: "",
- warnNum: "",
- isChecked: false,
- },
- productRules: {
- productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
- });
- const { productForm, productRules } = toRefs(productFormData);
- const upload = reactive({
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- });
-
- // 瀵煎叆鐩稿叧
- const importUploadRef = ref(null);
- const importUpload = reactive({
- title: "瀵煎叆閲囪喘鍙拌处",
- open: false,
- url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
- headers: { Authorization: "Bearer " + getToken() },
- isUploading: false,
- beforeUpload: file => {
- const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
- const isLt10M = file.size / 1024 / 1024 < 10;
- if (!isExcel) {
- proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
- return false;
- }
- if (!isLt10M) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
- return false;
- }
- return true;
- },
- onChange: (file, fileList) => {
- // noop
- },
- onProgress: (event, file, fileList) => {
- // noop
- },
- onSuccess: (response, file, fileList) => {
- importUpload.isUploading = false;
- if (response?.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importUpload.open = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles?.();
- }
- getList();
- } else {
- proxy.$modal.msgError(response?.msg || "瀵煎叆澶辫触");
- }
- },
- onError: () => {
- importUpload.isUploading = false;
- proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
- },
- });
-
- const handleImport = () => {
- importUpload.title = "瀵煎叆閲囪喘鍙拌处";
- importUpload.open = true;
- importUpload.isUploading = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles?.();
- }
- };
-
- // 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
- const downloadTemplate = () => {
- proxy.download(
- "/purchase/ledger/exportTemplate",
- {},
- "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx"
- );
- };
-
- const submitImportFile = () => {
- importUpload.isUploading = true;
- proxy.$refs["importUploadRef"]?.submit?.();
- };
-
- const changeDaterange = value => {
- if (value) {
- searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- searchForm.entryDateStart = undefined;
- searchForm.entryDateEnd = undefined;
- }
- handleQuery();
- };
-
- const formattedNumber = (row, column, cellValue) => {
- return parseFloat(cellValue).toFixed(2);
- };
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
-
- // 淇濆瓨妯℃澘
- const handleButtonClick = async () => {
- // 妫�鏌ユā鏉垮悕绉版槸鍚︿负绌�
- if (!templateName.value || templateName.value.trim() === "") {
- ElMessage({
- message: "璇疯緭鍏ユā鏉垮悕绉�",
- type: "warning",
- });
- return;
- }
-
- // 濡傛灉鏄�滄柊澧炴ā鏉库�濓紙娌℃湁閫変腑宸叉湁妯℃澘锛夛紝鎵嶉渶瑕佸仛閲嶅悕鏍¢獙锛�
- // 鑻ユ槸閫変腑宸叉湁妯℃澘鍚庝慨鏀癸紝鍒欏厑璁镐娇鐢ㄥ師鍚嶇О锛堣涓烘洿鏂帮級
- if (!currentTemplateId.value) {
- const isDuplicate = checkTemplateNameDuplicate(templateName.value);
+// 闃叉姈瀹氭椂鍣�
+let duplicateCheckTimer = null;
+const onTemplateFilterChange = val => {
+ filterInputValue.value = val ?? "";
+ // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+ if (duplicateCheckTimer) {
+ clearTimeout(duplicateCheckTimer);
+ }
+ // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
+ if (val && val.trim()) {
+ duplicateCheckTimer = setTimeout(() => {
+ const isDuplicate = checkTemplateNameDuplicate(val);
if (isDuplicate) {
ElMessage({
message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
type: "warning",
+ duration: 2000,
});
- return;
}
+ }, 300); // 300ms 闃叉姈
+ } else {
+ isTemplateNameDuplicate.value = false;
+ }
+};
+
+// allow-create 鏃讹紝杈撳叆涓嶅瓨鍦ㄧ殑鍐呭浼氫綔涓� string 鍊艰繑鍥烇紱杩欓噷鍚屾鍥炶緭鍏ユ浠ョ‘淇濇枃瀛椾笉涓�
+const onTemplateChange = async val => {
+ if (typeof val === "string") {
+ filterInputValue.value = val;
+ // 閫夋嫨鎴栬緭鍏ユ椂妫�鏌ラ噸澶�
+ checkTemplateNameDuplicate(val);
+ }
+
+ // 杩囨护鏁版嵁锛屾煡鎵惧尮閰嶇殑妯℃澘
+ const matchedTemplate = templateList.value.find(
+ item => item.templateName === val
+ );
+
+ if (matchedTemplate?.id) {
+ // 璁板綍褰撳墠閫変腑鐨勬ā鏉縄D锛屽悗缁繚瀛樻椂杩涜鏇存柊鎿嶄綔
+ currentTemplateId.value = matchedTemplate.id;
+ // 閫変腑宸叉湁妯℃澘鏃讹紝涓嶅簲瑙嗕负鈥滄ā鏉垮悕绉伴噸澶嶅鑷翠笉鍙繚瀛樷��
+ isTemplateNameDuplicate.value = false;
+ // 濡傛灉鎵惧埌妯℃澘锛屽彧璧嬪�间緵搴斿晢銆侀」鐩悕绉般�佷粯娆炬柟寮忓拰浜у搧淇℃伅
+ if (matchedTemplate.supplierId) {
+ form.value.supplierId = matchedTemplate.supplierId;
+ }
+ if (matchedTemplate.supplierName) {
+ form.value.supplierName = matchedTemplate.supplierName;
+ }
+ if (matchedTemplate.projectName) {
+ form.value.projectName = matchedTemplate.projectName;
+ }
+ if (matchedTemplate.paymentMethod) {
+ form.value.paymentMethod = matchedTemplate.paymentMethod;
+ }
+ // 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
+ productData.value =
+ matchedTemplate.productList || matchedTemplate.productData || [];
+ } else {
+ // 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
+ currentTemplateId.value = null;
+ // 濡傛灉娌℃湁鎵惧埌妯℃澘锛岄噸缃〃鍗曪紙淇濇寔褰撳墠琛ㄥ崟鐘舵�侊級
+ const currentFormData = { ...form.value };
+ const currentProductData = [...productData.value];
+
+ // 濡傛灉瀵硅瘽妗嗘湭鎵撳紑锛屽厛鎵撳紑
+ if (!dialogFormVisible.value) {
+ operationType.value = "add";
+ dialogFormVisible.value = true;
}
- // 妫�鏌ヤ緵搴斿晢鏄惁閫夋嫨
- if (!form.value.supplierId) {
+ // 绛夊緟涓嬩竴涓� tick 鍚庢仮澶嶆暟鎹�
+ await nextTick();
+ form.value = {
+ ...form.value,
+ ...currentFormData,
+ };
+ productData.value = currentProductData;
+ }
+};
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ supplierName: "", // 渚涘簲鍟嗗悕绉�
+ purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ projectName: "", // 椤圭洰鍚嶇О
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ form: {
+ purchaseContractNumber: "",
+ salesLedgerId: "",
+ projectName: "",
+ recorderId: "",
+ entryDate: "",
+ productData: [],
+ supplierName: "",
+ supplierId: "",
+ paymentMethod: "",
+ executionDate: "",
+ isChecked: false,
+ },
+ rules: {
+ purchaseContractNumber: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ projectName: [
+ { required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" },
+ ],
+ supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { form, rules } = toRefs(data);
+const { form: searchForm } = useFormData({
+ ...data.searchForm,
+});
+
+// 浜у搧琛ㄥ崟寮规鏁版嵁
+const productFormVisible = ref(false);
+const showProductSelectDialog = ref(false);
+const productOperationType = ref("");
+const productOperationIndex = ref("");
+const currentId = ref("");
+const productFormData = reactive({
+ productForm: {
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ warnNum: "",
+ isChecked: false,
+ },
+ productRules: {
+ productCategory: [{ required: true, message: "璇烽�夋嫨浜у搧澶х被", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨瑙勬牸鍨嬪彿", trigger: "change" }],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ // warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { productForm, productRules } = toRefs(productFormData);
+const upload = reactive({
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+});
+
+// 瀵煎叆鐩稿叧
+const importUploadRef = ref(null);
+const importUpload = reactive({
+ title: "瀵煎叆閲囪喘鍙拌处",
+ open: false,
+ url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
+ headers: { Authorization: "Bearer " + getToken() },
+ isUploading: false,
+ beforeUpload: file => {
+ const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isExcel) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+ return false;
+ }
+ if (!isLt10M) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
+ }
+ return true;
+ },
+ onChange: (file, fileList) => {
+ // noop
+ },
+ onProgress: (event, file, fileList) => {
+ // noop
+ },
+ onSuccess: (response, file, fileList) => {
+ importUpload.isUploading = false;
+ if (response?.code === 200) {
+ proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+ importUpload.open = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles?.();
+ }
+ getList();
+ } else {
+ proxy.$modal.msgError(response?.msg || "瀵煎叆澶辫触");
+ }
+ },
+ onError: () => {
+ importUpload.isUploading = false;
+ proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+ },
+});
+
+const handleImport = () => {
+ importUpload.title = "瀵煎叆閲囪喘鍙拌处";
+ importUpload.open = true;
+ importUpload.isUploading = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles?.();
+ }
+};
+
+// 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
+const downloadTemplate = () => {
+ proxy.download(
+ "/purchase/ledger/exportTemplate",
+ {},
+ "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx"
+ );
+};
+
+const submitImportFile = () => {
+ importUpload.isUploading = true;
+ proxy.$refs["importUploadRef"]?.submit?.();
+};
+
+const changeDaterange = value => {
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
+ }
+ handleQuery();
+};
+
+const formattedNumber = tableAmountFormatter;
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+
+// 淇濆瓨妯℃澘
+const handleButtonClick = async () => {
+ // 妫�鏌ユā鏉垮悕绉版槸鍚︿负绌�
+ if (!templateName.value || templateName.value.trim() === "") {
+ ElMessage({
+ message: "璇疯緭鍏ユā鏉垮悕绉�",
+ type: "warning",
+ });
+ return;
+ }
+
+ // 濡傛灉鏄�滄柊澧炴ā鏉库�濓紙娌℃湁閫変腑宸叉湁妯℃澘锛夛紝鎵嶉渶瑕佸仛閲嶅悕鏍¢獙锛�
+ // 鑻ユ槸閫変腑宸叉湁妯℃澘鍚庝慨鏀癸紝鍒欏厑璁镐娇鐢ㄥ師鍚嶇О锛堣涓烘洿鏂帮級
+ if (!currentTemplateId.value) {
+ const isDuplicate = checkTemplateNameDuplicate(templateName.value);
+ if (isDuplicate) {
ElMessage({
- message: "璇峰厛閫夋嫨渚涘簲鍟�",
+ message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
type: "warning",
});
return;
}
+ }
- // 妫�鏌ユ槸鍚︽湁浜у搧鏁版嵁
- if (!productData.value || productData.value.length === 0) {
- ElMessage({
- message: "璇峰厛娣诲姞浜у搧淇℃伅",
- type: "warning",
+ // 妫�鏌ヤ緵搴斿晢鏄惁閫夋嫨
+ if (!form.value.supplierId) {
+ ElMessage({
+ message: "璇峰厛閫夋嫨渚涘簲鍟�",
+ type: "warning",
+ });
+ return;
+ }
+
+ // 妫�鏌ユ槸鍚︽湁浜у搧鏁版嵁
+ if (!productData.value || productData.value.length === 0) {
+ ElMessage({
+ message: "璇峰厛娣诲姞浜у搧淇℃伅",
+ type: "warning",
+ });
+ return;
+ }
+
+ try {
+ let params = {
+ productData: proxy.HaveJson(productData.value),
+ supplierId: form.value.supplierId,
+ paymentMethod: form.value.paymentMethod,
+ recorderId: form.value.recorderId,
+ projectName: form.value.projectName,
+ templateName: templateName.value.trim(),
+ };
+ console.log(
+ "template params ===>",
+ params,
+ "currentTemplateId:",
+ currentTemplateId.value
+ );
+
+ // 濡傛灉 currentTemplateId 鏈夊�硷紝璇存槑褰撳墠鏄�滅紪杈戝凡鏈夋ā鏉库�� 鈫� 璋冪敤鏇存柊鎺ュ彛
+ // 鍚﹀垯涓衡�滄柊寤烘ā鏉库�� 鈫� 璋冪敤鏂板鎺ュ彛
+ let res;
+ if (currentTemplateId.value) {
+ res = await updatePurchaseTemplate({
+ id: currentTemplateId.value,
+ ...params,
});
- return;
+ } else {
+ res = await addPurchaseTemplate(params);
}
- try {
- let params = {
- productData: proxy.HaveJson(productData.value),
- supplierId: form.value.supplierId,
- paymentMethod: form.value.paymentMethod,
- recorderId: form.value.recorderId,
- projectName: form.value.projectName,
- templateName: templateName.value.trim(),
- };
- console.log(
- "template params ===>",
- params,
- "currentTemplateId:",
- currentTemplateId.value
- );
-
- // 濡傛灉 currentTemplateId 鏈夊�硷紝璇存槑褰撳墠鏄�滅紪杈戝凡鏈夋ā鏉库�� 鈫� 璋冪敤鏇存柊鎺ュ彛
- // 鍚﹀垯涓衡�滄柊寤烘ā鏉库�� 鈫� 璋冪敤鏂板鎺ュ彛
- let res;
- if (currentTemplateId.value) {
- res = await updatePurchaseTemplate({
- id: currentTemplateId.value,
- ...params,
- });
- } else {
- res = await addPurchaseTemplate(params);
- }
-
- if (res && res.code === 200) {
- ElMessage({
- message: currentTemplateId.value ? "妯℃澘鏇存柊鎴愬姛" : "妯℃澘淇濆瓨鎴愬姛",
- type: "success",
- });
- // 淇濆瓨鎴愬姛鍚庨噸鏂拌幏鍙栨ā鏉垮垪琛�
- await getTemplateList();
- // 娓呯┖妯℃澘鍚嶇О杈撳叆
- templateName.value = "";
- filterInputValue.value = "";
- isTemplateNameDuplicate.value = false;
- // 淇濆瓨/鏇存柊瀹屾垚鍚庯紝閲嶇疆褰撳墠妯℃澘ID
- currentTemplateId.value = null;
- } else {
- ElMessage({
- message: res?.msg || "妯℃澘淇濆瓨澶辫触",
- type: "error",
- });
- }
- } catch (error) {
- console.error("淇濆瓨妯℃澘澶辫触:", error);
+ if (res && res.code === 200) {
ElMessage({
- message: "妯℃澘淇濆瓨澶辫触锛岃绋嶅悗閲嶈瘯",
+ message: currentTemplateId.value ? "妯℃澘鏇存柊鎴愬姛" : "妯℃澘淇濆瓨鎴愬姛",
+ type: "success",
+ });
+ // 淇濆瓨鎴愬姛鍚庨噸鏂拌幏鍙栨ā鏉垮垪琛�
+ await getTemplateList();
+ // 娓呯┖妯℃澘鍚嶇О杈撳叆
+ templateName.value = "";
+ filterInputValue.value = "";
+ isTemplateNameDuplicate.value = false;
+ // 淇濆瓨/鏇存柊瀹屾垚鍚庯紝閲嶇疆褰撳墠妯℃澘ID
+ currentTemplateId.value = null;
+ } else {
+ ElMessage({
+ message: res?.msg || "妯℃澘淇濆瓨澶辫触",
type: "error",
});
}
- };
- // 瀛愯〃鍚堣鏂规硶
- const summarizeChildrenTable = param => {
- return proxy.summarizeTable(
- param,
+ } catch (error) {
+ console.error("淇濆瓨妯℃澘澶辫触:", error);
+ ElMessage({
+ message: "妯℃澘淇濆瓨澶辫触锛岃绋嶅悗閲嶈瘯",
+ type: "error",
+ });
+ }
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeChildrenTable = param => {
+ return proxy.summarizeTable(
+ param,
+ [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ "ticketsNum",
+ "ticketsAmount",
+ "futureTickets",
+ "futureTicketsAmount",
+ ],
+ buildAmountSummaryFormat(
[
"taxInclusiveUnitPrice",
"taxInclusiveTotalPrice",
"taxExclusiveTotalPrice",
- "ticketsNum",
"ticketsAmount",
- "futureTickets",
"futureTicketsAmount",
],
{
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ ticketsNum: { noDecimal: true },
+ futureTickets: { noDecimal: true },
}
- );
- };
- const paginationChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const { entryDate, ...rest } = searchForm;
- purchaseListPage({ ...rest, ...page })
- .then(res => {
- tableLoading.value = false;
- // tableData.value = res.data.records;
- tableData.value = res.data.records.map(record => ({
- ...record,
- }));
- // 鍒濆鍖栧瓙鏁版嵁鏁扮粍
- tableData.value.forEach(item => {
- item.children = [];
- });
- total.value = res.data.total;
- expandedRowKeys.value = [];
- })
- .catch(() => {
- tableLoading.value = false;
+ )
+ );
+};
+const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const { entryDate, ...rest } = searchForm;
+ purchaseListPage({ ...rest, ...page })
+ .then(res => {
+ tableLoading.value = false;
+ // tableData.value = res.data.records;
+ tableData.value = res.data.records.map(record => ({
+ ...record,
+ }));
+ // 鍒濆鍖栧瓙鏁版嵁鏁扮粍
+ tableData.value.forEach(item => {
+ item.children = [];
});
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
- const productSelected = selectedRows => {
- productSelectedRows.value = selectedRows;
- };
- const expandedRowKeys = ref([]);
- // 灞曞紑琛�
- const expandChange = async (row, expandedRows) => {
- if (expandedRows.length > 0) {
+ total.value = res.data.total;
expandedRowKeys.value = [];
- try {
- const res = await productList({ salesLedgerId: row.id, type: 2 });
- 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.error("鍔犺浇浜у搧鍒楄〃澶辫触:", error);
- proxy.$modal.msgError("鍔犺浇浜у搧鍒楄〃澶辫触");
- // 灞曞紑澶辫触鏃讹紝绉婚櫎灞曞紑鐘舵��
- const index = expandedRows.findIndex(item => item.id === row.id);
- if (index > -1) {
- expandedRows.splice(index, 1);
- }
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+};
+const productSelected = selectedRows => {
+ productSelectedRows.value = selectedRows;
+};
+const expandedRowKeys = ref([]);
+// 灞曞紑琛�
+const expandChange = async (row, expandedRows) => {
+ if (expandedRows.length > 0) {
+ expandedRowKeys.value = [];
+ try {
+ const res = await productList({ salesLedgerId: row.id, type: 2 });
+ const index = tableData.value.findIndex(item => item.id === row.id);
+ if (index > -1) {
+ tableData.value[index].children = res.data || [];
+ expandedRowKeys.value.push(row.id);
}
- } else {
- expandedRowKeys.value = [];
+ } catch (error) {
+ console.error("鍔犺浇浜у搧鍒楄〃澶辫触:", error);
+ proxy.$modal.msgError("鍔犺浇浜у搧鍒楄〃澶辫触");
+ // 灞曞紑澶辫触鏃讹紝绉婚櫎灞曞紑鐘舵��
+ const index = expandedRows.findIndex(item => item.id === row.id);
+ if (index > -1) {
+ expandedRows.splice(index, 1);
+ }
}
- };
- // 涓昏〃鍚堣鏂规硶
- const summarizeMainTable = param => {
- return proxy.summarizeTable(param, ["contractAmount", "netContractAmount"]);
- };
- const formatMoney = value => {
- if (value === null || value === undefined || value === "") {
- return "--";
- }
- const num = Number(value);
- return Number.isFinite(num) ? num.toFixed(2) : "--";
- };
- // 瀛愯〃鍚堣鏂规硶
- const summarizeProTable = param => {
- return proxy.summarizeTable(param, [
+ } else {
+ expandedRowKeys.value = [];
+ }
+};
+// 涓昏〃鍚堣鏂规硶
+const summarizeMainTable = param => {
+ return proxy.summarizeTable(
+ param,
+ ["contractAmount"],
+ buildAmountSummaryFormat(["contractAmount"])
+ );
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeProTable = param => {
+ return proxy.summarizeTable(
+ param,
+ [
"taxInclusiveUnitPrice",
"taxInclusiveTotalPrice",
"taxExclusiveTotalPrice",
+ ],
+ buildAmountSummaryFormat([
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ])
+ );
+};
+// 鎵撳紑寮规
+const openForm = async (type, row) => {
+ if (type === 'detail') {
+ detailRef.value.open(row.id);
+ return;
+ }
+ // 缂栬緫鏃舵鏌ュ叆搴撶姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
+ if (type === "edit" && row) {
+ if (row.stockInStatus === '瀹屽叏鍏ュ簱') {
+ proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑璁板綍涓嶈兘缂栬緫");
+ return;
+ }
+ }
+
+ await getTemplateList();
+ await userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ operationType.value = type;
+ form.value = {};
+ productData.value = [];
+ fileList.value = [];
+ templateName.value = "";
+ filterInputValue.value = "";
+ isTemplateNameDuplicate.value = false;
+ try {
+ // 骞惰鍔犺浇鍩虹鏁版嵁
+ const [salesRes, supplierRes] = await Promise.all([
+ getSalesNo(),
+ getOptions(),
]);
- };
- // 鎵撳紑寮规
- const openForm = async (type, row) => {
- // 缂栬緫鏃舵鏌ュ叆搴撶姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
- if (type === "edit" && row) {
- if (row.stockInStatus === "瀹屽叏鍏ュ簱") {
- proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑璁板綍涓嶈兘缂栬緫");
+
+ salesContractList.value = salesRes || [];
+ // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
+ supplierList.value = (supplierRes.data || []).filter(
+ item => item.isWhite === 0
+ );
+
+ form.value.entryDate = getCurrentDate();
+ form.value.recorderId = userStore.id;
+
+ if (type === "add") {
+ // 鏂板鏃剁敓鎴愰噰璐悎鍚屽彿
+ try {
+ const purchaseNoRes = await createPurchaseNo();
+ if (purchaseNoRes?.data) {
+ form.value.purchaseContractNumber = purchaseNoRes.data;
+ }
+ } catch (error) {
+ console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
+ proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
+ }
+ } else if (type === "edit" && row?.id) {
+ // 缂栬緫鏃跺姞杞芥暟鎹�
+ currentId.value = row.id;
+ try {
+ const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
+ form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
+ fileList.value = purchaseRes.storageBlobVOS || [];
+ // 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
+ const productRes = await productList({ salesLedgerId: row.id, type: 2 });
+ productData.value = productRes.data || [];
+ } catch (error) {
+ console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
+ proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
return;
}
}
- await getTemplateList();
- await userListNoPage().then(res => {
- userList.value = res.data;
- });
- operationType.value = type;
- form.value = {};
- productData.value = [];
- fileList.value = [];
- templateName.value = "";
- filterInputValue.value = "";
- isTemplateNameDuplicate.value = false;
+ if (form.value.salesLedgerId == -1) {
+ form.value.salesLedgerId = null;
+ }
+ dialogFormVisible.value = true;
+ } catch (error) {
+ console.error("鎵撳紑琛ㄥ崟澶辫触:", error);
+ proxy.$modal.msgError("鍔犺浇鍩虹鏁版嵁澶辫触");
+ }
+};
+
+// 涓婁紶鍓嶆牎妫�
+function handleBeforeUpload(file) {
+ // 鏍℃鏂囦欢澶у皬
+ if (file.size > 1024 * 1024 * 10) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
+ 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) {
+ file.tempId = res.data.tempId;
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.fileUpload.handleRemove(file);
+ }
+}
+
+// 绉婚櫎鏂囦欢
+async function handleRemove(file) {
+ if (!file?.id) {
+ return;
+ }
+ console.log("handleRemove", file.id);
+ if (file.size > 1024 * 1024 * 10) {
+ // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
+ return;
+ }
+
+ if (operationType.value === "edit" && file.id) {
try {
- // 骞惰鍔犺浇鍩虹鏁版嵁
- const [salesRes, supplierRes] = await Promise.all([
- getSalesNo(),
- getOptions(),
- ]);
-
- salesContractList.value = salesRes || [];
- // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
- supplierList.value = (supplierRes.data || []).filter(
- item => item.isWhite === 0
- );
-
- form.value.entryDate = getCurrentDate();
-
- if (type === "edit" && row?.id) {
- // 缂栬緫鏃跺姞杞芥暟鎹�
- currentId.value = row.id;
- try {
- const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
- form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
- fileList.value = purchaseRes.storageBlobVOS || [];
- // 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
- const productRes = await productList({
- salesLedgerId: row.id,
- type: 2,
- });
- productData.value = productRes.data || [];
- } catch (error) {
- console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
- proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
- return;
- }
- }
-
- if (form.value.salesLedgerId == -1) {
- form.value.salesLedgerId = null;
- }
- console.log(form.value, "form.value===========");
- dialogFormVisible.value = true;
+ await delLedgerFile([file.id]);
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
} catch (error) {
- console.error("鎵撳紑琛ㄥ崟澶辫触:", error);
- proxy.$modal.msgError("鍔犺浇鍩虹鏁版嵁澶辫触");
- }
- };
-
- // 涓婁紶鍓嶆牎妫�
- function handleBeforeUpload(file) {
- // 鏍℃鏂囦欢澶у皬
- if (file.size > 1024 * 1024 * 10) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
- 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) {
- file.tempId = res.data.tempId;
- proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- proxy.$refs.fileUpload.handleRemove(file);
+ console.error("鍒犻櫎鏂囦欢澶辫触:", error);
+ proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
}
}
+}
- // 绉婚櫎鏂囦欢
- async function handleRemove(file) {
- if (!file?.id) {
- return;
- }
- console.log("handleRemove", file.id);
- if (file.size > 1024 * 1024 * 10) {
- // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
- return;
- }
-
- if (operationType.value === "edit" && file.id) {
- try {
- await delLedgerFile([file.id]);
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- } catch (error) {
- console.error("鍒犻櫎鏂囦欢澶辫触:", error);
- proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
- }
- }
- }
-
- // 鎻愪氦琛ㄥ崟
- const submitForm = () => {
- proxy.$refs["formRef"].validate(async valid => {
- if (valid) {
- if (productData.value.length > 0) {
- // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
- let processedProductData = productData.value;
- if (operationType.value === "add") {
- processedProductData = productData.value.map(product => {
- const { id, ...rest } = product;
- return rest;
- });
- }
- form.value.productData = proxy.HaveJson(processedProductData);
- } else {
- proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
- return;
- }
- form.value.storageBlobDTOS = fileList.value;
- form.value.type = 2;
-
- // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
- if (!form.value.salesLedgerId) {
- form.value.salesContractNo = "";
- }
-
- // 鏂板鏃朵笉浼犻�抜d
- const submitData = { ...form.value };
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (productData.value.length > 0) {
+ // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
+ let processedProductData = productData.value;
if (operationType.value === "add") {
- delete submitData.id;
+ processedProductData = productData.value.map(product => {
+ const { id, ...rest } = product;
+ return rest;
+ });
}
-
- // 濡傛灉閲囪喘鍚堝悓鍙蜂负绌猴紝鍒欐牴鎹綍鍏ユ棩鏈熻嚜鍔ㄧ敓鎴�
- if (!submitData.purchaseContractNumber) {
- try {
- const purchaseNoRes = await createPurchaseNo(submitData.entryDate);
- if (purchaseNoRes?.data) {
- submitData.purchaseContractNumber = purchaseNoRes.data;
- }
- } catch (error) {
- console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
- proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
- return;
- }
- }
-
- addOrEditPurchase(submitData).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
+ form.value.productData = proxy.HaveJson(processedProductData);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
}
- });
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- };
- // 鎵撳紑浜у搧寮规
- const openProductForm = async (type, row, index) => {
- // 缂栬緫鏃舵鏌ヤ骇鍝佸叆搴撳鏍哥姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
- if (type === "edit" && row && row.stockInApprovalStatus === "瀹屽叏鍏ュ簱") {
- proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑浜у搧涓嶈兘缂栬緫");
- return;
+ form.value.storageBlobDTOS = fileList.value;
+ form.value.type = 2;
+
+ // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
+ if (!form.value.salesLedgerId) {
+ form.value.salesContractNo = "";
+ }
+
+ // 鏂板鏃朵笉浼犻�抜d
+ const submitData = { ...form.value };
+ if (operationType.value === "add") {
+ delete submitData.id;
+ }
+
+ addOrEditPurchase(submitData).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
}
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+// 鎵撳紑浜у搧寮规
+const openProductForm = async (type, row, index) => {
+ // 缂栬緫鏃舵鏌ヤ骇鍝佸叆搴撳鏍哥姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
+ if (type === "edit" && row && row.stockInApprovalStatus === '瀹屽叏鍏ュ簱') {
+ proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑浜у搧涓嶈兘缂栬緫");
+ return;
+ }
- productOperationType.value = type;
- productOperationIndex.value = index;
- productForm.value = {};
- proxy.resetForm("productFormRef");
- productFormVisible.value = true;
+ productOperationType.value = type;
+ productOperationIndex.value = index;
+ productForm.value = {};
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = true;
- // 鍏堣幏鍙栦骇鍝侀�夐」锛岀‘淇濇暟鎹姞杞藉畬鎴�
- await getProductOptions();
+ // 鍏堣幏鍙栦骇鍝侀�夐」锛岀‘淇濇暟鎹姞杞藉畬鎴�
+ await getProductOptions();
- // 绛夊緟 DOM 鏇存柊
- await nextTick();
+ // 绛夊緟 DOM 鏇存柊
+ await nextTick();
- if (type === "add") {
- productForm.value.isChecked = false;
- }
+ if (type === "add") {
+ productForm.value.isChecked = false;
+ }
- if (type === "edit") {
- // 澶嶅埗琛屾暟鎹�
- productForm.value = { ...row };
+ if (type === "edit") {
+ // 澶嶅埗琛屾暟鎹�
+ productForm.value = { ...row };
- // 濡傛灉鏄粠妯℃澘鍔犺浇鐨勬暟鎹紝鍙兘娌℃湁 productId 鍜� productModelId
- // 闇�瑕佹牴鎹� productCategory 鍜� specificationModel 鏉ユ煡鎵惧搴旂殑 ID
- if (!productForm.value.productId && productForm.value.productCategory) {
- // 鏍规嵁 productCategory 鏌ユ壘 productId
- const findProductIdByCategory = (nodes, categoryName) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].label === categoryName) {
- return nodes[i].value;
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const found = findProductIdByCategory(
- nodes[i].children,
- categoryName
- );
- if (found) return found;
- }
+ // 濡傛灉鏄粠妯℃澘鍔犺浇鐨勬暟鎹紝鍙兘娌℃湁 productId 鍜� productModelId
+ // 闇�瑕佹牴鎹� productCategory 鍜� specificationModel 鏉ユ煡鎵惧搴旂殑 ID
+ if (!productForm.value.productId && productForm.value.productCategory) {
+ // 鏍规嵁 productCategory 鏌ユ壘 productId
+ const findProductIdByCategory = (nodes, categoryName) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].label === categoryName) {
+ return nodes[i].value;
}
- return null;
- };
-
- const productId = findProductIdByCategory(
- productOptions.value,
- productForm.value.productCategory
- );
- if (productId) {
- productForm.value.productId = productId;
- // 鑾峰彇鍨嬪彿鍒楄〃骞剁瓑寰呭畬鎴�
- const modelRes = await modelList({ id: productId });
- modelOptions.value = modelRes;
-
- // 绛夊緟 DOM 鏇存柊
- await nextTick();
-
- // 鏍规嵁 specificationModel 鏌ユ壘 productModelId
- if (
- productForm.value.specificationModel &&
- modelOptions.value.length > 0
- ) {
- const modelItem = modelOptions.value.find(
- item => item.model === productForm.value.specificationModel
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const found = findProductIdByCategory(
+ nodes[i].children,
+ categoryName
);
- if (modelItem) {
- productForm.value.productModelId = modelItem.id;
- // 璁剧疆瑙勬牸鍨嬪彿鍜屽崟浣�
- getProductModel(modelItem.id);
- }
+ if (found) return found;
}
}
- } else if (productForm.value.productId) {
- // 濡傛灉鏈� productId锛屾甯稿姞杞藉瀷鍙峰垪琛�
- await getModels(productForm.value.productId);
+ return null;
+ };
+
+ const productId = findProductIdByCategory(
+ productOptions.value,
+ productForm.value.productCategory
+ );
+ if (productId) {
+ productForm.value.productId = productId;
+ // 鑾峰彇鍨嬪彿鍒楄〃骞剁瓑寰呭畬鎴�
+ const modelRes = await modelList({ id: productId });
+ modelOptions.value = modelRes;
// 绛夊緟 DOM 鏇存柊
await nextTick();
- if (productForm.value.productModelId) {
- getProductModel(productForm.value.productModelId);
+ // 鏍规嵁 specificationModel 鏌ユ壘 productModelId
+ if (
+ productForm.value.specificationModel &&
+ modelOptions.value.length > 0
+ ) {
+ const modelItem = modelOptions.value.find(
+ item => item.model === productForm.value.specificationModel
+ );
+ if (modelItem) {
+ productForm.value.productModelId = modelItem.id;
+ // 璁剧疆瑙勬牸鍨嬪彿鍜屽崟浣�
+ getProductModel(modelItem.id);
+ }
}
}
+ } else if (productForm.value.productId) {
+ // 濡傛灉鏈� productId锛屾甯稿姞杞藉瀷鍙峰垪琛�
+ await getModels(productForm.value.productId);
- // 鏈�鍚庡啀绛夊緟涓�娆� DOM 鏇存柊锛岀‘淇濇墍鏈夋暟鎹兘宸茶缃�
+ // 绛夊緟 DOM 鏇存柊
await nextTick();
+
+ if (productForm.value.productModelId) {
+ getProductModel(productForm.value.productModelId);
+ }
}
- };
- const getProductOptions = () => {
- return productTreeList().then(res => {
- productOptions.value = convertIdToValue(res);
+
+ // 鏈�鍚庡啀绛夊緟涓�娆� DOM 鏇存柊锛岀‘淇濇墍鏈夋暟鎹兘宸茶缃�
+ await nextTick();
+ }
+};
+
+// ProductSelectDialog 閫変腑鍥炶皟
+const handleProductSelect = (products) => {
+ if (!products || !products.length) return;
+ const p = products[0];
+ productForm.value.productId = p.productId;
+ productForm.value.productCategory = p.productName || '';
+ productForm.value.productModelId = p.id;
+ productForm.value.specificationModel = p.model || '';
+ productForm.value.unit = p.unit || '';
+ showProductSelectDialog.value = false;
+};
+
+const getProductOptions = () => {
+ return productTreeList().then(res => {
+ productOptions.value = convertIdToValue(res);
+ return res;
+ });
+};
+const getModels = value => {
+ if (value) {
+ productForm.value.productCategory =
+ findNodeById(productOptions.value, value) || "";
+ return modelList({ id: value }).then(res => {
+ modelOptions.value = res;
return res;
});
- };
- const getModels = value => {
- if (value) {
- productForm.value.productCategory =
- findNodeById(productOptions.value, value) || "";
- return modelList({ id: value }).then(res => {
- modelOptions.value = res;
- return res;
- });
- } else {
- productForm.value.productCategory = "";
- modelOptions.value = [];
- return Promise.resolve([]);
+ } else {
+ productForm.value.productCategory = "";
+ modelOptions.value = [];
+ return Promise.resolve([]);
+ }
+};
+const getProductModel = value => {
+ const index = modelOptions.value.findIndex(item => item.id === value);
+ if (index !== -1) {
+ productForm.value.specificationModel = modelOptions.value[index].model;
+ productForm.value.unit = modelOptions.value[index].unit;
+ } else {
+ productForm.value.specificationModel = null;
+ productForm.value.unit = null;
+ }
+};
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣鐨刲abel
}
- };
- const getProductModel = value => {
- const index = modelOptions.value.findIndex(item => item.id === value);
- if (index !== -1) {
- productForm.value.specificationModel = modelOptions.value[index].model;
- productForm.value.unit = modelOptions.value[index].unit;
- } else {
- productForm.value.specificationModel = null;
- productForm.value.unit = null;
- }
- };
- const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣鐨刲abel
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝鐩存帴杩斿洖锛堝凡缁忔槸label瀛楃涓诧級
}
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝鐩存帴杩斿洖锛堝凡缁忔槸label瀛楃涓诧級
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+
+function convertIdToValue(data) {
+ return data.map(item => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+}
+
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitProduct = () => {
+ proxy.$refs["productFormRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitProductEdit();
+ } else {
+ if (productOperationType.value === "add") {
+ productData.value.push({ ...productForm.value });
+ console.log("productData.value---", productData.value);
+ } else {
+ productData.value[productOperationIndex.value] = {
+ ...productForm.value,
+ };
}
+ closeProductDia();
}
}
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
- };
-
- function convertIdToValue(data) {
- return data.map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
+ });
+};
+const submitProductEdit = () => {
+ productForm.value.salesLedgerId = currentId.value;
+ productForm.value.type = 2;
+ addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeProductDia();
+ // 浣跨敤 productList 鎺ュ彛鍒锋柊浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
+ productList({ salesLedgerId: currentId.value, type: 2 }).then(res => {
+ productData.value = res.data || [];
});
+ });
+};
+// 鍒犻櫎浜у搧
+const deleteProduct = () => {
+ if (productSelectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ // 妫�鏌ラ�変腑鐨勪骇鍝佷腑鏄惁鏈夊畬鍏ㄥ叆搴撶殑
+ const hasFullyStocked = productSelectedRows.value.some(
+ row => row.stockInApprovalStatus === '瀹屽叏鍏ュ簱'
+ );
+ if (hasFullyStocked) {
+ proxy.$modal.msgWarning("閫変腑鐨勪骇鍝佷腑鍖呭惈瀹屽叏鍏ュ簱鐨勪骇鍝侊紝鏃犳硶鍒犻櫎");
+ return;
+ }
+ if (operationType.value === "add") {
+ productData.value = productData.value.filter(
+ item => !productSelectedRows.value.includes(item)
+ );
+ productSelectedRows.value = [];
+ } else {
+ let ids = [];
+ if (productSelectedRows.value.length > 0) {
+ ids = productSelectedRows.value.map(item => item.id);
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delProduct(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ closeProductDia();
+ // 浣跨敤 productList 鎺ュ彛鍒锋柊浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
+ productList({ salesLedgerId: currentId.value, type: 2 }).then(res => {
+ productData.value = res.data || [];
+ });
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ }
+};
+// 鍏抽棴浜у搧寮规
+const closeProductDia = () => {
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/purchase/ledger/export", {}, "閲囪喘鍙拌处.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value
+ .filter(item => item.salesLedgerId === null)
+ .map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delPurchase(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鎵归噺鎵撳嵃閲囪喘鍗� - 澶氶�夊悎骞堕瑙�
+const handlePrint = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+ proxy.$modal.loading("姝e湪鍔犺浇鎵撳嵃鏁版嵁...");
+ try {
+ const orders = [];
+ let companyName = '';
+ for (const row of selectedRows.value) {
+ const res = await getPrintData(row.id);
+ const data = res.data || res;
+ companyName = data.companyName || companyName;
+ orders.push({ ledger: data.ledger, products: data.products });
+ }
+ printPurchaseMulti(companyName, orders);
+ } catch (e) {
+ console.error('鎵撳嵃澶辫触:', e);
+ proxy.$modal.msgError("鎵撳嵃澶辫触");
+ } finally {
+ proxy.$modal.closeLoading();
+ }
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+const mathNum = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (!productForm.value.taxInclusiveUnitPrice) {
+ return;
+ }
+ if (!productForm.value.quantity) {
+ return;
+ }
+ // 鍚◣鎬讳环璁$畻
+ productForm.value.taxInclusiveTotalPrice =
+ proxy.calculateTaxIncludeTotalPrice(
+ productForm.value.taxInclusiveUnitPrice,
+ productForm.value.quantity
+ );
+ if (productForm.value.taxRate) {
+ // 涓嶅惈绋庢�讳环璁$畻
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+};
+const reverseMathNum = field => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ const taxRate = Number(productForm.value.taxRate);
+ if (!taxRate) return;
+
+ // 纭繚杈撳叆鍊间笉涓鸿礋鏁�
+ if (
+ field === "taxInclusiveTotalPrice" ||
+ field === "taxExclusiveTotalPrice"
+ ) {
+ const value = Number(productForm.value[field]);
+ if (value < 0) {
+ productForm.value[field] = "0";
+ proxy.$modal.msgWarning("鍊间笉鑳藉皬浜�0");
+ return;
+ }
}
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitProduct = () => {
- proxy.$refs["productFormRef"].validate(valid => {
- if (valid) {
- if (operationType.value === "edit") {
- submitProductEdit();
- } else {
- if (productOperationType.value === "add") {
- productData.value.push({ ...productForm.value });
- console.log("productData.value---", productData.value);
- } else {
- productData.value[productOperationIndex.value] = {
- ...productForm.value,
- };
- }
- closeProductDia();
- }
- }
- });
- };
- const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 2;
- addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- // 浣跨敤 productList 鎺ュ彛鍒锋柊浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
- productList({ salesLedgerId: currentId.value, type: 2 }).then(res => {
- productData.value = res.data || [];
- });
- });
- };
- // 鍒犻櫎浜у搧
- const deleteProduct = () => {
- if (productData.value.length <= 1) {
- proxy.$modal.msgWarning("閲囪喘鍙拌处鑷冲皯闇�瑕佷繚鐣欎竴鏉′骇鍝佹暟鎹�");
- return;
- }
- if (productSelectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- // 妫�鏌ラ�変腑鐨勪骇鍝佷腑鏄惁鏈夊畬鍏ㄥ叆搴撶殑
- const hasFullyStocked = productSelectedRows.value.some(
- row => row.stockInApprovalStatus === "瀹屽叏鍏ュ簱"
- );
- if (hasFullyStocked) {
- proxy.$modal.msgWarning("閫変腑鐨勪骇鍝佷腑鍖呭惈瀹屽叏鍏ュ簱鐨勪骇鍝侊紝鏃犳硶鍒犻櫎");
- return;
- }
- if (operationType.value === "add") {
- productData.value = productData.value.filter(
- item => !productSelectedRows.value.includes(item)
+ if (field === "taxInclusiveTotalPrice") {
+ // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
+ if (productForm.value.quantity) {
+ productForm.value.taxInclusiveUnitPrice = formatDecimal(
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.quantity)
);
- productSelectedRows.value = [];
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map(item => item.id);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
+ productForm.value.taxInclusiveUnitPrice = "0";
}
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
+ }
+ // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
+ else if (productForm.value.taxInclusiveUnitPrice) {
+ productForm.value.quantity = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.taxInclusiveUnitPrice)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.quantity) < 0) {
+ productForm.value.quantity = "0";
+ }
+ }
+ // 鍙嶇畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice = formatDecimal(
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ (1 + taxRate / 100)
+ );
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxExclusiveTotalPrice) < 0) {
+ productForm.value.taxExclusiveTotalPrice = "0";
+ }
+ } else if (field === "taxExclusiveTotalPrice") {
+ // 鍙嶇畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = formatDecimal(
+ Number(productForm.value.taxExclusiveTotalPrice) *
+ (1 + taxRate / 100)
+ );
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxInclusiveTotalPrice) < 0) {
+ productForm.value.taxInclusiveTotalPrice = "0";
+ }
+ // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
+ if (productForm.value.quantity) {
+ productForm.value.taxInclusiveUnitPrice = formatDecimal(
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.quantity)
+ );
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
+ productForm.value.taxInclusiveUnitPrice = "0";
+ }
+ }
+ // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
+ else if (productForm.value.taxInclusiveUnitPrice) {
+ productForm.value.quantity = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.taxInclusiveUnitPrice)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.quantity) < 0) {
+ productForm.value.quantity = "0";
+ }
+ }
+ }
+};
+// 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
+const salesLedgerChange = async row => {
+ var index = salesContractList.value.findIndex(item => item.id == row);
+ if (index > -1) {
+ await querygProductInfoByContractNo();
+ }
+};
+
+const querygProductInfoByContractNo = async () => {
+ const { code, data } = await getProductInfoByContractNo({
+ contractNo: form.value.salesLedgerId,
+ });
+ if (code == 200) {
+ productData.value = data;
+ }
+};
+
+// 鑾峰彇妯℃澘淇℃伅
+const getTemplateList = async () => {
+ let res = await getPurchaseTemplateList();
+ if (res && res.code === 200 && Array.isArray(res.data)) {
+ templateList.value = res.data;
+ }
+};
+
+// 鎵撳紑闄勪欢寮规
+const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileListDialogVisible.value = true;
+};
+
+// 涓嬭浇閲囪喘鍗�
+const downloadOrder = async (id) => {
+ try {
+ const res = await getPrintData(id);
+ const data = res.data || res;
+ downloadPurchaseJpg(data.companyName, data.ledger, data.products, '閲囪喘鍗昣' + (data.ledger.purchaseContractNumber || id) + '.jpg');
+ } catch (e) {
+ console.error('涓嬭浇澶辫触:', e);
+ }
+};
+
+// 鎵撳嵃閲囪喘鍗�
+const printOrder = async (id) => {
+ try {
+ const res = await getPrintData(id);
+ const data = res.data || res;
+ printPurchase(data.companyName, data.ledger, data.products);
+ } catch (e) {
+ console.error('鎵撳嵃澶辫触:', e);
+ }
+};
+
+// 鍒犻櫎妯℃澘
+const handleDeleteTemplate = async item => {
+ if (!item.id) {
+ proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
+ return;
+ }
+
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
+ "鍒犻櫎纭",
+ {
+ confirmButtonText: "纭畾",
cancelButtonText: "鍙栨秷",
type: "warning",
- })
- .then(() => {
- delProduct(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- // 浣跨敤 productList 鎺ュ彛鍒锋柊浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
- productList({ salesLedgerId: currentId.value, type: 2 }).then(res => {
- productData.value = res.data || [];
- });
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- }
- };
- // 鍏抽棴浜у搧寮规
- const closeProductDia = () => {
- proxy.resetForm("productFormRef");
- productFormVisible.value = false;
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/purchase/ledger/export", {}, "閲囪喘鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ }
+ );
+
+ const res = await delPurchaseTemplate([item.id]);
+ if (res && res.code === 200) {
+ ElMessage({
+ message: "鍒犻櫎鎴愬姛",
+ type: "success",
});
- };
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value
- .filter(item => item.salesLedgerId === null)
- .map(item => item.id);
+ // 濡傛灉鍒犻櫎鐨勬槸褰撳墠閫変腑鐨勬ā鏉匡紝娓呯┖閫夋嫨
+ if (templateName.value === item.templateName) {
+ templateName.value = "";
+ filterInputValue.value = "";
+ }
+ // 閲嶆柊鑾峰彇妯℃澘鍒楄〃
+ await getTemplateList();
} else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delPurchase(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ ElMessage({
+ message: res?.msg || "鍒犻櫎澶辫触",
+ type: "error",
});
- };
-
- const handleBatchGenerate = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
}
- const ids = selectedRows.value.map((item) => item.id);
-
- ElMessageBox.confirm("纭鎵归噺鐢熸垚鏁版嵁锛�", "鎵归噺鐢熸垚", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "info",
- })
- .then(() => {
- proxy.$modal.loading("姝e湪鎵归噺鐢熸垚鏁版嵁锛岃绋嶅��...");
- batchGeneratePurchaseInboundSteps({ ids })
- .then((res) => {
- proxy.$modal.msgSuccess("鎵归噺鐢熸垚鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鎵归噺鐢熸垚澶辫触");
- })
- .finally(() => {
- proxy.$modal.closeLoading();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ } catch (error) {
+ if (error !== "cancel") {
+ console.error("鍒犻櫎妯℃澘澶辫触:", error);
+ ElMessage({
+ message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
+ type: "error",
});
- };
-
- // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
- function getCurrentDate() {
- const today = new Date();
- const year = today.getFullYear();
- const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
- const day = String(today.getDate()).padStart(2, "0");
- return `${year}-${month}-${day}`;
+ }
}
+};
- const mathNum = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (!productForm.value.taxInclusiveUnitPrice) {
- return;
- }
- if (!productForm.value.quantity) {
- return;
- }
- // 鍚◣鎬讳环璁$畻
- productForm.value.taxInclusiveTotalPrice =
- proxy.calculateTaxIncludeTotalPrice(
- productForm.value.taxInclusiveUnitPrice,
- productForm.value.quantity
- );
- if (productForm.value.taxRate) {
- // 涓嶅惈绋庢�讳环璁$畻
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
- };
- const reverseMathNum = field => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- const taxRate = Number(productForm.value.taxRate);
- if (!taxRate) return;
-
- // 纭繚杈撳叆鍊间笉涓鸿礋鏁�
- if (
- field === "taxInclusiveTotalPrice" ||
- field === "taxExclusiveTotalPrice"
- ) {
- const value = Number(productForm.value[field]);
- if (value < 0) {
- productForm.value[field] = "0";
- proxy.$modal.msgWarning("鍊间笉鑳藉皬浜�0");
- return;
- }
- }
-
- if (field === "taxInclusiveTotalPrice") {
- // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
- if (productForm.value.quantity) {
- productForm.value.taxInclusiveUnitPrice = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.quantity)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
- productForm.value.taxInclusiveUnitPrice = "0";
- }
- }
- // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
- else if (productForm.value.taxInclusiveUnitPrice) {
- productForm.value.quantity = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.taxInclusiveUnitPrice)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.quantity) < 0) {
- productForm.value.quantity = "0";
- }
- }
- // 鍙嶇畻涓嶅惈绋庢�讳环
- productForm.value.taxExclusiveTotalPrice = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- (1 + taxRate / 100)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxExclusiveTotalPrice) < 0) {
- productForm.value.taxExclusiveTotalPrice = "0";
- }
- } else if (field === "taxExclusiveTotalPrice") {
- // 鍙嶇畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (
- Number(productForm.value.taxExclusiveTotalPrice) *
- (1 + taxRate / 100)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxInclusiveTotalPrice) < 0) {
- productForm.value.taxInclusiveTotalPrice = "0";
- }
- // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
- if (productForm.value.quantity) {
- productForm.value.taxInclusiveUnitPrice = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.quantity)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
- productForm.value.taxInclusiveUnitPrice = "0";
- }
- }
- // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
- else if (productForm.value.taxInclusiveUnitPrice) {
- productForm.value.quantity = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.taxInclusiveUnitPrice)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.quantity) < 0) {
- productForm.value.quantity = "0";
- }
- }
- }
- };
- // 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
- const salesLedgerChange = async row => {
- console.log("row", row);
- var index = salesContractList.value.findIndex(item => item.id == row);
- console.log("index", index);
- if (index > -1) {
- await querygProductInfoByContractNo();
- }
- };
-
- const querygProductInfoByContractNo = async () => {
- const { code, data } = await getProductInfoByContractNo({
- contractNo: form.value.salesLedgerId,
- });
- if (code == 200) {
- productData.value = data || [];
- }
- };
-
- // 鑾峰彇妯℃澘淇℃伅
- const getTemplateList = async () => {
- let res = await getPurchaseTemplateList();
- if (res && res.code === 200 && Array.isArray(res.data)) {
- templateList.value = res.data;
- }
- };
-
- // 鎵撳紑闄勪欢寮规
- const openFileDialog = async row => {
- recordId.value = row.id;
- fileListDialogVisible.value = true;
- };
-
- // 鍒犻櫎妯℃澘
- const handleDeleteTemplate = async item => {
- if (!item.id) {
- proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
- return;
- }
-
- try {
- await ElMessageBox.confirm(
- `纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
- "鍒犻櫎纭",
- {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }
- );
-
- const res = await delPurchaseTemplate([item.id]);
- if (res && res.code === 200) {
- ElMessage({
- message: "鍒犻櫎鎴愬姛",
- type: "success",
- });
- // 濡傛灉鍒犻櫎鐨勬槸褰撳墠閫変腑鐨勬ā鏉匡紝娓呯┖閫夋嫨
- if (templateName.value === item.templateName) {
- templateName.value = "";
- filterInputValue.value = "";
- }
- // 閲嶆柊鑾峰彇妯℃澘鍒楄〃
- await getTemplateList();
- } else {
- ElMessage({
- message: res?.msg || "鍒犻櫎澶辫触",
- type: "error",
- });
- }
- } catch (error) {
- if (error !== "cancel") {
- console.error("鍒犻櫎妯℃澘澶辫触:", error);
- ElMessage({
- message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
- type: "error",
- });
- }
- }
- };
-
- onMounted(() => {
- getList();
- getTemplateList();
- });
+onMounted(() => {
+ getList();
+ getTemplateList();
+});
</script>
<style scoped lang="scss">
- .invalid-row {
- opacity: 0.6;
- background-color: #f5f7fa;
- }
+.invalid-row {
+ opacity: 0.6;
+ background-color: #f5f7fa;
+}
- .el-row {
- justify-content: space-between;
- align-items: center;
- }
+.el-row {
+ justify-content: space-between;
+ align-items: center;
+}
- .no-arrow-select {
- --el-select-suffix-icon-color: transparent; /* 闅愯棌榛樿涓嬫媺绠ご */
- }
+.no-arrow-select {
+ --el-select-suffix-icon-color: transparent;
+ /* 闅愯棌榛樿涓嬫媺绠ご */
+}
- .select-button-group {
- display: flex;
- align-items: center;
- }
+.readonly-text {
+ display: inline-block;
+ width: 100%;
+ padding: 0 15px;
+ height: 32px;
+ line-height: 32px;
+ background-color: var(--el-fill-color-light);
+ border-radius: var(--el-border-radius-base);
+ color: var(--el-text-color-regular);
+ font-size: var(--el-font-size-base);
+ box-sizing: border-box;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
- // 瀹℃壒浜鸿妭鐐瑰鍣ㄦ牱寮�
- .approver-nodes-container {
- display: flex;
- flex-wrap: wrap;
- gap: 16px;
- padding: 16px;
- background-color: #f8f9fa;
- border-radius: 4px;
- border: 1px solid #e4e7ed;
- }
+.readonly-text-area {
+ width: 100%;
+ min-height: 52px;
+ padding: 5px 15px;
+ background-color: var(--el-fill-color-light);
+ border-radius: var(--el-border-radius-base);
+ color: var(--el-text-color-regular);
+ font-size: var(--el-font-size-base);
+ box-sizing: border-box;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+.detail-file-list {
+ width: 100%;
+ padding: 10px 15px;
+ background-color: var(--el-fill-color-light);
+ border-radius: var(--el-border-radius-base);
+}
+
+.detail-file-item {
+ line-height: 24px;
+ margin-bottom: 5px;
+}
+
+.detail-file-item:last-child {
+ margin-bottom: 0;
+}
+
+.select-button-group {
+ display: flex;
+ align-items: center;
+}
+
+// 瀹℃壒浜鸿妭鐐瑰鍣ㄦ牱寮�
+.approver-nodes-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ padding: 16px;
+ background-color: #f8f9fa;
+ border-radius: 4px;
+ border: 1px solid #e4e7ed;
+}
+
+.approver-node-item {
+ flex: 0 0 calc(33.333% - 12px);
+ min-width: 200px;
+ padding: 12px;
+ background-color: #fff;
+ border-radius: 4px;
+ border: 1px solid #dcdfe6;
+ transition: all 0.3s;
+
+ &:hover {
+ border-color: #409eff;
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
+ }
+}
+
+.approver-node-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+}
+
+.approver-node-label {
+ font-size: 13px;
+ font-weight: 500;
+ color: #606266;
+}
+
+@media (max-width: 1200px) {
.approver-node-item {
- flex: 0 0 calc(33.333% - 12px);
- min-width: 200px;
- padding: 12px;
- background-color: #fff;
- border-radius: 4px;
- border: 1px solid #dcdfe6;
- transition: all 0.3s;
-
- &:hover {
- border-color: #409eff;
- box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
- }
+ flex: 0 0 calc(50% - 8px);
}
+}
- .approver-node-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 8px;
+@media (max-width: 768px) {
+ .approver-node-item {
+ flex: 0 0 100%;
}
+}
- .approver-node-label {
- font-size: 13px;
- font-weight: 500;
- color: #606266;
+// 鍒犻櫎鍥炬爣鏍峰紡
+.delete-icon {
+ transition: all 0.3s;
+
+ &:hover {
+ color: #f56c6c !important;
+ transform: scale(1.2);
}
-
- @media (max-width: 1200px) {
- .approver-node-item {
- flex: 0 0 calc(50% - 8px);
- }
- }
-
- @media (max-width: 768px) {
- .approver-node-item {
- flex: 0 0 100%;
- }
- }
-
- // 鍒犻櫎鍥炬爣鏍峰紡
- .delete-icon {
- transition: all 0.3s;
-
- &:hover {
- color: #f56c6c !important;
- transform: scale(1.2);
- }
- }
+}
</style>
diff --git a/src/views/procurementManagement/procurementPlan/index.vue b/src/views/procurementManagement/procurementPlan/index.vue
index ba9a38c..42a1bcf 100644
--- a/src/views/procurementManagement/procurementPlan/index.vue
+++ b/src/views/procurementManagement/procurementPlan/index.vue
@@ -1,205 +1,158 @@
<template>
<div class="app-container">
<!-- 鎼滅储鍖哄煙 -->
- <el-card class="search-card"
- shadow="never">
- <el-form :model="searchForm"
- :inline="true"
- class="search-form">
+ <el-card class="search-card" shadow="never">
+ <el-form :model="searchForm" :inline="true" class="search-form">
<el-form-item label="璁″垝鍚嶇О">
- <el-input v-model="searchForm.planName"
- placeholder="璇疯緭鍏ヨ鍒掑悕绉�"
- clearable />
+ <el-input v-model="searchForm.planName" placeholder="璇疯緭鍏ヨ鍒掑悕绉�" clearable />
</el-form-item>
<el-form-item label="鐘舵��">
- <el-select v-model="searchForm.status"
- placeholder="璇烽�夋嫨鐘舵��"
- clearable
- style="width: 150px">
- <el-option label="鍚敤"
- value="active" />
- <el-option label="绂佺敤"
- value="disabled" />
+ <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px">
+ <el-option label="鍚敤" value="active" />
+ <el-option label="绂佺敤" value="disabled" />
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary"
- @click="handleSearch">
- <el-icon>
- <Search />
- </el-icon>
+ <el-button type="primary" @click="handleSearch">
+ <el-icon><Search /></el-icon>
鎼滅储
</el-button>
<el-button @click="handleReset">
- <el-icon>
- <Refresh />
- </el-icon>
+ <el-icon><Refresh /></el-icon>
閲嶇疆
</el-button>
</el-form-item>
</el-form>
</el-card>
+
<!-- 鎿嶄綔鎸夐挳 -->
- <el-card class="table-card"
- shadow="never">
+ <el-card class="table-card" shadow="never">
<div class="table-header">
<div class="table-title">閲囪喘璁″垝鍒楄〃</div>
<div class="table-actions">
- <el-button type="primary"
- @click="handleAdd">
- <el-icon>
- <Plus />
- </el-icon>
+ <el-button type="primary" @click="handleAdd">
+ <el-icon><Plus /></el-icon>
鏂板璁″垝
</el-button>
- <el-button type="info"
- @click="handleExport">
- <el-icon>
- <Download />
- </el-icon>
+ <el-button type="info" @click="handleExport">
+ <el-icon><Download /></el-icon>
瀵煎嚭
</el-button>
</div>
</div>
+
<!-- 鏁版嵁琛ㄦ牸 -->
- <el-table v-loading="loading"
- :data="tableData"
- stripe
- border
- style="width: 100%">
- <el-table-column prop="planName"
- label="璁″垝鍚嶇О"
- min-width="150" />
- <el-table-column prop="description"
- label="鎻忚堪"
- min-width="200"
- show-overflow-tooltip />
- <el-table-column prop="formula"
- label="璁$畻鍏紡"
- min-width="200"
- show-overflow-tooltip>
+ <el-table
+ v-loading="loading"
+ :data="tableData"
+ stripe
+ border
+ style="width: 100%"
+ >
+ <el-table-column prop="planName" label="璁″垝鍚嶇О" min-width="150" />
+ <el-table-column prop="description" label="鎻忚堪" min-width="200" show-overflow-tooltip />
+ <el-table-column prop="formula" label="璁$畻鍏紡" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
- <el-tag type="info"
- size="small">{{ row.formula }}</el-tag>
+ <el-tag type="info" size="small">{{ row.formula }}</el-tag>
</template>
</el-table-column>
- <el-table-column prop="status"
- label="鐘舵��"
- width="80"
- align="center">
+ <el-table-column prop="status" label="鐘舵��" width="80" align="center">
<template #default="{ row }">
- <el-tag :type="row.status === 'active' ? 'success' : 'info'"
- size="small">
+ <el-tag :type="row.status === 'active' ? 'success' : 'info'" size="small">
{{ row.status === 'active' ? '鍚敤' : '绂佺敤' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column prop="updateTime"
- label="鏈�鍚庤绠楁椂闂�"
- width="160" />
- <el-table-column label="鎿嶄綔"
- width="200"
- fixed="right"
- align="center">
+ <el-table-column prop="updateTime" label="鏈�鍚庤绠楁椂闂�" width="160" />
+ <el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
<template #default="{ row }">
- <el-button type="primary"
- link
- @click="handleEdit(row)">缂栬緫</el-button>
- <el-button type="success"
- link
- @click="handleCalculate(row)">璁$畻</el-button>
- <el-button type="danger"
- link
- @click="handleDelete(row)">鍒犻櫎</el-button>
+ <el-button type="primary" link @click="handleEdit(row)">缂栬緫</el-button>
+ <el-button type="success" link @click="handleCalculate(row)">璁$畻</el-button>
+ <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
+
<!-- 鍒嗛〉 -->
<div class="pagination-container">
- <el-pagination v-model:current-page="pagination.current"
- v-model:page-size="pagination.size"
- :page-sizes="[10, 20, 50, 100]"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange" />
+ <el-pagination
+ v-model:current-page="pagination.current"
+ v-model:page-size="pagination.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
</div>
</el-card>
+
<!-- 鏂板/缂栬緫瀵硅瘽妗� -->
- <FormDialog v-model="dialogVisible"
- :title="dialogType === 'add' ? '鏂板閲囪喘璁″垝' : '缂栬緫閲囪喘璁″垝'"
- :width="'1000px'"
- :operation-type="dialogType"
- :close-on-click-modal="false"
- @close="dialogVisible = false"
- @confirm="handleSubmit"
- @cancel="dialogVisible = false">
+ <FormDialog
+ v-model="dialogVisible"
+ :title="dialogType === 'add' ? '鏂板閲囪喘璁″垝' : '缂栬緫閲囪喘璁″垝'"
+ :width="'1000px'"
+ :operation-type="dialogType"
+ :close-on-click-modal="false"
+ @close="dialogVisible = false"
+ @confirm="handleSubmit"
+ @cancel="dialogVisible = false"
+ >
<div class="form-container">
<!-- 鍩烘湰淇℃伅 -->
<div class="form-section">
<div class="section-title">鍩烘湰淇℃伅</div>
- <el-form ref="formRef"
- :model="formData"
- :rules="formRules"
- label-width="120px">
+ <el-form
+ ref="formRef"
+ :model="formData"
+ :rules="formRules"
+ label-width="120px"
+ >
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="缂栫爜"
- prop="code">
- <el-input v-model="formData.code"
- placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�"
- disabled />
+ <el-form-item label="缂栫爜" prop="code">
+ <el-input v-model="formData.code" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鍚嶇О"
- prop="planName"
- required>
- <el-input v-model="formData.planName"
- placeholder="璇疯緭鍏ヨ鍒掑悕绉�" />
+ <el-form-item label="鍚嶇О" prop="planName" required>
+ <el-input v-model="formData.planName" placeholder="璇疯緭鍏ヨ鍒掑悕绉�" />
</el-form-item>
</el-col>
</el-row>
- <el-form-item label="鎻忚堪"
- prop="description">
- <el-input v-model="formData.description"
- type="textarea"
- :rows="3"
- placeholder="璇疯緭鍏ヨ鍒掓弿杩�" />
+
+ <el-form-item label="鎻忚堪" prop="description">
+ <el-input
+ v-model="formData.description"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヨ鍒掓弿杩�"
+ />
</el-form-item>
+
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鐘舵��"
- prop="status">
- <el-select v-model="formData.status"
- placeholder="璇烽�夋嫨鐘舵��"
- style="width: 100%">
- <el-option label="鍚敤"
- value="active" />
- <el-option label="绂佺敤"
- value="disabled" />
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="formData.status" placeholder="璇烽�夋嫨鐘舵��" style="width: 100%">
+ <el-option label="鍚敤" value="active" />
+ <el-option label="绂佺敤" value="disabled" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
- <el-date-picker v-model="formCreateTimeDate"
- type="date"
- placeholder="閫夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- style="width: 100%" />
+ <el-form-item label="鏄惁绯荤粺棰勭疆">
+ <el-checkbox v-model="formData.isSystemPreset">鏄�</el-checkbox>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
+
<!-- 璁$畻鍙傛暟 -->
<div class="form-section">
<div class="section-title">璁$畻鍙傛暟</div>
- <el-tabs v-model="activeTab"
- class="param-tabs">
- <el-tab-pane label="闇�姹傚弬鏁�"
- name="demand">
+ <el-tabs v-model="activeTab" class="param-tabs">
+ <el-tab-pane label="闇�姹傚弬鏁�" name="demand">
<div class="checkbox-group">
<el-checkbox v-model="formData.considerExistingStock">鑰冭檻鐜版湁搴撳瓨</el-checkbox>
<el-checkbox v-model="formData.warehouseControl">浠撳簱杩愯MRP鐨勬帶鍒�</el-checkbox>
@@ -210,8 +163,7 @@
<el-checkbox v-model="formData.negativeStockAsDemand">璐熷簱瀛樹綔涓洪渶姹�</el-checkbox>
</div>
</el-tab-pane>
- <el-tab-pane label="璁$畻鍙傛暟"
- name="calculation">
+ <el-tab-pane label="璁$畻鍙傛暟" name="calculation">
<div class="checkbox-group">
<el-checkbox v-model="formData.considerExistingStock">鑰冭檻鐜版湁搴撳瓨</el-checkbox>
<el-checkbox v-model="formData.warehouseControl">浠撳簱杩愯MRP鐨勬帶鍒�</el-checkbox>
@@ -224,6 +176,7 @@
</el-tab-pane>
</el-tabs>
</div>
+
<!-- 姹囨�诲悎骞堕�夐」 -->
<div class="form-section">
<div class="section-title">姹囨�诲悎骞堕�夐」</div>
@@ -233,20 +186,20 @@
<el-checkbox v-model="formData.summaryDemandDate">闇�姹傛棩鏈�</el-checkbox>
</div>
</div>
+
<!-- 璁$畻鍏紡 -->
<div class="form-section">
<div class="section-title">璁$畻鍏紡</div>
<div class="formula-input-section">
- <el-form-item label="璁$畻鍏紡"
- prop="formula"
- required>
- <el-input v-model="formData.formula"
- placeholder="渚嬪: 棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺"
- @input="validateFormula" />
+ <el-form-item label="璁$畻鍏紡" prop="formula" required>
+ <el-input
+ v-model="formData.formula"
+ placeholder="渚嬪: 棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺"
+ @input="validateFormula"
+ />
</el-form-item>
<div class="formula-help">
- <el-text type="info"
- size="small">
+ <el-text type="info" size="small">
鏀寔鍙橀噺锛氶璁″嚭搴撴暟閲忋�佺幇鏈夊簱瀛樸�佸畨鍏ㄥ簱瀛樸�侀璁″叆搴撴暟閲�
</el-text>
</div>
@@ -254,117 +207,87 @@
</div>
</div>
</FormDialog>
+
<!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
- <FormDialog v-model="productSelectDialogVisible"
- title="閫夋嫨浜у搧"
- :width="'800px'"
- :close-on-click-modal="false"
- @close="productSelectDialogVisible = false"
- @confirm="handleConfirmProductSelection"
- @cancel="productSelectDialogVisible = false">
+ <FormDialog
+ v-model="productSelectDialogVisible"
+ title="閫夋嫨浜у搧"
+ :width="'800px'"
+ :close-on-click-modal="false"
+ @close="productSelectDialogVisible = false"
+ @confirm="handleConfirmProductSelection"
+ @cancel="productSelectDialogVisible = false"
+ >
<div class="product-select">
- <el-alert title="璇烽�夋嫨瑕佽绠楃殑浜у搧"
- type="info"
- :closable="false"
- show-icon>
+ <el-alert
+ title="璇烽�夋嫨瑕佽绠楃殑浜у搧"
+ type="info"
+ :closable="false"
+ show-icon
+ >
<template #default>
<p>閫夋嫨浜у搧鍚庯紝绯荤粺灏嗘牴鎹綋鍓嶈绠楀叕寮忓拰浜у搧搴撳瓨鎯呭喌杩涜璁$畻銆�</p>
</template>
</el-alert>
- <el-table v-loading="productLoading"
- :data="productList"
- @selection-change="handleProductSelectionChange"
- stripe
- border
- style="width: 100%; margin-top: 20px;">
- <el-table-column type="selection"
- width="55" />
- <el-table-column prop="productCategory"
- label="浜у搧澶х被"
- min-width="150" />
- <el-table-column prop="specificationModel"
- label="瑙勬牸鍨嬪彿"
- width="120" />
- <el-table-column prop="inboundNum0"
- label="鐜版湁搴撳瓨"
- width="100"
- align="right" />
- <el-table-column prop="inboundNum"
- label="瀹夊叏搴撳瓨"
- width="100"
- align="right" />
- <el-table-column prop="inboundNum"
- label="棰勮鍑哄簱"
- width="100"
- align="right" />
- <el-table-column prop="inboundNum0"
- label="棰勮鍏ュ簱"
- width="100"
- align="right" />
+
+ <el-table
+ v-loading="productLoading"
+ :data="productList"
+ @selection-change="handleProductSelectionChange"
+ stripe
+ border
+ style="width: 100%; margin-top: 20px;"
+ >
+ <el-table-column type="selection" width="55" />
+ <el-table-column prop="productCategory" label="浜у搧澶х被" min-width="150" />
+ <el-table-column prop="specificationModel" label="浜у搧瑙勬牸" width="120" />
+ <el-table-column prop="inboundNum0" label="鐜版湁搴撳瓨" width="100" align="right" />
+ <el-table-column prop="inboundNum" label="瀹夊叏搴撳瓨" width="100" align="right" />
+ <el-table-column prop="inboundNum" label="棰勮鍑哄簱" width="100" align="right" />
+ <el-table-column prop="inboundNum0" label="棰勮鍏ュ簱" width="100" align="right" />
</el-table>
</div>
</FormDialog>
+
<!-- 璁$畻缁撴灉瀵硅瘽妗� -->
- <FormDialog v-model="calculateDialogVisible"
- title="閲囪喘璁$畻缁撴灉"
- :width="'1000px'"
- :close-on-click-modal="false"
- @close="calculateDialogVisible = false"
- @confirm="handleCreatePurchaseOrder"
- @cancel="calculateDialogVisible = false">
+ <FormDialog
+ v-model="calculateDialogVisible"
+ title="閲囪喘璁$畻缁撴灉"
+ :width="'1000px'"
+ :close-on-click-modal="false"
+ @close="calculateDialogVisible = false"
+ @confirm="handleCreatePurchaseOrder"
+ @cancel="calculateDialogVisible = false"
+ >
<div class="calculate-result">
- <el-alert title="璁$畻缁撴灉"
- type="success"
- :closable="false"
- show-icon>
+ <el-alert
+ title="璁$畻缁撴灉"
+ type="success"
+ :closable="false"
+ show-icon
+ >
<template #default>
<p>鍩轰簬褰撳墠閰嶇疆鐨勮绠楀叕寮忓拰搴撳瓨鎯呭喌锛岀郴缁熷凡璁$畻鍑哄悇浜у搧鐨勯噰璐渶姹傘��</p>
</template>
</el-alert>
- <el-table :data="calculateResult"
- stripe
- border
- style="width: 100%; margin-top: 20px;">
- <el-table-column prop="productCategory"
- label="浜у搧澶х被"
- min-width="150" />
- <el-table-column prop="specificationModel"
- label="瑙勬牸鍨嬪彿"
- width="120" />
- <el-table-column prop="inboundNum0"
- label="鐜版湁搴撳瓨"
- width="100"
- align="right" />
- <el-table-column prop="inboundNum"
- label="瀹夊叏搴撳瓨"
- width="100"
- align="right" />
- <el-table-column prop="inboundNum"
- label="棰勮鍑哄簱鏁伴噺"
- width="120"
- align="right" />
- <el-table-column prop="inboundNum0"
- label="棰勮鍏ュ簱鏁伴噺"
- width="120"
- align="right" />
- <el-table-column prop="weeklyNetDemand"
- label="鎸夊懆鍑�闇�姹�"
- width="120"
- align="right">
+
+ <el-table :data="calculateResult" stripe border style="width: 100%; margin-top: 20px;">
+ <el-table-column prop="productCategory" label="浜у搧澶х被" min-width="150" />
+ <el-table-column prop="specificationModel" label="浜у搧瑙勬牸" width="120" />
+ <el-table-column prop="inboundNum0" label="鐜版湁搴撳瓨" width="100" align="right" />
+ <el-table-column prop="inboundNum" label="瀹夊叏搴撳瓨" width="100" align="right" />
+ <el-table-column prop="inboundNum" label="棰勮鍑哄簱鏁伴噺" width="120" align="right" />
+ <el-table-column prop="inboundNum0" label="棰勮鍏ュ簱鏁伴噺" width="120" align="right" />
+ <el-table-column prop="weeklyNetDemand" label="鎸夊懆鍑�闇�姹�" width="120" align="right">
<template #default="{ row }">
- <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'"
- size="small">
+ <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'" size="small">
{{ row.weeklyNetDemand }}
</el-tag>
</template>
</el-table-column>
- <el-table-column prop="suggestedPurchase"
- label="寤鸿閲囪喘"
- width="100"
- align="right">
+ <el-table-column prop="suggestedPurchase" label="寤鸿閲囪喘" width="100" align="right">
<template #default="{ row }">
- <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'"
- size="small">
+ <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'" size="small">
{{ row.suggestedPurchase }}
</el-tag>
</template>
@@ -376,51 +299,214 @@
</template>
<script setup>
- import FormDialog from "@/components/Dialog/FormDialog.vue";
- import { ref, reactive, onMounted, getCurrentInstance, computed } from "vue";
- import dayjs from "dayjs";
- import { ElMessage, ElMessageBox } from "element-plus";
- import { Search, Refresh, Plus, Download } from "@element-plus/icons-vue";
- import {
- listPage,
- add,
- update,
- del,
- listPageCopy,
- } from "@/api/procurementManagement/procurementPlan.js";
+import FormDialog from '@/components/Dialog/FormDialog.vue';
+import {ref, reactive, onMounted, getCurrentInstance} from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Search, Refresh, Plus, Download } from '@element-plus/icons-vue'
+import {listPage,add,update,del,listPageCopy} from "@/api/procurementManagement/procurementPlan.js"
- // 鍝嶅簲寮忔暟鎹�
- const loading = ref(false);
- const submitLoading = ref(false);
- const dialogVisible = ref(false);
- const productSelectDialogVisible = ref(false);
- const calculateDialogVisible = ref(false);
- const dialogType = ref("add");
- const productLoading = ref(false);
- const selectedProducts = ref([]);
- const currentPlan = ref(null);
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+const submitLoading = ref(false)
+const dialogVisible = ref(false)
+const productSelectDialogVisible = ref(false)
+const calculateDialogVisible = ref(false)
+const dialogType = ref('add')
+const productLoading = ref(false)
+const selectedProducts = ref([])
+const currentPlan = ref(null)
- // 鎼滅储琛ㄥ崟
- const searchForm = reactive({
- planName: "",
- status: "",
- });
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+ planName: '',
+ status: ''
+})
- // 鍒嗛〉鏁版嵁
- const pagination = reactive({
- current: 1,
- size: 20,
- });
+// 鍒嗛〉鏁版嵁
+const pagination = reactive({
+ current: 1,
+ size: 20
+})
- // 琛ㄥ崟鏁版嵁
- const formData = reactive({
- code: "",
- planName: "",
- description: "",
- status: "",
+// 琛ㄥ崟鏁版嵁
+const formData = reactive({
+ code: '',
+ planName: '',
+ description: '',
+ status: '',
+ isSystemPreset: false,
+ formula: '',
+ // 璁$畻鍙傛暟
+ considerExistingStock: false,
+ warehouseControl: false,
+ calculateTotalDemand: false,
+ considerSafetyStock: false,
+ considerLockedStock: false,
+ notConsiderMaterialAux: false,
+ negativeStockAsDemand: false,
+ // 姹囨�诲悎骞堕�夐」
+ summaryMaterial: false,
+ summaryAuxAttributes: false,
+ summaryDemandDate: false
+})
+
+// 褰撳墠婵�娲荤殑鏍囩椤�
+const activeTab = ref('demand')
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const formRules = {
+ planName: [
+ { required: true, message: '璇疯緭鍏ヨ鍒掑悕绉�', trigger: 'blur' }
+ ],
+ status: [
+ { required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }
+ ],
+ formula: [
+ { required: true, message: '璇疯緭鍏ヨ绠楀叕寮�', trigger: 'blur' }
+ ]
+}
+
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([])
+
+// 浜у搧鍒楄〃鏁版嵁
+const productList = ref([
+ {
+ id: 4,
+ productName: '浜у搧D',
+ productCode: 'PD004',
+ existingStock: 90,
+ safetyStock: 40,
+ expectedOutbound: 160,
+ expectedInbound: 35
+ }
+])
+
+// 璁$畻缁撴灉鏁版嵁
+const calculateResult = ref([
+ {
+ productName: '浜у搧A',
+ existingStock: 100,
+ safetyStock: 50,
+ expectedOutbound: 200,
+ expectedInbound: 30,
+ weeklyNetDemand: 120,
+ suggestedPurchase: 150
+ },
+ {
+ productName: '浜у搧B',
+ existingStock: 80,
+ safetyStock: 30,
+ expectedOutbound: 150,
+ expectedInbound: 20,
+ weeklyNetDemand: 100,
+ suggestedPurchase: 120
+ }
+])
+const total = ref(0)
+// 鏂规硶
+const handleSearch = () => {
+ pagination.current = 1
+ loadData()
+}
+
+const handleReset = () => {
+ Object.assign(searchForm, {
+ planName: '',
+ status: ''
+ })
+ handleSearch()
+}
+
+const loadData = () => {
+ loading.value = true
+ listPage({...searchForm,...pagination}).then(res => {
+ if(res.code === 200){
+ tableData.value = res.data.records
+ total.value = res.data.total
+ loading.value = false
+ }
+ })
+}
+
+const handleAdd = () => {
+ dialogType.value = 'add'
+ resetForm()
+ // 鑷姩鐢熸垚缂栫爜
+ formData.code = 'CGJH' + String(Date.now()).slice(-4)
+ dialogVisible.value = true
+}
+
+const handleEdit = (row) => {
+ dialogType.value = 'edit'
+ Object.assign(formData, row)
+ dialogVisible.value = true
+}
+
+const handleDelete = async (row) => {
+ try {
+ await ElMessageBox.confirm('纭畾瑕佸垹闄よ繖涓噰璐鍒掑悧锛�', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ })
+ let ids = [row.id]
+ del(ids).then(res =>{
+ if(res.code === 200){
+ ElMessage.success('鍒犻櫎鎴愬姛')
+ loadData()
+ }
+ })
+ } catch {
+ // 鐢ㄦ埛鍙栨秷鍒犻櫎
+ }
+}
+
+const handleSubmit = async () => {
+ try {
+ // 琛ㄥ崟楠岃瘉
+ if (!formData.planName || !formData.formula) {
+ ElMessage.error('璇峰~鍐欏繀濉」')
+ return
+ }
+
+ submitLoading.value = true
+
+ if (dialogType.value === 'add') {
+ add(formData).then(res => {
+ if(res.code === 200){
+ ElMessage.success('鏂板鎴愬姛')
+ dialogVisible.value = false
+ loadData()
+ }
+ })
+ } else {
+ // 缂栬緫
+ update(formData).then(res => {
+ if(res.code === 200){
+ ElMessage.success('缂栬緫鎴愬姛')
+ dialogVisible.value = false
+ loadData()
+ }
+ })
+ }
+
+
+ } catch (error) {
+ ElMessage.error('鎿嶄綔澶辫触')
+ } finally {
+ submitLoading.value = false
+ }
+}
+
+const resetForm = () => {
+ Object.assign(formData, {
+ code: '',
+ planName: '',
+ description: '',
+ status: '',
isSystemPreset: false,
- formula: "",
- createTime: "",
+ formula: '棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺',
// 璁$畻鍙傛暟
considerExistingStock: false,
warehouseControl: false,
@@ -432,425 +518,255 @@
// 姹囨�诲悎骞堕�夐」
summaryMaterial: false,
summaryAuxAttributes: false,
- summaryDemandDate: false,
- });
- const formCreateTimeDate = computed({
- get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""),
- set: (value) => {
- formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
- });
+ summaryDemandDate: false
+ })
+ activeTab.value = 'demand'
+}
- // 褰撳墠婵�娲荤殑鏍囩椤�
- const activeTab = ref("demand");
+const validateFormula = () => {
+ // 绠�鍗曠殑鍏紡楠岃瘉
+ const formula = formData.formula
+ if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) {
+ ElMessage.warning('鍏紡鏍煎紡鍙兘涓嶆纭紝璇锋鏌�')
+ }
+}
- // 琛ㄥ崟楠岃瘉瑙勫垯
- const formRules = {
- planName: [{ required: true, message: "璇疯緭鍏ヨ鍒掑悕绉�", trigger: "blur" }],
- status: [{ required: true, message: "璇烽�夋嫨鐘舵��", trigger: "change" }],
- formula: [{ required: true, message: "璇疯緭鍏ヨ绠楀叕寮�", trigger: "blur" }],
- };
+const handleCalculate = (row) => {
+ currentPlan.value = row
+ productSelectDialogVisible.value = true
+ loadProductList()
+}
- // 琛ㄦ牸鏁版嵁
- const tableData = ref([]);
-
- // 浜у搧鍒楄〃鏁版嵁
- const productList = ref([
- {
- id: 4,
- productName: "浜у搧D",
- productCode: "PD004",
- existingStock: 90,
- safetyStock: 40,
- expectedOutbound: 160,
- expectedInbound: 35,
- },
- ]);
-
- // 璁$畻缁撴灉鏁版嵁
- const calculateResult = ref([
- {
- productName: "浜у搧A",
- existingStock: 100,
- safetyStock: 50,
- expectedOutbound: 200,
- expectedInbound: 30,
- weeklyNetDemand: 120,
- suggestedPurchase: 150,
- },
- {
- productName: "浜у搧B",
- existingStock: 80,
- safetyStock: 30,
- expectedOutbound: 150,
- expectedInbound: 20,
- weeklyNetDemand: 100,
- suggestedPurchase: 120,
- },
- ]);
- const total = ref(0);
- // 鏂规硶
- const handleSearch = () => {
- pagination.current = 1;
- loadData();
- };
-
- const handleReset = () => {
- Object.assign(searchForm, {
- planName: "",
- status: "",
- });
- handleSearch();
- };
-
- const loadData = () => {
- loading.value = true;
- listPage({ ...searchForm, ...pagination }).then(res => {
- if (res.code === 200) {
- tableData.value = res.data.records;
- total.value = res.data.total;
- loading.value = false;
- }
- });
- };
-
- const handleAdd = () => {
- dialogType.value = "add";
- resetForm();
- formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
- dialogVisible.value = true;
- };
-
- const handleEdit = row => {
- dialogType.value = "edit";
- Object.assign(formData, row);
- dialogVisible.value = true;
- };
-
- const handleDelete = async row => {
- try {
- await ElMessageBox.confirm("纭畾瑕佸垹闄よ繖涓噰璐鍒掑悧锛�", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- });
- let ids = [row.id];
- del(ids).then(res => {
- if (res.code === 200) {
- ElMessage.success("鍒犻櫎鎴愬姛");
- loadData();
- }
- });
- } catch {
- // 鐢ㄦ埛鍙栨秷鍒犻櫎
+const loadProductList = () => {
+ productLoading.value = true
+ // 妯℃嫙鍔犺浇浜у搧鏁版嵁
+ listPageCopy({size:-1}).then(res => {
+ if(res.code === 200){
+ productList.value = res.data.records
+ productLoading.value = false
}
- };
+ })
+}
- const handleSubmit = async () => {
- try {
- // 琛ㄥ崟楠岃瘉
- if (!formData.planName || !formData.formula) {
- ElMessage.error("璇峰~鍐欏繀濉」");
- return;
- }
+const handleProductSelectionChange = (selection) => {
+ selectedProducts.value = selection
+}
- submitLoading.value = true;
+const handleConfirmProductSelection = () => {
+ if (selectedProducts.value.length === 0) {
+ ElMessage.warning('璇烽�夋嫨瑕佽绠楃殑浜у搧')
+ return
+ }
+
+ ElMessage.success(`姝e湪璁$畻 ${currentPlan.value.planName} 鐨勯噰璐渶姹�...`)
+ productSelectDialogVisible.value = false
+
+ // 鏍规嵁閫夋嫨鐨勪骇鍝佸拰璁$畻鍏紡杩涜璁$畻
+ calculateWithSelectedProducts()
+}
- if (dialogType.value === "add") {
- add(formData).then(res => {
- if (res.code === 200) {
- ElMessage.success("鏂板鎴愬姛");
- dialogVisible.value = false;
- loadData();
- }
- });
- } else {
- // 缂栬緫
- update(formData).then(res => {
- if (res.code === 200) {
- ElMessage.success("缂栬緫鎴愬姛");
- dialogVisible.value = false;
- loadData();
- }
- });
- }
- } catch (error) {
- ElMessage.error("鎿嶄綔澶辫触");
- } finally {
- submitLoading.value = false;
+const calculateWithSelectedProducts = () => {
+ // 妯℃嫙璁$畻杩囩▼
+ // 鏍规嵁閫夋嫨鐨勪骇鍝佹洿鏂拌绠楃粨鏋�
+ const result = selectedProducts.value.map(product => {
+ // 杩欓噷搴旇鏍规嵁瀹為檯鐨勮绠楀叕寮忚繘琛岃绠�
+ // 绀轰緥锛氶璁″嚭搴撴暟閲� - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺
+ const weeklyNetDemand = product.inboundNum - product.inboundNum0 + product.inboundNum - product.inboundNum0
+ const suggestedPurchase = Math.max(0, weeklyNetDemand)
+
+ return {
+ productCategory: product.productCategory,
+ specificationModel: product.specificationModel,
+ inboundNum0: product.inboundNum0,
+ inboundNum: product.inboundNum,
+ weeklyNetDemand: weeklyNetDemand,
+ suggestedPurchase: suggestedPurchase
}
- };
+ })
- const resetForm = () => {
- Object.assign(formData, {
- code: "",
- planName: "",
- description: "",
- status: "",
- isSystemPreset: false,
- formula: "棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺",
- // 璁$畻鍙傛暟
- considerExistingStock: false,
- warehouseControl: false,
- calculateTotalDemand: false,
- considerSafetyStock: false,
- considerLockedStock: false,
- notConsiderMaterialAux: false,
- negativeStockAsDemand: false,
- // 姹囨�诲悎骞堕�夐」
- summaryMaterial: false,
- summaryAuxAttributes: false,
- summaryDemandDate: false,
- });
- activeTab.value = "demand";
- };
+ calculateResult.value = result
+ calculateDialogVisible.value = true
+}
- const validateFormula = () => {
- // 绠�鍗曠殑鍏紡楠岃瘉
- const formula = formData.formula;
- if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) {
- ElMessage.warning("鍏紡鏍煎紡鍙兘涓嶆纭紝璇锋鏌�");
- }
- };
- const handleCalculate = row => {
- currentPlan.value = row;
- productSelectDialogVisible.value = true;
- loadProductList();
- };
-
- const loadProductList = () => {
- productLoading.value = true;
- // 妯℃嫙鍔犺浇浜у搧鏁版嵁
- listPageCopy({ size: -1 }).then(res => {
- if (res.code === 200) {
- productList.value = res.data.records;
- productLoading.value = false;
- }
- });
- };
-
- const handleProductSelectionChange = selection => {
- selectedProducts.value = selection;
- };
-
- const handleConfirmProductSelection = () => {
- if (selectedProducts.value.length === 0) {
- ElMessage.warning("璇烽�夋嫨瑕佽绠楃殑浜у搧");
- return;
- }
-
- ElMessage.success(`姝e湪璁$畻 ${currentPlan.value.planName} 鐨勯噰璐渶姹�...`);
- productSelectDialogVisible.value = false;
-
- // 鏍规嵁閫夋嫨鐨勪骇鍝佸拰璁$畻鍏紡杩涜璁$畻
- calculateWithSelectedProducts();
- };
-
- const calculateWithSelectedProducts = () => {
- // 妯℃嫙璁$畻杩囩▼
- // 鏍规嵁閫夋嫨鐨勪骇鍝佹洿鏂拌绠楃粨鏋�
- const result = selectedProducts.value.map(product => {
- // 杩欓噷搴旇鏍规嵁瀹為檯鐨勮绠楀叕寮忚繘琛岃绠�
- // 绀轰緥锛氶璁″嚭搴撴暟閲� - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺
- const weeklyNetDemand =
- product.inboundNum -
- product.inboundNum0 +
- product.inboundNum -
- product.inboundNum0;
- const suggestedPurchase = Math.max(0, weeklyNetDemand);
-
- return {
- productCategory: product.productCategory,
- specificationModel: product.specificationModel,
- inboundNum0: product.inboundNum0,
- inboundNum: product.inboundNum,
- weeklyNetDemand: weeklyNetDemand,
- suggestedPurchase: suggestedPurchase,
- };
- });
-
- calculateResult.value = result;
- calculateDialogVisible.value = true;
- };
-
- const handleCreatePurchaseOrder = () => {
- calculateDialogVisible.value = false;
- };
- const { proxy } = getCurrentInstance();
- const handleExport = () => {
- ElMessageBox.confirm("鍐呭灏嗚瀵煎嚭锛屾槸鍚︾‘璁ゅ鍑猴紵", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+const handleCreatePurchaseOrder = () => {
+ calculateDialogVisible.value = false
+}
+const { proxy } = getCurrentInstance();
+const handleExport = () => {
+ ElMessageBox.confirm("鍐呭灏嗚瀵煎嚭锛屾槸鍚︾‘璁ゅ鍑猴紵", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
proxy.download("/procurementPlan/export", {}, "閲囪喘璁″垝.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+}
- const handleSizeChange = size => {
- pagination.size = size;
- loadData();
- };
- const handleCurrentChange = current => {
- pagination.current = current;
- loadData();
- };
+const handleSizeChange = (size) => {
+ pagination.size = size
+ loadData()
+}
- // 鐢熷懡鍛ㄦ湡
- onMounted(() => {
- loadData();
- });
+const handleCurrentChange = (current) => {
+ pagination.current = current
+ loadData()
+}
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+ loadData()
+})
</script>
<style scoped>
- .app-container {
- padding: 20px;
- }
+.app-container {
+ padding: 20px;
+}
- .page-header {
- margin-bottom: 20px;
- }
+.page-header {
+ margin-bottom: 20px;
+}
- .page-header h2 {
- margin: 0 0 8px 0;
- color: #303133;
- font-size: 24px;
- font-weight: 600;
- }
+.page-header h2 {
+ margin: 0 0 8px 0;
+ color: #303133;
+ font-size: 24px;
+ font-weight: 600;
+}
- .page-header p {
- margin: 0;
- color: #909399;
- font-size: 14px;
- }
+.page-header p {
+ margin: 0;
+ color: #909399;
+ font-size: 14px;
+}
- .search-card {
- margin-bottom: 20px;
- }
+.search-card {
+ margin-bottom: 20px;
+}
- .search-form {
- margin-bottom: 0;
- }
+.search-form {
+ margin-bottom: 0;
+}
- .table-card {
- margin-bottom: 20px;
- }
+.table-card {
+ margin-bottom: 20px;
+}
- .table-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- }
+.table-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+}
- .table-title {
- font-size: 16px;
- font-weight: 600;
- color: #303133;
- }
+.table-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+}
- .table-actions {
- display: flex;
- gap: 10px;
- }
+.table-actions {
+ display: flex;
+ gap: 10px;
+}
- .pagination-container {
- margin-top: 20px;
- display: flex;
- justify-content: end;
- }
+.pagination-container {
+ margin-top: 20px;
+ display: flex;
+ justify-content: end;
+}
- .form-container {
- padding: 0 20px;
- }
+.form-container {
+ padding: 0 20px;
+}
- .formula-help {
- margin-top: 5px;
- }
+.formula-help {
+ margin-top: 5px;
+}
- .calculate-result {
- padding: 20px 0;
- }
+.calculate-result {
+ padding: 20px 0;
+}
- .dialog-footer {
- text-align: right;
- }
+.dialog-footer {
+ text-align: right;
+}
- :deep(.el-card__body) {
- padding: 20px;
- }
+:deep(.el-card__body) {
+ padding: 20px;
+}
- :deep(.el-table) {
- font-size: 14px;
- }
+:deep(.el-table) {
+ font-size: 14px;
+}
- :deep(.el-form-item__label) {
- font-weight: 500;
- }
+:deep(.el-form-item__label) {
+ font-weight: 500;
+}
- .form-container {
- padding: 0;
- }
+.form-container {
+ padding: 0;
+}
- .form-section {
- margin-bottom: 24px;
- border: 1px solid #e4e7ed;
- border-radius: 6px;
- overflow: hidden;
- }
+.form-section {
+ margin-bottom: 24px;
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ overflow: hidden;
+}
- .section-title {
- background-color: #f5f7fa;
- padding: 12px 16px;
- font-weight: 600;
- color: #303133;
- border-bottom: 1px solid #e4e7ed;
- }
+.section-title {
+ background-color: #f5f7fa;
+ padding: 12px 16px;
+ font-weight: 600;
+ color: #303133;
+ border-bottom: 1px solid #e4e7ed;
+}
- .form-section .el-form {
- padding: 20px;
- }
+.form-section .el-form {
+ padding: 20px;
+}
- .param-tabs {
- padding: 20px;
- }
+.param-tabs {
+ padding: 20px;
+}
- .param-tabs :deep(.el-tabs__header) {
- margin-bottom: 20px;
- }
+.param-tabs :deep(.el-tabs__header) {
+ margin-bottom: 20px;
+}
- .param-tabs :deep(.el-tabs__item.is-active) {
- color: #f56c6c;
- border-bottom-color: #f56c6c;
- }
+.param-tabs :deep(.el-tabs__item.is-active) {
+ color: #f56c6c;
+ border-bottom-color: #f56c6c;
+}
- .checkbox-group {
- display: flex;
- flex-wrap: wrap;
- gap: 16px;
- }
+.checkbox-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+}
- .checkbox-group .el-checkbox {
- margin-right: 0;
- margin-bottom: 8px;
- }
+.checkbox-group .el-checkbox {
+ margin-right: 0;
+ margin-bottom: 8px;
+}
- .formula-input-section {
- padding: 20px;
- }
+.formula-input-section {
+ padding: 20px;
+}
- .formula-input-section .el-form-item {
- margin-bottom: 12px;
- }
+.formula-input-section .el-form-item {
+ margin-bottom: 12px;
+}
- .formula-help {
- text-align: center;
- margin-top: 8px;
- }
+.formula-help {
+ text-align: center;
+ margin-top: 8px;
+}
</style>
diff --git a/src/views/procurementManagement/procurementReport/index.vue b/src/views/procurementManagement/procurementReport/index.vue
index 26e682d..e891868 100644
--- a/src/views/procurementManagement/procurementReport/index.vue
+++ b/src/views/procurementManagement/procurementReport/index.vue
@@ -83,6 +83,7 @@
import PIMTable from '@/components/PIMTable/PIMTable.vue'
import { procurementBusinessSummaryListPage } from '@/api/procurementManagement/procurementReport'
import { productTreeList } from '@/api/basicData/product'
+import { formatDecimal, formatCurrency } from '@/utils/numberFormat'
const { proxy } = getCurrentInstance()
@@ -135,14 +136,14 @@
prop: 'returnAmount',
width: 120,
formatData: (val) => {
- return val ? `楼${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '楼0.00'
+ return val ? formatCurrency(val) : '楼0'
}
},
{
label: '閫�娆惧偍閲�',
prop: 'purchaseAmount',
formatData: (val) => {
- return val ? `楼${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '楼0.00'
+ return val ? formatCurrency(val) : '楼0'
}
},
{
@@ -155,7 +156,7 @@
prop: 'averagePrice',
width: 120,
formatData: (val) => {
- return val ? `楼${parseFloat(val).toFixed(2)}` : '楼0.00'
+ return val ? formatCurrency(val) : '楼0'
}
},
{
diff --git a/src/views/procurementManagement/purchaseOrder/index.vue b/src/views/procurementManagement/purchaseOrder/index.vue
index 4f9812f..7e56cb4 100644
--- a/src/views/procurementManagement/purchaseOrder/index.vue
+++ b/src/views/procurementManagement/purchaseOrder/index.vue
@@ -56,13 +56,6 @@
<el-option label="渚涘簲鍟咮" value="渚涘簲鍟咮" />
</el-select>
</el-form-item>
- <el-form-item label="鍒涘缓鏃堕棿">
- <el-date-picker v-model="formCreateTimeDate"
- type="date"
- placeholder="閫夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- style="width: 100%" />
- </el-form-item>
<el-form-item label="澶囨敞">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" />
</el-form-item>
@@ -73,8 +66,7 @@
<script setup>
import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { ref, reactive, computed } from 'vue'
-import dayjs from 'dayjs'
+import { ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false)
@@ -89,14 +81,7 @@
const formData = reactive({
supplierName: '',
- remark: '',
- createTime: ''
-})
-const formCreateTimeDate = computed({
- get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''),
- set: (value) => {
- formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : ''
- }
+ remark: ''
})
const mockData = [
@@ -137,9 +122,9 @@
const openDialog = (type, row = {}) => {
dialogType.value = type
if (type === 'edit' && row.id) {
- Object.assign(formData, { supplierName: row.supplierName, remark: row.remark, createTime: row.createTime || '' })
+ Object.assign(formData, { supplierName: row.supplierName, remark: row.remark })
} else {
- Object.assign(formData, { supplierName: '', remark: '', createTime: dayjs().format('YYYY-MM-DD HH:mm:ss') })
+ Object.assign(formData, { supplierName: '', remark: '' })
}
dialogVisible.value = true
}
@@ -148,11 +133,11 @@
if (dialogType.value === 'add') {
const newOrder = {
id: Date.now(),
- orderNo: '',
+ orderNo: `PO${Date.now()}`,
supplierName: formData.supplierName,
status: 'draft',
totalAmount: 0,
- createTime: formData.createTime,
+ createTime: new Date().toLocaleString(),
remark: formData.remark
}
tableData.value.unshift(newOrder)
diff --git a/src/views/procurementManagement/purchaseReturnOrder/New.vue b/src/views/procurementManagement/purchaseReturnOrder/New.vue
index 186a552..9474b11 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/New.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/New.vue
@@ -58,63 +58,6 @@
</el-form-item>
<el-form-item
- label="鍙戣揣绫诲瀷"
- prop="shippingType"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨鍙戣揣绫诲瀷',
- trigger: 'change',
- }
- ]"
- >
- <el-select
- v-model="formState.shippingType"
- placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 240px"
- @change="handleShippingTypeChange"
- >
- <el-option label="璐ц溅" :value="1" />
- <el-option label="蹇��" :value="2" />
- </el-select>
- </el-form-item>
-
- <el-form-item
- v-if="formState.shippingType === 1"
- label="鍙戣揣杞︾墝鍙�"
- prop="truckPlateNo"
- >
- <el-input
- v-model="formState.truckPlateNo"
- placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
- style="width: 240px"
- />
- </el-form-item>
-
- <template v-else-if="formState.shippingType === 2">
- <el-form-item
- label="蹇�掑叕鍙�"
- prop="expressCompany"
- >
- <el-input
- v-model="formState.expressCompany"
- placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
- style="width: 240px"
- />
- </el-form-item>
- <el-form-item
- label="蹇�掑崟鍙�"
- prop="expressNo"
- >
- <el-input
- v-model="formState.expressNo"
- placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
- style="width: 240px"
- />
- </el-form-item>
- </template>
-
- <el-form-item
label="渚涘簲鍟嗗悕绉�"
prop="supplierId"
:rules="[
@@ -316,16 +259,13 @@
<el-table-column label="鏁伴噺"
prop="stockInNum"
width="100" />
- <el-table-column label="閿�鍞彂璐ф暟閲�"
- prop="saleOutQuantity"
- width="120" />
<el-table-column label="鍙��璐ф暟閲�"
prop="unQuantity"
width="130" />
<el-table-column label="宸查��璐ф暟閲�"
width="130">
<template #default="scope">
- {{ formattedNumber(scope.row, null, scope.row.totalReturnNum || 0) }}
+ {{ calcAlreadyReturned(scope.row) }}
</template>
</el-table-column>
<el-table-column label="閫�璐ф暟閲�"
@@ -480,7 +420,7 @@
<script setup>
import {ref, computed, getCurrentInstance, watch, defineAsyncComponent} from "vue";
import {createPurchaseReturnOrder} from "@/api/procurementManagement/purchase_return_order.js";
-import {getOptions, purchaseReturnableList} from "@/api/procurementManagement/procurementLedger.js";
+import {getOptions, purchaseList} from "@/api/procurementManagement/procurementLedger.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
const ProductList = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/ProductList.vue"));
const props = defineProps({
@@ -515,10 +455,6 @@
no: '',
isDefaultNo: true,
returnType: 0,
- shippingType: undefined,
- truckPlateNo: '',
- expressCompany: '',
- expressNo: '',
incomeType: undefined,
remark: '',
supplierId: undefined,
@@ -565,19 +501,6 @@
// 鏄惁灞曠ず浜у搧鍒楄〃鏁版嵁
const isShowProductsModal = ref(false)
-const handleShippingTypeChange = (val) => {
- if (val === 1) {
- formState.value.expressCompany = '';
- formState.value.expressNo = '';
- } else if (val === 2) {
- formState.value.truckPlateNo = '';
- } else {
- formState.value.truckPlateNo = '';
- formState.value.expressCompany = '';
- formState.value.expressNo = '';
- }
-};
-
const isShow = computed({
get() {
return props.visible;
@@ -605,6 +528,14 @@
const toNumber = (val) => {
const num = Number(val)
return Number.isNaN(num) ? 0 : num
+}
+
+/** 宸查��璐ф暟閲� = 鍏ュ簱琛屾�绘暟閲� 鈭� 褰撳墠鍙��璐ф暟閲忥紙鍓╀綑锛� */
+const calcAlreadyReturned = (row) => {
+ const total = Number(row?.stockInNum ?? row?.totalQuantity ?? row?.quantity ?? 0)
+ const un = Number(row?.unQuantity ?? 0)
+ if (!Number.isFinite(total) || !Number.isFinite(un)) return 0
+ return Math.max(total - un, 0)
}
const getReturnTotal = (row) => {
@@ -650,10 +581,6 @@
}
const closeModal = () => {
- formState.value.shippingType = undefined;
- formState.value.truckPlateNo = '';
- formState.value.expressCompany = '';
- formState.value.expressNo = '';
isShow.value = false;
};
@@ -747,7 +674,7 @@
const fetchPurchaseLedgerOptions = () => {
purchaseLedgerOptions.value = []
if (formState.value.supplierId) {
- purchaseReturnableList({ supplierId: formState.value.supplierId }).then((res) => {
+ purchaseList({supplierId: formState.value.supplierId,approvalStatus:3}).then((res) => {
purchaseLedgerOptions.value = res.rows;
});
}
@@ -878,4 +805,4 @@
}
-</style>
+</style>
\ No newline at end of file
diff --git a/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue b/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
index 9b3e6f7..27fae4a 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
@@ -34,16 +34,13 @@
<el-table-column label="鏁伴噺"
prop="stockInNum"
width="70" />
- <el-table-column label="閿�鍞彂璐ф暟閲�"
- prop="saleOutQuantity"
- width="120" />
<el-table-column label="鍙��璐ф暟閲�"
prop="unQuantity"
width="130" />
<el-table-column label="宸查��璐ф暟閲�"
width="130">
<template #default="scope">
- {{ formattedNumber(scope.row, null, scope.row.totalReturnNum || 0) }}
+ {{ calcAlreadyReturned(scope.row) }}
</template>
</el-table-column>
<!-- <el-table-column label="搴撳瓨棰勮鏁伴噺"
@@ -122,6 +119,14 @@
return parseFloat(cellValue).toFixed(2);
};
+/** 宸查��璐ф暟閲� = 鍏ュ簱琛屾�绘暟閲� 鈭� 褰撳墠鍙��璐ф暟閲忥紙鍓╀綑锛� */
+const calcAlreadyReturned = (row) => {
+ const total = Number(row?.stockInNum ?? row?.totalQuantity ?? row?.quantity ?? 0)
+ const un = Number(row?.unQuantity ?? 0)
+ if (!Number.isFinite(total) || !Number.isFinite(un)) return 0
+ return Math.max(total - un, 0)
+}
+
const handleChangeSelection = (val) => {
selectedRows.value = val;
}
diff --git a/src/views/procurementManagement/purchaseReturnOrder/index.vue b/src/views/procurementManagement/purchaseReturnOrder/index.vue
index 2b73253..f8866e1 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/index.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/index.vue
@@ -45,13 +45,8 @@
@click="handleDetail(row)"
>璇︽儏</el-button
>
- <el-button
- link
- size="small"
- :disabled="row.stockOutApproved"
- :style="{ color: row.stockOutApproved ? '#c0c4cc' : undefined }"
- @click="handleDelete(row)"
- >{{ row.stockOutApproved }}</el-button
+ <el-button link size="small" @click="handleDelete(row)"
+ >鍒犻櫎</el-button
>
</template>
</PIMTable>
@@ -94,20 +89,6 @@
<el-descriptions-item label="閫�鏂欎汉">{{
detailData.returnUserName || "--"
}}</el-descriptions-item>
- <el-descriptions-item label="鍙戣揣绫诲瀷">{{
- getShippingTypeLabel(detailData.shippingType)
- }}</el-descriptions-item>
- <el-descriptions-item v-if="String(detailData.shippingType) === '1'" label="鍙戣揣杞︾墝鍙�">{{
- detailData.truckPlateNo || "--"
- }}</el-descriptions-item>
- <template v-else-if="String(detailData.shippingType) === '2'">
- <el-descriptions-item label="蹇�掑叕鍙�">{{
- detailData.expressCompany || "--"
- }}</el-descriptions-item>
- <el-descriptions-item label="蹇�掑崟鍙�">{{
- detailData.expressNo || "--"
- }}</el-descriptions-item>
- </template>
<el-descriptions-item label="鏁村崟鎶樻墸棰�">{{
formatAmount(detailData.totalDiscountAmount)
}}</el-descriptions-item>
@@ -161,14 +142,13 @@
/>
<el-table-column label="鍗曚綅" prop="unit" width="80" />
<el-table-column label="鏁伴噺" prop="stockInNum" width="80" />
- <el-table-column label="閿�鍞彂璐ф暟閲�" prop="saleOutQuantity" width="110" />
<el-table-column label="鍙��璐ф暟閲�"
prop="unQuantity"
width="100" />
<el-table-column label="宸查��璐ф暟閲�"
width="100">
<template #default="scope">
- {{ formatAmount(scope.row.totalReturnNum || 0) }}
+ {{ calcAlreadyReturned(scope.row) }}
</template>
</el-table-column>
<!-- <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" width="120" /> -->
@@ -309,15 +289,6 @@
prop: "returnUserName",
width: 110,
},
- {
- label: "鍙戣揣绫诲瀷",
- prop: "shippingType",
- width: 100,
- formatData: (val) => getShippingTypeLabel(val),
- },
- { label: "鍙戣揣杞︾墝鍙�", prop: "truckPlateDisplay", width: 140 },
- { label: "蹇�掑叕鍙�", prop: "expressCompanyDisplay", width: 140 },
- { label: "蹇�掑崟鍙�", prop: "expressNoDisplay", width: 150 },
{
label: "鏁村崟鎶樻墸棰�",
@@ -370,7 +341,6 @@
},
{
name: "鍒犻櫎",
- disabled: (row) => !!row.stockOutApproved,
clickFun: (row) => {
handleDelete(row);
},
@@ -452,12 +422,7 @@
findPurchaseReturnOrderListPage({ ...searchForm.value, ...page })
.then((res) => {
tableLoading.value = false;
- tableData.value = (res.data.records || []).map((row) => ({
- ...row,
- truckPlateDisplay: String(row?.shippingType) === "1" ? (row?.truckPlateNo || "--") : "--",
- expressCompanyDisplay: String(row?.shippingType) === "2" ? (row?.expressCompany || "--") : "--",
- expressNoDisplay: String(row?.shippingType) === "2" ? (row?.expressNo || "--") : "--",
- }));
+ tableData.value = res.data.records;
page.total = res.data.total;
})
.catch(() => {
@@ -485,14 +450,6 @@
);
};
-const getShippingTypeLabel = (value) => {
- const shippingTypeMap = {
- 1: "璐ц溅",
- 2: "蹇��",
- };
- return shippingTypeMap[String(value)] || shippingTypeMap[value] || "--";
-};
-
const formatAmount = (value) => {
if (value === null || value === undefined || value === "") {
return "--";
@@ -504,6 +461,14 @@
return num.toFixed(2);
};
+/** 宸查��璐ф暟閲� = 鍏ュ簱琛屾�绘暟閲� 鈭� 褰撳墠鍙��璐ф暟閲忥紙鍓╀綑锛� */
+const calcAlreadyReturned = (row) => {
+ const total = Number(row?.stockInNum ?? row?.totalQuantity ?? row?.quantity ?? 0);
+ const un = Number(row?.unQuantity ?? 0);
+ if (!Number.isFinite(total) || !Number.isFinite(un)) return 0;
+ return Math.max(total - un, 0);
+};
+
onMounted(() => {
getList();
});
@@ -513,3 +478,4 @@
margin-top: unset;
}
</style>
+
diff --git a/src/views/procurementManagement/qualityInspection/index.vue b/src/views/procurementManagement/qualityInspection/index.vue
index aee1d99..7628839 100644
--- a/src/views/procurementManagement/qualityInspection/index.vue
+++ b/src/views/procurementManagement/qualityInspection/index.vue
@@ -116,18 +116,6 @@
<el-input v-model="formData.inspector" placeholder="璇疯緭鍏ヨ川妫�鍛樺鍚�" />
</el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿">
- <el-date-picker v-model="formCreateTimeDate"
- type="date"
- placeholder="閫夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- style="width: 100%" />
- </el-form-item>
- </el-col>
- </el-row>
-
<el-form-item label="澶囨敞">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" />
</el-form-item>
@@ -138,8 +126,7 @@
<script setup>
import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { ref, reactive, computed } from 'vue'
-import dayjs from 'dayjs'
+import { ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false)
@@ -157,14 +144,7 @@
supplierName: '',
products: [],
inspector: '',
- remark: '',
- createTime: ''
-})
-const formCreateTimeDate = computed({
- get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''),
- set: (value) => {
- formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : ''
- }
+ remark: ''
})
const mockData = [
@@ -210,17 +190,15 @@
arrivalNo: row.arrivalNo,
supplierName: row.supplierName,
inspector: row.inspector,
- remark: row.remark,
- createTime: row.createTime || ''
+ remark: row.remark
})
} else {
- Object.assign(formData, {
- arrivalNo: '',
- supplierName: '',
+ Object.assign(formData, {
+ arrivalNo: '',
+ supplierName: '',
products: [],
- inspector: '',
- remark: '',
- createTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
+ inspector: '',
+ remark: ''
})
}
dialogVisible.value = true
@@ -250,13 +228,13 @@
if (dialogType.value === 'add') {
const newInspection = {
id: Date.now(),
- inspectionNo: '',
+ inspectionNo: `QI${Date.now()}`,
arrivalNo: formData.arrivalNo,
supplierName: formData.supplierName,
status: 'pending',
qualifiedQuantity: totalQualified,
unqualifiedQuantity: totalUnqualified,
- inspectionTime: formData.createTime,
+ inspectionTime: new Date().toLocaleString(),
inspector: formData.inspector,
remark: formData.remark
}
diff --git a/src/views/productManagement/productIdentifier/index.vue b/src/views/productManagement/productIdentifier/index.vue
index d638e7a..94359e4 100644
--- a/src/views/productManagement/productIdentifier/index.vue
+++ b/src/views/productManagement/productIdentifier/index.vue
@@ -239,13 +239,6 @@
<el-form-item label="鏍囪瘑绫诲瀷">
<span>{{ currentProduct.identifierType }}</span>
</el-form-item>
- <el-form-item label="鍒涘缓鏃堕棿">
- <el-date-picker v-model="createTimeDate"
- type="date"
- placeholder="閫夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- style="width: 100%"></el-date-picker>
- </el-form-item>
<el-form-item label="鐢熸垚鏁伴噺"
prop="generateQuantity">
<el-input-number v-model="generateQuantity"
@@ -363,7 +356,6 @@
<script setup>
import { ref, reactive, computed } from "vue";
- import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, Search, Loading, Download } from "@element-plus/icons-vue";
import Pagination from "@/components/PIMTable/Pagination.vue";
@@ -450,13 +442,6 @@
const generateQuantity = ref(1);
const codeRule = ref("");
const customPrefix = ref("");
- const createTime = ref(dayjs().format("YYYY-MM-DD HH:mm:ss"));
- const createTimeDate = computed({
- get: () => (createTime.value ? String(createTime.value).split(" ")[0] : ""),
- set: (value) => {
- createTime.value = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
- });
const newBatchNo = ref("");
const reassignReason = ref("");
const formRef = ref();
@@ -674,9 +659,9 @@
currentProduct.value.batchNo
}_${String(i).padStart(3, "0")}`;
} else if (codeRule.value === "鏃堕棿鎴�+闅忔満鏁�") {
- identifierCode = "";
+ identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
} else if (codeRule.value === "鑷畾涔夎鍒�") {
- identifierCode = "";
+ identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`;
}
newIdentifiers.push({
@@ -687,7 +672,7 @@
identifierType: currentProduct.value.identifierType,
identifierCode: identifierCode,
status: "宸茬敓鎴�",
- generateTime: createTime.value,
+ generateTime: new Date().toLocaleString(),
remark: "鎵归噺鐢熸垚",
});
}
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index 3c52410..41e2109 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -340,7 +340,6 @@
style="margin: 0">
<el-input-number v-model="row.unitQuantity"
:min="0"
- :precision="2"
:step="1"
controls-position="right"
style="width: 100%"
@@ -358,7 +357,6 @@
style="margin: 0">
<el-input-number v-model="row.demandedQuantity"
:min="0"
- :precision="2"
:step="1"
controls-position="right"
style="width: 100%"
@@ -1203,7 +1201,7 @@
if (!Number.isFinite(numberValue)) {
return 0;
}
- return Number(numberValue.toFixed(2));
+ return Number(numberValue.toFixed(4));
};
const syncDemandedQuantityTree = (items, parentDemandedQuantity = null) => {
diff --git a/src/views/productionManagement/productStructure/Detail/index.vue b/src/views/productionManagement/productStructure/Detail/index.vue
index dba448a..ec18ddf 100644
--- a/src/views/productionManagement/productStructure/Detail/index.vue
+++ b/src/views/productionManagement/productStructure/Detail/index.vue
@@ -82,7 +82,6 @@
style="margin: 0">
<el-input-number v-model="row.unitQuantity"
:min="0"
- :precision="2"
:step="1"
controls-position="right"
style="width: 100%"
@@ -100,7 +99,6 @@
style="margin: 0">
<el-input-number v-model="row.demandedQuantity"
:min="0"
- :precision="2"
:step="1"
controls-position="right"
style="width: 100%"
@@ -274,7 +272,7 @@
if (!Number.isFinite(numberValue)) {
return 0;
}
- return Number(numberValue.toFixed(2));
+ return Number(numberValue.toFixed(4));
};
const syncDemandedQuantityTree = (
@@ -384,7 +382,7 @@
};
const fetchProcessOptions = async () => {
- const { data } = await list({ size: -1, current: -1 });
+ const { data } = await list({});
console.log(data, "dataValue.dataList");
dataValue.processOptions = normalizeListData(data);
};
diff --git a/src/views/productionManagement/productStructure/StructureEdit.vue b/src/views/productionManagement/productStructure/StructureEdit.vue
index 4d07f5d..7762467 100644
--- a/src/views/productionManagement/productStructure/StructureEdit.vue
+++ b/src/views/productionManagement/productStructure/StructureEdit.vue
@@ -86,7 +86,6 @@
style="margin: 0">
<el-input-number v-model="row.unitQuantity"
:min="0"
- :precision="2"
:step="1"
controls-position="right"
style="width: 100%"
@@ -103,7 +102,6 @@
style="margin: 0">
<el-input-number v-model="row.demandedQuantity"
:min="0"
- :precision="2"
:step="1"
controls-position="right"
style="width: 100%"
diff --git a/src/views/productionManagement/productStructure/index.vue b/src/views/productionManagement/productStructure/index.vue
index a70631d..e05ed3c 100644
--- a/src/views/productionManagement/productStructure/index.vue
+++ b/src/views/productionManagement/productStructure/index.vue
@@ -1,30 +1,6 @@
<template>
<div class="app-container">
<div class="table_list">
- <el-form :inline="true" :model="queryParams" class="search-bar" @submit.prevent>
- <el-form-item label="浜у搧鍚嶇О">
- <el-input
- v-model="queryParams.productName"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="瑙勬牸鍨嬪彿">
- <el-input
- v-model="queryParams.productModelName"
- placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery">鏌ヨ</el-button>
- <el-button @click="resetQuery">閲嶇疆</el-button>
- </el-form-item>
- </el-form>
<div style="text-align: right; margin-bottom: 10px;">
<el-button type="primary"
@click="handleAdd">鏂板</el-button>
@@ -157,7 +133,6 @@
dataType: "slot",
slot: "detail",
minWidth: 140,
- align: 'center'
},
{
label: "浜у搧鍚嶇О",
@@ -222,10 +197,6 @@
const operationType = ref("add"); // add | edit
const formRef = ref(null);
const showProductSelectDialog = ref(false);
- const queryParams = reactive({
- productName: "",
- productModelName: "",
- });
// BOM瀵煎叆鍙傛暟
const upload = reactive({
@@ -278,25 +249,12 @@
getList();
};
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
-
- const resetQuery = () => {
- queryParams.productName = "";
- queryParams.productModelName = "";
- handleQuery();
- };
-
// 鏌ヨ鍒楄〃
const getList = () => {
tableLoading.value = true;
listPage({
current: page.current,
size: page.size,
- productName: queryParams.productName || undefined,
- productModelName: queryParams.productModelName || undefined,
})
.then(res => {
const records = res?.data?.records || [];
diff --git a/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
index 370815e..3373374 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
@@ -21,28 +21,34 @@
prop="batchNo"
min-width="150" />
<el-table-column label="闇�姹傛暟閲�"
- prop="demandedQuantity"
- min-width="110" />
+ min-width="110">
+ <template #default="{ row }">
+ {{ stripTrailingZeros(row.demandedQuantity) }}
+ </template>
+ </el-table-column>
<el-table-column label="璁¢噺鍗曚綅"
prop="unit"
width="100" />
<el-table-column label="棰嗙敤鏁伴噺"
- prop="pickQuantity"
- min-width="110" />
+ min-width="110">
+ <template #default="{ row }">
+ {{ stripTrailingZeros(row.pickQuantity) }}
+ </template>
+ </el-table-column>
<el-table-column label="琛ユ枡鏁伴噺"
min-width="120">
<template #default="{ row }">
<el-button type="primary"
link
@click="handleViewSupplementRecord(row)">
- {{ row.feedingQty ?? 0 }}
+ {{ stripTrailingZeros(row.feedingQty) ?? 0 }}
</el-button>
</template>
</el-table-column>
<el-table-column label="閫�鏂欐暟閲�"
min-width="110">
<template #default="{ row }">
- {{ row.returnQty ?? 0 }}
+ {{ stripTrailingZeros(row.returnQty) ?? 0 }}
</template>
</el-table-column>
<el-table-column label="瀹為檯鏁伴噺"
@@ -50,10 +56,11 @@
<template #default="{ row }">
<el-input-number v-model="row.actualQty"
:min="0"
- :precision="3"
:step="1"
controls-position="right"
placeholder="杈撳叆瀹為檯鏁伴噺"
+ :formatter="value => stripTrailingZeros(value)"
+ :parser="value => parseFloat(value) || 0"
style="width: 100%;"
:disabled="row.returned || orderRow?.end"
@change="val => handleActualQtyChange(row, val)" />
@@ -115,8 +122,11 @@
prop="unit"
min-width="100" />
<el-table-column label="閫�鏂欐眹鎬绘暟閲�"
- prop="returnQtyTotal"
- min-width="140" />
+ min-width="140">
+ <template #default="{ row }">
+ {{ stripTrailingZeros(row.returnQtyTotal) }}
+ </template>
+ </el-table-column>
</el-table>
<template #footer>
<span class="dialog-footer">
@@ -139,6 +149,14 @@
updateMaterialPickingLedger,
} from "@/api/productionManagement/productionOrder.js";
+ const stripTrailingZeros = val => {
+ const str = String(val ?? "");
+ if (str.includes(".")) {
+ return parseFloat(str).toString();
+ }
+ return str;
+ };
+
const props = defineProps({
modelValue: { type: Boolean, default: false },
orderRow: { type: Object, default: null },
diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
index 09e7421..6c175f9 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -2,7 +2,7 @@
<div>
<el-dialog v-model="dialogVisible"
title="棰嗘枡鍙拌处"
- width="1200px"
+ width="1350px"
@close="handleClose">
<div class="material-toolbar">
<el-button type="primary"
@@ -13,7 +13,7 @@
border
row-key="tempId">
<el-table-column label="宸ュ簭鍚嶇О"
- min-width="140">
+ min-width="80">
<template #default="{ row }">
<span v-if="row.bom === true">{{ row.operationName || "-" }}</span>
<el-select v-else
@@ -31,7 +31,7 @@
</template>
</el-table-column>
<el-table-column label="鍘熸枡鍚嶇О"
- min-width="140">
+ min-width="120">
<template #default="{ row }">
<span v-if="row.bom === true">{{ row.materialName || "-" }}</span>
<el-button v-else
@@ -43,7 +43,7 @@
</template>
</el-table-column>
<el-table-column label="鍘熸枡鍨嬪彿"
- min-width="140">
+ min-width="120">
<template #default="{ row }">
{{ row.materialModel || "-" }}
</template>
@@ -66,21 +66,22 @@
</template>
</el-table-column>
<el-table-column label="闇�姹傛暟閲�"
- min-width="120">
+ min-width="100">
<template #default="{ row }">
- <span v-if="row.bom === true">{{ row.demandedQuantity ?? "-" }}</span>
+ <span v-if="row.bom === true">{{ stripTrailingZeros(row.demandedQuantity) ?? "-" }}</span>
<el-input-number v-else
v-model="row.demandedQuantity"
:min="0"
- :precision="3"
:step="1"
controls-position="right"
+ :formatter="value => stripTrailingZeros(value)"
+ :parser="value => parseFloat(value) || 0"
style="width: 100%;"
@change="val => handleRequiredQtyChange(row, val)" />
</template>
</el-table-column>
<el-table-column label="璁¢噺鍗曚綅"
- width="100">
+ width="80">
<template #default="{ row }">
{{ row.unit || "-" }}
</template>
@@ -90,9 +91,10 @@
<template #default="{ row }">
<el-input-number v-model="row.pickQty"
:min="0"
- :precision="3"
:step="1"
controls-position="right"
+ :formatter="value => stripTrailingZeros(value)"
+ :parser="value => parseFloat(value) || 0"
style="width: 100%;" />
</template>
</el-table-column>
@@ -187,26 +189,36 @@
const currentMaterialSelectRowIndex = ref(-1);
let materialTempId = 0;
- const createMaterialRow = (row = {}) => ({
- tempId: row.id || `temp_${++materialTempId}`,
- id: row.id,
- processId: row.processId || row.technologyOperationId,
- technologyOperationId: row.technologyOperationId || row.processId,
- operationName: row.operationName || "",
- bom: row.bom === true,
- materialModelId: row.materialModelId || row.productModelId,
- materialName: row.materialName || row.productName || "",
- materialModel: row.materialModel || row.model || "",
- demandedQuantity: Number(row.requiredQty ?? row.demandedQuantity ?? 0),
- unit: row.unit || "",
- pickQty: Number(row.pickQty ?? row.pickQuantity ?? 0),
- batchNo: row.batchNo
+ const getDefaultBatchNo = batchNoList => {
+ if (!Array.isArray(batchNoList) || batchNoList.length === 0) return [];
+ return [batchNoList[0]];
+ };
+
+ const createMaterialRow = (row = {}) => {
+ const batchNoList = Array.isArray(row.batchNoList) ? row.batchNoList : [];
+ const batchNo = row.batchNo
? typeof row.batchNo === "string"
? row.batchNo.split(",")
: row.batchNo
- : [],
- batchNoList: row.batchNoList || [],
- });
+ : getDefaultBatchNo(batchNoList);
+
+ return {
+ tempId: row.id || `temp_${++materialTempId}`,
+ id: row.id,
+ processId: row.processId || row.technologyOperationId,
+ technologyOperationId: row.technologyOperationId || row.processId,
+ operationName: row.operationName || "",
+ bom: row.bom === true,
+ materialModelId: row.materialModelId || row.productModelId,
+ materialName: row.materialName || row.productName || "",
+ materialModel: row.materialModel || row.model || "",
+ demandedQuantity: Number(row.requiredQty ?? row.demandedQuantity ?? 0),
+ unit: row.unit || "",
+ pickQty: Number(row.pickQty ?? row.pickQuantity ?? row.requiredQty ?? row.demandedQuantity ?? 0),
+ batchNo,
+ batchNoList,
+ };
+ };
const getProcessOptions = async () => {
if (!props.orderRow?.id) return;
@@ -270,6 +282,14 @@
}
);
+ const stripTrailingZeros = val => {
+ const str = String(val);
+ if (str.includes(".")) {
+ return parseFloat(str).toString();
+ }
+ return str;
+ };
+
const handleClose = () => {
materialTableData.value = [];
currentMaterialSelectRowIndex.value = -1;
@@ -319,7 +339,8 @@
product.materialName || product.productName || product.name || "";
row.materialModel = product.materialModel || product.model || "";
row.unit = product.unit || product.measureUnit || "";
- row.batchNoList = product.batchNoList;
+ row.batchNoList = Array.isArray(product.batchNoList) ? product.batchNoList : [];
+ row.batchNo = getDefaultBatchNo(row.batchNoList);
currentMaterialSelectRowIndex.value = -1;
materialProductDialogVisible.value = false;
};
diff --git a/src/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue
index 4f052ed..7ff1eb1 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue
@@ -20,23 +20,33 @@
prop="unit"
width="100" />
<el-table-column label="闇�姹傛暟閲�"
- prop="demandedQuantity"
- width="100" />
+ min-width="100">
+ <template #default="{ row }">
+ {{ stripTrailingZeros(row.demandedQuantity) }}
+ </template>
+ </el-table-column>
<el-table-column label="棰嗙敤鏁伴噺"
- prop="pickQuantity"
- width="100" />
+ min-width="100">
+ <template #default="{ row }">
+ {{ stripTrailingZeros(row.pickQuantity) }}
+ </template>
+ </el-table-column>
<el-table-column label="宸茶ˉ鏁伴噺"
- prop="feedingQty"
- width="100" />
+ min-width="100">
+ <template #default="{ row }">
+ {{ stripTrailingZeros(row.feedingQty) }}
+ </template>
+ </el-table-column>
<el-table-column label="琛ユ枡鏁伴噺"
min-width="150">
<template #default="{ row }">
<el-input-number v-model="row.newSupplementQty"
:min="0"
- :precision="3"
:step="1"
controls-position="right"
placeholder="杈撳叆琛ユ枡鏁伴噺"
+ :formatter="value => stripTrailingZeros(value)"
+ :parser="value => parseFloat(value) || 0"
style="width: 100%;" />
</template>
</el-table-column>
@@ -69,6 +79,14 @@
updateMaterialPickingLedger,
} from "@/api/productionManagement/productionOrder.js";
+ const stripTrailingZeros = val => {
+ const str = String(val ?? "");
+ if (str.includes(".")) {
+ return parseFloat(str).toString();
+ }
+ return str;
+ };
+
const props = defineProps({
modelValue: { type: Boolean, default: false },
orderRow: { type: Object, default: null },
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index ba1d155..5c3d4cf 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -8,7 +8,7 @@
placeholder="璇疯緭鍏�"
clearable
prefix-icon="Search"
- style="width: 160px"
+ style="width: 160px;"
@change="handleQuery" />
</el-form-item>
<el-form-item label="浜у搧鍚嶇О:">
@@ -16,7 +16,7 @@
placeholder="璇疯緭鍏�"
clearable
prefix-icon="Search"
- style="width: 160px"
+ style="width: 160px;"
@change="handleQuery" />
</el-form-item>
<el-form-item label="瑙勬牸:">
@@ -24,13 +24,13 @@
placeholder="璇疯緭鍏�"
clearable
prefix-icon="Search"
- style="width: 160px"
+ style="width: 160px;"
@change="handleQuery" />
</el-form-item>
<el-form-item label="鐘舵��:">
<el-select v-model="searchForm.status"
placeholder="璇烽�夋嫨"
- style="width: 160px"
+ style="width: 160px;"
@change="handleQuery">
<el-option label="寰呭紑濮�"
value="1" />
@@ -38,8 +38,8 @@
value="2" />
<el-option label="宸插畬鎴�"
value="3" />
- <!-- <el-option label="宸插彇娑�"-->
- <!-- value="4" />-->
+ <el-option label="宸插彇娑�"
+ value="4" />
<el-option label="宸茬粨鏉�"
value="5" />
</el-select>
@@ -67,17 +67,13 @@
:tableLoading="tableLoading"
:row-class-name="tableRowClassName"
:isSelection="true"
- :selectable="(row) => !row.endOrder"
+ :selectable="row => !row.endOrder"
@selection-change="handleSelectionChange"
@pagination="pagination">
<template #completionStatus="{ row }">
<el-progress :percentage="toProgressPercentage(row?.completionStatus)"
:color="progressColor(toProgressPercentage(row?.completionStatus))"
- :status="
- toProgressPercentage(row?.completionStatus) >= 100
- ? 'success'
- : ''
- " />
+ :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
</template>
<template #processRouteStatus="{ row }">
<div v-if="row.processRouteStatus && row.processRouteStatus.length"
@@ -89,14 +85,7 @@
<div class="step-circle"
:class="{ 'is-completed': item.percentage >= 100 }">
<span class="step-percentage"
- :style="{
- color:
- item.percentage >= 70
- ? item.percentage >= 100
- ? '#67c23a'
- : '#f56c6c'
- : '#000',
- }">{{ item.percentage }}%</span>
+ :style="{ color: item.percentage >= 70 ? item.percentage >= 100 ? '#67c23a' : '#f56c6c' : '#000' }">{{ item.percentage }}%</span>
</div>
<div class="step-name">{{ item.name }}</div>
</div>
@@ -115,7 +104,7 @@
<el-form-item label="宸ヨ壓璺嚎">
<el-select v-model="bindForm.routeId"
placeholder="璇烽�夋嫨宸ヨ壓璺嚎"
- style="width: 100%"
+ style="width: 100%;"
:loading="bindRouteLoading">
<el-option v-for="item in routeOptions"
:key="item.id"
@@ -136,23 +125,18 @@
<!-- 鏉ユ簮鏁版嵁寮圭獥 -->
<el-dialog v-model="sourceDataDialogVisible"
title="鏉ユ簮鏁版嵁"
- width="1200px"
- top="5vh"
- class="source-data-dialog"
- append-to-body>
+ width="1200px">
<div v-if="sourceRowData"
class="applyno-summary1">
<div class="summary-item">
<span class="summary-label">浜у搧鍚嶇О锛�</span>
<span class="summary-value">
- <el-tag type="primary">{{
- sourceRowData.productName || "-"
- }}</el-tag>
+ <el-tag type="primary">{{ sourceRowData.productName || '-' }}</el-tag>
</span>
</div>
<div class="summary-item">
<span class="summary-label">瑙勬牸锛�</span>
- <span class="summary-value">{{ sourceRowData.model || "-" }}</span>
+ <span class="summary-value">{{ sourceRowData.model || '-' }}</span>
</div>
<div class="summary-item">
<span class="summary-label">璁㈠崟闇�姹傛暟閲忥細</span>
@@ -168,49 +152,39 @@
<div class="info-grid">
<div class="info-item">
<div class="info-label">璁″垝鍙�</div>
- <div class="info-value">{{ item.mpsNo || "-" }}</div>
+ <div class="info-value">{{ item.mpsNo || '-' }}</div>
</div>
<div class="info-item">
<div class="info-label">鏁版嵁鏉ユ簮</div>
<div class="info-value">
<el-tag :type="item.source === '閿�鍞�' ? 'primary' : 'warning'">
- {{ item.source || "鏈煡" }}
+ {{ item.source || '鏈煡' }}
</el-tag>
</div>
</div>
<div class="info-item">
<div class="info-label">鍚堝悓鍙�</div>
- <div class="info-value">
- {{ item.salesContractNo || "-" }}
- </div>
+ <div class="info-value">{{ item.salesContractNo || '-' }}</div>
</div>
<div class="info-item">
<div class="info-label">瀹㈡埛鍚嶇О</div>
- <div class="info-value">{{ item.customerName || "-" }}</div>
+ <div class="info-value">{{ item.customerName || '-' }}</div>
</div>
<div class="info-item">
<div class="info-label">椤圭洰鍚嶇О</div>
- <div class="info-value">{{ item.projectName || "-" }}</div>
+ <div class="info-value">{{ item.projectName || '-' }}</div>
</div>
<div class="info-item">
<div class="info-label">璁″垝闇�姹傛暟閲�</div>
- <div class="info-value">
- {{ item.qtyRequired || 0 }} {{ item.unit || "" }}
- </div>
+ <div class="info-value">{{ item.qtyRequired || 0 }} {{ item.unit || '' }}</div>
</div>
<div class="info-item">
<div class="info-label">鍗曚綅</div>
- <div class="info-value">{{ item.unit || "-" }}</div>
+ <div class="info-value">{{ item.unit || '-' }}</div>
</div>
<div class="info-item">
<div class="info-label">闇�姹傛棩鏈�</div>
- <div class="info-value">
- {{
- item.requiredDate
- ? dayjs(item.requiredDate).format("YYYY-MM-DD")
- : "-"
- }}
- </div>
+ <div class="info-value">{{ item.requiredDate ? dayjs(item.requiredDate).format('YYYY-MM-DD') : '-' }}</div>
</div>
</div>
</div>
@@ -220,7 +194,7 @@
</el-dialog>
<MaterialLedgerDialog v-model="materialDialogVisible"
:order-row="currentMaterialOrder"
- @saved="getList" />
+ />
<MaterialDetailDialog v-model="materialDetailDialogVisible"
:order-row="currentMaterialDetailOrder"
@confirmed="getList" />
@@ -261,7 +235,6 @@
getProductOrderSource,
updateProductOrder,
} from "@/api/productionManagement/productionOrder.js";
- import { productWorkOrderPage } from "@/api/productionManagement/workOrder.js";
import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
import MaterialDetailDialog from "@/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue";
@@ -404,8 +377,7 @@
{
name: "缁戝畾宸ヨ壓璺嚎",
type: "text",
- showHide: row =>
- !row.processRouteCode && !row.endOrder && row.status !== 3,
+ showHide: row => !row.processRouteCode && !row.endOrder,
clickFun: row => {
openBindRouteDialog(row, "add");
},
@@ -413,8 +385,7 @@
{
name: "鏇存崲宸ヨ壓璺嚎",
type: "text",
- showHide: row =>
- row.processRouteCode && !row.endOrder && row.status !== 3,
+ showHide: row => row.processRouteCode && !row.endOrder,
clickFun: row => {
openBindRouteDialog(row, "change");
},
@@ -515,7 +486,7 @@
if (!Number.isFinite(n)) return 0;
if (n <= 0) return 0;
if (n >= 100) return 100;
- return parseFloat(n.toFixed(2));
+ return Math.round(n);
};
// 30/50/80/100 鍒嗘棰滆壊锛氱孩/姗�/钃�/缁�
@@ -692,37 +663,11 @@
};
const getList = () => {
tableLoading.value = true;
- // 鏋勯�犱竴涓柊鐨勫璞★紝涓嶅寘鍚玡ntryDate瀛楁
const params = { ...searchForm.value, ...page };
params.entryDate = undefined;
productOrderListPage(params)
- .then(async res => {
- const records = res.data.records || [];
- // 涓烘瘡涓鍗曟煡璇㈠搴旂殑宸ュ簭杩涘害鏁版嵁
- const processPromises = records.map(async item => {
- if (item.npsNo) {
- try {
- const workOrderRes = await productWorkOrderPage({
- npsNo: item.npsNo,
- size: 100,
- });
- const workOrders = workOrderRes.data.records || [];
- // 鎸夌収宸ュ簭椤哄簭鎺掑簭锛堝鏋滄湁椤哄簭瀛楁锛屽亣璁句负 orderNum 鎴栨寜杩斿洖椤哄簭锛�
- // 杞崲涓� processRouteStatus 鏍煎紡
- const processRouteStatus = workOrders.map(wo => ({
- name: wo.operationName || "鏈煡宸ュ簭",
- percentage: wo.completionStatus > 100 ? 100 : wo.completionStatus,
- }));
- return { ...item, processRouteStatus };
- } catch (error) {
- console.error(`鑾峰彇宸ュ崟 ${item.npsNo} 杩涘害澶辫触:`, error);
- return { ...item, processRouteStatus: [] };
- }
- }
- return { ...item, processRouteStatus: [] };
- });
-
- tableData.value = await Promise.all(processPromises);
+ .then(res => {
+ tableData.value = res.data.records || [];
page.total = res.data.total;
tableLoading.value = false;
})
@@ -754,7 +699,7 @@
technologyRoutingId: data.technologyRoutingId,
orderId,
type: "order",
- editable: !row.endOrder && row.status !== 3,
+ editable: !row.endOrder,
},
});
} catch (e) {
@@ -974,19 +919,13 @@
.source-table-container {
margin-top: 20px;
- flex: 1;
- min-height: 0;
- max-height: 500px;
- overflow: auto;
}
.source-data-cards-container {
display: flex;
flex-direction: column;
gap: 16px;
- flex: 1;
- min-height: 0;
- max-height: none;
+ max-height: 500px;
overflow-y: auto;
padding: 10px;
background-color: #f5f7fa;
@@ -1054,22 +993,6 @@
color: #303133;
font-weight: 500;
}
- }
- }
-
- .source-data-dialog {
- .el-dialog {
- display: flex;
- flex-direction: column;
- max-height: 90vh;
- }
-
- .el-dialog__body {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- overflow: hidden;
}
}
</style>
diff --git a/src/views/productionManagement/productionReporting/index.vue b/src/views/productionManagement/productionReporting/index.vue
index fa4e163..e94919b 100644
--- a/src/views/productionManagement/productionReporting/index.vue
+++ b/src/views/productionManagement/productionReporting/index.vue
@@ -163,6 +163,7 @@
import { productionProductMainListPage } from "@/api/productionManagement/productionProductMain.js";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import InputModal from "@/views/productionManagement/productionReporting/Input.vue";
+ import dayjs from "dayjs";
const data = reactive({
searchForm: {
@@ -179,27 +180,27 @@
{
label: "鎶ュ伐鍗曞彿",
prop: "productNo",
- width: 120,
+ width: 140,
},
{
label: "鎶ュ伐浜哄憳",
prop: "nickName",
width: 120,
},
- {
- label: "宸ユ椂锛坔锛�",
- width: 100,
- prop: "workHour",
- },
+ // {
+ // label: "宸ユ椂锛坔锛�",
+ // width: 100,
+ // prop: "workHour",
+ // },
{
label: "宸ュ簭",
prop: "process",
- width: 120,
+ width: 100,
},
{
label: "宸ュ崟缂栧彿",
prop: "workOrderNo",
- width: 120,
+ width: 140,
},
{
label: "閿�鍞悎鍚屽彿",
@@ -235,7 +236,8 @@
{
label: "鍒涘缓鏃堕棿",
prop: "createTime",
- width: 120,
+ width: 160,
+ formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
},
{
dataType: "action",
diff --git a/src/views/productionManagement/productionTraceability/index.vue b/src/views/productionManagement/productionTraceability/index.vue
index a726ad0..19f7ed9 100644
--- a/src/views/productionManagement/productionTraceability/index.vue
+++ b/src/views/productionManagement/productionTraceability/index.vue
@@ -35,7 +35,7 @@
border>
<el-descriptions-item label="鐢熶骇璁㈠崟鍙�">{{ rowData.productionOrderDto?.npsNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="浜у搧鍚嶇О">{{ rowData.productionOrderDto?.productName || '-' }}</el-descriptions-item>
- <el-descriptions-item label="瑙勬牸鍨嬪彿">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="浜у搧瑙勬牸">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item>
<!-- <el-descriptions-item label="鐗╂枡缂栫爜">{{ rowData.productionOrderDto?.materialCode || '-' }}</el-descriptions-item> -->
<el-descriptions-item label="璁″垝鏁伴噺">{{ rowData.productionOrderDto?.quantity || 0 }} <span class="unit">{{ rowData.productionOrderDto?.unit || '-' }}</span></el-descriptions-item>
<el-descriptions-item label="褰撳墠鐘舵��">
@@ -44,7 +44,7 @@
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="瀹㈡埛鍚嶇О">{{ rowData.productionOrderDto?.customerName || '-' }}</el-descriptions-item>
- <el-descriptions-item label="寮�濮嬫棩鏈�">{{ parseTime(rowData.productionOrderDto?.startTime) || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="寮�濮嬫棩鏈�">{{ parseTime(rowData.productionOrderDto?.startTime,'{y}-{m}-{d}') || '-' }}</el-descriptions-item>
<el-descriptions-item label="瀹屾垚杩涘害">
<el-progress :percentage="rowData.productionOrderDto?.completionStatus>=100?100:rowData.productionOrderDto?.completionStatus"
:color="customColors(rowData.productionOrderDto?.completionStatus)"
@@ -132,8 +132,8 @@
<el-descriptions-item label="鐢熶骇宸ュ崟鍙�">{{ detailData.workOrder.workOrderNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="璁″垝鏁伴噺">{{ detailData.workOrder.planQuantity || 0 }}</el-descriptions-item>
<el-descriptions-item label="瀹屾垚鏁伴噺">{{ detailData.workOrder.completeQuantity || 0 }}</el-descriptions-item>
- <el-descriptions-item label="瀹為檯寮�濮嬫椂闂�">{{ parseTime(detailData.workOrder.actualStartTime) || '-' }}</el-descriptions-item>
- <el-descriptions-item label="瀹為檯缁撴潫鏃堕棿">{{ parseTime(detailData.workOrder.actualEndTime) || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="瀹為檯寮�濮嬫椂闂�">{{ parseTime(detailData.workOrder.actualStartTime, '{y}-{m}-{d}') || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="瀹為檯缁撴潫鏃堕棿">{{ parseTime(detailData.workOrder.actualEndTime, '{y}-{m}-{d}') || '-' }}</el-descriptions-item>
<!-- <el-descriptions-item label="瀹屾垚杩涘害">
<el-progress :percentage="detailData.workOrder.completionStatus >= 100 ? 100 : (detailData.workOrder.completionStatus || 0)"
:color="customColors(detailData.workOrder.completionStatus)"
@@ -175,7 +175,7 @@
<template #default="{ row }">
<el-button type="primary"
link
- @click="showInput(row.id)">鏌ョ湅鎶曞叆</el-button>
+ @click="showInput(row.productionProductMainId)">鏌ョ湅鎶曞叆</el-button>
<el-button type="primary"
link
@click="showParamDetail(row.productionOperationParamList)">鍙傛暟璇︽儏</el-button>
@@ -230,19 +230,20 @@
:key="record.id"
class="quality-record-block">
<div class="detail-section">
- <h3 class="section-title">妫�娴嬭褰� {{ index + 1 }} - {{ parseTime(record.createTime) }}</h3>
+ <h3 class="section-title">妫�娴嬭褰� {{ index + 1 }} - {{ parseTime(record.createTime, '{y}-{m}-{d}') }}</h3>
<el-descriptions :column="3"
border>
- <el-descriptions-item label="妫�娴嬫棩鏈�">{{ parseTime(record.createTime) || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="妫�娴嬫棩鏈�">{{ parseTime(record.createTime, '{y}-{m}-{d}') || '-' }}</el-descriptions-item>
<el-descriptions-item label="鎶ュ伐鍗曞彿">{{ record.reportNo || '-' }}</el-descriptions-item>
- <el-descriptions-item label="妫�楠屽憳">{{ record.userName || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鎶ュ伐浜哄憳">{{ record.userName || '-' }}</el-descriptions-item>
<el-descriptions-item label="浜у搧鍚嶇О">{{ record.productName || '-' }}</el-descriptions-item>
<el-descriptions-item label="瑙勬牸鍨嬪彿">{{ record.model || '-' }}</el-descriptions-item>
<el-descriptions-item label="鏁伴噺">{{ record.quantity || 0 }} {{ record.unit || '-' }}</el-descriptions-item>
<el-descriptions-item label="妫�娴嬪崟浣�">{{ record.checkCompany || '-' }}</el-descriptions-item>
- <el-descriptions-item label="妫�娴嬬粨鏋�">
- <el-tag :type="record.checkResult === '鍚堟牸' ? 'success' : 'danger'">
- {{ record.checkResult || '寰呮娴�' }}
+ <el-descriptions-item label="妫�楠屽憳">{{ record.checkName || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鍚堟牸鐜�">
+ <el-tag :type="getPassRateTagType(record)">
+ {{ getPassRateDisplay(record) }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
@@ -360,6 +361,28 @@
return "#67c23a";
};
+ const getPassRate = (record) => {
+ const qualified = Number(record.qualifiedQuantity) || 0;
+ const unqualified = Number(record.unqualifiedQuantity) || 0;
+ const total = qualified + unqualified;
+ if (total === 0) return null;
+ return Number(((qualified / total) * 100).toFixed(2));
+ };
+
+ const getPassRateDisplay = (record) => {
+ const rate = getPassRate(record);
+ if (rate === null) return '鈥�';
+ return `${rate}%`;
+ };
+
+ const getPassRateTagType = (record) => {
+ const rate = getPassRate(record);
+ if (rate === null) return 'info';
+ if (rate >= 100) return 'success';
+ if (rate >= 75) return 'primary';
+ return 'danger';
+ };
+
// 妯℃嫙鎼滅储鏂规硶
const handleNpsNoSearch = async query => {
npsNoLoading.value = true;
diff --git a/src/views/productionManagement/workOrder/index.vue b/src/views/productionManagement/workOrder/index.vue
index d3b0f93..1e4810a 100644
--- a/src/views/productionManagement/workOrder/index.vue
+++ b/src/views/productionManagement/workOrder/index.vue
@@ -93,7 +93,7 @@
<span class="info-value">{{ transferCardRowData.productName }}</span>
</div>
<div class="info-item">
- <span class="info-label">瑙勬牸鍨嬪彿</span>
+ <span class="info-label">浜у搧瑙勬牸</span>
<span class="info-value">{{ transferCardRowData.model }}</span>
</div>
<!-- <div class="info-item">
@@ -475,7 +475,7 @@
if (!Number.isFinite(n)) return 0;
if (n <= 0) return 0;
if (n >= 100) return 100;
- return parseFloat(n.toFixed(2));
+ return Math.round(n);
};
const progressColor = percentage => {
const p = toProgressPercentage(percentage);
diff --git a/src/views/productionManagement/workOrderEdit/index.vue b/src/views/productionManagement/workOrderEdit/index.vue
index 98d29f5..37cbb4e 100644
--- a/src/views/productionManagement/workOrderEdit/index.vue
+++ b/src/views/productionManagement/workOrderEdit/index.vue
@@ -297,7 +297,7 @@
if (!Number.isFinite(n)) return 0;
if (n <= 0) return 0;
if (n >= 100) return 100;
- return parseFloat(n.toFixed(2));
+ return Math.round(n);
};
const progressColor = percentage => {
diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index b721de6..b2ac432 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -57,7 +57,7 @@
<span class="info-value">{{ transferCardRowData.productName }}</span>
</div>
<div class="info-item">
- <span class="info-label">瑙勬牸鍨嬪彿</span>
+ <span class="info-label">浜у搧瑙勬牸</span>
<span class="info-value">{{ transferCardRowData.model }}</span>
</div>
<div class="info-item">
@@ -133,7 +133,7 @@
<el-input v-model.number="reportForm.quantity"
type="number"
min="0"
- step="1"
+ step="0.0001"
style="width: 300px"
placeholder="璇疯緭鍏ョ敓浜у悎鏍兼暟閲�"
@input="handleQuantityInput" />
@@ -143,7 +143,7 @@
<el-input v-model.number="reportForm.scrapQty"
type="number"
min="0"
- step="1"
+ step="0.0001"
style="width: 300px"
placeholder="璇疯緭鍏ユ姤搴熸暟閲�"
@input="handleScrapQtyInput" />
@@ -245,6 +245,7 @@
<template #footer>
<span class="dialog-footer">
<el-button type="primary"
+ :loading="reportLoading"
@click="handleReport">纭畾</el-button>
<el-button @click="reportDialogVisible = false">鍙栨秷</el-button>
</span>
@@ -363,12 +364,12 @@
dataType: "action",
fixed: "right",
operation: [
- {
+ /*{
name: "娴佽浆鍗�",
clickFun: row => {
downloadAndPrintWorkOrder(row);
},
- },
+ },*/
{
name: "闄勪欢",
clickFun: row => {
@@ -414,6 +415,7 @@
const transferCardQrUrl = ref("");
const transferCardRowData = ref(null);
const reportDialogVisible = ref(false);
+ const reportLoading = ref(false);
const fileDialogVisible = ref(false);
const currentWorkOrderId = ref(null);
const reportFormRef = ref(null);
@@ -421,7 +423,7 @@
const reportForm = reactive({
planQuantity: 0,
quantity: null,
- scrapQty: null,
+ scrapQty: 0,
userName: "",
workOrderId: "",
reportWork: "",
@@ -445,8 +447,7 @@
return;
}
const num = Number(value);
- // 鏁存暟涓斿ぇ浜庣瓑浜�1
- if (isNaN(num) || !Number.isInteger(num) || num < 0) {
+ if (isNaN(num) || num < 0) {
callback(new Error("鐢熶骇鍚堟牸鏁伴噺蹇呴』澶т簬绛変簬0"));
return;
}
@@ -460,8 +461,7 @@
return;
}
const num = Number(value);
- // 鏁存暟涓斿ぇ浜庣瓑浜�0
- if (isNaN(num) || !Number.isInteger(num) || num < 0) {
+ if (isNaN(num) || num < 0) {
callback(new Error("鎶ュ簾鏁伴噺蹇呴』澶т簬绛変簬0"));
return;
}
@@ -484,20 +484,8 @@
if (isNaN(num)) {
return;
}
- // 濡傛灉灏忎簬1锛屾竻闄�
if (num < 0) {
reportForm.quantity = null;
- return;
- }
- // 濡傛灉鏄皬鏁板彇鏁存暟閮ㄥ垎
- if (!Number.isInteger(num)) {
- const intValue = Math.floor(num);
- // 濡傛灉鍙栨暣鍚庡皬浜�1锛屾竻闄�
- if (intValue < 0) {
- reportForm.quantity = null;
- return;
- }
- reportForm.quantity = intValue;
return;
}
reportForm.quantity = num;
@@ -510,21 +498,13 @@
return;
}
const num = Number(value);
- // 濡傛灉鏄疦aN锛屼繚鎸佸師鍊�
if (isNaN(num)) {
return;
}
- // 濡傛灉鏄礋鏁帮紝娓呴櫎杈撳叆
if (num < 0) {
reportForm.scrapQty = null;
return;
}
- // 濡傛灉鏄皬鏁帮紝鍙栨暣鏁伴儴鍒�
- if (!Number.isInteger(num)) {
- reportForm.scrapQty = Math.floor(num);
- return;
- }
- // 鏈夋晥鐨勯潪璐熸暣鏁帮紙鍖呮嫭0锛�
reportForm.scrapQty = num;
};
@@ -549,7 +529,13 @@
if (!Number.isFinite(n)) return 0;
if (n <= 0) return 0;
if (n >= 100) return 100;
- return parseFloat(n.toFixed(2));
+ return Math.round(n);
+ };
+ const subtractQuantity = (minuend, subtrahend, precision = 4) => {
+ const factor = 10 ** precision;
+ const a = Math.round((Number(minuend) || 0) * factor);
+ const b = Math.round((Number(subtrahend) || 0) * factor);
+ return Math.max(0, (a - b) / factor);
};
const progressColor = percentage => {
const p = toProgressPercentage(percentage);
@@ -673,20 +659,18 @@
}
}
currentReportRowData.value = row;
- const planQuantity = Number(row.planQuantity || 0);
- const completeQuantity = Number(row.completeQuantity || 0);
- const remainingQuantity = Math.max(0, planQuantity - completeQuantity);
- reportForm.planQuantity = remainingQuantity;
+ reportForm.planQuantity = subtractQuantity(
+ row.planQuantity,
+ row.completeQuantity
+ );
reportForm.quantity =
row.quantity !== undefined && row.quantity !== null ? row.quantity : null;
reportForm.productProcessRouteItemId = row.productProcessRouteItemId;
reportForm.workOrderId = row.id;
reportForm.reportWork = row.reportWork;
reportForm.productMainId = row.productMainId;
- reportForm.scrapQty =
- row.scrapQty !== undefined && row.scrapQty !== null ? row.scrapQty : null;
- reportForm.productionOrderRoutingOperationId =
- row.productionOrderRoutingOperationId;
+ reportForm.scrapQty = 0;
+ reportForm.productionOrderRoutingOperationId = row.productionOrderRoutingOperationId;
reportForm.productionOrderId = row.productionOrderId;
if (row.type == 0) {
reportForm.workHour = row.workHour || 0;
@@ -796,6 +780,7 @@
productionOperationParamList: productionOperationParamList,
};
+ reportLoading.value = true;
addProductMain(submitParams)
.then(res => {
proxy.$modal.msgSuccess("鎶ュ伐鎴愬姛");
@@ -806,6 +791,9 @@
ElMessageBox.alert("鎶ュ伐澶辫触", "鎻愮ず", {
confirmButtonText: "纭畾",
});
+ })
+ .finally(() => {
+ reportLoading.value = false;
});
});
};
diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index 1acb28f..fd56e89 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -56,7 +56,7 @@
style="width: 160px;"
@keyup.enter="handleQuery" />
</el-form-item>
- <el-form-item label="瑙勬牸鍨嬪彿:"
+ <el-form-item label="浜у搧瑙勬牸:"
prop="model">
<el-input v-model="searchForm.model"
placeholder="璇疯緭鍏�"
@@ -121,7 +121,7 @@
</el-row>
<el-row :gutter="20">
<el-col>
- <el-form-item label="瑙勬牸鍨嬪彿">
+ <el-form-item label="浜у搧瑙勬牸">
<div class="info-display">{{ mergeForm.model || '-' }}</div>
</el-form-item>
</el-col>
@@ -139,16 +139,11 @@
@change="onBlur"
style="width: 100%" />
</el-form-item>
- <el-form-item label="鍒涘缓鏃堕棿">
- <el-date-picker v-model="mergeCreateTimeDate"
- type="date"
- value-format="YYYY-MM-DD"
- style="width: 100%" />
- </el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary"
+ :loading="mergeSubmitLoading"
@click="handleMergeSubmit">纭畾涓嬪彂</el-button>
<el-button @click="isShowNewModal = false">鍙栨秷</el-button>
</span>
@@ -179,7 +174,7 @@
prop="mpsNo">
<el-input v-model="form.mpsNo"
disabled
- placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" />
+ placeholder="鏂板鍚庤嚜鍔ㄧ敓鎴�" />
</el-form-item>
<el-form-item label="浜у搧鍚嶇О"
prop="productId">
@@ -192,7 +187,7 @@
@change="handleProductChange"
style="width: 100%" />
</el-form-item>
- <el-form-item label="瑙勬牸鍨嬪彿"
+ <el-form-item label="浜у搧瑙勬牸"
prop="productModelId">
<el-select v-model="form.productModelId"
@change="handleChangeSpecification"
@@ -232,14 +227,6 @@
value-format="YYYY-MM-DD"
style="width: 100%"
placeholder="璇烽�夋嫨鎵胯鏃ユ湡" />
- </el-form-item>
- <el-form-item label="鍒涘缓鏃堕棿"
- prop="createTime">
- <el-date-picker v-model="formCreateTimeDate"
- type="date"
- value-format="YYYY-MM-DD"
- style="width: 100%"
- placeholder="璇烽�夋嫨鍒涘缓鏃堕棿" />
</el-form-item>
<el-form-item label="澶囨敞"
prop="remark">
@@ -335,7 +322,7 @@
},
},
{
- label: "瑙勬牸鍨嬪彿",
+ label: "浜у搧瑙勬牸",
prop: "model",
width: "150px",
className: "spec-cell",
@@ -444,7 +431,6 @@
Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
mergeForm.planCompleteTime = row.requiredDate || "";
mergeForm.productId = row.productId || "";
- mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
mergeForm.ids = [row.id];
sumAssignedQuantity.value =
Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
@@ -456,7 +442,7 @@
type: "danger",
link: true,
showHide: row => {
- return row.status == 0 && row.source != "閿�鍞�";
+ return row.status == 0;
},
clickFun: row => {
handleDelete(row);
@@ -481,6 +467,7 @@
// 鍚堝苟涓嬪彂寮圭獥鎺у埗
const isShowNewModal = ref(false);
+ const mergeSubmitLoading = ref(false);
// 鍚堝苟涓嬪彂琛ㄥ崟鏁版嵁
const mergeForm = reactive({
productName: "",
@@ -488,16 +475,6 @@
totalAssignedQuantity: 0,
planCompleteTime: "",
productId: "",
- createTime: "",
- });
- const mergeCreateTimeDate = computed({
- get: () =>
- mergeForm.createTime ? String(mergeForm.createTime).split(" ")[0] : "",
- set: value => {
- mergeForm.createTime = value
- ? `${value} ${dayjs().format("HH:mm:ss")}`
- : "";
- },
});
// 瀵煎叆鐩稿叧
@@ -528,18 +505,11 @@
requiredDate: "",
promisedDeliveryDate: "",
remark: "",
- createTime: "",
- });
- const formCreateTimeDate = computed({
- get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
- set: value => {
- form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
const rules = reactive({
productId: [{ required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" }],
productModelId: [
- { required: true, message: "璇烽�夋嫨瑙勬牸鍨嬪彿", trigger: "change" },
+ { required: true, message: "璇烽�夋嫨浜у搧瑙勬牸", trigger: "change" },
],
qtyRequired: [{ required: true, message: "璇疯緭鍏ユ暟閲�", trigger: "blur" }],
requiredDate: [
@@ -718,17 +688,17 @@
});
};
- // 閫変腑鐨勮鏍煎瀷鍙稩D
+ // 閫変腑鐨勪骇鍝佽鏍糏D
const selectedProductModelId = ref("");
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = selection => {
selectedRows.value = selection;
- // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑瑙勬牸鍨嬪彿ID
+ // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑浜у搧瑙勬牸ID
if (selection.length > 0) {
selectedProductModelId.value = selection[0].productModelId;
} else {
- // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌鸿鏍煎瀷鍙稩D
+ // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌轰骇鍝佽鏍糏D
selectedProductModelId.value = "";
}
};
@@ -749,7 +719,7 @@
if (!selectedProductModelId.value) {
return true;
}
- // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈夎鏍煎瀷鍙稩D鐩稿悓鐨勮鎵嶅彲閫夋嫨
+ // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈変骇鍝佽鏍糏D鐩稿悓鐨勮鎵嶅彲閫夋嫨
return row.productModelId === selectedProductModelId.value;
};
// 鎷夊彇鏁版嵁鎸夐挳鎿嶄綔
@@ -778,7 +748,6 @@
mergeForm.totalAssignedQuantity = totalAssignedQuantity;
mergeForm.planCompleteTime = firstRow.requiredDate || "";
mergeForm.productId = firstRow.productId || "";
- mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
mergeForm.ids = selectedRows.value.map(row => row.id);
// 鎵撳紑寮圭獥
@@ -811,6 +780,7 @@
const payload = {
...mergeForm,
};
+ mergeSubmitLoading.value = true;
productionPlanCombine(payload)
.then(res => {
if (res.code === 200) {
@@ -826,6 +796,9 @@
.catch(err => {
console.error("鍚堝苟涓嬪彂寮傚父锛�", err);
ElMessage.error("绯荤粺寮傚父锛屽悎骞朵笅鍙戝け璐�");
+ })
+ .finally(() => {
+ mergeSubmitLoading.value = false;
});
// 鍙互閫夋嫨鍒锋柊鍒楄〃鎴栧叾浠栨搷浣�
};
@@ -922,7 +895,6 @@
requiredDate: "",
promisedDeliveryDate: "",
remark: "",
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
dialogVisible.value = true;
fetchProductOptions();
@@ -943,7 +915,6 @@
requiredDate: row.requiredDate || "",
promisedDeliveryDate: row.promisedDeliveryDate || "",
remark: row.remark || "",
- createTime: row.createTime || "",
});
dialogVisible.value = true;
fetchProductOptions();
diff --git a/src/views/qualityManagement/finalInspection/components/filesDia.vue b/src/views/qualityManagement/finalInspection/components/filesDia.vue
index 4517844..691e651 100644
--- a/src/views/qualityManagement/finalInspection/components/filesDia.vue
+++ b/src/views/qualityManagement/finalInspection/components/filesDia.vue
@@ -13,7 +13,7 @@
:action="uploadUrl"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
- name="file"
+ name="files"
:show-file-list="false"
:headers="headers"
style="display: inline;margin-right: 10px"
@@ -40,11 +40,12 @@
</div>
</template>
</el-dialog>
+ <filePreview ref="filePreviewRef" />
</div>
</template>
<script setup>
-import {ref} from "vue";
+import {ref, reactive, getCurrentInstance} from "vue";
import {Search} from "@element-plus/icons-vue";
import {
qualityInspectParamDel,
@@ -53,17 +54,20 @@
} from "@/api/qualityManagement/qualityInspectParam.js";
import {ElMessageBox} from "element-plus";
import {getToken} from "@/utils/auth.js";
+import filePreview from '@/components/filePreview/index.vue'
import {
- qualityInspectFileAdd,
- qualityInspectFileDel,
- qualityInspectFileListPage
-} from "@/api/qualityManagement/qualityInspectFile.js";
+ attachmentList,
+ createAttachment,
+ deleteAttachment
+} from "@/api/basicData/storageAttachment.js";
+
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const currentId = ref('')
const selectedRows = ref([]);
+const filePreviewRef = ref()
const tableColumn = ref([
{
label: "鏂囦欢鍚嶇О",
@@ -80,6 +84,13 @@
clickFun: (row) => {
downLoadFile(row);
},
+ },
+ {
+ name: "棰勮",
+ type: "text",
+ clickFun: (row) => {
+ lookFile(row);
+ },
}
],
},
@@ -95,7 +106,7 @@
const headers = ref({
Authorization: "Bearer " + getToken(),
});
-const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 涓婁紶鐨勬湇鍔″櫒鍦板潃
// 鎵撳紑寮规
const openDialog = (row) => {
@@ -109,9 +120,12 @@
getList();
};
const getList = () => {
- qualityInspectFileListPage({inspectId: currentId.value, ...page}).then(res => {
- tableData.value = res.data.records;
- page.total = res.data.total;
+ attachmentList({recordId: currentId.value, recordType: 'quality_inspect'}).then(res => {
+ tableData.value = (res.data || []).map(item => ({
+ ...item,
+ name: item.originalFilename || item.name
+ }));
+ page.total = res.data ? res.data.length : 0;
})
}
// 琛ㄦ牸閫夋嫨鏁版嵁
@@ -127,24 +141,42 @@
dialogFormVisible.value = false;
emit('close')
};
+let pendingFiles = [];
+let uploadTimer = null;
+
// 涓婁紶鎴愬姛澶勭悊
function handleUploadSuccess(res, file) {
// 濡傛灉涓婁紶鎴愬姛
- if (res.code == 200) {
- const fileRow = {}
- fileRow.name = res.data.originalName
- fileRow.url = res.data.tempPath
- uploadFile(fileRow)
+ if (res.code == 200 && res.data && res.data.length > 0) {
+ const newFiles = res.data.map(item => ({
+ ...item,
+ name: item.originalFilename || item.name
+ }));
+
+ pendingFiles = [...pendingFiles, ...newFiles];
+
+ // 闃叉姈澶勭悊锛岄伩鍏嶅鏂囦欢鍚屾椂涓婁紶瀵艰嚧鍒楄〃琚鐩�
+ if (uploadTimer) clearTimeout(uploadTimer);
+ uploadTimer = setTimeout(() => {
+ const mergedFiles = [...(tableData.value || []), ...pendingFiles];
+ const storageAttachmentDTO = {
+ recordType: 'quality_inspect',
+ recordId: currentId.value,
+ application: "file",
+ storageBlobDTOs: mergedFiles
+ };
+ createAttachment(storageAttachmentDTO).then(r => {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ getList()
+ }).catch(() => {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ }).finally(() => {
+ pendingFiles = []; // 閲嶇疆
+ });
+ }, 500);
} else {
proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
}
-}
-function uploadFile(file) {
- file.inspectId = currentId.value;
- qualityInspectFileAdd(file).then(res => {
- proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
- getList()
- })
}
// 涓婁紶澶辫触澶勭悊
function handleUploadError() {
@@ -154,17 +186,17 @@
const handleDelete = () => {
let ids = [];
if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map((item) => item.id);
+ ids = selectedRows.value.map((item) => item.storageAttachmentId);
} else {
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
}
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鎻愮ず", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
}).then(() => {
- qualityInspectFileDel(ids).then((res) => {
+ deleteAttachment(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -172,6 +204,11 @@
proxy.$modal.msg("宸插彇娑�");
});
};
+// 棰勮闄勪欢
+const lookFile = (row) => {
+ filePreviewRef.value.open(row.url)
+}
+
defineExpose({
openDialog,
});
diff --git a/src/views/qualityManagement/finalInspection/components/formDia.vue b/src/views/qualityManagement/finalInspection/components/formDia.vue
index 94801ff..e5cd36e 100644
--- a/src/views/qualityManagement/finalInspection/components/formDia.vue
+++ b/src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -1,86 +1,67 @@
<template>
<div>
- <el-dialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板鍑哄巶妫�楠�' : operationType === 'view' ? '鏌ョ湅鍑哄巶妫�楠�' : '缂栬緫鍑哄巶妫�楠�'"
- width="70%"
- @close="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鍑哄巶妫�楠�' : operationType === 'view' ? '鏌ョ湅鍑哄巶妫�楠�' : '缂栬緫鍑哄巶妫�楠�'"
+ width="70%"
+ @close="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="productId">
- <el-tree-select v-model="form.productId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- :disabled="isViewMode || operationType === 'edit'"
- style="width: 100%" />
+ <el-form-item label="浜у搧鍚嶇О锛�" prop="productId">
+ <el-tree-select
+ v-model="form.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels"
+ :data="productOptions"
+ :render-after-expand="false"
+ :disabled="isViewMode || operationType === 'edit'"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="瑙勬牸鍨嬪彿锛�"
- prop="productModelId">
- <el-select v-model="form.productModelId"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="isViewMode || operationType === 'edit'"
- filterable
- readonly
- @change="handleChangeModel">
- <el-option v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id" />
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-select v-model="form.productModelId" placeholder="璇烽�夋嫨" clearable :disabled="isViewMode || operationType === 'edit'"
+ filterable readonly @change="handleChangeModel">
+ <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鎸囨爣閫夋嫨锛�"
- prop="testStandardId">
- <el-select v-model="form.testStandardId"
- placeholder="璇烽�夋嫨鎸囨爣"
- clearable
- @change="handleTestStandardChange"
- style="width: 100%"
- :disabled="isViewMode">
- <el-option v-for="item in testStandardOptions"
- :key="item.id"
- :label="item.standardName || item.standardNo"
- :value="item.id" />
+ <el-form-item label="鎸囨爣閫夋嫨锛�" prop="testStandardId">
+ <el-select
+ v-model="form.testStandardId"
+ placeholder="璇烽�夋嫨鎸囨爣"
+ clearable
+ @change="handleTestStandardChange"
+ style="width: 100%"
+ :disabled="isViewMode"
+ >
+ <el-option
+ v-for="item in testStandardOptions"
+ :key="item.id"
+ :label="item.standardName || item.standardNo"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍗曚綅锛�"
- prop="unit">
- <el-input v-model="form.unit"
- placeholder="璇疯緭鍏�"
- disabled />
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input v-model="form.unit" placeholder="璇疯緭鍏�" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏁伴噺锛�"
- prop="quantity">
- <el-input-number :step="0.01"
- :min="0"
- style="width: 100%"
- v-model="form.quantity"
- placeholder="璇疯緭鍏�"
- clearable
- :precision="2"
- :disabled="isViewMode || processQuantityDisabled" />
+ <el-form-item label="鏁伴噺锛�" prop="quantity">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="璇疯緭鍏�" clearable :precision="2" :disabled="isViewMode || processQuantityDisabled"/>
</el-form-item>
</el-col>
</el-row>
@@ -116,79 +97,87 @@
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="妫�娴嬪崟浣嶏細"
- prop="checkCompany">
- <el-input v-model="form.checkCompany"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="isViewMode" />
+ <el-form-item label="鏄惁鎶芥锛�"
+ prop="isSampling">
+ <el-radio-group v-model="form.isSampling"
+ class="sampling-radio-group"
+ :disabled="isViewMode"
+ @change="handleSamplingChange">
+ <el-radio-button :label="1">鏄�</el-radio-button>
+ <el-radio-button :label="0">鍚�</el-radio-button>
+ </el-radio-group>
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="妫�娴嬬粨鏋滐細"
- prop="checkResult">
- <el-select v-model="form.checkResult"
- :disabled="isViewMode">
- <el-option label="鍚堟牸"
- value="鍚堟牸" />
- <el-option label="涓嶅悎鏍�"
- value="涓嶅悎鏍�" />
- <el-option label="閮ㄥ垎鍚堟牸"
- value="閮ㄥ垎鍚堟牸" />
- </el-select>
+ <el-col :span="12"
+ v-if="form.isSampling === 1">
+ <el-form-item label="鎶芥鏁伴噺锛�"
+ prop="samplingQuantity">
+ <el-input-number :step="0.01"
+ :min="0"
+ style="width: 100%"
+ v-model="form.samplingQuantity"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :precision="2"
+ :disabled="isViewMode" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="妫�楠屽憳锛�"
- prop="checkName">
- <el-select v-model="form.checkName"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="isViewMode">
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form-item label="妫�娴嬪崟浣嶏細" prop="checkCompany">
+ <el-input v-model="form.checkCompany" placeholder="璇疯緭鍏�" clearable :disabled="isViewMode"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚堟牸鐜囷細">
+ <el-tag :type="passRateTagType">{{ passRateDisplayText }}</el-tag>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+ <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable :disabled="isViewMode">
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+ :value="item.nickName"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="妫�娴嬫棩鏈燂細"
- prop="checkTime">
- <el-date-picker v-model="form.checkTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- :disabled="isViewMode" />
+ <el-form-item label="妫�娴嬫棩鏈燂細" prop="checkTime">
+ <el-date-picker
+ v-model="form.checkTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ :disabled="isViewMode"
+ />
</el-form-item>
</el-col>
</el-row>
</el-form>
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :tableLoading="tableLoading"
- height="400">
- <template #slot="{ row }">
- <el-input v-model="row.testValue"
- clearable
- :disabled="isViewMode" />
- </template>
- </PIMTable>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="400"
+ >
+ <template #slot="{ row }">
+ <el-input v-model="row.testValue" clearable :disabled="isViewMode"/>
+ </template>
+ </PIMTable>
<template #footer>
<div class="dialog-footer">
<template v-if="!isViewMode">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
+ <el-button type="primary" @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</template>
- <el-button v-else
- @click="closeDia">鍏抽棴</el-button>
+ <el-button v-else @click="closeDia">鍏抽棴</el-button>
</div>
</template>
</el-dialog>
@@ -196,370 +185,380 @@
</template>
<script setup>
- import {
- ref,
- reactive,
- toRefs,
- computed,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
- import { modelList, productTreeList } from "@/api/basicData/product.js";
- import {
- qualityInspectAdd,
- qualityInspectUpdate,
- } from "@/api/qualityManagement/rawMaterialInspection.js";
- import { userListNoPage } from "@/api/system/user.js";
- import {
- qualityInspectDetailByProductId,
- getQualityTestStandardParamByTestStandardId,
- } from "@/api/qualityManagement/metricMaintenance.js";
- import { qualityInspectParamInfo } from "@/api/qualityManagement/qualityInspectParam.js";
- const { proxy } = getCurrentInstance();
- const emit = defineEmits(["close"]);
+import {ref, reactive, toRefs, computed, getCurrentInstance, nextTick} from "vue";
+import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
+import {modelList, productTreeList} from "@/api/basicData/product.js";
+import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
+import {userListNoPage} from "@/api/system/user.js";
+import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
+import {qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
- const dialogFormVisible = ref(false);
- const operationType = ref("");
- const data = reactive({
- form: {
- checkTime: "",
- process: "",
- checkName: "",
- productName: "",
- productId: "",
- productModelId: "",
- model: "",
- testStandardId: "",
- unit: "",
- quantity: "",
- qualifiedQuantity: "",
- unqualifiedQuantity: "",
- checkCompany: "",
- checkResult: "",
- },
- rules: {
- checkTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- process: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- testStandardId: [
- { required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change" },
- ],
- unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- qualifiedQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- unqualifiedQuantity: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- checkResult: [{ required: true, message: "璇疯緭鍏�", trigger: "change" }],
- },
- });
- const { form, rules } = toRefs(data);
- // 鏄惁涓烘煡鐪嬫ā寮�
- const isViewMode = computed(() => operationType.value === "view");
- // 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯宸ュ簭銆佹暟閲忕疆鐏�
- const processQuantityDisabled = computed(() => {
- const v = form.value || {};
- return !!(v.productMainId != null || v.purchaseLedgerId != null);
- });
- const supplierList = ref([]);
- const productOptions = ref([]);
- const tableColumn = ref([
- {
- label: "鎸囨爣",
- prop: "parameterItem",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鏍囧噯鍊�",
- prop: "standardValue",
- },
- {
- label: "鍐呮帶鍊�",
- prop: "controlValue",
- },
- {
- label: "妫�楠屽��",
- prop: "testValue",
- dataType: "slot",
- slot: "slot",
- },
+const dialogFormVisible = ref(false);
+const operationType = ref("");
+const data = reactive({
+ form: {
+ checkTime: "",
+ process: "",
+ checkName: "",
+ productName: "",
+ productId: "",
+ productModelId: "",
+ model: "",
+ testStandardId: "",
+ unit: "",
+ quantity: "",
+ qualifiedQuantity: "",
+ unqualifiedQuantity: "",
+ checkCompany: "",
+ isSampling: 0,
+ samplingQuantity: "",
+ },
+ rules: {
+ checkTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ process: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ testStandardId: [{ required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change" }],
+ unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ qualifiedQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ unqualifiedQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ isSampling: [{ required: true, message: "璇烽�夋嫨鏄惁鎶芥", trigger: "change" }],
+ samplingQuantity: [{ required: true, message: "璇疯緭鍏ユ娊妫�鏁伴噺", trigger: "blur" }],
+ },
+});
+const { form, rules } = toRefs(data);
+// 鏄惁涓烘煡鐪嬫ā寮�
+const isViewMode = computed(() => operationType.value === 'view');
+
+const passRateValue = computed(() => {
+ const fromApi = form.value.passRate;
+ if (fromApi != null && fromApi !== '') {
+ const n = Number(fromApi);
+ if (!Number.isNaN(n)) return n;
+ }
+ const qualified = Number(form.value.qualifiedQuantity) || 0;
+ const unqualified = Number(form.value.unqualifiedQuantity) || 0;
+ const total = qualified + unqualified;
+ if (!total || total === 0) return null;
+ return (qualified / total) * 100;
+});
+
+const passRateDisplayText = computed(() => {
+ const params = passRateValue.value;
+ if (params == null || params === '') return '鈥�';
+ const n = Number(params);
+ if (Number.isNaN(n)) return '鈥�';
+ return `${n.toFixed(2)}%`;
+});
+
+const passRateTagType = computed(() => {
+ const params = passRateValue.value;
+ if (params == null || params === '') return 'info';
+ const n = Number(params);
+ if (Number.isNaN(n)) return 'info';
+ if (n >= 100) return 'success';
+ if (n >= 90) return 'warning';
+ return 'danger';
+});
+// 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯宸ュ簭銆佹暟閲忕疆鐏�
+const processQuantityDisabled = computed(() => {
+ const v = form.value || {};
+ return !!(v.productMainId != null || v.purchaseLedgerId != null);
+});
+const supplierList = ref([]);
+const productOptions = ref([]);
+const tableColumn = ref([
+ {
+ label: "鎸囨爣",
+ prop: "parameterItem",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鏍囧噯鍊�",
+ prop: "standardValue",
+ },
+ {
+ label: "鍐呮帶鍊�",
+ prop: "controlValue",
+ },
+ {
+ label: "妫�楠屽��",
+ prop: "testValue",
+ dataType: 'slot',
+ slot: 'slot',
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const userList = ref([]);
+const currentProductId = ref(0);
+const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
+const modelOptions = ref([]);
+
+// 鎵撳紑寮规
+const openDialog = async (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ // 鍏堟竻绌鸿〃鍗曢獙璇佺姸鎬侊紝閬垮厤闂儊
+ await nextTick();
+ proxy.$refs.formRef?.clearValidate();
+
+ // 骞惰鍔犺浇鍩虹鏁版嵁
+ const [userListsRes] = await Promise.all([
+ userListNoPage(),
+ getProductOptions(),
+ getOptions().then((res) => {
+ supplierList.value = res.data;
+ })
]);
- const tableData = ref([]);
- const tableLoading = ref(false);
- const userList = ref([]);
- const currentProductId = ref(0);
- const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
- const modelOptions = ref([]);
+ userList.value = userListsRes.data;
- // 鎵撳紑寮规
- const openDialog = async (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- // 鍏堟竻绌鸿〃鍗曢獙璇佺姸鎬侊紝閬垮厤闂儊
- await nextTick();
- proxy.$refs.formRef?.clearValidate();
+ form.value = { isSampling: 0, samplingQuantity: "" }
+ testStandardOptions.value = [];
+ tableData.value = [];
- // 骞惰鍔犺浇鍩虹鏁版嵁
- const [userListsRes] = await Promise.all([
- userListNoPage(),
- getProductOptions(),
- getOptions().then(res => {
- supplierList.value = res.data;
- }),
- ]);
- userList.value = userListsRes.data;
+ if (operationType.value === 'edit' || operationType.value === 'view') {
+ // 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
+ const savedTestStandardId = row.testStandardId;
+ const { passRate, ...rowWithoutPassRate } = row;
+ form.value = { ...rowWithoutPassRate, testStandardId: '' };
+ currentProductId.value = row.productId || 0
+ // 娓呯┖楠岃瘉鐘舵�侊紝閬垮厤鏁版嵁鍔犺浇杩囩▼涓殑鏍¢獙闂儊
+ nextTick(() => {
+ proxy.$refs.formRef?.clearValidate();
+ });
- form.value = {};
- testStandardOptions.value = [];
- tableData.value = [];
+ // 缂栬緫妯″紡涓嬶紝骞惰鍔犺浇瑙勬牸鍨嬪彿鍜屾寚鏍囬�夐」
+ if (currentProductId.value) {
+ // 璁剧疆浜у搧鍚嶇О
+ form.value.productName = findNodeById(productOptions.value, currentProductId.value);
- if (operationType.value === "edit" || operationType.value === "view") {
- // 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
- const savedTestStandardId = row.testStandardId;
- // 鍏堣缃〃鍗曟暟鎹紝浣嗘殏鏃舵竻绌� testStandardId锛岀瓑閫夐」鍔犺浇瀹屾垚鍚庡啀璁剧疆
- form.value = { ...row, testStandardId: "" };
- currentProductId.value = row.productId || 0;
- // 娓呯┖楠岃瘉鐘舵�侊紝閬垮厤鏁版嵁鍔犺浇杩囩▼涓殑鏍¢獙闂儊
- nextTick(() => {
- proxy.$refs.formRef?.clearValidate();
- });
+ // 骞惰鍔犺浇瑙勬牸鍨嬪彿鍜屾寚鏍囬�夐」
+ const params = {
+ productId: currentProductId.value,
+ inspectType: 2
+ };
- // 缂栬緫妯″紡涓嬶紝骞惰鍔犺浇瑙勬牸鍨嬪彿鍜屾寚鏍囬�夐」
- if (currentProductId.value) {
- // 璁剧疆浜у搧鍚嶇О
- form.value.productName = findNodeById(
- productOptions.value,
- currentProductId.value
- );
+ Promise.all([
+ modelList({ id: currentProductId.value }),
+ qualityInspectDetailByProductId(params)
+ ]).then(([modelRes, testStandardRes]) => {
+ // 璁剧疆瑙勬牸鍨嬪彿閫夐」
+ modelOptions.value = modelRes || [];
+ // 濡傛灉琛ㄥ崟涓凡鏈� productModelId锛岃缃搴旂殑 model 鍜� unit
+ if (form.value.productModelId && modelOptions.value.length > 0) {
+ const selectedModel = modelOptions.value.find(item => item.id == form.value.productModelId);
+ if (selectedModel) {
+ form.value.model = selectedModel.model || '';
+ form.value.unit = selectedModel.unit || '';
+ }
+ }
- // 骞惰鍔犺浇瑙勬牸鍨嬪彿鍜屾寚鏍囬�夐」
- const params = {
- productId: currentProductId.value,
- inspectType: 2,
- };
+ // 璁剧疆鎸囨爣閫夐」
+ testStandardOptions.value = testStandardRes.data || [];
- Promise.all([
- modelList({ id: currentProductId.value }),
- qualityInspectDetailByProductId(params),
- ]).then(([modelRes, testStandardRes]) => {
- // 璁剧疆瑙勬牸鍨嬪彿閫夐」
- modelOptions.value = modelRes || [];
- // 濡傛灉琛ㄥ崟涓凡鏈� productModelId锛岃缃搴旂殑 model 鍜� unit
- if (form.value.productModelId && modelOptions.value.length > 0) {
- const selectedModel = modelOptions.value.find(
- item => item.id == form.value.productModelId
+ // 璁剧疆 testStandardId 骞跺姞杞藉弬鏁板垪琛�
+ nextTick(() => {
+ if (savedTestStandardId) {
+ // 纭繚绫诲瀷鍖归厤锛坕tem.id 鍙兘鏄暟瀛楁垨瀛楃涓诧級
+ const matchedOption = testStandardOptions.value.find(item =>
+ item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId)
);
- if (selectedModel) {
- form.value.model = selectedModel.model || "";
- form.value.unit = selectedModel.unit || "";
+ if (matchedOption) {
+ // 纭繚浣跨敤鍖归厤椤圭殑 id锛堜繚鎸佺被鍨嬩竴鑷达級
+ form.value.testStandardId = matchedOption.id;
+ } else {
+ // 濡傛灉鎵句笉鍒板尮閰嶉」锛屽皾璇曠洿鎺ヤ娇鐢ㄥ師鍊�
+ console.warn('鏈壘鍒板尮閰嶇殑鎸囨爣閫夐」锛宼estStandardId:', savedTestStandardId, '鍙敤閫夐」:', testStandardOptions.value);
+ form.value.testStandardId = savedTestStandardId;
}
}
+ // 缂栬緫鍦烘櫙淇濈暀宸叉湁妫�楠屽�硷紝鐩存帴鎷夊彇鍘熷弬鏁版暟鎹�
+ getQualityInspectParamList(row.id);
+ });
+ });
+ } else {
+ getQualityInspectParamList(row.id);
+ }
+ }
+}
+const getProductOptions = () => {
+ return productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ });
+};
+const getModels = (value) => {
+ form.value.productModelId = undefined;
+ form.value.unit = undefined;
+ modelOptions.value = [];
+ currentProductId.value = value
+ form.value.productName = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ })
+ if (currentProductId.value) {
+ getList();
+ }
+};
- // 璁剧疆鎸囨爣閫夐」
- testStandardOptions.value = testStandardRes.data || [];
+const handleChangeModel = (value) => {
+ form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
+ form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
+}
- // 璁剧疆 testStandardId 骞跺姞杞藉弬鏁板垪琛�
- nextTick(() => {
- if (savedTestStandardId) {
- // 纭繚绫诲瀷鍖归厤锛坕tem.id 鍙兘鏄暟瀛楁垨瀛楃涓诧級
- const matchedOption = testStandardOptions.value.find(
- item =>
- item.id == savedTestStandardId ||
- String(item.id) === String(savedTestStandardId)
- );
- if (matchedOption) {
- // 纭繚浣跨敤鍖归厤椤圭殑 id锛堜繚鎸佺被鍨嬩竴鑷达級
- form.value.testStandardId = matchedOption.id;
- } else {
- // 濡傛灉鎵句笉鍒板尮閰嶉」锛屽皾璇曠洿鎺ヤ娇鐢ㄥ師鍊�
- console.warn(
- "鏈壘鍒板尮閰嶇殑鎸囨爣閫夐」锛宼estStandardId:",
- savedTestStandardId,
- "鍙敤閫夐」:",
- testStandardOptions.value
- );
- form.value.testStandardId = savedTestStandardId;
- }
- }
- // 缂栬緫鍦烘櫙淇濈暀宸叉湁妫�楠屽�硷紝鐩存帴鎷夊彇鍘熷弬鏁版暟鎹�
- getQualityInspectParamList(row.id);
- });
+const handleQualifiedQuantityChange = (value) => {
+ if (value === null || value === undefined) {
+ form.value.qualifiedQuantity = 0;
+ return;
+ }
+ const quantity = parseFloat(form.value.quantity) || 0;
+ const qualified = parseFloat(value) || 0;
+ form.value.qualifiedQuantity = qualified > quantity?quantity:qualified;
+ form.value.unqualifiedQuantity = Math.max(0, quantity - qualified);
+};
+
+const handleUnqualifiedQuantityChange = (value) => {
+ if (value === null || value === undefined) {
+ form.value.unqualifiedQuantity = 0;
+ return;
+ }
+ const quantity = parseFloat(form.value.quantity) || 0;
+ const unqualified = parseFloat(value) || 0;
+ form.value.unqualifiedQuantity = unqualified > quantity?quantity:unqualified;
+ form.value.qualifiedQuantity = Math.max(0, quantity - unqualified);
+};
+
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+function convertIdToValue(data) {
+ return data.map((item) => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs.formRef.validate(valid => {
+ if (valid) {
+ form.value.inspectType = 2;
+ if (operationType.value === "add") {
+ tableData.value.forEach((item) => {
+ delete item.id;
+ });
+ }
+ const data = { ...form.value, qualityInspectParams: tableData.value };
+ if (operationType.value === "add") {
+ qualityInspectAdd(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
});
} else {
- getQualityInspectParamList(row.id);
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ });
}
}
+ });
+}
+const getList = () => {
+ if (!currentProductId.value) {
+ testStandardOptions.value = [];
+ tableData.value = [];
+ return;
+ }
+ let params = {
+ productId: currentProductId.value,
+ inspectType: 2
};
- const getProductOptions = () => {
- return productTreeList().then(res => {
- productOptions.value = convertIdToValue(res);
- });
- };
- const getModels = value => {
- form.value.productModelId = undefined;
- form.value.unit = undefined;
- modelOptions.value = [];
- currentProductId.value = value;
- form.value.productName = findNodeById(productOptions.value, value);
- modelList({ id: value }).then(res => {
- modelOptions.value = res;
- });
- if (currentProductId.value) {
- getList();
- }
- };
+ qualityInspectDetailByProductId(params).then(res => {
+ // 淇濆瓨涓嬫媺妗嗛�夐」鏁版嵁
+ testStandardOptions.value = res.data || [];
+ // 娓呯┖琛ㄦ牸鏁版嵁锛岀瓑寰呯敤鎴烽�夋嫨鎸囨爣
+ tableData.value = [];
+ // 娓呯┖鎸囨爣閫夋嫨
+ form.value.testStandardId = '';
+ });
+}
- const handleChangeModel = value => {
- form.value.model =
- modelOptions.value.find(item => item.id == value)?.model || "";
- form.value.unit =
- modelOptions.value.find(item => item.id == value)?.unit || "";
- };
-
- const handleQualifiedQuantityChange = value => {
- if (value === null || value === undefined) {
- form.value.qualifiedQuantity = 0;
- return;
- }
- const quantity = parseFloat(form.value.quantity) || 0;
- const qualified = parseFloat(value) || 0;
- form.value.qualifiedQuantity = qualified > quantity ? quantity : qualified;
- form.value.unqualifiedQuantity = Math.max(0, quantity - qualified);
- };
-
- const handleUnqualifiedQuantityChange = value => {
- if (value === null || value === undefined) {
- form.value.unqualifiedQuantity = 0;
- return;
- }
- const quantity = parseFloat(form.value.quantity) || 0;
- const unqualified = parseFloat(value) || 0;
- form.value.unqualifiedQuantity =
- unqualified > quantity ? quantity : unqualified;
- form.value.qualifiedQuantity = Math.max(0, quantity - unqualified);
- };
-
- const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
- };
- function convertIdToValue(data) {
- return data.map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
+// 鎸囨爣閫夋嫨鍙樺寲澶勭悊
+const handleTestStandardChange = (testStandardId) => {
+ if (!testStandardId) {
+ tableData.value = [];
+ return;
+ }
+ tableLoading.value = true;
+ getQualityTestStandardParamByTestStandardId(testStandardId).then(res => {
+ tableData.value = res.data || [];
+ tableData.value = tableData.value.map(item => ({
+ ...item,
+ id: null
+ }));
+ }).catch(error => {
+ console.error('鑾峰彇鏍囧噯鍙傛暟澶辫触:', error);
+ tableData.value = [];
+ }).finally(() => {
+ tableLoading.value = false;
+ });
+}
+const getQualityInspectParamList = (id) => {
+ qualityInspectParamInfo(id).then(res => {
+ tableData.value = res.data;
+ });
+}
+// 鏄惁鎶芥鍒囨崲
+const handleSamplingChange = (value) => {
+ if (value !== 1) {
+ form.value.samplingQuantity = "";
+ nextTick(() => {
+ proxy.$refs?.formRef?.clearValidate?.("samplingQuantity");
});
}
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitForm = () => {
- proxy.$refs.formRef.validate(valid => {
- if (valid) {
- form.value.inspectType = 2;
- if (operationType.value === "add") {
- tableData.value.forEach(item => {
- delete item.id;
- });
- }
- const data = { ...form.value, qualityInspectParams: tableData.value };
- if (operationType.value === "add") {
- qualityInspectAdd(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- } else {
- qualityInspectUpdate(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- }
- }
- });
- };
- const getList = () => {
- if (!currentProductId.value) {
- testStandardOptions.value = [];
- tableData.value = [];
- return;
- }
- let params = {
- productId: currentProductId.value,
- inspectType: 2,
- };
- qualityInspectDetailByProductId(params).then(res => {
- // 淇濆瓨涓嬫媺妗嗛�夐」鏁版嵁
- testStandardOptions.value = res.data || [];
- // 娓呯┖琛ㄦ牸鏁版嵁锛岀瓑寰呯敤鎴烽�夋嫨鎸囨爣
- tableData.value = [];
- // 娓呯┖鎸囨爣閫夋嫨
- form.value.testStandardId = "";
- });
- };
-
- // 鎸囨爣閫夋嫨鍙樺寲澶勭悊
- const handleTestStandardChange = testStandardId => {
- if (!testStandardId) {
- tableData.value = [];
- return;
- }
- tableLoading.value = true;
- getQualityTestStandardParamByTestStandardId(testStandardId)
- .then(res => {
- tableData.value = res.data || [];
- tableData.value = tableData.value.map(item => ({
- ...item,
- id: null,
- }));
- })
- .catch(error => {
- console.error("鑾峰彇鏍囧噯鍙傛暟澶辫触:", error);
- tableData.value = [];
- })
- .finally(() => {
- tableLoading.value = false;
- });
- };
- const getQualityInspectParamList = id => {
- qualityInspectParamInfo(id).then(res => {
- tableData.value = res.data;
- });
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- tableData.value = [];
- testStandardOptions.value = [];
- form.value.testStandardId = "";
- dialogFormVisible.value = false;
- emit("close");
- };
- defineExpose({
- openDialog,
- });
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ tableData.value = [];
+ testStandardOptions.value = [];
+ form.value.testStandardId = '';
+ dialogFormVisible.value = false;
+ emit('close');
+}
+defineExpose({
+ openDialog,
+});
</script>
<style scoped>
+.sampling-radio-group {
+ height: 32px;
+}
</style>
diff --git a/src/views/qualityManagement/finalInspection/index.vue b/src/views/qualityManagement/finalInspection/index.vue
index 4a59fa4..181f8bb 100644
--- a/src/views/qualityManagement/finalInspection/index.vue
+++ b/src/views/qualityManagement/finalInspection/index.vue
@@ -1,111 +1,59 @@
<template>
<div class="app-container">
<div class="search_form mb20">
- <el-form ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline">
- <el-row :gutter="20">
- <el-col :span="4">
- <el-form-item label="浜у搧鍚嶇О"
- prop="productName">
- <el-input v-model="searchForm.productName"
- style="width: 240px"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉版悳绱�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="妫�娴嬫棩鏈�"
- prop="entryDate">
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
- </el-form-item>
- </el-col>
- <el-col :span="4">
- <el-form-item label="閿�鍞崟鍙�"
- prop="salesContractNo">
- <el-input v-model="searchForm.salesContractNo"
- style="width: 240px"
- placeholder="璇疯緭鍏ラ攢鍞崟鍙锋悳绱�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="4">
- <el-form-item label="鐢熶骇宸ュ崟鍙�"
- prop="workOrderNo">
- <el-input v-model="searchForm.workOrderNo"
- style="width: 240px"
- placeholder="璇疯緭鍏ョ敓浜у伐鍗曞彿鎼滅储"
- clearable />
- </el-form-item>
- </el-col>
- <!-- 鎸夐挳 -->
- <el-col :span="4">
- <el-form-item>
- <el-button type="primary"
- @click="getList">
- 鎼滅储
- </el-button>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <div class="actions">
- <el-button type="primary"
- @click="openForm('add')">鏂板</el-button>
+ <div>
+ <span class="search_title">浜у搧鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.productName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ヤ骇鍝佸悕绉版悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span style="margin-left: 10px" class="search_title">妫�娴嬫棩鏈燂細</span>
+ <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+ placeholder="璇烽�夋嫨" clearable @change="changeDaterange"/>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储
+ </el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"></PIMTable>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"
+ ></PIMTable>
</div>
- <InspectionFormDia ref="inspectionFormDia"
- @close="handleQuery"></InspectionFormDia>
- <FormDia ref="formDia"
- @close="handleQuery"></FormDia>
- <files-dia ref="filesDia"
- @close="handleQuery"></files-dia>
- <el-dialog v-model="dialogFormVisible"
- title="缂栬緫妫�楠屽憳"
- width="30%"
+ <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
+ <FormDia ref="formDia" @close="handleQuery"></FormDia>
+ <files-dia ref="filesDia" ></files-dia>
+ <el-dialog v-model="dialogFormVisible" title="缂栬緫妫�楠屽憳" width="30%"
@close="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
- <el-form-item label="妫�楠屽憳锛�"
- prop="checkName">
- <el-select v-model="form.checkName"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+ <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+ <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable>
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+ :value="item.nickName"/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
+ <el-button type="primary" @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
@@ -114,320 +62,298 @@
</template>
<script setup>
- import { Search } from "@element-plus/icons-vue";
- import {
- onMounted,
- ref,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue";
- import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue";
- import { ElMessageBox } from "element-plus";
- import {
- downloadQualityInspect,
- qualityInspectDel,
- qualityInspectListPage,
- qualityInspectUpdate,
- submitQualityInspect,
- } from "@/api/qualityManagement/rawMaterialInspection.js";
- import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue";
- import dayjs from "dayjs";
- import { userListNoPage } from "@/api/system/user.js";
- import useUserStore from "@/store/modules/user";
+import {Search} from "@element-plus/icons-vue";
+import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
+import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue";
+import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue";
+import {ElMessageBox} from "element-plus";
+import {
+ downloadQualityInspect,
+ qualityInspectDel,
+ qualityInspectListPage, qualityInspectUpdate,
+ submitQualityInspect
+} from "@/api/qualityManagement/rawMaterialInspection.js";
+import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue";
+import dayjs from "dayjs";
+import {userListNoPage} from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
- const data = reactive({
- searchForm: {
- productName: "",
- salesContractNo: "",
- workOrderNo: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
+const data = reactive({
+ searchForm: {
+ productName: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ rules: {
+ checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ },
+});
+const {searchForm} = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "妫�娴嬫棩鏈�",
+ prop: "checkTime",
+ width: 120
+ },
+ {
+ label: "閿�鍞崟鍙�",
+ prop: "salesContractNo",
+ width: 120
+ },
+ {
+ label: "鐢熶骇宸ュ崟鍙�",
+ prop: "workOrderNo",
+ width: 120
+ },
+ {
+ label: "妫�楠屽憳",
+ prop: "checkName",
+ },
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鎬绘暟閲�",
+ prop: "quantity",
+ width: 100
+ },
+ {
+ label: "鍚堟牸鏁伴噺",
+ prop: "qualifiedQuantity",
+ width: 100
+ },
+ {
+ label: "涓嶅悎鏍兼暟閲�",
+ prop: "unqualifiedQuantity",
+ width: 100
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "passRate",
+ width: 100,
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == null || params === '') return '鈥�';
+ const n = Number(params);
+ if (Number.isNaN(n)) return '鈥�';
+ return `${n.toFixed(2)}%`;
},
- rules: {
- checkName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ formatType: (params) => {
+ if (params == null || params === '') return 'info';
+ const n = Number(params);
+ if (Number.isNaN(n)) return 'info';
+ if (n === 100) return 'success';
+ if (n >= 75) return 'primary';
+ if (n >= 50) return 'warning';
+ if (n >= 25) return 'danger';
+ return 'danger';
},
- });
- const { searchForm } = toRefs(data);
- const tableColumn = ref([
- {
- label: "妫�娴嬫棩鏈�",
- prop: "checkTime",
- width: 120,
+ },
+ {
+ label: "鎻愪氦鐘舵��",
+ prop: "inspectState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params) {
+ return "宸叉彁浜�";
+ } else {
+ return "鏈彁浜�";
+ }
},
- {
- label: "閿�鍞崟鍙�",
- prop: "salesContractNo",
- width: 120,
+ formatType: (params) => {
+ if (params) {
+ return "success";
+ } else {
+ return "info";
+ }
},
- {
- label: "鐢熶骇宸ュ崟鍙�",
- prop: "workOrderNo",
- width: 120,
- },
- {
- label: "妫�楠屽憳",
- prop: "checkName",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鎬绘暟閲�",
- prop: "quantity",
- width: 100,
- },
- {
- label: "鍚堟牸鏁伴噺",
- prop: "qualifiedQuantity",
- width: 100,
- },
- {
- label: "涓嶅悎鏍兼暟閲�",
- prop: "unqualifiedQuantity",
- width: 100,
- },
- {
- label: "鍚堟牸鐜�",
- prop: "passRate",
- width: 100,
- dataType: "tag",
- formatType: params => {
- if (!params) return "";
- const rate = parseFloat(params);
- if (rate < 90) {
- return "danger";
- } else if (rate === 100) {
- return "success";
- } else {
- return "warning";
- }
- },
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120,
- },
- {
- label: "妫�娴嬬粨鏋�",
- prop: "checkResult",
- dataType: "tag",
- formatType: params => {
- if (params == "涓嶅悎鏍�") {
- return "danger";
- } else if (params == "鍚堟牸") {
- return "success";
- } else {
- return "danger";
- }
- },
- },
- {
- label: "鎻愪氦鐘舵��",
- prop: "inspectState",
- formatData: params => {
- if (params) {
- return "宸叉彁浜�";
- } else {
- return "鏈彁浜�";
- }
- },
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: row => {
- openForm("edit", row);
- },
- disabled: row => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- },
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
},
- {
- name: "鏌ョ湅",
- type: "text",
- clickFun: row => {
- openForm("view", row);
- },
- },
- {
- name: "闄勪欢",
- type: "text",
- clickFun: row => {
- openFilesFormDia(row);
- },
- },
- {
- name: "鎻愪氦",
- type: "text",
- clickFun: row => {
- submit(row.id);
- },
- disabled: row => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- },
- },
- {
- name: "鍒嗛厤妫�楠屽憳",
- type: "text",
- clickFun: row => {
- if (!row.checkName) {
- open(row);
- } else {
- proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
- }
- },
- disabled: row => {
- return row.inspectState == 1 || row.checkName;
- },
- },
- {
- name: "涓嬭浇",
- type: "text",
- clickFun: row => {
- downLoadFile(row);
- },
- },
- ],
- },
- ]);
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- const currentRow = ref(null);
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
- const formDia = ref();
- const filesDia = ref();
- const inspectionFormDia = ref();
- const { proxy } = getCurrentInstance();
- const userStore = useUserStore();
- const userList = ref([]);
- const form = ref({
- checkName: "",
- });
- const dialogFormVisible = ref(false);
-
- const changeDaterange = value => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- }
- getList();
- };
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined;
- qualityInspectListPage({ ...params, inspectType: 2 })
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => {
- const quantity = parseFloat(item.quantity);
- const qualifiedQuantity = parseFloat(item.qualifiedQuantity);
- let passRate = null;
- if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) {
- passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%";
+ disabled: (row) => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
}
- return {
- ...item,
- passRate: passRate,
- };
- });
- page.total = res.data.total;
- })
- .catch(err => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
+ return false;
+ }
+ },
+ {
+ name: "鏌ョ湅",
+ type: "text",
+ clickFun: (row) => {
+ openForm("view", row);
+ },
+ },
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: (row) => {
+ openFilesFormDia(row);
+ },
+ },
+ {
+ name: "鎻愪氦",
+ type: "text",
+ clickFun: (row) => {
+ submit(row.id);
+ },
+ loading: (row) => submitLoadingId.value === row.id,
+ disabled: (row) => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ }
+ },
+ {
+ name: "鍒嗛厤妫�楠屽憳",
+ type: "text",
+ clickFun: (row) => {
+ if (!row.checkName) {
+ open(row)
+ } else {
+ proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+ }
+ },
+ disabled: (row) => {
+ return row.inspectState == 1 || row.checkName;
+ }
+ },
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: (row) => {
+ downLoadFile(row);
+ },
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const submitLoadingId = ref(null);
+const currentRow = ref(null)
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0
+});
+const formDia = ref()
+const filesDia = ref()
+const inspectionFormDia = ref()
+const {proxy} = getCurrentInstance()
+const userStore = useUserStore()
+const userList = ref([]);
+const form = ref({
+ checkName: ""
+});
+const dialogFormVisible = ref(false);
- // 鎵撳紑寮规
- const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row);
- });
- };
- // 鎵撳紑鏂板妫�楠屽脊妗�
- const openInspectionForm = (type, row) => {
- nextTick(() => {
- inspectionFormDia.value?.openDialog(type, row);
- });
- };
- // 鎵撳紑闄勪欢寮规
- const openFilesFormDia = (type, row) => {
- nextTick(() => {
- filesDia.value?.openDialog(type, row);
- });
- };
+const changeDaterange = (value) => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
+ getList();
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const params = {...searchForm.value, ...page};
+ params.entryDate = undefined
+ qualityInspectListPage({...params, inspectType: 2}).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records
+ page.total = res.data.total;
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map(item => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row)
+ })
+};
+// 鎵撳紑鏂板妫�楠屽脊妗�
+const openInspectionForm = (type, row) => {
+ nextTick(() => {
+ inspectionFormDia.value?.openDialog(type, row)
+ })
+};
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (type, row) => {
+ nextTick(() => {
+ filesDia.value?.openDialog(type, row)
+ })
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- qualityInspectDel(ids).then(res => {
+ qualityInspectDel(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -435,88 +361,86 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download(
- "/quality/qualityInspect/export",
- { inspectType: 2 },
- "鍑哄巶妫�楠�.xlsx"
- );
+ proxy.download("/quality/qualityInspect/export", {inspectType: 2}, "鍑哄巶妫�楠�.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+};
- // 鎻愪环
- const submit = async id => {
- const res = await submitQualityInspect({ id: id });
+// 鎻愪氦
+const submit = async (id) => {
+ submitLoadingId.value = id;
+ try {
+ const res = await submitQualityInspect({ id });
if (res.code === 200) {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ const row = tableData.value.find(item => item.id === id);
+ if (row) {
+ row.inspectState = 1;
+ }
+ }
+ } finally {
+ submitLoadingId.value = null;
+ }
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+
+const submitForm = () => {
+ if (currentRow.value) {
+ const data = {
+ ...form.value,
+ id: currentRow.value.id
+ }
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
getList();
- }
- };
+ })
+ }
+};
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- };
+const open = async (row) => {
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ currentRow.value = row
+ dialogFormVisible.value = true
+}
- const submitForm = () => {
- if (currentRow.value) {
- const data = {
- ...form.value,
- id: currentRow.value.id,
- };
- qualityInspectUpdate(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- };
+const downLoadFile = (row) => {
+ downloadQualityInspect({id: row.id}).then((blobData) => {
+ const blob = new Blob([blobData], {
+ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ })
+ const downloadUrl = window.URL.createObjectURL(blob)
- const open = async row => {
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- currentRow.value = row;
- dialogFormVisible.value = true;
- };
+ const link = document.createElement('a')
+ link.href = downloadUrl
+ link.download = '鍘熸潗鏂欐楠屾姤鍛�.docx'
+ document.body.appendChild(link)
+ link.click()
- const downLoadFile = row => {
- downloadQualityInspect({ id: row.id }).then(blobData => {
- const blob = new Blob([blobData], {
- type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
- });
- const downloadUrl = window.URL.createObjectURL(blob);
-
- const link = document.createElement("a");
- link.href = downloadUrl;
- link.download = "鍘熸潗鏂欐楠屾姤鍛�.docx";
- document.body.appendChild(link);
- link.click();
-
- document.body.removeChild(link);
- window.URL.revokeObjectURL(downloadUrl);
- });
- };
- onMounted(() => {
- getList();
- });
+ document.body.removeChild(link)
+ window.URL.revokeObjectURL(downloadUrl)
+ })
+};
+onMounted(() => {
+ getList();
+});
</script>
-<style scoped lang="scss">
- .actions {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 10px;
- }
-</style>
+<style scoped></style>
diff --git a/src/views/qualityManagement/metricBinding/index.vue b/src/views/qualityManagement/metricBinding/index.vue
index 6e7a881..ba989ea 100644
--- a/src/views/qualityManagement/metricBinding/index.vue
+++ b/src/views/qualityManagement/metricBinding/index.vue
@@ -1,167 +1,168 @@
<template>
<div class="app-container metric-binding">
- <el-row :gutter="16"
- class="metric-binding-row">
+ <el-row :gutter="16" class="metric-binding-row">
<!-- 宸︿晶锛氭娴嬫爣鍑嗗垪琛� -->
- <el-col :xs="24"
- :sm="24"
- :md="12"
- :lg="14"
- :xl="14"
- class="left-col">
+ <el-col :xs="24" :sm="24" :md="12" :lg="14" :xl="14" class="left-col">
<div class="panel left-panel">
- <PIMTable rowKey="id"
- :column="standardColumns"
- :tableData="standardTableData"
- :page="page"
- :isSelection="false"
- :rowClassName="rowClassNameCenter"
- :tableLoading="tableLoading"
- :rowClick="handleTableRowClick"
- @pagination="handlePagination"
- :total="page.total">
- <template #standardNoCell="{ row }">
- <span class="clickable-link"
- @click="handleStandardRowClick(row)">
- {{ row.standardNo }}
- </span>
- </template>
- <!-- 琛ㄥご鎼滅储 -->
- <template #standardNoHeader>
- <el-input v-model="searchForm.standardNo"
- placeholder="鏍囧噯缂栧彿"
- clearable
- size="small"
- @change="handleQuery"
- @clear="handleQuery" />
- </template>
- <template #standardNameHeader>
- <el-input v-model="searchForm.standardName"
- placeholder="鏍囧噯鍚嶇О"
- clearable
- size="small"
- @change="handleQuery"
- @clear="handleQuery" />
- </template>
- <template #inspectTypeHeader>
- <el-select v-model="searchForm.inspectType"
- placeholder="绫诲埆"
- clearable
- size="small"
- style="width: 120px"
- @change="handleQuery"
- @clear="handleQuery">
- <el-option label="鍘熸潗鏂欐楠�"
- value="0" />
- <el-option label="杩囩▼妫�楠�"
- value="1" />
- <el-option label="鍑哄巶妫�楠�"
- value="2" />
- </el-select>
- </template>
- <template #stateHeader>
- <el-select v-model="searchForm.state"
- placeholder="鐘舵��"
- clearable
- size="small"
- style="width: 110px"
- @change="handleQuery"
- @clear="handleQuery">
- <el-option label="鑽夌"
- value="0" />
- <el-option label="閫氳繃"
- value="1" />
- <el-option label="鎾ら攢"
- value="2" />
- </el-select>
- </template>
- </PIMTable>
+ <PIMTable
+ rowKey="id"
+ :column="standardColumns"
+ :tableData="standardTableData"
+ :page="page"
+ :isSelection="false"
+ :rowClassName="rowClassNameCenter"
+ :tableLoading="tableLoading"
+ :rowClick="handleTableRowClick"
+ @pagination="handlePagination"
+ :total="page.total"
+ >
+ <template #standardNoCell="{ row }">
+ <span class="clickable-link" @click="handleStandardRowClick(row)">
+ {{ row.standardNo }}
+ </span>
+ </template>
+
+ <!-- 琛ㄥご鎼滅储 -->
+ <template #standardNoHeader>
+ <el-input
+ v-model="searchForm.standardNo"
+ placeholder="鏍囧噯缂栧彿"
+ clearable
+ size="small"
+ @change="handleQuery"
+ @clear="handleQuery"
+ />
+ </template>
+ <template #standardNameHeader>
+ <el-input
+ v-model="searchForm.standardName"
+ placeholder="鏍囧噯鍚嶇О"
+ clearable
+ size="small"
+ @change="handleQuery"
+ @clear="handleQuery"
+ />
+ </template>
+ <template #inspectTypeHeader>
+ <el-select
+ v-model="searchForm.inspectType"
+ placeholder="绫诲埆"
+ clearable
+ size="small"
+ style="width: 120px"
+ @change="handleQuery"
+ @clear="handleQuery"
+ >
+ <el-option label="鍘熸潗鏂欐楠�" value="0" />
+ <el-option label="杩囩▼妫�楠�" value="1" />
+ <el-option label="鍑哄巶妫�楠�" value="2" />
+ </el-select>
+ </template>
+ <template #stateHeader>
+ <el-select
+ v-model="searchForm.state"
+ placeholder="鐘舵��"
+ clearable
+ size="small"
+ style="width: 110px"
+ @change="handleQuery"
+ @clear="handleQuery"
+ >
+ <el-option label="鑽夌" value="0" />
+ <el-option label="閫氳繃" value="1" />
+ <el-option label="鎾ら攢" value="2" />
+ </el-select>
+ </template>
+ </PIMTable>
</div>
</el-col>
+
<!-- 鍙充晶锛氱粦瀹氬垪琛� -->
- <el-col :xs="24"
- :sm="24"
- :md="12"
- :lg="10"
- :xl="10"
- class="right-col">
+ <el-col :xs="24" :sm="24" :md="12" :lg="10" :xl="10" class="right-col">
<div class="panel right-panel">
- <div class="right-header">
- <div class="title">缁戝畾鍏崇郴</div>
- <div class="desc"
- v-if="currentStandard">
- 褰撳墠妫�娴嬫爣鍑嗙紪鍙凤細<span class="link-text">{{ currentStandard.standardNo }}</span>
- </div>
- <div class="desc"
- v-else>璇烽�夋嫨宸︿晶妫�娴嬫爣鍑�</div>
- </div>
- <div class="right-toolbar">
- <el-button type="primary"
- :disabled="!currentStandard"
- @click="openBindingDialog">娣诲姞缁戝畾</el-button>
- <el-button type="danger"
- plain
- :disabled="!currentStandard"
- @click="handleBatchUnbind">鍒犻櫎</el-button>
- </div>
- <el-table v-loading="bindingLoading"
- :data="bindingTableData"
- border
- :row-class-name="() => 'row-center'"
- class="center-table"
- style="width: 100%"
- height="calc(100vh - 220px)"
- @selection-change="handleBindingSelectionChange">
- <el-table-column type="selection"
- width="48"
- align="center" />
- <el-table-column type="index"
- label="搴忓彿"
- width="60"
- align="center" />
- <el-table-column prop="productName"
- label="浜у搧鍚嶇О"
- min-width="140" />
- <el-table-column label="鎿嶄綔"
- width="120"
- fixed="right"
- align="center">
- <template #default="{ row }">
- <el-button link
- type="danger"
- size="small"
- @click="handleUnbind(row)">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
+ <div class="right-header">
+ <div class="title">缁戝畾鍏崇郴</div>
+ <div class="desc" v-if="currentStandard">
+ 褰撳墠妫�娴嬫爣鍑嗙紪鍙凤細<span class="link-text">{{ currentStandard.standardNo }}</span>
+ </div>
+ <div class="desc" v-else>璇烽�夋嫨宸︿晶妫�娴嬫爣鍑�</div>
+ </div>
+
+ <div class="right-toolbar">
+ <el-button type="primary" :disabled="!currentStandard" @click="openBindingDialog">娣诲姞缁戝畾</el-button>
+ <el-button type="danger" plain :disabled="!currentStandard" @click="handleBatchUnbind">鍒犻櫎</el-button>
+ </div>
+
+ <el-table
+ v-loading="bindingLoading"
+ :data="bindingTableData"
+ border
+ :row-class-name="() => 'row-center'"
+ class="center-table"
+ style="width: 100%"
+ height="calc(100vh - 220px)"
+ @selection-change="handleBindingSelectionChange"
+ >
+ <el-table-column type="selection" width="48" align="center" />
+ <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+ <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="140" />
+ <el-table-column label="鎿嶄綔" width="120" fixed="right" align="center">
+ <template #default="{ row }">
+ <el-button link type="danger" size="small" @click="handleUnbind(row)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
</div>
</el-col>
</el-row>
+
<!-- 娣诲姞缁戝畾寮规 -->
- <el-dialog v-model="bindingDialogVisible"
- title="娣诲姞缁戝畾"
- width="520px"
- @close="closeBindingDialog">
- <el-form label-width="100px">
- <el-form-item label="浜у搧">
- <PIMTreeSelect v-model="selectedProductIds"
- multiple
- filterable
- collapse-tags
- collapse-tags-tooltip
- placeholder="璇烽�夋嫨浜у搧锛堝彲澶氶�夛級"
- clearable
- check-strictly
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%" />
- </el-form-item>
- </el-form>
+ <el-dialog
+ v-model="bindingDialogVisible"
+ title="娣诲姞缁戝畾"
+ width="640px"
+ @close="closeBindingDialog"
+ >
+ <div class="binding-dialog">
+ <el-input
+ v-model="productSearchKeyword"
+ placeholder="鎼滅储浜у搧"
+ clearable
+ prefix-icon="Search"
+ class="binding-search"
+ />
+ <el-tree
+ ref="productTreeRef"
+ :key="productTreeKey"
+ v-loading="productTreeLoading"
+ :data="productTreeData"
+ show-checkbox
+ check-strictly
+ node-key="id"
+ :props="{ label: 'label', children: 'children', disabled: 'disabled' }"
+ :filter-node-method="filterProductNode"
+ class="product-binding-tree"
+ @check="handleProductTreeCheck"
+ />
+ <div v-if="selectedProductLabels.length" class="selected-products">
+ <div class="selected-title">宸查�夋嫨锛坽{ selectedProductLabels.length }}锛�</div>
+ <div class="selected-tags">
+ <el-tag
+ v-for="item in selectedProductLabels"
+ :key="item.id"
+ closable
+ type="info"
+ @close="removeSelectedProduct(item.id)"
+ >
+ {{ item.label }}
+ </el-tag>
+ </div>
+ </div>
+ </div>
<template #footer>
<span class="dialog-footer">
<el-button @click="closeBindingDialog">鍙栨秷</el-button>
- <el-button type="primary"
- @click="submitBinding">纭畾</el-button>
+ <el-button type="primary" @click="submitBinding">纭畾</el-button>
</span>
</template>
</el-dialog>
@@ -169,404 +170,476 @@
</template>
<script setup>
- import { Search } from "@element-plus/icons-vue";
- import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
- import { ElMessageBox } from "element-plus";
- import PIMTable from "@/components/PIMTable/PIMTable.vue";
- import PIMTreeSelect from "@/components/PIMTreeSelect/index.vue";
- import { productTreeList } from "@/api/basicData/product.js";
- import { qualityTestStandardListPage } from "@/api/qualityManagement/metricMaintenance.js";
- import { productProcessListPage } from "@/api/basicData/productProcess.js";
- import {
- qualityTestStandardBindingList,
- qualityTestStandardBindingAdd,
- qualityTestStandardBindingDel,
- } from "@/api/qualityManagement/qualityTestStandardBinding.js";
+import { ref, reactive, toRefs, computed, watch, nextTick, onMounted, getCurrentInstance } from 'vue'
+import { ElMessageBox } from 'element-plus'
+import PIMTable from '@/components/PIMTable/PIMTable.vue'
+import { productTreeList } from '@/api/basicData/product.js'
+import {
+ qualityTestStandardListPage
+} from '@/api/qualityManagement/metricMaintenance.js'
+import { productProcessListPage } from '@/api/basicData/productProcess.js'
+import {
+ qualityTestStandardBindingList,
+ qualityTestStandardBindingAdd,
+ qualityTestStandardBindingDel
+} from '@/api/qualityManagement/qualityTestStandardBinding.js'
- const { proxy } = getCurrentInstance();
+const { proxy } = getCurrentInstance()
- // 宸︿晶鏍囧噯鍒楄〃锛氭暣琛屽唴瀹瑰眳涓紙閰嶅悎鏍峰紡锛�
- const rowClassNameCenter = () => "row-center";
+// 宸︿晶鏍囧噯鍒楄〃锛氭暣琛屽唴瀹瑰眳涓紙閰嶅悎鏍峰紡锛�
+const rowClassNameCenter = () => 'row-center'
- const data = reactive({
- searchForm: {
- standardNo: "",
- standardName: "",
- state: "",
- inspectType: "",
- },
- });
- const { searchForm } = toRefs(data);
-
- // 宸︿晶
- const standardTableData = ref([]);
- const tableLoading = ref(false);
- const page = reactive({ current: 1, size: 10, total: 0 });
-
- // 宸ュ簭涓嬫媺锛堢敤浜庡垪琛ㄥ洖鏄撅級
- const processOptions = ref([]);
-
- const getProcessList = async () => {
- try {
- const res = await productProcessListPage({ current: 1, size: 1000 });
- if (res?.code === 200) {
- const records = res?.data?.records || [];
- processOptions.value = records.map(item => ({
- label: item.processName || item.name || item.label,
- value: item.id || item.processId || item.value,
- }));
- }
- } catch (error) {
- console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触:", error);
- }
- };
-
- const standardColumns = ref([
- {
- label: "鏍囧噯缂栧彿",
- prop: "standardNo",
- dataType: "slot",
- slot: "standardNoCell",
- minWidth: 160,
- align: "center",
- headerSlot: "standardNoHeader",
- },
- {
- label: "鏍囧噯鍚嶇О",
- prop: "standardName",
- minWidth: 180,
- align: "center",
- headerSlot: "standardNameHeader",
- },
- {
- label: "绫诲埆",
- prop: "inspectType",
- headerSlot: "inspectTypeHeader",
- align: "center",
- dataType: "tag",
- formatData: val => {
- const map = { 0: "鍘熸潗鏂欐楠�", 1: "杩囩▼妫�楠�", 2: "鍑哄巶妫�楠�" };
- return map[val] || val;
- },
- },
- {
- label: "宸ュ簭",
- prop: "processId",
- align: "center",
- dataType: "tag",
- formatData: val => {
- const target = processOptions.value.find(
- item => String(item.value) === String(val)
- );
- return target?.label || val;
- },
- },
- {
- label: "澶囨敞",
- prop: "remark",
- minWidth: 160,
- align: "center",
- },
- // {
- // label: '鐘舵��',
- // prop: 'state',
- // headerSlot: 'stateHeader',
- // dataType: 'tag',
- // formatData: (val) => {
- // const map = { 0: '鑽夌', 1: '閫氳繃', 2: '鎾ら攢' }
- // return map[val] || val
- // },
- // formatType: (val) => {
- // if (val == 1) return 'success'
- // if (val == 2) return 'warning'
- // return 'info'
- // }
- // }
- ]);
-
- const currentStandard = ref(null);
-
- // 鍙充晶缁戝畾
- const bindingTableData = ref([]);
- const bindingLoading = ref(false);
- const bindingSelectedRows = ref([]);
- const bindingDialogVisible = ref(false);
-
- // 浜у搧鏍戯紙鐢ㄤ簬缁戝畾閫夋嫨锛�
- const productOptions = ref([]);
- const selectedProductIds = ref([]);
-
- const getProductOptions = async () => {
- // 閬垮厤閲嶅璇锋眰
- if (productOptions.value?.length) return;
- const res = await productTreeList();
- productOptions.value = convertIdToValue(Array.isArray(res) ? res : []);
- };
-
- function convertIdToValue(data) {
- return (data || []).map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id,
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
- return newItem;
- });
+const data = reactive({
+ searchForm: {
+ standardNo: '',
+ standardName: '',
+ state: '',
+ inspectType: ''
}
+})
+const { searchForm } = toRefs(data)
- const handleQuery = () => {
- page.current = 1;
- getStandardList();
- };
+// 宸︿晶
+const standardTableData = ref([])
+const tableLoading = ref(false)
+const page = reactive({ current: 1, size: 10, total: 0 })
- const handlePagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getStandardList();
- };
+// 宸ュ簭涓嬫媺锛堢敤浜庡垪琛ㄥ洖鏄撅級
+const processOptions = ref([])
- const getStandardList = () => {
- tableLoading.value = true;
- qualityTestStandardListPage({
- ...searchForm.value,
- current: page.current,
- size: page.size,
- state: 1,
+const getProcessList = async () => {
+ try {
+ const res = await productProcessListPage({ current: 1, size: 1000 })
+ if (res?.code === 200) {
+ const records = res?.data?.records || []
+ processOptions.value = records.map((item) => ({
+ label: item.processName || item.name || item.label,
+ value: item.id || item.processId || item.value
+ }))
+ }
+ } catch (error) {
+ console.error('鑾峰彇宸ュ簭鍒楄〃澶辫触:', error)
+ }
+}
+
+const standardColumns = ref([
+ { label: '鏍囧噯缂栧彿', prop: 'standardNo', dataType: 'slot', slot: 'standardNoCell', minWidth: 160, align: 'center', headerSlot: 'standardNoHeader' },
+ { label: '鏍囧噯鍚嶇О', prop: 'standardName', minWidth: 180, align: 'center', headerSlot: 'standardNameHeader' },
+ {
+ label: '绫诲埆',
+ prop: 'inspectType',
+ headerSlot: 'inspectTypeHeader',
+ align: 'center',
+ dataType: 'tag',
+ formatData: (val) => {
+ const map = { 0: '鍘熸潗鏂欐楠�', 1: '杩囩▼妫�楠�', 2: '鍑哄巶妫�楠�' }
+ return map[val] || val
+ }
+ },
+ {
+ label: '宸ュ簭',
+ prop: 'processId',
+ align: 'center',
+ dataType: 'tag',
+ formatData: (val) => {
+ const target = processOptions.value.find(
+ (item) => String(item.value) === String(val)
+ )
+ return target?.label || val
+ }
+ },
+ {
+ label: '澶囨敞',
+ prop: 'remark',
+ minWidth: 160,
+ align: 'center'
+ }
+ // {
+ // label: '鐘舵��',
+ // prop: 'state',
+ // headerSlot: 'stateHeader',
+ // dataType: 'tag',
+ // formatData: (val) => {
+ // const map = { 0: '鑽夌', 1: '閫氳繃', 2: '鎾ら攢' }
+ // return map[val] || val
+ // },
+ // formatType: (val) => {
+ // if (val == 1) return 'success'
+ // if (val == 2) return 'warning'
+ // return 'info'
+ // }
+ // }
+])
+
+const currentStandard = ref(null)
+
+// 鍙充晶缁戝畾
+const bindingTableData = ref([])
+const bindingLoading = ref(false)
+const bindingSelectedRows = ref([])
+const bindingDialogVisible = ref(false)
+
+// 浜у搧鏍戯紙鐢ㄤ簬缁戝畾閫夋嫨锛�
+const productTreeData = ref([])
+const productTreeLoading = ref(false)
+const productTreeRef = ref(null)
+const productTreeKey = ref(0)
+const productSearchKeyword = ref('')
+const selectedProductIds = ref([])
+
+const markParentNodesDisabled = (nodes) => {
+ return (nodes || []).map((node) => {
+ const children = node.children?.length ? markParentNodesDisabled(node.children) : []
+ return {
+ ...node,
+ children,
+ disabled: children.length > 0
+ }
+ })
+}
+
+const buildProductLabelMap = (nodes, map = {}) => {
+ ;(nodes || []).forEach((node) => {
+ if (node.id != null) {
+ map[node.id] = node.label
+ }
+ if (node.children?.length) {
+ buildProductLabelMap(node.children, map)
+ }
+ })
+ return map
+}
+
+const productLabelMap = computed(() => buildProductLabelMap(productTreeData.value))
+
+const selectedProductLabels = computed(() =>
+ selectedProductIds.value.map((id) => ({
+ id,
+ label: productLabelMap.value[id] || id
+ }))
+)
+
+const filterProductNode = (value, data) => {
+ if (!value) return true
+ return String(data.label || '').includes(value)
+}
+
+watch(productSearchKeyword, (val) => {
+ productTreeRef.value?.filter(val)
+})
+
+const getProductTreeData = async () => {
+ if (productTreeData.value?.length) return
+ productTreeLoading.value = true
+ try {
+ const res = await productTreeList()
+ productTreeData.value = markParentNodesDisabled(Array.isArray(res) ? res : [])
+ } catch (error) {
+ console.error('鑾峰彇浜у搧鏍戝け璐�:', error)
+ } finally {
+ productTreeLoading.value = false
+ }
+}
+
+const handleProductTreeCheck = () => {
+ selectedProductIds.value = productTreeRef.value?.getCheckedKeys(true) || []
+}
+
+const removeSelectedProduct = (id) => {
+ selectedProductIds.value = selectedProductIds.value.filter((item) => item !== id)
+ productTreeRef.value?.setChecked(id, false, false)
+}
+
+const handleQuery = () => {
+ page.current = 1
+ getStandardList()
+}
+
+const handlePagination = (obj) => {
+ page.current = obj.page
+ page.size = obj.limit
+ getStandardList()
+}
+
+const getStandardList = () => {
+ tableLoading.value = true
+ qualityTestStandardListPage({
+ ...searchForm.value,
+ current: page.current,
+ size: page.size,
+ state: 1
+ })
+ .then((res) => {
+ const records = res?.data?.records || []
+ standardTableData.value = records
+ page.total = res?.data?.total || records.length
})
- .then(res => {
- const records = res?.data?.records || [];
- standardTableData.value = records;
- page.total = res?.data?.total || records.length;
- })
- .finally(() => {
- tableLoading.value = false;
- });
- };
+ .finally(() => {
+ tableLoading.value = false
+ })
+}
- // 琛ㄦ牸琛岀偣鍑伙紝鍔犺浇鍙充晶缁戝畾鍒楄〃
- const handleTableRowClick = row => {
- currentStandard.value = row;
- loadBindingList();
- };
+// 琛ㄦ牸琛岀偣鍑伙紝鍔犺浇鍙充晶缁戝畾鍒楄〃
+const handleTableRowClick = (row) => {
+ currentStandard.value = row
+ loadBindingList()
+}
- // 宸︿晶琛岀偣鍑伙紝鍔犺浇鍙充晶缁戝畾鍒楄〃锛堜繚鐣欑敤浜庢爣鍑嗙紪鍙峰垪鐨勭偣鍑伙級
- const handleStandardRowClick = row => {
- currentStandard.value = row;
- loadBindingList();
- };
+// 宸︿晶琛岀偣鍑伙紝鍔犺浇鍙充晶缁戝畾鍒楄〃锛堜繚鐣欑敤浜庢爣鍑嗙紪鍙峰垪鐨勭偣鍑伙級
+const handleStandardRowClick = (row) => {
+ currentStandard.value = row
+ loadBindingList()
+}
- const loadBindingList = () => {
- if (!currentStandard.value?.id) {
- bindingTableData.value = [];
- return;
- }
- bindingLoading.value = true;
- qualityTestStandardBindingList({ testStandardId: currentStandard.value.id })
- .then(res => {
- const base = res?.data || [];
- // 灏嗗綋鍓嶆爣鍑嗙殑宸ュ簭鍜屽娉ㄥ甫鍒扮粦瀹氬垪琛ㄤ腑灞曠ず
- bindingTableData.value = base.map(item => ({
- ...item,
- processId: currentStandard.value?.processId,
- remark: currentStandard.value?.remark,
- }));
- })
- .finally(() => {
- bindingLoading.value = false;
- });
- };
+const loadBindingList = () => {
+ if (!currentStandard.value?.id) {
+ bindingTableData.value = []
+ return
+ }
+ bindingLoading.value = true
+ qualityTestStandardBindingList({ testStandardId: currentStandard.value.id })
+ .then((res) => {
+ const base = res?.data || []
+ // 灏嗗綋鍓嶆爣鍑嗙殑宸ュ簭鍜屽娉ㄥ甫鍒扮粦瀹氬垪琛ㄤ腑灞曠ず
+ bindingTableData.value = base.map((item) => ({
+ ...item,
+ processId: currentStandard.value?.processId,
+ remark: currentStandard.value?.remark
+ }))
+ })
+ .finally(() => {
+ bindingLoading.value = false
+ })
+}
- const handleBindingSelectionChange = selection => {
- bindingSelectedRows.value = selection;
- };
+const handleBindingSelectionChange = (selection) => {
+ bindingSelectedRows.value = selection
+}
- const openBindingDialog = () => {
- if (!currentStandard.value?.id) return;
- selectedProductIds.value = [];
- getProductOptions();
- bindingDialogVisible.value = true;
- };
+const openBindingDialog = () => {
+ if (!currentStandard.value?.id) return
+ selectedProductIds.value = []
+ productSearchKeyword.value = ''
+ productTreeKey.value += 1
+ bindingDialogVisible.value = true
+ nextTick(() => {
+ productTreeRef.value?.setCheckedKeys([])
+ productTreeRef.value?.filter('')
+ })
+}
- const closeBindingDialog = () => {
- bindingDialogVisible.value = false;
- };
+const closeBindingDialog = () => {
+ bindingDialogVisible.value = false
+ selectedProductIds.value = []
+ productSearchKeyword.value = ''
+ productTreeRef.value?.setCheckedKeys([])
+}
- const submitBinding = async () => {
- const testStandardId = currentStandard.value?.id;
- if (!testStandardId) return;
- const ids = (selectedProductIds.value || []).filter(Boolean);
- if (!ids.length) {
- proxy.$message.warning("璇烽�夋嫨浜у搧");
- return;
- }
- const payload = ids.map(pid => ({
- productId: pid,
- testStandardId,
- }));
- await qualityTestStandardBindingAdd(payload);
- proxy.$message.success("娣诲姞鎴愬姛");
- bindingDialogVisible.value = false;
- loadBindingList();
- };
+const submitBinding = async () => {
+ const testStandardId = currentStandard.value?.id
+ if (!testStandardId) return
+ const ids = (selectedProductIds.value || []).filter(Boolean)
+ if (!ids.length) {
+ proxy.$message.warning('璇烽�夋嫨浜у搧')
+ return
+ }
+ const payload = ids.map((pid) => ({
+ productId: pid,
+ testStandardId
+ }))
+ await qualityTestStandardBindingAdd(payload)
+ proxy.$message.success('娣诲姞鎴愬姛')
+ bindingDialogVisible.value = false
+ loadBindingList()
+}
- const handleUnbind = async row => {
- const id = row?.id ?? row?.qualityTestStandardBindingId;
- if (id == null || id === "") return;
- try {
- await ElMessageBox.confirm("纭鍒犻櫎璇ョ粦瀹氾紵", "鎻愮ず", { type: "warning" });
- } catch {
- return;
- }
- try {
- await qualityTestStandardBindingDel([id]);
- proxy.$message.success("鍒犻櫎鎴愬姛");
- loadBindingList();
- } catch (err) {
- console.error("鍒犻櫎缁戝畾澶辫触:", err);
- proxy.$message?.error(err?.message || "鍒犻櫎澶辫触");
- }
- };
+const handleUnbind = async (row) => {
+ const id = row?.id ?? row?.qualityTestStandardBindingId
+ if (id == null || id === '') return
+ try {
+ await ElMessageBox.confirm('纭鍒犻櫎璇ョ粦瀹氾紵', '鎻愮ず', { type: 'warning' })
+ } catch {
+ return
+ }
+ try {
+ await qualityTestStandardBindingDel([id])
+ proxy.$message.success('鍒犻櫎鎴愬姛')
+ loadBindingList()
+ } catch (err) {
+ console.error('鍒犻櫎缁戝畾澶辫触:', err)
+ proxy.$message?.error(err?.message || '鍒犻櫎澶辫触')
+ }
+}
- const handleBatchUnbind = async () => {
- if (!bindingSelectedRows.value.length) {
- proxy.$message.warning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const ids = bindingSelectedRows.value
- .map(i => i?.id ?? i?.qualityTestStandardBindingId)
- .filter(id => id != null && id !== "");
- if (!ids.length) {
- proxy.$message.warning("閫変腑鏁版嵁缂哄皯鏈夋晥 id");
- return;
- }
- try {
- await ElMessageBox.confirm(
- "閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�",
- "鍒犻櫎鎻愮ず",
- { type: "warning" }
- );
- } catch {
- return;
- }
- try {
- await qualityTestStandardBindingDel(ids);
- proxy.$message.success("鍒犻櫎鎴愬姛");
- loadBindingList();
- } catch (err) {
- console.error("鎵归噺鍒犻櫎缁戝畾澶辫触:", err);
- proxy.$message?.error(err?.message || "鍒犻櫎澶辫触");
- }
- };
+const handleBatchUnbind = async () => {
+ if (!bindingSelectedRows.value.length) {
+ proxy.$message.warning('璇烽�夋嫨鏁版嵁')
+ return
+ }
+ const ids = bindingSelectedRows.value
+ .map((i) => i?.id ?? i?.qualityTestStandardBindingId)
+ .filter((id) => id != null && id !== '')
+ if (!ids.length) {
+ proxy.$message.warning('閫変腑鏁版嵁缂哄皯鏈夋晥 id')
+ return
+ }
+ try {
+ await ElMessageBox.confirm('閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�', '鍒犻櫎鎻愮ず', { type: 'warning' })
+ } catch {
+ return
+ }
+ try {
+ await qualityTestStandardBindingDel(ids)
+ proxy.$message.success('鍒犻櫎鎴愬姛')
+ loadBindingList()
+ } catch (err) {
+ console.error('鎵归噺鍒犻櫎缁戝畾澶辫触:', err)
+ proxy.$message?.error(err?.message || '鍒犻櫎澶辫触')
+ }
+}
- onMounted(() => {
- getStandardList();
- getProcessList();
- });
+onMounted(() => {
+ getStandardList()
+ getProcessList()
+ getProductTreeData()
+})
</script>
<style scoped>
- .metric-binding-row {
- width: 100%;
- }
+.metric-binding-row {
+ width: 100%;
+}
- .metric-binding-row .left-col,
- .metric-binding-row .right-col {
- margin-bottom: 16px;
- }
+.metric-binding-row .left-col,
+.metric-binding-row .right-col {
+ margin-bottom: 16px;
+}
- .metric-binding-row .panel {
- background: #ffffff;
- padding: 16px;
- box-sizing: border-box;
- height: 100%;
- min-height: 400px;
- }
+.metric-binding-row .panel {
+ background: #ffffff;
+ padding: 16px;
+ box-sizing: border-box;
+ height: 100%;
+ min-height: 400px;
+}
- .left-panel,
- .right-panel {
- height: 100%;
- }
+.left-panel,
+.right-panel {
+ height: 100%;
+}
- .toolbar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 12px;
- }
+.toolbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+}
- .toolbar-right {
- flex-shrink: 0;
- }
+.toolbar-right {
+ flex-shrink: 0;
+}
- .right-header {
- display: flex;
- align-items: baseline;
- justify-content: space-between;
- margin-bottom: 10px;
- }
+.right-header {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ margin-bottom: 10px;
+}
- .right-header .title {
- font-size: 16px;
- font-weight: 600;
- }
+.right-header .title {
+ font-size: 16px;
+ font-weight: 600;
+}
- .right-header .desc {
- font-size: 13px;
- color: #666;
- }
+.right-header .desc {
+ font-size: 13px;
+ color: #666;
+}
- .right-toolbar {
- display: flex;
- justify-content: flex-end;
- gap: 10px;
- margin-bottom: 10px;
- }
+.right-toolbar {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-bottom: 10px;
+}
- .link-text {
- color: #409eff;
- cursor: default;
- }
+.link-text {
+ color: #409eff;
+ cursor: default;
+}
- .clickable-link {
- color: #409eff;
- cursor: pointer;
- }
+.clickable-link {
+ color: #409eff;
+ cursor: pointer;
+}
- .clickable-link:hover {
- text-decoration: underline;
- }
+.clickable-link:hover {
+ text-decoration: underline;
+}
- :deep(.row-center td) {
- text-align: center !important;
- }
+:deep(.row-center td) {
+ text-align: center !important;
+}
- /* el-table 琛ㄥご/鍐呭缁熶竴灞呬腑锛坮ow-class-name 涓嶄綔鐢ㄤ簬琛ㄥご锛� */
- :deep(.center-table .el-table__header-wrapper th .cell) {
- text-align: center !important;
- }
- :deep(.center-table .el-table__body-wrapper td .cell) {
- text-align: center !important;
- }
+/* el-table 琛ㄥご/鍐呭缁熶竴灞呬腑锛坮ow-class-name 涓嶄綔鐢ㄤ簬琛ㄥご锛� */
+:deep(.center-table .el-table__header-wrapper th .cell) {
+ text-align: center !important;
+}
+:deep(.center-table .el-table__body-wrapper td .cell) {
+ text-align: center !important;
+}
- /* PIMTable 琛ㄥご灞呬腑 */
- :deep(.lims-table .pim-table-header-cell) {
- text-align: center;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
+/* PIMTable 琛ㄥご灞呬腑 */
+:deep(.lims-table .pim-table-header-cell) {
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
- :deep(.lims-table .pim-table-header-title) {
- text-align: center;
- width: 100%;
- }
+:deep(.lims-table .pim-table-header-title) {
+ text-align: center;
+ width: 100%;
+}
- :deep(.lims-table .pim-table-header-extra) {
- width: 100%;
- margin-top: 4px;
- }
+:deep(.lims-table .pim-table-header-extra) {
+ width: 100%;
+ margin-top: 4px;
+}
+
+.binding-dialog {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.binding-search {
+ width: 100%;
+}
+
+.product-binding-tree {
+ max-height: 360px;
+ overflow-y: auto;
+ border: 1px solid #ebeef5;
+ border-radius: 4px;
+ padding: 8px;
+}
+
+.selected-products {
+ border-top: 1px solid #ebeef5;
+ padding-top: 12px;
+}
+
+.selected-title {
+ font-size: 13px;
+ color: #606266;
+ margin-bottom: 8px;
+}
+
+.selected-tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
</style>
diff --git a/src/views/qualityManagement/nearExpiryReturn/index.vue b/src/views/qualityManagement/nearExpiryReturn/index.vue
index 26dc747..93e19c2 100644
--- a/src/views/qualityManagement/nearExpiryReturn/index.vue
+++ b/src/views/qualityManagement/nearExpiryReturn/index.vue
@@ -1,257 +1,213 @@
<template>
<div class="app-container">
- <el-form :model="queryParams"
- ref="queryForm"
- :inline="true"
- v-show="showSearch"
- label-width="68px">
- <el-form-item label="浜у搧鍚嶇О"
- prop="productName">
- <el-input v-model="queryParams.productName"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
- clearable
- @keyup.enter.native="handleQuery" />
+ <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="浜у搧鍚嶇О" prop="productName">
+ <el-input
+ v-model="queryParams.productName"
+ placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
</el-form-item>
- <el-form-item label="鎵规鍙�"
- prop="batchNumber">
- <el-input v-model="queryParams.batchNumber"
- placeholder="璇疯緭鍏ユ壒娆″彿"
- clearable
- @keyup.enter.native="handleQuery" />
+ <el-form-item label="鎵规鍙�" prop="batchNumber">
+ <el-input
+ v-model="queryParams.batchNumber"
+ placeholder="璇疯緭鍏ユ壒娆″彿"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
</el-form-item>
- <el-form-item label="閫�鍥炴棩鏈�"
- prop="returnDate">
- <el-date-picker clearable
- v-model="queryParams.returnDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
+ <el-form-item label="閫�鍥炴棩鏈�" prop="returnDate">
+ <el-date-picker
+ clearable
+ v-model="queryParams.returnDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
</el-date-picker>
</el-form-item>
<el-form-item>
- <el-button type="primary"
- icon="Search"
- @click="handleQuery">鎼滅储</el-button>
- <el-button icon="Refresh"
- @click="resetQuery">閲嶇疆</el-button>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
</el-form-item>
</el-form>
- <el-row :gutter="10"
- class="mb8">
+
+ <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
- <el-button type="primary"
- plain
- icon="Plus"
- @click="handleAdd">鏂板</el-button>
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="handleAdd"
+ >鏂板</el-button>
</el-col>
<el-col :span="1.5">
- <el-button type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate">淇敼</el-button>
+ <el-button
+ type="success"
+ plain
+ icon="Edit"
+ :disabled="single"
+ @click="handleUpdate"
+ >淇敼</el-button>
</el-col>
<el-col :span="1.5">
- <el-button type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete">鍒犻櫎</el-button>
+ <el-button
+ type="danger"
+ plain
+ icon="Delete"
+ :disabled="multiple"
+ @click="handleDelete"
+ >鍒犻櫎</el-button>
</el-col>
<el-col :span="1.5">
- <el-button type="warning"
- plain
- icon="Download"
- @click="handleExport">瀵煎嚭</el-button>
+ <el-button
+ type="warning"
+ plain
+ icon="Download"
+ @click="handleExport"
+ >瀵煎嚭</el-button>
</el-col>
- <right-toolbar v-model:showSearch="showSearch"
- @queryTable="getList"></right-toolbar>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
- <el-table v-loading="loading"
- :data="nearExpiryReturnList"
- @selection-change="handleSelectionChange">
- <el-table-column type="selection"
- width="55"
- align="center" />
- <el-table-column label="搴忓彿"
- type="index"
- width="50"
- align="center" />
- <el-table-column label="浜у搧鍚嶇О"
- prop="productName" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="productSpec" />
- <el-table-column label="鎵规鍙�"
- prop="batchNumber" />
- <el-table-column label="鐢熶骇鏃ユ湡"
- prop="productionDate"
- align="center">
+
+ <el-table v-loading="loading" :data="nearExpiryReturnList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="搴忓彿" type="index" width="50" align="center" />
+ <el-table-column label="浜у搧鍚嶇О" prop="productName" />
+ <el-table-column label="浜у搧瑙勬牸" prop="productSpec" />
+ <el-table-column label="鎵规鍙�" prop="batchNumber" />
+ <el-table-column label="鐢熶骇鏃ユ湡" prop="productionDate" align="center">
<template #default="scope">
<span>{{ parseTime(scope.row.productionDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
- <el-table-column label="鍒版湡鏃ユ湡"
- prop="expiryDate"
- align="center">
+ <el-table-column label="鍒版湡鏃ユ湡" prop="expiryDate" align="center">
<template #default="scope">
<span>{{ parseTime(scope.row.expiryDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
- <el-table-column label="閫�鍥炴暟閲�"
- prop="returnQuantity" />
- <el-table-column label="閫�鍥炲師鍥�"
- prop="returnReason" />
- <el-table-column label="閫�鍥炴棩鏈�"
- prop="returnDate"
- align="center">
+ <el-table-column label="閫�鍥炴暟閲�" prop="returnQuantity" />
+ <el-table-column label="閫�鍥炲師鍥�" prop="returnReason" />
+ <el-table-column label="閫�鍥炴棩鏈�" prop="returnDate" align="center">
<template #default="scope">
<span>{{ parseTime(scope.row.returnDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
- <el-table-column label="澶勭悊鐘舵��"
- prop="status"
- align="center">
+ <el-table-column label="澶勭悊鐘舵��" prop="status" align="center">
<template #default="scope">
- <dict-tag :options="statusOptions"
- :value="scope.row.status" />
+ <dict-tag :options="statusOptions" :value="scope.row.status"/>
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔"
- align="center"
- class-name="small-padding fixed-width">
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
<template #default="scope">
- <el-button size="mini"
- type="text"
- icon="Edit"
- @click="handleUpdate(scope.row)">淇敼</el-button>
- <el-button size="mini"
- type="text"
- icon="Delete"
- @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+ <el-button size="mini" type="text" icon="Edit" @click="handleUpdate(scope.row)">淇敼</el-button>
+ <el-button size="mini" type="text" icon="Delete" @click="handleDelete(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" />
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ v-model:page="queryParams.pageNum"
+ v-model:limit="queryParams.pageSize"
+ @pagination="getList"
+ />
+
<!-- 娣诲姞鎴栦慨鏀逛复鏈熼��鍥炲彴璐﹀璇濇 -->
- <el-dialog :title="title"
- v-model="open"
- width="800px"
- append-to-body>
- <el-form ref="formRef"
- :model="form"
- :rules="rules"
- label-width="100px">
+ <el-dialog :title="title" v-model="open" width="800px" append-to-body>
+ <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="12">
- <el-form-item label="浜у搧鍚嶇О"
- prop="productName">
- <el-input v-model="form.productName"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+ <el-form-item label="浜у搧鍚嶇О" prop="productName">
+ <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="瑙勬牸鍨嬪彿"
- prop="productSpec">
- <el-input v-model="form.productSpec"
- placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+ <el-form-item label="浜у搧瑙勬牸" prop="productSpec">
+ <el-input v-model="form.productSpec" placeholder="璇疯緭鍏ヤ骇鍝佽鏍�" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
- <el-form-item label="鎵规鍙�"
- prop="batchNumber">
- <el-input v-model="form.batchNumber"
- placeholder="璇疯緭鍏ユ壒娆″彿" />
+ <el-form-item label="鎵规鍙�" prop="batchNumber">
+ <el-input v-model="form.batchNumber" placeholder="璇疯緭鍏ユ壒娆″彿" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="閫�鍥炴暟閲�"
- prop="returnQuantity">
- <el-input-number v-model="form.returnQuantity"
- controls-position="right"
- :min="1" />
+ <el-form-item label="閫�鍥炴暟閲�" prop="returnQuantity">
+ <el-input-number v-model="form.returnQuantity" controls-position="right" :min="1" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
- <el-form-item label="鐢熶骇鏃ユ湡"
- prop="productionDate">
- <el-date-picker clearable
- v-model="form.productionDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨鐢熶骇鏃ユ湡">
+ <el-form-item label="鐢熶骇鏃ユ湡" prop="productionDate">
+ <el-date-picker
+ clearable
+ v-model="form.productionDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鐢熶骇鏃ユ湡">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鍒版湡鏃ユ湡"
- prop="expiryDate">
- <el-date-picker clearable
- v-model="form.expiryDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨鍒版湡鏃ユ湡">
+ <el-form-item label="鍒版湡鏃ユ湡" prop="expiryDate">
+ <el-date-picker
+ clearable
+ v-model="form.expiryDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鍒版湡鏃ユ湡">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
- <el-form-item label="閫�鍥炴棩鏈�"
- prop="returnDate">
- <el-date-picker clearable
- v-model="form.returnDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
+ <el-form-item label="閫�鍥炴棩鏈�" prop="returnDate">
+ <el-date-picker
+ clearable
+ v-model="form.returnDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="澶勭悊鐘舵��"
- prop="status">
- <el-select v-model="form.status"
- placeholder="璇烽�夋嫨澶勭悊鐘舵��">
- <el-option v-for="dict in statusOptions"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"></el-option>
+ <el-form-item label="澶勭悊鐘舵��" prop="status">
+ <el-select v-model="form.status" placeholder="璇烽�夋嫨澶勭悊鐘舵��">
+ <el-option
+ v-for="dict in statusOptions"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ ></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
- <el-form-item label="閫�鍥炲師鍥�"
- prop="returnReason">
- <el-input v-model="form.returnReason"
- type="textarea"
- placeholder="璇疯緭鍏ラ��鍥炲師鍥�" />
+ <el-form-item label="閫�鍥炲師鍥�" prop="returnReason">
+ <el-input v-model="form.returnReason" type="textarea" placeholder="璇疯緭鍏ラ��鍥炲師鍥�" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
- <el-form-item label="澶囨敞"
- prop="remark">
- <el-input v-model="form.remark"
- type="textarea"
- placeholder="璇疯緭鍏ュ娉�" />
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ娉�" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭� 瀹�</el-button>
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
<el-button @click="cancel">鍙� 娑�</el-button>
</div>
</template>
@@ -260,186 +216,180 @@
</template>
<script setup name="NearExpiryReturn">
- import { ref, reactive, onMounted } from "vue";
- import { ElMessageBox } from "element-plus";
- // API鎺ュ彛宸茬Щ闄わ紝涓嶅啀璋冪敤鍚庣鎺ュ彛
+import { ref, reactive, onMounted } from "vue";
+import { ElMessageBox } from "element-plus";
+// API鎺ュ彛宸茬Щ闄わ紝涓嶅啀璋冪敤鍚庣鎺ュ彛
- const { proxy } = getCurrentInstance();
- const { parseTime } = proxy;
+const { proxy } = getCurrentInstance();
+const { parseTime } = proxy;
- const nearExpiryReturnList = ref([]);
- const open = ref(false);
- const loading = ref(true);
- const showSearch = ref(true);
- const ids = ref([]);
- const single = ref(true);
- const multiple = ref(true);
- const total = ref(0);
- const title = ref("");
+const nearExpiryReturnList = ref([]);
+const open = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const title = ref("");
- // 鐘舵�佸瓧鍏�
- const statusOptions = ref([
- { label: "寰呭鐞�", value: "0" },
- { label: "澶勭悊涓�", value: "1" },
- { label: "宸插畬鎴�", value: "2" },
- ]);
+// 鐘舵�佸瓧鍏�
+const statusOptions = ref([
+ { label: "寰呭鐞�", value: "0" },
+ { label: "澶勭悊涓�", value: "1" },
+ { label: "宸插畬鎴�", value: "2" }
+]);
- const data = reactive({
- form: {},
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- productName: null,
- batchNumber: null,
- returnDate: null,
- },
- rules: {
- productName: [
- { required: true, message: "浜у搧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" },
- ],
- productSpec: [
- { required: true, message: "瑙勬牸鍨嬪彿涓嶈兘涓虹┖", trigger: "blur" },
- ],
- batchNumber: [
- { required: true, message: "鎵规鍙蜂笉鑳戒负绌�", trigger: "blur" },
- ],
- returnQuantity: [
- { required: true, message: "閫�鍥炴暟閲忎笉鑳戒负绌�", trigger: "blur" },
- ],
- productionDate: [
- { required: true, message: "鐢熶骇鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" },
- ],
- expiryDate: [
- { required: true, message: "鍒版湡鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" },
- ],
- returnDate: [
- { required: true, message: "閫�鍥炴棩鏈熶笉鑳戒负绌�", trigger: "blur" },
- ],
- returnReason: [
- { required: true, message: "閫�鍥炲師鍥犱笉鑳戒负绌�", trigger: "blur" },
- ],
- status: [
- { required: true, message: "澶勭悊鐘舵�佷笉鑳戒负绌�", trigger: "change" },
- ],
- },
- });
-
- const { queryParams, form, rules } = toRefs(data);
-
- /** 鏌ヨ涓存湡閫�鍥炲彴璐﹀垪琛� */
- function getList() {
- loading.value = true;
- // 涓嶈皟鐢ㄦ帴鍙o紝杩斿洖绌烘暟鎹�
- nearExpiryReturnList.value = [];
- total.value = 0;
- loading.value = false;
+const data = reactive({
+ form: {},
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ productName: null,
+ batchNumber: null,
+ returnDate: null
+ },
+ rules: {
+ productName: [
+ { required: true, message: "浜у搧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ productSpec: [
+ { required: true, message: "浜у搧瑙勬牸涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ batchNumber: [
+ { required: true, message: "鎵规鍙蜂笉鑳戒负绌�", trigger: "blur" }
+ ],
+ returnQuantity: [
+ { required: true, message: "閫�鍥炴暟閲忎笉鑳戒负绌�", trigger: "blur" }
+ ],
+ productionDate: [
+ { required: true, message: "鐢熶骇鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ expiryDate: [
+ { required: true, message: "鍒版湡鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ returnDate: [
+ { required: true, message: "閫�鍥炴棩鏈熶笉鑳戒负绌�", trigger: "blur" }
+ ],
+ returnReason: [
+ { required: true, message: "閫�鍥炲師鍥犱笉鑳戒负绌�", trigger: "blur" }
+ ],
+ status: [
+ { required: true, message: "澶勭悊鐘舵�佷笉鑳戒负绌�", trigger: "change" }
+ ]
}
+});
- // 鍙栨秷鎸夐挳
- function cancel() {
- open.value = false;
- reset();
- }
+const { queryParams, form, rules } = toRefs(data);
- // 琛ㄥ崟閲嶇疆
- function reset() {
- form.value = {
- id: null,
- productName: null,
- productSpec: null,
- batchNumber: null,
- productionDate: null,
- expiryDate: null,
- returnQuantity: null,
- returnReason: null,
- returnDate: null,
- status: null,
- remark: null,
- };
- proxy.resetForm("formRef");
- }
+/** 鏌ヨ涓存湡閫�鍥炲彴璐﹀垪琛� */
+function getList() {
+ loading.value = true;
+ // 涓嶈皟鐢ㄦ帴鍙o紝杩斿洖绌烘暟鎹�
+ nearExpiryReturnList.value = [];
+ total.value = 0;
+ loading.value = false;
+}
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
- }
+// 鍙栨秷鎸夐挳
+function cancel() {
+ open.value = false;
+ reset();
+}
- /** 閲嶇疆鎸夐挳鎿嶄綔 */
- function resetQuery() {
- proxy.resetForm("queryForm");
- handleQuery();
- }
+// 琛ㄥ崟閲嶇疆
+function reset() {
+ form.value = {
+ id: null,
+ productName: null,
+ productSpec: null,
+ batchNumber: null,
+ productionDate: null,
+ expiryDate: null,
+ returnQuantity: null,
+ returnReason: null,
+ returnDate: null,
+ status: null,
+ remark: null
+ };
+ proxy.resetForm("formRef");
+}
- // 澶氶�夋閫変腑鏁版嵁
- function handleSelectionChange(selection) {
- ids.value = selection.map(item => item.id);
- single.value = selection.length !== 1;
- multiple.value = !selection.length;
- }
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ queryParams.value.pageNum = 1;
+ getList();
+}
- /** 鏂板鎸夐挳鎿嶄綔 */
- function handleAdd() {
- reset();
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+ proxy.resetForm("queryForm");
+ handleQuery();
+}
+
+// 澶氶�夋閫変腑鏁版嵁
+function handleSelectionChange(selection) {
+ ids.value = selection.map(item => item.id);
+ single.value = selection.length !== 1;
+ multiple.value = !selection.length;
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+ reset();
+ open.value = true;
+ title.value = "娣诲姞涓存湡閫�鍥炲彴璐�";
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+ reset();
+ // 涓嶈皟鐢ㄦ帴鍙o紝鐩存帴浣跨敤浼犲叆鐨勬暟鎹�
+ if (row) {
+ form.value = { ...row };
open.value = true;
- title.value = "娣诲姞涓存湡閫�鍥炲彴璐�";
+ title.value = "淇敼涓存湡閫�鍥炲彴璐�";
}
+}
- /** 淇敼鎸夐挳鎿嶄綔 */
- function handleUpdate(row) {
- reset();
- // 涓嶈皟鐢ㄦ帴鍙o紝鐩存帴浣跨敤浼犲叆鐨勬暟鎹�
- if (row) {
- form.value = { ...row };
- open.value = true;
- title.value = "淇敼涓存湡閫�鍥炲彴璐�";
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
+ if (form.value.id != null) {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛");
+ } else {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛");
+ }
+ open.value = false;
+ getList();
}
- }
-
- /** 鎻愪氦鎸夐挳 */
- function submitForm() {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
- if (form.value.id != null) {
- proxy.$modal.msgSuccess("淇敼鎴愬姛");
- } else {
- proxy.$modal.msgSuccess("鏂板鎴愬姛");
- }
- open.value = false;
- getList();
- }
- });
- }
-
- /** 鍒犻櫎鎸夐挳鎿嶄綔 */
- function handleDelete(row) {
- const deleteIds = row.id || ids.value;
- ElMessageBox.confirm(
- '鏄惁纭鍒犻櫎涓存湡閫�鍥炲彴璐︾紪鍙蜂负"' + deleteIds + '"鐨勬暟鎹」锛�',
- "璀﹀憡",
- {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- }
- )
- .then(function () {
- // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .catch(() => {});
- }
-
- /** 瀵煎嚭鎸夐挳鎿嶄綔 */
- function handleExport() {
- // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘彁绀�
- proxy.$modal.msgSuccess("瀵煎嚭鍔熻兘鏆傛湭瀹炵幇");
- }
-
- onMounted(() => {
- getList();
});
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ const deleteIds = row.id || ids.value;
+ ElMessageBox.confirm('鏄惁纭鍒犻櫎涓存湡閫�鍥炲彴璐︾紪鍙蜂负"' + deleteIds + '"鐨勬暟鎹」锛�', "璀﹀憡", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning"
+ }).then(function() {
+ // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ }).catch(() => {});
+}
+
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+ // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘彁绀�
+ proxy.$modal.msgSuccess("瀵煎嚭鍔熻兘鏆傛湭瀹炵幇");
+}
+
+onMounted(() => {
+ getList();
+});
</script>
diff --git a/src/views/qualityManagement/nonconformingManagement/components/formDia.vue b/src/views/qualityManagement/nonconformingManagement/components/formDia.vue
index 5e20709..e747d04 100644
--- a/src/views/qualityManagement/nonconformingManagement/components/formDia.vue
+++ b/src/views/qualityManagement/nonconformingManagement/components/formDia.vue
@@ -1,168 +1,121 @@
<template>
<div>
- <el-dialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板涓嶅悎鏍肩鐞�' : '缂栬緫涓嶅悎鏍肩鐞�'"
- width="70%"
- @close="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板涓嶅悎鏍肩鐞�' : '缂栬緫涓嶅悎鏍肩鐞�'"
+ width="70%"
+ @close="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="inspectType">
+ <el-form-item label="绫诲埆锛�" prop="inspectType">
<el-select v-model="form.inspectType">
- <el-option label="鍘熸潗鏂欐楠�"
- :value="0" />
- <el-option label="杩囩▼妫�楠�"
- :value="1" />
- <el-option label="鍑哄巶妫�楠�"
- :value="2" />
+ <el-option label="鍘熸潗鏂欐楠�" :value="0" />
+ <el-option label="杩囩▼妫�楠�" :value="1" />
+ <el-option label="鍑哄巶妫�楠�" :value="2" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="浜у搧鍚嶇О锛�"
- prop="productId">
- <el-tree-select v-model="form.productId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%" />
+ <el-form-item label="浜у搧鍚嶇О锛�" prop="productId">
+ <el-tree-select
+ v-model="form.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels"
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="瑙勬牸鍨嬪彿锛�"
- prop="model">
- <el-select v-model="form.productModelId"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'edit'"
- filterable
- readonly
- @change="handleChangeModel">
- <el-option v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id" />
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="model">
+ <el-select v-model="form.productModelId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'edit'"
+ filterable readonly @change="handleChangeModel">
+ <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍗曚綅锛�"
- prop="unit">
- <el-input v-model="form.unit"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input v-model="form.unit" placeholder="璇疯緭鍏�" clearable/>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏁伴噺锛�"
- prop="quantity">
- <el-input-number :step="0.01"
- :min="0"
- style="width: 100%"
- v-model="form.quantity"
- placeholder="璇疯緭鍏�"
- clearable
- :precision="2" />
+ <el-form-item label="鏁伴噺锛�" prop="quantity">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="璇疯緭鍏�" clearable :precision="2"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="妫�楠屽憳锛�"
- prop="checkName">
- <el-select v-model="form.checkName"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%">
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+ <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable style="width: 100%">
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="妫�娴嬫棩鏈燂細"
- prop="checkTime">
- <el-date-picker v-model="form.checkTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%" />
+ <el-form-item label="妫�娴嬫棩鏈燂細" prop="checkTime">
+ <el-date-picker
+ v-model="form.checkTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="涓嶅悎鏍肩幇璞★細"
- prop="defectivePhenomena">
- <el-input v-model="form.defectivePhenomena"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="涓嶅悎鏍肩幇璞★細" prop="defectivePhenomena">
+ <el-input v-model="form.defectivePhenomena" placeholder="璇疯緭鍏�" clearable/>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="澶勭悊缁撴灉锛�"
- prop="dealResult">
- <el-select v-model="form.dealResult"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option :label="item.label"
- :value="item.value"
- v-for="item in rejection_handling"
- :key="item.value" />
+ <el-form-item label="澶勭悊缁撴灉锛�" prop="dealResult">
+ <el-select v-model="form.dealResult" placeholder="璇烽�夋嫨" clearable>
+ <el-option :label="item.label" :value="item.value" v-for="item in rejection_handling" :key="item.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="澶勭悊浜猴細"
- prop="dealName">
- <el-select v-model="form.dealName"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%">
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form-item label="澶勭悊浜猴細" prop="dealName">
+ <el-select v-model="form.dealName" placeholder="璇烽�夋嫨" clearable style="width: 100%">
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="澶勭悊鏃ユ湡锛�"
- prop="dealTime">
- <el-date-picker v-model="form.dealTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%" />
+ <el-form-item label="澶勭悊鏃ユ湡锛�" prop="dealTime">
+ <el-date-picker
+ v-model="form.dealTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
+ <el-button type="primary" @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
@@ -171,172 +124,173 @@
</template>
<script setup>
- import { ref, reactive, toRefs } from "vue";
- import { modelList, productTreeList } from "@/api/basicData/product.js";
- import {
- getQualityUnqualifiedInfo,
- qualityUnqualifiedAdd,
- qualityUnqualifiedUpdate,
- } from "@/api/qualityManagement/nonconformingManagement.js";
- import { userListNoPage } from "@/api/system/user.js";
- import useUserStore from "@/store/modules/user";
- const { proxy } = getCurrentInstance();
- const userStore = useUserStore();
- const emit = defineEmits(["close"]);
+import {ref, reactive, toRefs} from "vue";
+import {modelList, productTreeList} from "@/api/basicData/product.js";
+import {
+ getQualityUnqualifiedInfo,
+ qualityUnqualifiedAdd,
+ qualityUnqualifiedUpdate
+} from "@/api/qualityManagement/nonconformingManagement.js";
+import {userListNoPage} from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+const { proxy } = getCurrentInstance()
+const userStore = useUserStore()
+const emit = defineEmits(['close'])
- const dialogFormVisible = ref(false);
- const operationType = ref("");
- const { rejection_handling } = proxy.useDict("rejection_handling");
- const data = reactive({
- form: {
- checkTime: "",
- process: "",
- checkName: "",
- productName: "",
- productId: "",
- model: "",
- unit: "",
- quantity: undefined,
- checkCompany: "",
- checkResult: "",
- inspectType: "",
- defectivePhenomena: "",
- dealResult: "",
- dealName: "",
- dealTime: "",
- productModelId: undefined,
- },
- rules: {
- checkTime: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- process: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- checkName: [{ required: true, message: "璇烽�夋嫨妫�楠屽憳", trigger: "change" }],
- productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- model: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- checkResult: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- dealName: [{ required: true, message: "璇烽�夋嫨澶勭悊浜�", trigger: "change" }],
- },
- });
- const { form, rules } = toRefs(data);
- const productOptions = ref([]);
- const modelOptions = ref([]);
- const userList = ref([]); // 妫�楠屽憳/澶勭悊浜轰笅鎷夊垪琛�
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const { rejection_handling } = proxy.useDict("rejection_handling")
+const data = reactive({
+ form: {
+ checkTime: "",
+ process: "",
+ checkName: "",
+ productName: "",
+ productId: "",
+ model: "",
+ unit: "",
+ quantity: undefined,
+ checkCompany: "",
+ checkResult: "",
+ inspectType: '',
+ defectivePhenomena: '',
+ dealResult: '',
+ dealName: '',
+ dealTime: '',
+ productModelId: undefined,
+ },
+ rules: {
+ checkTime: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" },],
+ process: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ checkName: [{ required: true, message: "璇烽�夋嫨妫�楠屽憳", trigger: "change" }],
+ productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ model: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ checkResult: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ dealName: [{ required: true, message: "璇烽�夋嫨澶勭悊浜�", trigger: "change" }],
+ },
+});
+const { form, rules } = toRefs(data);
+const productOptions = ref([]);
+const modelOptions = ref([]);
+const userList = ref([]); // 妫�楠屽憳/澶勭悊浜轰笅鎷夊垪琛�
- // 鎵撳紑寮规
- const openDialog = async (type, row) => {
- operationType.value = type;
- try {
- const userRes = await userListNoPage();
- userList.value = userRes.data || [];
- } catch (e) {
- console.error("鍔犺浇鐢ㄦ埛鍒楄〃澶辫触", e);
- userList.value = [];
- }
- dialogFormVisible.value = true;
- if (operationType.value === "add") {
- form.value = {
- checkName: userStore.nickName || "",
- dealName: "",
- dealTime: "",
- dealResult: "",
- defectivePhenomena: "",
- inspectType: "",
- checkTime: "",
- productId: "",
- model: "",
- unit: "",
- quantity: undefined,
- productName: "",
- productModelId: undefined,
- };
- } else {
- form.value = {};
- }
- getProductOptions();
- if (operationType.value === "edit") {
- getQualityUnqualifiedInfo(row.id).then(res => {
- const { inspectState, ...rest } = res.data || {};
- form.value = { ...rest };
- });
- }
- };
- const getProductOptions = () => {
- productTreeList().then(res => {
- productOptions.value = convertIdToValue(res);
- });
- };
- const getModels = value => {
- form.value.productName = findNodeById(productOptions.value, value);
- modelList({ id: value }).then(res => {
- modelOptions.value = res;
- });
- };
- const handleChangeModel = value => {
- const selectedModel = modelOptions.value.find(item => item.id === value);
- if (selectedModel) {
- form.value.model = selectedModel.model;
- }
- };
- const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
- };
- function convertIdToValue(data) {
- return data.map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
+// 鎵撳紑寮规
+const openDialog = async (type, row) => {
+ operationType.value = type;
+ try {
+ const userRes = await userListNoPage();
+ userList.value = userRes.data || [];
+ } catch (e) {
+ console.error("鍔犺浇鐢ㄦ埛鍒楄〃澶辫触", e);
+ userList.value = [];
}
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitForm = () => {
- proxy.$refs.formRef.validate(valid => {
- if (valid) {
- // 鐘舵�佸瓧娈典笉鍦ㄨ〃鍗曞~鍐欙紝涔熶笉浼犵粰鍚庣
- const { inspectState, ...payload } = form.value || {};
- if (operationType.value === "add") {
- qualityUnqualifiedAdd(payload).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- } else {
- qualityUnqualifiedUpdate(payload).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- }
- }
- });
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- emit("close");
- };
- defineExpose({
- openDialog,
+ dialogFormVisible.value = true;
+ if (operationType.value === 'add') {
+ form.value = {
+ checkName: userStore.nickName || '',
+ dealName: '',
+ dealTime: '',
+ dealResult: '',
+ defectivePhenomena: '',
+ inspectType: '',
+ checkTime: '',
+ productId: '',
+ model: '',
+ unit: '',
+ quantity: undefined,
+ productName: '',
+ productModelId: undefined,
+ };
+ } else {
+ form.value = {};
+ }
+ getProductOptions();
+ if (operationType.value === 'edit') {
+ getQualityUnqualifiedInfo(row.id).then(res => {
+ const { inspectState, ...rest } = (res.data || {})
+ form.value = { ...rest }
+ })
+ }
+}
+const getProductOptions = () => {
+ productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
});
+};
+const getModels = (value) => {
+ form.value.productName = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ })
+};
+const handleChangeModel = (value) => {
+ const selectedModel = modelOptions.value.find(item => item.id === value);
+ if (selectedModel) {
+ form.value.model = selectedModel.model;
+ }
+};
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+function convertIdToValue(data) {
+ return data.map((item) => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs.formRef.validate(valid => {
+ if (valid) {
+ // 鐘舵�佸瓧娈典笉鍦ㄨ〃鍗曞~鍐欙紝涔熶笉浼犵粰鍚庣
+ const { inspectState, ...payload } = (form.value || {})
+ if (operationType.value === "add") {
+ qualityUnqualifiedAdd(payload).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ } else {
+ qualityUnqualifiedUpdate(payload).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ }
+ }
+ })
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ emit('close')
+};
+defineExpose({
+ openDialog,
+});
</script>
<style scoped>
+
</style>
diff --git a/src/views/qualityManagement/processInspection/components/formDia.vue b/src/views/qualityManagement/processInspection/components/formDia.vue
index 370b5f6..a02976e 100644
--- a/src/views/qualityManagement/processInspection/components/formDia.vue
+++ b/src/views/qualityManagement/processInspection/components/formDia.vue
@@ -30,7 +30,6 @@
prop="productId">
<el-tree-select v-model="form.productId"
placeholder="璇烽�夋嫨"
- filterable
clearable
check-strictly
@change="getModels"
@@ -131,6 +130,34 @@
</el-row>
<el-row :gutter="30">
<el-col :span="12">
+ <el-form-item label="鏄惁鎶芥锛�"
+ prop="isSampling">
+ <el-radio-group v-model="form.isSampling"
+ class="sampling-radio-group"
+ :disabled="isViewMode"
+ @change="handleSamplingChange">
+ <el-radio-button :label="1">鏄�</el-radio-button>
+ <el-radio-button :label="0">鍚�</el-radio-button>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12"
+ v-if="form.isSampling === 1">
+ <el-form-item label="鎶芥鏁伴噺锛�"
+ prop="samplingQuantity">
+ <el-input-number :step="0.01"
+ :min="0"
+ style="width: 100%"
+ v-model="form.samplingQuantity"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :precision="2"
+ :disabled="isViewMode" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
<el-form-item label="妫�娴嬪崟浣嶏細"
prop="checkCompany">
<el-input v-model="form.checkCompany"
@@ -140,17 +167,8 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="妫�娴嬬粨鏋滐細"
- prop="checkResult">
- <el-select v-model="form.checkResult"
- :disabled="isViewMode">
- <el-option label="鍚堟牸"
- value="鍚堟牸" />
- <el-option label="涓嶅悎鏍�"
- value="涓嶅悎鏍�" />
- <el-option label="閮ㄥ垎鍚堟牸"
- value="閮ㄥ垎鍚堟牸" />
- </el-select>
+ <el-form-item label="鍚堟牸鐜囷細">
+ <el-tag :type="passRateTagType">{{ passRateDisplayText }}</el-tag>
</el-form-item>
</el-col>
</el-row>
@@ -202,8 +220,7 @@
@click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</template>
- <el-button v-else
- @click="closeDia">鍏抽棴</el-button>
+ <el-button v-else @click="closeDia">鍏抽棴</el-button>
</div>
</template>
</el-dialog>
@@ -253,7 +270,8 @@
qualifiedQuantity: "",
unqualifiedQuantity: "",
checkCompany: "",
- checkResult: "",
+ isSampling: 0,
+ samplingQuantity: "",
},
rules: {
checkTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -261,23 +279,51 @@
checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- testStandardId: [
- { required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change" },
- ],
+ testStandardId: [{ required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change" }],
unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
qualifiedQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- unqualifiedQuantity: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
+ unqualifiedQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- checkResult: [{ required: true, message: "璇疯緭鍏�", trigger: "change" }],
+ isSampling: [{ required: true, message: "璇烽�夋嫨鏄惁鎶芥", trigger: "change" }],
+ samplingQuantity: [{ required: true, message: "璇疯緭鍏ユ娊妫�鏁伴噺", trigger: "blur" }],
},
});
const userList = ref([]);
const { form, rules } = toRefs(data);
// 鏄惁涓烘煡鐪嬫ā寮�
- const isViewMode = computed(() => operationType.value === "view");
+ const isViewMode = computed(() => operationType.value === 'view');
+
+ const passRateValue = computed(() => {
+ const fromApi = form.value.passRate;
+ if (fromApi != null && fromApi !== '') {
+ const n = Number(fromApi);
+ if (!Number.isNaN(n)) return n;
+ }
+ const qualified = Number(form.value.qualifiedQuantity) || 0;
+ const unqualified = Number(form.value.unqualifiedQuantity) || 0;
+ const total = qualified + unqualified;
+ if (!total || total === 0) return null;
+ return (qualified / total) * 100;
+ });
+
+ const passRateDisplayText = computed(() => {
+ const params = passRateValue.value;
+ if (params == null || params === '') return '鈥�';
+ const n = Number(params);
+ if (Number.isNaN(n)) return '鈥�';
+ return `${n.toFixed(2)}%`;
+ });
+
+ const passRateTagType = computed(() => {
+ const params = passRateValue.value;
+ if (params == null || params === '') return 'info';
+ const n = Number(params);
+ if (Number.isNaN(n)) return 'info';
+ if (n >= 100) return 'success';
+ if (n >= 90) return 'warning';
+ return 'danger';
+ });
// 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯宸ュ簭銆佹暟閲忕疆鐏�
const processQuantityDisabled = computed(() => {
const v = form.value || {};
@@ -345,7 +391,8 @@
unit: "",
quantity: "",
checkCompany: "",
- checkResult: "",
+ isSampling: 0,
+ samplingQuantity: "",
};
testStandardOptions.value = [];
tableData.value = [];
@@ -354,8 +401,8 @@
if (operationType.value === "edit" || operationType.value === "view") {
// 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
const savedTestStandardId = row.testStandardId;
- // 鍏堣缃〃鍗曟暟鎹紝浣嗘殏鏃舵竻绌� testStandardId锛岀瓑閫夐」鍔犺浇瀹屾垚鍚庡啀璁剧疆
- form.value = { ...row, testStandardId: "" };
+ const { passRate, ...rowWithoutPassRate } = row;
+ form.value = { ...rowWithoutPassRate, testStandardId: "" };
currentProductId.value = row.productId || 0;
// 鍏抽敭锛氱紪杈戞椂鍔犺浇瑙勬牸鍨嬪彿涓嬫媺閫夐」锛屾墠鑳藉弽鏄� productModelId
if (currentProductId.value) {
@@ -452,26 +499,25 @@
modelOptions.value.find(item => item.id == value)?.unit || "";
};
- const handleQualifiedQuantityChange = value => {
+ const handleQualifiedQuantityChange = (value) => {
if (value === null || value === undefined) {
form.value.qualifiedQuantity = 0;
return;
}
const quantity = parseFloat(form.value.quantity) || 0;
const qualified = parseFloat(value) || 0;
- form.value.qualifiedQuantity = qualified > quantity ? quantity : qualified;
+ form.value.qualifiedQuantity = qualified > quantity?quantity:qualified;
form.value.unqualifiedQuantity = Math.max(0, quantity - qualified);
};
- const handleUnqualifiedQuantityChange = value => {
+ const handleUnqualifiedQuantityChange = (value) => {
if (value === null || value === undefined) {
form.value.unqualifiedQuantity = 0;
return;
}
const quantity = parseFloat(form.value.quantity) || 0;
const unqualified = parseFloat(value) || 0;
- form.value.unqualifiedQuantity =
- unqualified > quantity ? quantity : unqualified;
+ form.value.unqualifiedQuantity = unqualified > quantity?quantity:unqualified;
form.value.qualifiedQuantity = Math.max(0, quantity - unqualified);
};
@@ -579,7 +625,7 @@
tableData.value = res.data || [];
tableData.value = tableData.value.map(item => ({
...item,
- id: null,
+ id: null
}));
})
.catch(error => {
@@ -594,6 +640,15 @@
qualityInspectParamInfo(id).then(res => {
tableData.value = res.data;
});
+ };
+ // 鏄惁鎶芥鍒囨崲
+ const handleSamplingChange = (value) => {
+ if (value !== 1) {
+ form.value.samplingQuantity = "";
+ nextTick(() => {
+ proxy.$refs?.formRef?.clearValidate?.("samplingQuantity");
+ });
+ }
};
// 鍏抽棴寮规
const closeDia = () => {
@@ -610,4 +665,7 @@
</script>
<style scoped>
+.sampling-radio-group {
+ height: 32px;
+}
</style>
diff --git a/src/views/qualityManagement/processInspection/index.vue b/src/views/qualityManagement/processInspection/index.vue
index 58d1a3a..1f2b26e 100644
--- a/src/views/qualityManagement/processInspection/index.vue
+++ b/src/views/qualityManagement/processInspection/index.vue
@@ -3,436 +3,395 @@
<div class="search_form mb20">
<div>
<span class="search_title">宸ュ簭锛�</span>
- <el-input v-model="searchForm.process"
- style="width: 240px"
- placeholder="璇疯緭鍏ュ伐搴忔悳绱�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search" />
- <span style="margin-left: 10px"
- class="search_title">妫�娴嬫棩鏈燂細</span>
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
- <span style="margin-left: 10px"
- class="search_title">鐢熶骇宸ュ崟鍙凤細</span>
- <el-input v-model="searchForm.workOrderNo"
- 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.process"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ュ伐搴忔悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span style="margin-left: 10px" class="search_title">妫�娴嬫棩鏈燂細</span>
+ <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+ placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
</div>
<div>
- <el-button type="primary"
- @click="openForm('add')">鏂板</el-button>
+ <el-button type="primary" @click="openForm('add')">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"></PIMTable>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"
+ ></PIMTable>
</div>
- <InspectionFormDia ref="inspectionFormDia"
- @close="handleQuery"></InspectionFormDia>
- <FormDia ref="formDia"
- @close="handleQuery"></FormDia>
- <files-dia ref="filesDia"
- @close="handleQuery"></files-dia>
- <el-dialog v-model="dialogFormVisible"
- title="缂栬緫妫�楠屽憳"
- width="30%"
- @close="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
- <el-form-item label="妫�楠屽憳锛�"
- prop="checkName">
- <el-select v-model="form.checkName"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
+ <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
+ <FormDia ref="formDia" @close="handleQuery"></FormDia>
+ <files-dia ref="filesDia"></files-dia>
+ <el-dialog v-model="dialogFormVisible" title="缂栬緫妫�楠屽憳" width="30%"
+ @close="closeDia">
+ <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+ <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+ <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable>
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+ :value="item.nickName"/>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
- import { Search } from "@element-plus/icons-vue";
- import {
- onMounted,
- ref,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue";
- import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue";
- import { ElMessageBox } from "element-plus";
- import {
- downloadQualityInspect,
- qualityInspectDel,
- qualityInspectListPage,
- qualityInspectUpdate,
- submitQualityInspect,
- } from "@/api/qualityManagement/rawMaterialInspection.js";
- import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue";
- import dayjs from "dayjs";
- import { userListNoPage } from "@/api/system/user.js";
- import useUserStore from "@/store/modules/user";
+import { Search } from "@element-plus/icons-vue";
+import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
+import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue";
+import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue";
+import {ElMessageBox} from "element-plus";
+import {
+ downloadQualityInspect,
+ qualityInspectDel,
+ qualityInspectListPage, qualityInspectUpdate,
+ submitQualityInspect
+} from "@/api/qualityManagement/rawMaterialInspection.js";
+import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue";
+import dayjs from "dayjs";
+import {userListNoPage} from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
- const data = reactive({
- searchForm: {
- process: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- workOrderNo: "",
- entryDateStart: undefined,
- entryDateEnd: undefined,
+const data = reactive({
+ searchForm: {
+ process: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ rules: {
+ checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ },
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "妫�娴嬫棩鏈�",
+ prop: "checkTime",
+ width: 120
+ },
+ {
+ label: "鐢熶骇宸ュ崟鍙�",
+ prop: "workOrderNo",
+ width: 120
+ },
+ {
+ label: "宸ュ簭",
+ prop: "process",
+ width: 230
+ },
+ {
+ label: "妫�楠屽憳",
+ prop: "checkName",
+ },
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鎬绘暟閲�",
+ prop: "quantity",
+ width: 100
+ },
+ {
+ label: "鍚堟牸鏁伴噺",
+ prop: "qualifiedQuantity",
+ width: 100
+ },
+ {
+ label: "涓嶅悎鏍兼暟閲�",
+ prop: "unqualifiedQuantity",
+ width: 100
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "passRate",
+ width: 100,
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == null || params === '') return '鈥�';
+ const n = Number(params);
+ if (Number.isNaN(n)) return '鈥�';
+ return `${n.toFixed(2)}%`;
},
- rules: {
- checkName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ formatType: (params) => {
+ if (params == null || params === '') return 'info';
+ const n = Number(params);
+ if (Number.isNaN(n)) return 'info';
+ if (n === 100) return 'success';
+ if (n >= 75) return 'primary';
+ if (n >= 50) return 'warning';
+ if (n >= 25) return 'danger';
+ return 'danger';
},
- });
- const { searchForm } = toRefs(data);
- const tableColumn = ref([
- {
- label: "妫�娴嬫棩鏈�",
- prop: "checkTime",
- width: 120,
- },
- {
- label: "鐢熶骇宸ュ崟鍙�",
- prop: "workOrderNo",
- width: 120,
- },
- {
- label: "宸ュ簭",
- prop: "process",
- width: 230,
- },
- {
- label: "妫�楠屽憳",
- prop: "checkName",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鎬绘暟閲�",
- prop: "quantity",
- width: 100,
- },
- {
- label: "鍚堟牸鏁伴噺",
- prop: "qualifiedQuantity",
- width: 100,
- },
- {
- label: "涓嶅悎鏍兼暟閲�",
- prop: "unqualifiedQuantity",
- width: 100,
- },
- {
- label: "鍚堟牸鐜�",
- prop: "passRate",
- width: 100,
- dataType: "tag",
- formatType: params => {
- if (!params) return "";
- const rate = parseFloat(params);
- if (rate < 90) {
- return "danger";
- } else if (rate === 100) {
- return "success";
- } else {
- return "warning";
- }
+ },
+ {
+ label: "鎻愪氦鐘舵��",
+ prop: "inspectState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params) {
+ return "宸叉彁浜�";
+ } else {
+ return "鏈彁浜�";
+ }
+ },
+ formatType: (params) => {
+ if (params) {
+ return "success";
+ } else {
+ return "info";
+ }
+ },
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ }
},
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120,
- },
- {
- label: "妫�娴嬬粨鏋�",
- prop: "checkResult",
- dataType: "tag",
- formatType: params => {
- if (params == "涓嶅悎鏍�") {
- return "danger";
- } else if (params == "鍚堟牸") {
- return "success";
- } else {
- return "danger";
- }
+ {
+ name: "鏌ョ湅",
+ type: "text",
+ clickFun: (row) => {
+ openForm("view", row);
+ },
},
- },
- {
- label: "鎻愪氦鐘舵��",
- prop: "inspectState",
- formatData: params => {
- if (params) {
- return "宸叉彁浜�";
- } else {
- return "鏈彁浜�";
- }
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: (row) => {
+ openFilesFormDia(row);
+ },
},
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: row => {
- openForm("edit", row);
- },
- disabled: row => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- },
- },
- {
- name: "鏌ョ湅",
- type: "text",
- clickFun: row => {
- openForm("view", row);
- },
- },
- {
- name: "闄勪欢",
- type: "text",
- clickFun: row => {
- openFilesFormDia(row);
- },
- },
- {
- name: "鎻愪氦",
- type: "text",
- clickFun: row => {
- submit(row.id);
- },
- disabled: row => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- },
- },
- {
- name: "鍒嗛厤妫�楠屽憳",
- type: "text",
- clickFun: row => {
- if (!row.checkName) {
- open(row);
- } else {
- proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
- }
- },
- disabled: row => {
- return row.inspectState == 1 || row.checkName;
- },
- },
- {
- name: "涓嬭浇",
- type: "text",
- clickFun: row => {
- downLoadFile(row);
- },
- },
- ],
- },
- ]);
- const userList = ref([]);
- const currentRow = ref(null);
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- const dialogFormVisible = ref(false);
- const form = ref({
- checkName: "",
- });
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
- const formDia = ref();
- const filesDia = ref();
- const inspectionFormDia = ref();
- const { proxy } = getCurrentInstance();
- const userStore = useUserStore();
- const changeDaterange = value => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- }
- getList();
- };
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined;
- qualityInspectListPage({ ...params, inspectType: 1 })
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => {
- const quantity = parseFloat(item.quantity);
- const qualifiedQuantity = parseFloat(item.qualifiedQuantity);
- let passRate = null;
- if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) {
- passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%";
- }
- return {
- ...item,
- passRate: passRate,
- };
- });
- page.total = res.data.total;
- })
- .catch(err => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
+ {
+ name: "鎻愪氦",
+ type: "text",
+ clickFun: (row) => {
+ submit(row.id);
+ },
+ loading: (row) => submitLoadingId.value === row.id,
+ disabled: (row) => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ }
+ },
+ {
+ name: "鍒嗛厤妫�楠屽憳",
+ type: "text",
+ clickFun: (row) => {
+ if (!row.checkName) {
+ open(row)
+ } else {
+ proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+ }
+ },
+ disabled: (row) => {
+ return row.inspectState == 1 || row.checkName;
+ }
+ },
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: (row) => {
+ downLoadFile(row);
+ },
+ },
+ ],
+ },
+]);
+const userList = ref([]);
+const currentRow = ref(null)
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const submitLoadingId = ref(null);
+const dialogFormVisible = ref(false);
+const form = ref({
+ checkName: ""
+});
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0
+});
+const formDia = ref()
+const filesDia = ref()
+const inspectionFormDia = ref()
+const { proxy } = getCurrentInstance()
+const userStore = useUserStore()
+const changeDaterange = (value) => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
+ getList();
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined
+ qualityInspectListPage({...params, inspectType: 1}).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records
+ page.total = res.data.total;
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
- // 鎵撳紑寮规
- const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row);
- });
- };
- // 鎵撳紑鏂板妫�楠屽脊妗�
- const openInspectionForm = (type, row) => {
- nextTick(() => {
- inspectionFormDia.value?.openDialog(type, row);
- });
- };
- // 鎵撳紑闄勪欢寮规
- const openFilesFormDia = (type, row) => {
- nextTick(() => {
- filesDia.value?.openDialog(type, row);
- });
- };
- // 鎻愪环
- const submit = async id => {
- const res = await submitQualityInspect({ id: id });
- if (res.code === 200) {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- getList();
- }
- };
- const open = async row => {
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- currentRow.value = row;
- dialogFormVisible.value = true;
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- };
- const submitForm = () => {
- if (currentRow.value) {
- const data = {
- ...form.value,
- id: currentRow.value.id,
- };
- qualityInspectUpdate(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- };
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row)
+ })
+};
+// 鎵撳紑鏂板妫�楠屽脊妗�
+const openInspectionForm = (type, row) => {
+ nextTick(() => {
+ inspectionFormDia.value?.openDialog(type, row)
+ })
+};
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (type, row) => {
+ nextTick(() => {
+ filesDia.value?.openDialog(type, row)
+ })
+};
+// 鎻愪氦
+const submit = async (id) => {
+ submitLoadingId.value = id;
+ try {
+ const res = await submitQualityInspect({ id });
+ if (res.code === 200) {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ const row = tableData.value.find(item => item.id === id);
+ if (row) {
+ row.inspectState = 1;
+ }
+ }
+ } finally {
+ submitLoadingId.value = null;
+ }
+}
+const open = async (row) => {
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ currentRow.value = row
+ dialogFormVisible.value = true
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+const submitForm = () => {
+ if (currentRow.value) {
+ const data = {
+ ...form.value,
+ id: currentRow.value.id
+ }
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ })
+ }
+};
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map(item => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- qualityInspectDel(ids).then(res => {
+ qualityInspectDel(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -440,45 +399,41 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
- const downLoadFile = row => {
- downloadQualityInspect({ id: row.id }).then(blobData => {
- const blob = new Blob([blobData], {
- type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
- });
- const downloadUrl = window.URL.createObjectURL(blob);
+};
+const downLoadFile = (row) => {
+ downloadQualityInspect({ id: row.id }).then((blobData) => {
+ const blob = new Blob([blobData], {
+ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ })
+ const downloadUrl = window.URL.createObjectURL(blob)
- const link = document.createElement("a");
- link.href = downloadUrl;
- link.download = "杩囩▼妫�楠屾姤鍛�.docx";
- document.body.appendChild(link);
- link.click();
+ const link = document.createElement('a')
+ link.href = downloadUrl
+ link.download = '杩囩▼妫�楠屾姤鍛�.docx'
+ document.body.appendChild(link)
+ link.click()
- document.body.removeChild(link);
- window.URL.revokeObjectURL(downloadUrl);
- });
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ document.body.removeChild(link)
+ window.URL.revokeObjectURL(downloadUrl)
+ })
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download(
- "/quality/qualityInspect/export",
- { inspectType: 1 },
- "杩囩▼妫�楠�.xlsx"
- );
+ proxy.download("/quality/qualityInspect/export", {inspectType: 1}, "杩囩▼妫�楠�.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
- onMounted(() => {
- getList();
- });
+};
+onMounted(() => {
+ getList();
+});
</script>
<style scoped></style>
diff --git a/src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue b/src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue
index e4c9700..5bb666a 100644
--- a/src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue
@@ -13,7 +13,7 @@
:action="uploadUrl"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
- name="file"
+ name="files"
:show-file-list="false"
:headers="headers"
style="display: inline;margin-right: 10px"
@@ -50,10 +50,10 @@
import {ElMessageBox} from "element-plus";
import {getToken} from "@/utils/auth.js";
import {
- qualityInspectFileAdd,
- qualityInspectFileDel,
- qualityInspectFileListPage
-} from "@/api/qualityManagement/qualityInspectFile.js";
+ createAttachment,
+ deleteAttachment,
+ attachmentList
+} from "@/api/basicData/storageAttachment.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
@@ -99,7 +99,7 @@
const headers = ref({
Authorization: "Bearer " + getToken(),
});
-const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 涓婁紶鐨勬湇鍔″櫒鍦板潃
// 鎵撳紑寮规
const openDialog = (row) => {
@@ -113,9 +113,12 @@
getList();
};
const getList = () => {
- qualityInspectFileListPage({inspectId: currentId.value, ...page}).then(res => {
- tableData.value = res.data.records;
- page.total = res.data.total;
+ attachmentList({recordId: currentId.value, recordType: 'quality_inspect'}).then(res => {
+ tableData.value = (res.data || []).map(item => ({
+ ...item,
+ name: item.originalFilename || item.name
+ }));
+ page.total = res.data ? res.data.length : 0;
})
}
// 琛ㄦ牸閫夋嫨鏁版嵁
@@ -128,24 +131,42 @@
dialogFormVisible.value = false;
emit('close')
};
+let pendingFiles = [];
+let uploadTimer = null;
+
// 涓婁紶鎴愬姛澶勭悊
function handleUploadSuccess(res, file) {
// 濡傛灉涓婁紶鎴愬姛
- if (res.code == 200) {
- const fileRow = {}
- fileRow.name = res.data.originalName
- fileRow.url = res.data.tempPath
- uploadFile(fileRow)
+ if (res.code == 200 && res.data && res.data.length > 0) {
+ const newFiles = res.data.map(item => ({
+ ...item,
+ name: item.originalFilename || item.name
+ }));
+
+ pendingFiles = [...pendingFiles, ...newFiles];
+
+ // 闃叉姈澶勭悊锛岄伩鍏嶅鏂囦欢鍚屾椂涓婁紶瀵艰嚧鍒楄〃琚鐩�
+ if (uploadTimer) clearTimeout(uploadTimer);
+ uploadTimer = setTimeout(() => {
+ const mergedFiles = [...(tableData.value || []), ...pendingFiles];
+ const storageAttachmentDTO = {
+ recordType: 'quality_inspect',
+ recordId: currentId.value,
+ application: "file",
+ storageBlobDTOs: mergedFiles
+ };
+ createAttachment(storageAttachmentDTO).then(r => {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ getList()
+ }).catch(() => {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ }).finally(() => {
+ pendingFiles = []; // 閲嶇疆
+ });
+ }, 500);
} else {
proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
}
-}
-function uploadFile(file) {
- file.inspectId = currentId.value;
- qualityInspectFileAdd(file).then(res => {
- proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
- getList()
- })
}
// 涓婁紶澶辫触澶勭悊
function handleUploadError() {
@@ -163,7 +184,7 @@
const handleDelete = () => {
let ids = [];
if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map((item) => item.id);
+ ids = selectedRows.value.map((item) => item.storageAttachmentId);
} else {
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
@@ -173,7 +194,7 @@
cancelButtonText: "鍙栨秷",
type: "warning",
}).then(() => {
- qualityInspectFileDel(ids).then((res) => {
+ deleteAttachment(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
diff --git a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
index 595bf80..d3f9fc0 100644
--- a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -1,211 +1,180 @@
<template>
<div>
- <el-dialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板鍘熸潗鏂欐楠�' : operationType === 'view' ? '鏌ョ湅鍘熸潗鏂欐楠�' : '缂栬緫鍘熸潗鏂欐楠�'"
- width="70%"
- @close="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鍘熸潗鏂欐楠�' : operationType === 'view' ? '鏌ョ湅鍘熸潗鏂欐楠�' : '缂栬緫鍘熸潗鏂欐楠�'"
+ width="70%"
+ @close="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="supplier">
- <el-select v-model="form.supplier"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="isViewMode || supplierQuantityDisabled">
- <el-option v-for="item in supplierList"
- :key="item.id"
- :label="item.supplierName"
- :value="item.supplierName" />
+ <el-form-item label="渚涘簲鍟嗭細" prop="supplier">
+ <el-select
+ v-model="form.supplier"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ :disabled="isViewMode || supplierQuantityDisabled"
+ >
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.supplierName"
+ />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="浜у搧鍚嶇О锛�"
- prop="productId">
- <el-tree-select v-model="form.productId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- :disabled="isViewMode || operationType === 'edit'"
- style="width: 100%" />
+ <el-form-item label="浜у搧鍚嶇О锛�" prop="productId">
+ <el-tree-select
+ v-model="form.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels"
+ :data="productOptions"
+ :render-after-expand="false"
+ :disabled="isViewMode || operationType === 'edit'"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="瑙勬牸鍨嬪彿锛�"
- prop="productModelId">
- <el-select v-model="form.productModelId"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="isViewMode || operationType === 'edit'"
- filterable
- readonly
- @change="handleChangeModel">
- <el-option v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id" />
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-select v-model="form.productModelId" placeholder="璇烽�夋嫨" clearable :disabled="isViewMode || operationType === 'edit'"
+ filterable readonly @change="handleChangeModel">
+ <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鎸囨爣閫夋嫨锛�"
- prop="testStandardId">
- <el-select v-model="form.testStandardId"
- placeholder="璇烽�夋嫨鎸囨爣"
- clearable
- @change="handleTestStandardChange"
- style="width: 100%"
- :disabled="isViewMode">
- <el-option v-for="item in testStandardOptions"
- :key="item.id"
- :label="item.standardName || item.standardNo"
- :value="item.id" />
+ <el-form-item label="鎸囨爣閫夋嫨锛�" prop="testStandardId">
+ <el-select
+ v-model="form.testStandardId"
+ placeholder="璇烽�夋嫨鎸囨爣"
+ clearable
+ @change="handleTestStandardChange"
+ style="width: 100%"
+ :disabled="isViewMode"
+ >
+ <el-option
+ v-for="item in testStandardOptions"
+ :key="item.id"
+ :label="item.standardName || item.standardNo"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍗曚綅锛�"
- prop="unit">
- <el-input v-model="form.unit"
- disabled />
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input v-model="form.unit" disabled/>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏁伴噺锛�"
- prop="quantity">
- <el-input-number :step="0.01"
- :min="0"
- style="width: 100%"
- v-model="form.quantity"
- placeholder="璇疯緭鍏�"
- clearable
- :precision="2"
- :disabled="isViewMode || supplierQuantityDisabled" />
+ <el-form-item label="鏁伴噺锛�" prop="quantity">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="璇疯緭鍏�"
+ clearable :precision="2" :disabled="isViewMode || supplierQuantityDisabled"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鍚堟牸鏁伴噺锛�"
- prop="qualifiedQuantity">
- <el-input-number :step="0.01"
- :min="0"
- :max="form.quantity || 0"
- style="width: 100%"
- v-model="form.qualifiedQuantity"
- placeholder="璇疯緭鍏�"
- :precision="2"
- @change="onQualifiedChange"
- :disabled="isViewMode" />
+ <el-form-item label="鍚堟牸鏁伴噺锛�" prop="qualifiedQuantity">
+ <el-input-number :step="0.01" :min="0" :max="form.quantity || 0" style="width: 100%"
+ v-model="form.qualifiedQuantity" placeholder="璇疯緭鍏�" :precision="2"
+ @change="onQualifiedChange" :disabled="isViewMode"/>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="涓嶅悎鏍兼暟閲忥細"
- prop="unqualifiedQuantity">
- <el-input-number :step="0.01"
- :min="0"
- :max="form.quantity || 0"
- style="width: 100%"
- v-model="form.unqualifiedQuantity"
- placeholder="璇疯緭鍏�"
- :precision="2"
- @change="onUnqualifiedChange"
- :disabled="isViewMode" />
+ <el-form-item label="涓嶅悎鏍兼暟閲忥細" prop="unqualifiedQuantity">
+ <el-input-number :step="0.01" :min="0" :max="form.quantity || 0" style="width: 100%"
+ v-model="form.unqualifiedQuantity" placeholder="璇疯緭鍏�" :precision="2"
+ @change="onUnqualifiedChange" :disabled="isViewMode"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏄惁鎶芥锛�" prop="isSampling">
+ <el-radio-group v-model="form.isSampling" class="sampling-radio-group" :disabled="isViewMode" @change="handleSamplingChange">
+ <el-radio-button :label="1">鏄�</el-radio-button>
+ <el-radio-button :label="0">鍚�</el-radio-button>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12" v-if="form.isSampling === 1">
+ <el-form-item label="鎶芥鏁伴噺锛�" prop="samplingQuantity">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.samplingQuantity"
+ placeholder="璇疯緭鍏�" clearable :precision="2" :disabled="isViewMode"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="妫�娴嬪崟浣嶏細" prop="checkCompany">
+ <el-input v-model="form.checkCompany" placeholder="璇疯緭鍏�" clearable :disabled="isViewMode"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚堟牸鐜囷細">
+ <el-tag :type="passRateTagType">{{ passRateDisplayText }}</el-tag>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="妫�娴嬪崟浣嶏細"
- prop="checkCompany">
- <el-input v-model="form.checkCompany"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="isViewMode" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="妫�娴嬬粨鏋滐細"
- prop="checkResult">
- <el-select v-model="form.checkResult"
- :disabled="isViewMode">
- <el-option label="鍚堟牸"
- value="鍚堟牸" />
- <el-option label="涓嶅悎鏍�"
- value="涓嶅悎鏍�" />
- <el-option label="閮ㄥ垎鍚堟牸"
- value="閮ㄥ垎鍚堟牸" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="妫�楠屽憳锛�"
- prop="checkName">
- <el-select v-model="form.checkName"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%"
- :disabled="isViewMode">
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+ <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable style="width: 100%" :disabled="isViewMode">
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="妫�娴嬫棩鏈燂細"
- prop="checkTime">
- <el-date-picker v-model="form.checkTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- :disabled="isViewMode" />
+ <el-form-item label="妫�娴嬫棩鏈燂細" prop="checkTime">
+ <el-date-picker
+ v-model="form.checkTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ :disabled="isViewMode"
+ />
</el-form-item>
</el-col>
</el-row>
</el-form>
- <!-- <div style="margin-bottom: 10px;text-align: right">-->
- <!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
- <!-- </div>-->
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :tableLoading="tableLoading"
- height="400">
+<!-- <div style="margin-bottom: 10px;text-align: right">-->
+<!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
+<!-- </div>-->
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="400"
+ >
<template #slot="{ row }">
- <el-input v-model="row.testValue"
- clearable
- :disabled="isViewMode" />
+ <el-input v-model="row.testValue" clearable :disabled="isViewMode"/>
</template>
</PIMTable>
<template #footer>
<div class="dialog-footer">
<template v-if="!isViewMode">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
+ <el-button type="primary" @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</template>
- <el-button v-else
- @click="closeDia">鍏抽棴</el-button>
+ <el-button v-else @click="closeDia">鍏抽棴</el-button>
</div>
</template>
</el-dialog>
@@ -213,393 +182,405 @@
</template>
<script setup>
- import {
- ref,
- reactive,
- toRefs,
- computed,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
- import { modelList, productTreeList } from "@/api/basicData/product.js";
- import {
- qualityInspectAdd,
- qualityInspectUpdate,
- } from "@/api/qualityManagement/rawMaterialInspection.js";
- import {
- qualityInspectParamDel,
- qualityInspectParamInfo,
- } from "@/api/qualityManagement/qualityInspectParam.js";
- import {
- qualityInspectDetailByProductId,
- getQualityTestStandardParamByTestStandardId,
- } from "@/api/qualityManagement/metricMaintenance.js";
- import { userListNoPage } from "@/api/system/user.js";
+import {ref, reactive, toRefs, computed, getCurrentInstance, nextTick} from "vue";
+import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
+import {modelList, productTreeList} from "@/api/basicData/product.js";
+import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
+import {qualityInspectParamDel, qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js";
+import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
+import {userListNoPage} from "@/api/system/user.js";
- const { proxy } = getCurrentInstance();
- const emit = defineEmits(["close"]);
+const {proxy} = getCurrentInstance()
+const emit = defineEmits(['close'])
- const dialogFormVisible = ref(false);
- const operationType = ref("");
- const data = reactive({
- form: {
- checkTime: "",
- supplier: "",
- checkName: "",
- productName: "",
- productId: "",
- productModelId: "",
- model: "",
- testStandardId: "",
- unit: "",
- quantity: "",
- checkCompany: "",
- checkResult: "",
- },
- rules: {
- checkTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- supplier: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- productModelId: [
- { required: true, message: "璇烽�夋嫨浜у搧鍨嬪彿", trigger: "change" },
- ],
- testStandardId: [
- { required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change" },
- ],
- unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- qualifiedQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- unqualifiedQuantity: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- checkResult: [
- { required: true, message: "璇烽�夋嫨妫�娴嬬粨鏋�", trigger: "change" },
- ],
- },
- });
- const tableColumn = ref([
- {
- label: "鎸囨爣",
- prop: "parameterItem",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鏍囧噯鍊�",
- prop: "standardValue",
- },
- {
- label: "鍐呮帶鍊�",
- prop: "controlValue",
- },
- {
- label: "妫�楠屽��",
- prop: "testValue",
- dataType: "slot",
- slot: "slot",
- },
- ]);
- const tableData = ref([]);
- const tableLoading = ref(false);
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const data = reactive({
+ form: {
+ checkTime: "",
+ supplier: "",
+ checkName: "",
+ productName: "",
+ productId: "",
+ productModelId: "",
+ model: "",
+ testStandardId: "",
+ unit: "",
+ quantity: "",
+ checkCompany: "",
+ isSampling: 0,
+ samplingQuantity: "",
+ },
+ rules: {
+ checkTime: [{required: true, message: "璇疯緭鍏�", trigger: "blur"},],
+ supplier: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ checkName: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+ productId: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ productModelId: [{required: true, message: "璇烽�夋嫨浜у搧鍨嬪彿", trigger: "change"}],
+ testStandardId: [{required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change"}],
+ unit: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+ quantity: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ qualifiedQuantity: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ unqualifiedQuantity: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ checkCompany: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+ isSampling: [{required: true, message: "璇烽�夋嫨鏄惁鎶芥", trigger: "change"}],
+ samplingQuantity: [{required: true, message: "璇疯緭鍏ユ娊妫�鏁伴噺", trigger: "blur"}],
+ },
+});
+const tableColumn = ref([
+ {
+ label: "鎸囨爣",
+ prop: "parameterItem",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鏍囧噯鍊�",
+ prop: "standardValue",
+ },
+ {
+ label: "鍐呮帶鍊�",
+ prop: "controlValue",
+ },
+ {
+ label: "妫�楠屽��",
+ prop: "testValue",
+ dataType: 'slot',
+ slot: 'slot',
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
- const { form, rules } = toRefs(data);
- const supplierList = ref([]);
- const productOptions = ref([]);
- const currentProductId = ref(0);
- const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
- const modelOptions = ref([]);
- const userList = ref([]); // 妫�楠屽憳涓嬫媺鍒楄〃
+const {form, rules} = toRefs(data);
+const supplierList = ref([]);
+const productOptions = ref([]);
+const currentProductId = ref(0);
+const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
+const modelOptions = ref([]);
+const userList = ref([]); // 妫�楠屽憳涓嬫媺鍒楄〃
- // 鏄惁涓烘煡鐪嬫ā寮�
- const isViewMode = computed(() => operationType.value === "view");
+// 鏄惁涓烘煡鐪嬫ā寮�
+const isViewMode = computed(() => operationType.value === 'view');
- // 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯渚涘簲鍟嗐�佹暟閲忕疆鐏�
- const supplierQuantityDisabled = computed(() => {
- const v = form.value || {};
- return !!(v.productMainId != null || v.purchaseLedgerId != null);
+const passRateValue = computed(() => {
+ const fromApi = form.value.passRate;
+ if (fromApi != null && fromApi !== '') {
+ const n = Number(fromApi);
+ if (!Number.isNaN(n)) return n;
+ }
+ const qualified = Number(form.value.qualifiedQuantity) || 0;
+ const unqualified = Number(form.value.unqualifiedQuantity) || 0;
+ const total = qualified + unqualified;
+ if (!total || total === 0) return null;
+ return (qualified / total) * 100;
+});
+
+const passRateDisplayText = computed(() => {
+ const params = passRateValue.value;
+ if (params == null || params === '') return '鈥�';
+ const n = Number(params);
+ if (Number.isNaN(n)) return '鈥�';
+ return `${n.toFixed(2)}%`;
+});
+
+const passRateTagType = computed(() => {
+ const params = passRateValue.value;
+ if (params == null || params === '') return 'info';
+ const n = Number(params);
+ if (Number.isNaN(n)) return 'info';
+ if (n >= 100) return 'success';
+ if (n >= 90) return 'warning';
+ return 'danger';
+});
+
+// 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯渚涘簲鍟嗐�佹暟閲忕疆鐏�
+const supplierQuantityDisabled = computed(() => {
+ const v = form.value || {};
+ return !!(v.productMainId != null || v.purchaseLedgerId != null);
+});
+
+// 鎵撳紑寮规
+const openDialog = async (type, row) => {
+ operationType.value = type;
+ getOptions().then((res) => {
+ supplierList.value = res.data;
});
- // 鎵撳紑寮规
- const openDialog = async (type, row) => {
- operationType.value = type;
- getOptions().then(res => {
- supplierList.value = res.data;
- });
-
- try {
- const userRes = await userListNoPage();
- userList.value = userRes.data || [];
- } catch (e) {
- console.error("鍔犺浇妫�楠屽憳鍒楄〃澶辫触", e);
- userList.value = [];
- }
- // 鍏堥噸缃〃鍗曟暟鎹紙淇濇寔瀛楁瀹屾暣锛岄伩鍏嶅脊绐楅娆℃覆鏌撴椂瑙﹀彂蹇呭~绾㈡鈥滈棯涓�涓嬧�濓級
- form.value = {
- checkTime: "",
- supplier: "",
- checkName: "",
- productName: "",
- productId: "",
- productModelId: "",
- model: "",
- testStandardId: "",
- unit: "",
- quantity: "",
- checkCompany: "",
- checkResult: "",
- };
- testStandardOptions.value = [];
- tableData.value = [];
- // 鍏堢‘淇濅骇鍝佹爲宸插姞杞斤紝鍚﹀垯缂栬緫鏃朵骇鍝�/瑙勬牸鍨嬪彿鏃犳硶鍙嶆樉
- await getProductOptions();
- if (operationType.value === "edit" || operationType.value === "view") {
- // 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
- const savedTestStandardId = row.testStandardId;
- form.value = { ...row };
- currentProductId.value = row.productId || 0;
- // 鍏抽敭锛氱紪杈戞椂鍔犺浇瑙勬牸鍨嬪彿涓嬫媺閫夐」锛屾墠鑳藉弽鏄� productModelId
- if (currentProductId.value) {
- try {
- const res = await modelList({ id: currentProductId.value });
- modelOptions.value = res || [];
- // 鍚屾鍥炲~ model / unit锛堟湁浜涙帴鍙h繑鍥炵殑 row 閲屽彲鑳芥病甯﹀叏锛�
- if (form.value.productModelId) {
- handleChangeModel(form.value.productModelId);
- }
- } catch (e) {
- console.error("鍔犺浇瑙勬牸鍨嬪彿澶辫触", e);
- modelOptions.value = [];
+ try {
+ const userRes = await userListNoPage();
+ userList.value = userRes.data || [];
+ } catch (e) {
+ console.error("鍔犺浇妫�楠屽憳鍒楄〃澶辫触", e);
+ userList.value = [];
+ }
+ // 鍏堥噸缃〃鍗曟暟鎹紙淇濇寔瀛楁瀹屾暣锛岄伩鍏嶅脊绐楅娆℃覆鏌撴椂瑙﹀彂蹇呭~绾㈡鈥滈棯涓�涓嬧�濓級
+ form.value = {
+ checkTime: "",
+ supplier: "",
+ checkName: "",
+ productName: "",
+ productId: "",
+ productModelId: "",
+ model: "",
+ testStandardId: "",
+ unit: "",
+ quantity: "",
+ checkCompany: "",
+ isSampling: 0,
+ samplingQuantity: "",
+ }
+ testStandardOptions.value = [];
+ tableData.value = [];
+ // 鍏堢‘淇濅骇鍝佹爲宸插姞杞斤紝鍚﹀垯缂栬緫鏃朵骇鍝�/瑙勬牸鍨嬪彿鏃犳硶鍙嶆樉
+ await getProductOptions();
+ if (operationType.value === 'edit' || operationType.value === 'view') {
+ // 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
+ const savedTestStandardId = row.testStandardId;
+ const { passRate, ...rowWithoutPassRate } = row;
+ form.value = { ...rowWithoutPassRate, testStandardId: "" };
+ currentProductId.value = row.productId || 0
+ // 鍏抽敭锛氱紪杈戞椂鍔犺浇瑙勬牸鍨嬪彿涓嬫媺閫夐」锛屾墠鑳藉弽鏄� productModelId
+ if (currentProductId.value) {
+ try {
+ const res = await modelList({ id: currentProductId.value });
+ modelOptions.value = res || [];
+ // 鍚屾鍥炲~ model / unit锛堟湁浜涙帴鍙h繑鍥炵殑 row 閲屽彲鑳芥病甯﹀叏锛�
+ if (form.value.productModelId) {
+ handleChangeModel(form.value.productModelId);
}
+ } catch (e) {
+ console.error("鍔犺浇瑙勬牸鍨嬪彿澶辫触", e);
+ modelOptions.value = [];
}
- // 缂栬緫妯″紡涓嬶紝鍏堝姞杞芥寚鏍囬�夐」锛岀劧鍚庡姞杞藉弬鏁板垪琛�
- if (currentProductId.value) {
- // 鍏堝姞杞芥寚鏍囬�夐」
- let params = {
- productId: currentProductId.value,
- inspectType: 0,
- };
- qualityInspectDetailByProductId(params).then(res => {
- testStandardOptions.value = res.data || [];
- // 浣跨敤 nextTick 鍜� setTimeout 纭繚閫夐」宸茬粡娓叉煋鍒� DOM
- nextTick(() => {
- setTimeout(() => {
- // 濡傛灉缂栬緫鏁版嵁涓湁 testStandardId锛屽垯璁剧疆骞跺姞杞藉搴旂殑鍙傛暟
- if (savedTestStandardId) {
- // 纭繚绫诲瀷鍖归厤锛坕tem.id 鍙兘鏄暟瀛楁垨瀛楃涓诧級
- const matchedOption = testStandardOptions.value.find(
- item =>
- item.id == savedTestStandardId ||
- String(item.id) === String(savedTestStandardId)
- );
- if (matchedOption) {
- // 纭繚浣跨敤鍖归厤椤圭殑 id锛堜繚鎸佺被鍨嬩竴鑷达級
- form.value.testStandardId = matchedOption.id;
- // 缂栬緫淇濈暀鍘熸楠屽�硷紝鐩存帴鎷夊彇鍘熷弬鏁版暟鎹�
- getQualityInspectParamList(row.id);
- } else {
- // 濡傛灉鎵句笉鍒板尮閰嶉」锛屽皾璇曠洿鎺ヤ娇鐢ㄥ師鍊�
- console.warn(
- "鏈壘鍒板尮閰嶇殑鎸囨爣閫夐」锛宼estStandardId:",
- savedTestStandardId,
- "鍙敤閫夐」:",
- testStandardOptions.value
- );
- form.value.testStandardId = savedTestStandardId;
- getQualityInspectParamList(row.id);
- }
+ }
+ // 缂栬緫妯″紡涓嬶紝鍏堝姞杞芥寚鏍囬�夐」锛岀劧鍚庡姞杞藉弬鏁板垪琛�
+ if (currentProductId.value) {
+ // 鍏堝姞杞芥寚鏍囬�夐」
+ let params = {
+ productId: currentProductId.value,
+ inspectType: 0
+ }
+ qualityInspectDetailByProductId(params).then(res => {
+ testStandardOptions.value = res.data || [];
+ // 浣跨敤 nextTick 鍜� setTimeout 纭繚閫夐」宸茬粡娓叉煋鍒� DOM
+ nextTick(() => {
+ setTimeout(() => {
+ // 濡傛灉缂栬緫鏁版嵁涓湁 testStandardId锛屽垯璁剧疆骞跺姞杞藉搴旂殑鍙傛暟
+ if (savedTestStandardId) {
+ // 纭繚绫诲瀷鍖归厤锛坕tem.id 鍙兘鏄暟瀛楁垨瀛楃涓诧級
+ const matchedOption = testStandardOptions.value.find(item =>
+ item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId)
+ );
+ if (matchedOption) {
+ // 纭繚浣跨敤鍖归厤椤圭殑 id锛堜繚鎸佺被鍨嬩竴鑷达級
+ form.value.testStandardId = matchedOption.id;
+ // 缂栬緫淇濈暀鍘熸楠屽�硷紝鐩存帴鎷夊彇鍘熷弬鏁版暟鎹�
+ getQualityInspectParamList(row.id);
} else {
- // 鍚﹀垯浣跨敤鏃х殑閫昏緫
+ // 濡傛灉鎵句笉鍒板尮閰嶉」锛屽皾璇曠洿鎺ヤ娇鐢ㄥ師鍊�
+ console.warn('鏈壘鍒板尮閰嶇殑鎸囨爣閫夐」锛宼estStandardId:', savedTestStandardId, '鍙敤閫夐」:', testStandardOptions.value);
+ form.value.testStandardId = savedTestStandardId;
getQualityInspectParamList(row.id);
}
- }, 100);
- });
+ } else {
+ // 鍚﹀垯浣跨敤鏃х殑閫昏緫
+ getQualityInspectParamList(row.id);
+ }
+ }, 100);
});
+ });
+ } else {
+ getQualityInspectParamList(row.id);
+ }
+ }
+ // 鏈�鍚庡啀鎵撳紑寮圭獥锛屽苟娓呯悊鏍¢獙鎬侊紝閬垮厤蹇呭~鎻愮ず闂儊
+ dialogFormVisible.value = true;
+ nextTick(() => {
+ proxy.$refs?.formRef?.clearValidate?.();
+ });
+}
+const getProductOptions = () => {
+ return productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ return productOptions.value;
+ });
+};
+const getModels = (value) => {
+ form.value.productModelId = undefined;
+ form.value.unit = undefined;
+ modelOptions.value = [];
+ currentProductId.value = value
+ form.value.productName = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ })
+ if (currentProductId.value) {
+ getList();
+ }
+};
+
+const handleChangeModel = (value) => {
+ form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
+ form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
+}
+
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+
+function convertIdToValue(data) {
+ return data.map((item) => {
+ const {id, children, ...rest} = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+}
+
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs.formRef.validate(valid => {
+ if (valid) {
+ form.value.inspectType = 0
+ if (operationType.value === "add") {
+ tableData.value.forEach((item) => {
+ delete item.id
+ })
+ }
+ const data = {...form.value, qualityInspectParams: tableData.value}
+ if (operationType.value === "add") {
+ qualityInspectAdd(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
} else {
- getQualityInspectParamList(row.id);
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
}
}
- // 鏈�鍚庡啀鎵撳紑寮圭獥锛屽苟娓呯悊鏍¢獙鎬侊紝閬垮厤蹇呭~鎻愮ず闂儊
- dialogFormVisible.value = true;
+ })
+}
+
+const getList = () => {
+ if (!currentProductId.value) {
+ testStandardOptions.value = [];
+ tableData.value = [];
+ return;
+ }
+ let params = {
+ productId: currentProductId.value,
+ inspectType: 0
+ }
+ qualityInspectDetailByProductId(params).then(res => {
+ // 淇濆瓨涓嬫媺妗嗛�夐」鏁版嵁
+ testStandardOptions.value = res.data || [];
+ // 娓呯┖琛ㄦ牸鏁版嵁锛岀瓑寰呯敤鎴烽�夋嫨鎸囨爣
+ tableData.value = [];
+ // 娓呯┖鎸囨爣閫夋嫨
+ form.value.testStandardId = '';
+ })
+}
+
+// 鎸囨爣閫夋嫨鍙樺寲澶勭悊
+const handleTestStandardChange = (testStandardId) => {
+ if (!testStandardId) {
+ tableData.value = [];
+ return;
+ }
+ tableLoading.value = true;
+ getQualityTestStandardParamByTestStandardId(testStandardId).then(res => {
+ tableData.value = res.data || [];
+ tableData.value = tableData.value.map(item => ({
+ ...item,
+ id: null
+ }));
+ }).catch(error => {
+ console.error('鑾峰彇鏍囧噯鍙傛暟澶辫触:', error);
+ tableData.value = [];
+ }).finally(() => {
+ tableLoading.value = false;
+ })
+}
+
+const getQualityInspectParamList = (id) => {
+ qualityInspectParamInfo(id).then(res => {
+ tableData.value = res.data;
+ })
+}
+// 鑷姩璁$畻鍚堟牸鏁伴噺鍙樺寲鏃剁殑涓嶅悎鏍兼暟閲�
+const onQualifiedChange = (value) => {
+ if (form.value.quantity !== undefined && form.value.quantity !== null) {
+ const maxUnqualified = form.value.quantity - value;
+ if (maxUnqualified >= 0) {
+ form.value.unqualifiedQuantity = maxUnqualified;
+ } else {
+ form.value.qualifiedQuantity = form.value.quantity;
+ form.value.unqualifiedQuantity = 0;
+ }
+ }
+};
+
+// 鑷姩璁$畻涓嶅悎鏍兼暟閲忓彉鍖栨椂鐨勫悎鏍兼暟閲�
+const onUnqualifiedChange = (value) => {
+ if (form.value.quantity !== undefined && form.value.quantity !== null) {
+ const maxQualified = form.value.quantity - value;
+ if (maxQualified >= 0) {
+ form.value.qualifiedQuantity = maxQualified;
+ } else {
+ form.value.unqualifiedQuantity = form.value.quantity;
+ form.value.qualifiedQuantity = 0;
+ }
+ }
+};
+
+// 鏄惁鎶芥鍒囨崲
+const handleSamplingChange = (value) => {
+ if (value !== 1) {
+ form.value.samplingQuantity = "";
nextTick(() => {
- proxy.$refs?.formRef?.clearValidate?.();
- });
- };
- const getProductOptions = () => {
- return productTreeList().then(res => {
- productOptions.value = convertIdToValue(res);
- return productOptions.value;
- });
- };
- const getModels = value => {
- form.value.productModelId = undefined;
- form.value.unit = undefined;
- modelOptions.value = [];
- currentProductId.value = value;
- form.value.productName = findNodeById(productOptions.value, value);
- modelList({ id: value }).then(res => {
- modelOptions.value = res;
- });
- if (currentProductId.value) {
- getList();
- }
- };
-
- const handleChangeModel = value => {
- form.value.model =
- modelOptions.value.find(item => item.id == value)?.model || "";
- form.value.unit =
- modelOptions.value.find(item => item.id == value)?.unit || "";
- };
-
- const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
- };
-
- function convertIdToValue(data) {
- return data.map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
+ proxy.$refs?.formRef?.clearValidate?.("samplingQuantity");
});
}
+};
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitForm = () => {
- proxy.$refs.formRef.validate(valid => {
- if (valid) {
- form.value.inspectType = 0;
- if (operationType.value === "add") {
- tableData.value.forEach(item => {
- delete item.id;
- });
- }
- const data = { ...form.value, qualityInspectParams: tableData.value };
- if (operationType.value === "add") {
- qualityInspectAdd(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- } else {
- qualityInspectUpdate(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- });
- }
- }
- });
- };
-
- const getList = () => {
- if (!currentProductId.value) {
- testStandardOptions.value = [];
- tableData.value = [];
- return;
- }
- let params = {
- productId: currentProductId.value,
- inspectType: 0,
- };
- qualityInspectDetailByProductId(params).then(res => {
- // 淇濆瓨涓嬫媺妗嗛�夐」鏁版嵁
- testStandardOptions.value = res.data || [];
- // 娓呯┖琛ㄦ牸鏁版嵁锛岀瓑寰呯敤鎴烽�夋嫨鎸囨爣
- tableData.value = [];
- // 娓呯┖鎸囨爣閫夋嫨
- form.value.testStandardId = "";
- });
- };
-
- // 鎸囨爣閫夋嫨鍙樺寲澶勭悊
- const handleTestStandardChange = testStandardId => {
- if (!testStandardId) {
- tableData.value = [];
- return;
- }
- tableLoading.value = true;
- getQualityTestStandardParamByTestStandardId(testStandardId)
- .then(res => {
- tableData.value = res.data || [];
- tableData.value = tableData.value.map(item => ({
- ...item,
- id: null,
- }));
- })
- .catch(error => {
- console.error("鑾峰彇鏍囧噯鍙傛暟澶辫触:", error);
- tableData.value = [];
- })
- .finally(() => {
- tableLoading.value = false;
- });
- };
-
- const getQualityInspectParamList = id => {
- qualityInspectParamInfo(id).then(res => {
- tableData.value = res.data;
- });
- };
- // 鑷姩璁$畻鍚堟牸鏁伴噺鍙樺寲鏃剁殑涓嶅悎鏍兼暟閲�
- const onQualifiedChange = value => {
- if (form.value.quantity !== undefined && form.value.quantity !== null) {
- const maxUnqualified = form.value.quantity - value;
- if (maxUnqualified >= 0) {
- form.value.unqualifiedQuantity = maxUnqualified;
- } else {
- form.value.qualifiedQuantity = form.value.quantity;
- form.value.unqualifiedQuantity = 0;
- }
- }
- };
-
- // 鑷姩璁$畻涓嶅悎鏍兼暟閲忓彉鍖栨椂鐨勫悎鏍兼暟閲�
- const onUnqualifiedChange = value => {
- if (form.value.quantity !== undefined && form.value.quantity !== null) {
- const maxQualified = form.value.quantity - value;
- if (maxQualified >= 0) {
- form.value.qualifiedQuantity = maxQualified;
- } else {
- form.value.unqualifiedQuantity = form.value.quantity;
- form.value.qualifiedQuantity = 0;
- }
- }
- };
-
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- tableData.value = [];
- testStandardOptions.value = [];
- form.value.testStandardId = "";
- dialogFormVisible.value = false;
- emit("close");
- };
- defineExpose({
- openDialog,
- });
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ tableData.value = [];
+ testStandardOptions.value = [];
+ form.value.testStandardId = '';
+ dialogFormVisible.value = false;
+ emit('close')
+};
+defineExpose({
+ openDialog,
+});
</script>
<style scoped>
+.sampling-radio-group {
+ height: 32px;
+}
</style>
diff --git a/src/views/qualityManagement/rawMaterialInspection/index.vue b/src/views/qualityManagement/rawMaterialInspection/index.vue
index 6d2acd5..346ae9b 100644
--- a/src/views/qualityManagement/rawMaterialInspection/index.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -3,404 +3,353 @@
<div class="search_form mb20">
<div>
<span class="search_title">渚涘簲鍟嗭細</span>
- <el-input v-model="searchForm.supplier"
- style="width: 240px"
- placeholder="璇疯緭鍏ヤ緵搴斿晢鎼滅储"
- @change="handleQuery"
- clearable
- :prefix-icon="Search" />
- <span style="margin-left: 10px"
- class="search_title">妫�娴嬫棩鏈燂細</span>
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
- <span style="margin-left: 10px"
- class="search_title">閲囪喘璁㈠崟鍙凤細</span>
- <el-input v-model="searchForm.purchaseContractNo"
- 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.supplier"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ヤ緵搴斿晢鎼滅储"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span style="margin-left: 10px" class="search_title">妫�娴嬫棩鏈燂細</span>
+ <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+ placeholder="璇烽�夋嫨" clearable @change="changeDaterange"/>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储
+ </el-button
+ >
</div>
<div>
- <el-button type="primary"
- @click="openForm('add')">鏂板</el-button>
+ <el-button type="primary" @click="openForm('add')">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"></PIMTable>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"
+ ></PIMTable>
</div>
- <InspectionFormDia ref="inspectionFormDia"
- @close="handleQuery"></InspectionFormDia>
- <FormDia ref="formDia"
- @close="handleQuery"></FormDia>
- <files-dia ref="filesDia"
- @close="handleQuery"></files-dia>
- <el-dialog v-model="dialogFormVisible"
- title="缂栬緫妫�楠屽憳"
- width="30%"
+ <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
+ <FormDia ref="formDia" @close="handleQuery"></FormDia>
+ <files-dia ref="filesDia"></files-dia>
+ <el-dialog v-model="dialogFormVisible" title="缂栬緫妫�楠屽憳" width="30%"
@close="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
- <el-form-item label="妫�楠屽憳锛�"
- prop="checkName">
- <el-select v-model="form.checkName"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+ <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+ <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable>
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+ :value="item.nickName"/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
+ <el-button type="primary" @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
</el-dialog>
+
</div>
</template>
<script setup>
- import { Search } from "@element-plus/icons-vue";
- import {
- onMounted,
- ref,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue";
- import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue";
- import { ElMessageBox } from "element-plus";
- import {
- downloadQualityInspect,
- qualityInspectDel,
- qualityInspectListPage,
- qualityInspectUpdate,
- submitQualityInspect,
- } from "@/api/qualityManagement/rawMaterialInspection.js";
- import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue";
- import dayjs from "dayjs";
- import { userListNoPage } from "@/api/system/user.js";
- import useUserStore from "@/store/modules/user";
+import {Search} from "@element-plus/icons-vue";
+import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
+import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue";
+import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue";
+import {ElMessageBox} from "element-plus";
+import {
+ downloadQualityInspect,
+ qualityInspectDel,
+ qualityInspectListPage, qualityInspectUpdate,
+ submitQualityInspect
+} from "@/api/qualityManagement/rawMaterialInspection.js";
+import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue";
+import dayjs from "dayjs";
+import {userListNoPage} from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
- const data = reactive({
- searchForm: {
- supplier: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- purchaseContractNo: "",
- entryDateStart: undefined,
- entryDateEnd: undefined,
+const data = reactive({
+ searchForm: {
+ supplier: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ rules: {
+ checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ },
+});
+const {searchForm, rules} = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "妫�娴嬫棩鏈�",
+ prop: "checkTime",
+ width: 120
+ },
+ {
+ label: "閲囪喘璁㈠崟鍙�",
+ prop: "purchaseContractNo",
+ width: 120
+ },
+ {
+ label: "渚涘簲鍟�",
+ prop: "supplier",
+ width: 230
+ },
+ {
+ label: "妫�楠屽憳",
+ prop: "checkName",
+ },
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鎬绘暟閲�",
+ prop: "quantity",
+ width: 100
+ },
+ {
+ label: "鍚堟牸鏁伴噺",
+ prop: "qualifiedQuantity",
+ width: 100
+ },
+ {
+ label: "涓嶅悎鏍兼暟閲�",
+ prop: "unqualifiedQuantity",
+ width: 100
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "passRate",
+ width: 100,
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == null || params === '') return '鈥�';
+ const n = Number(params);
+ if (Number.isNaN(n)) return '鈥�';
+ return `${n.toFixed(2)}%`;
},
- rules: {
- checkName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ formatType: (params) => {
+ if (params == null || params === '') return 'info';
+ const n = Number(params);
+ if (Number.isNaN(n)) return 'info';
+ if (n === 100) return 'success';
+ if (n >= 75) return 'primary';
+ if (n >= 50) return 'warning';
+ if (n >= 25) return 'danger';
+ return 'danger';
},
- });
- const { searchForm, rules } = toRefs(data);
- const tableColumn = ref([
- {
- label: "妫�娴嬫棩鏈�",
- prop: "checkTime",
- width: 120,
+ },
+ {
+ label: "鎻愪氦鐘舵��",
+ prop: "inspectState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params) {
+ return "宸叉彁浜�";
+ } else {
+ return "鏈彁浜�";
+ }
},
- {
- label: "閲囪喘璁㈠崟鍙�",
- prop: "purchaseContractNo",
- width: 120,
+ formatType: (params) => {
+ if (params) {
+ return "success";
+ } else {
+ return "info";
+ }
},
- {
- label: "渚涘簲鍟�",
- prop: "supplier",
- width: 230,
- },
- {
- label: "妫�楠屽憳",
- prop: "checkName",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鎬绘暟閲�",
- prop: "quantity",
- width: 100,
- },
- {
- label: "鍚堟牸鏁伴噺",
- prop: "qualifiedQuantity",
- width: 100,
- },
- {
- label: "涓嶅悎鏍兼暟閲�",
- prop: "unqualifiedQuantity",
- width: 100,
- },
- {
- label: "鍚堟牸鐜�",
- prop: "passRate",
- width: 100,
- dataType: "tag",
- formatType: params => {
- if (!params) return "";
- const rate = parseFloat(params);
- if (rate < 90) {
- return "danger";
- } else if (rate === 100) {
- return "success";
- } else {
- return "warning";
- }
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ }
},
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120,
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120,
- },
- {
- label: "妫�娴嬬粨鏋�",
- prop: "checkResult",
- dataType: "tag",
- formatType: params => {
- if (params === "涓嶅悎鏍�") {
- return "danger";
- } else if (params === "鍚堟牸") {
- return "success";
- } else {
- return "danger";
- }
+ {
+ name: "鏌ョ湅",
+ type: "text",
+ clickFun: (row) => {
+ openForm("view", row);
+ },
},
- },
- {
- label: "鎻愪氦鐘舵��",
- prop: "inspectState",
- formatData: params => {
- if (params) {
- return "宸叉彁浜�";
- } else {
- return "鏈彁浜�";
- }
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: (row) => {
+ openFilesFormDia(row);
+ },
},
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: row => {
- openForm("edit", row);
- },
- disabled: row => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- },
+ {
+ name: "鎻愪氦",
+ type: "text",
+ clickFun: (row) => {
+ submit(row.id);
},
- {
- name: "鏌ョ湅",
- type: "text",
- clickFun: row => {
- openForm("view", row);
- },
- },
- {
- name: "闄勪欢",
- type: "text",
- clickFun: row => {
- openFilesFormDia(row);
- },
- },
- {
- name: "鎻愪氦",
- type: "text",
- clickFun: row => {
- submit(row.id);
- },
- disabled: row => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- },
- },
- {
- name: "鍒嗛厤妫�楠屽憳",
- type: "text",
- clickFun: row => {
- if (!row.checkName) {
- open(row);
- } else {
- proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
- }
- },
- disabled: row => {
- return row.inspectState == 1 || row.checkName;
- },
- },
- {
- name: "涓嬭浇",
- type: "text",
- clickFun: row => {
- downLoadFile(row);
- },
- },
- ],
- },
- ]);
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- const userList = ref([]);
- const dialogFormVisible = ref(false);
- const form = ref({
- checkName: "",
- });
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
- const currentRow = ref(null);
- const formDia = ref();
- const filesDia = ref();
- const inspectionFormDia = ref();
- const { proxy } = getCurrentInstance();
- const userStore = useUserStore();
- const changeDaterange = value => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- }
- getList();
- };
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined;
- qualityInspectListPage({ ...params, inspectType: 0 })
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => {
- const quantity = parseFloat(item.quantity);
- const qualifiedQuantity = parseFloat(item.qualifiedQuantity);
- let passRate = null;
- if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) {
- passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%";
+ loading: (row) => submitLoadingId.value === row.id,
+ disabled: (row) => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ }
+ },
+ {
+ name: "鍒嗛厤妫�楠屽憳",
+ type: "text",
+ clickFun: (row) => {
+ if (!row.checkName) {
+ open(row)
+ } else {
+ proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
}
- return {
- ...item,
- passRate: passRate,
- };
- });
- page.total = res.data.total;
- })
- .catch(err => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
+ },
+ disabled: (row) => {
+ return row.inspectState == 1 || row.checkName;
+ }
+ },
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: (row) => {
+ downLoadFile(row);
+ },
+ loading: (row) => downloadLoadingId.value === row.id,
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const submitLoadingId = ref(null);
+const downloadLoadingId = ref(null);
+const userList = ref([]);
+const dialogFormVisible = ref(false);
+const form = ref({
+ checkName: ""
+});
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0
+});
+const currentRow = ref(null)
+const formDia = ref()
+const filesDia = ref()
+const inspectionFormDia = ref()
+const {proxy} = getCurrentInstance()
+const userStore = useUserStore()
+const changeDaterange = (value) => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
+ getList();
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const params = {...searchForm.value, ...page};
+ params.entryDate = undefined
+ qualityInspectListPage({...params, inspectType: 0}).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records
+ page.total = res.data.total;
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
- // 鎵撳紑寮规
- const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row);
- });
- };
- // 鎵撳紑闄勪欢寮规
- const openFilesFormDia = (type, row) => {
- nextTick(() => {
- filesDia.value?.openDialog(type, row);
- });
- };
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row)
+ })
+};
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (type, row) => {
+ nextTick(() => {
+ filesDia.value?.openDialog(type, row)
+ })
+};
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map(item => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- qualityInspectDel(ids).then(res => {
+ qualityInspectDel(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -408,83 +357,91 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download(
- "/quality/qualityInspect/export",
- { inspectType: 0 },
- "鍘熸潗鏂欐楠�.xlsx"
- );
+ proxy.download("/quality/qualityInspect/export", {inspectType: 0}, "鍘熸潗鏂欐楠�.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+};
- // 鎻愪环
- const submit = async id => {
- const res = await submitQualityInspect({ id: id });
+// 鎻愪氦
+const submit = async (id) => {
+ submitLoadingId.value = id;
+ try {
+ const res = await submitQualityInspect({ id });
if (res.code === 200) {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ const row = tableData.value.find(item => item.id === id);
+ if (row) {
+ row.inspectState = 1;
+ }
+ }
+ } finally {
+ submitLoadingId.value = null;
+ }
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+
+const submitForm = () => {
+ if (currentRow.value) {
+ const data = {
+ ...form.value,
+ id: currentRow.value.id
+ }
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
getList();
- }
- };
+ })
+ }
+};
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- };
+const open = async (row) => {
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ currentRow.value = row
+ dialogFormVisible.value = true
+}
- const submitForm = () => {
- if (currentRow.value) {
- const data = {
- ...form.value,
- id: currentRow.value.id,
- };
- qualityInspectUpdate(data).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- };
+const downLoadFile = async (row) => {
+ downloadLoadingId.value = row.id;
+ try {
+ const blobData = await downloadQualityInspect({ id: row.id });
+ const blob = new Blob([blobData], {
+ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ })
+ const downloadUrl = window.URL.createObjectURL(blob)
- const open = async row => {
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- currentRow.value = row;
- dialogFormVisible.value = true;
- };
+ const link = document.createElement('a')
+ link.href = downloadUrl
+ link.download = '鍘熸潗鏂欐楠屾姤鍛�.docx'
+ document.body.appendChild(link)
+ link.click()
- const downLoadFile = row => {
- downloadQualityInspect({ id: row.id }).then(blobData => {
- const blob = new Blob([blobData], {
- type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
- });
- const downloadUrl = window.URL.createObjectURL(blob);
+ document.body.removeChild(link)
+ window.URL.revokeObjectURL(downloadUrl)
+ } finally {
+ downloadLoadingId.value = null;
+ }
+};
- const link = document.createElement("a");
- link.href = downloadUrl;
- link.download = "鍘熸潗鏂欐楠屾姤鍛�.docx";
- document.body.appendChild(link);
- link.click();
-
- document.body.removeChild(link);
- window.URL.revokeObjectURL(downloadUrl);
- });
- };
-
- onMounted(() => {
- getList();
- });
+onMounted(() => {
+ getList();
+});
</script>
<style scoped></style>
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue
index 313f1df..fad818d 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue
@@ -1,17 +1,35 @@
<template>
- <div class="panel-header">
+ <div
+ class="panel-header"
+ :class="{ clickable: !!to }"
+ @click="handleClick"
+ >
<span class="panel-title">{{ title }}</span>
</div>
</template>
<script setup>
-defineProps({
+import { useRouter } from 'vue-router'
+
+const props = defineProps({
title: {
type: String,
required: true,
default: ''
+ },
+ to: {
+ type: String,
+ default: ''
}
})
+
+const router = useRouter()
+
+const handleClick = () => {
+ if (props.to) {
+ router.push(props.to)
+ }
+}
</script>
<style scoped>
@@ -30,4 +48,12 @@
padding-left: 46px;
line-height: 36px;
}
+
+.panel-header.clickable {
+ cursor: pointer;
+}
+
+.panel-header.clickable:hover .panel-title {
+ color: #43e8fc;
+}
</style>
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue
index 87cde44..327bd72 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue
@@ -5,7 +5,7 @@
@change="handleChange"
>
<el-radio-button :label="1">鍘熸潗鏂�</el-radio-button>
- <el-radio-button :label="3">鍗婃垚鍝�</el-radio-button>
+ <!-- <el-radio-button :label="3">鍗婃垚鍝�</el-radio-button> -->
<el-radio-button :label="2">鎴愬搧</el-radio-button>
</el-radio-group>
</template>
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
index f4e49b6..b9b0d89 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="鍑哄叆搴撹秼鍔�" />
+ <PanelHeader title="鍑哄叆搴撹秼鍔�" to="/inventoryManagement/receiptManagement" />
<div class="main-panel panel-item-customers">
<div class="filters-row">
@@ -30,7 +30,7 @@
import ProductTypeSwitch from './ProductTypeSwitch.vue'
import { productInOutAnalysis } from '@/api/viewIndex.js'
-const productType = ref(1) // 1=鍘熸潗鏂� 2=鍗婃垚鍝� 3=鎴愬搧
+const productType = ref(2) // 1=鍘熸潗鏂� 3=鍗婃垚鍝� 2=鎴愬搧
const chartStyle = { width: '100%', height: '130%' }
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
index 6e39eb1..068f05a 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
@@ -2,7 +2,7 @@
<div>
<!-- 璁惧缁熻 -->
<div class="equipment-stats">
- <div class="equipment-header">
+ <div class="equipment-header clickable" @click="handleNavigate">
<img
src="@/assets/BI/shujutongjiicon@2x.png"
alt="鍥炬爣"
@@ -28,8 +28,19 @@
<script setup>
import { ref, onMounted, inject, watch } from 'vue'
+import { useRouter } from 'vue-router'
import Echarts from '@/components/Echarts/echarts.vue'
import { productTurnoverDays } from '@/api/viewIndex.js'
+import { getPsiRoute } from '../psiNavigation.js'
+
+const router = useRouter()
+
+const handleNavigate = () => {
+ const path = getPsiRoute('浜у搧鍛ㄨ浆澶╂暟')
+ if (path) {
+ router.push(path)
+ }
+}
const chartStyle = { width: '100%', height: '100%' }
const grid = { left: '3%', right: '4%', bottom: '3%', top: '4%', containLabel: true }
@@ -119,6 +130,14 @@
padding-bottom: 2px;
}
+.equipment-header.clickable {
+ cursor: pointer;
+}
+
+.equipment-header.clickable:hover .equipment-title {
+ opacity: 0.85;
+}
+
.equipment-title {
font-weight: 500;
font-size: 18px;
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
index 055fb66..80657c4 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
@@ -6,6 +6,8 @@
v-for="item in statItems"
:key="item.name"
class="stat-card"
+ :class="{ clickable: !!getStatRoute(item.name) }"
+ @click="handleStatClick(item.name)"
>
<img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
<div class="card-content">
@@ -25,9 +27,21 @@
<script setup>
import { ref, onMounted, inject, watch } from 'vue'
+import { useRouter } from 'vue-router'
import { salesPurchaseStorageProductCount } from '@/api/viewIndex.js'
+import { getPsiRoute } from '../psiNavigation.js'
+const router = useRouter()
const statItems = ref([])
+
+const getStatRoute = (name) => getPsiRoute(name)
+
+const handleStatClick = (name) => {
+ const path = getStatRoute(name)
+ if (path) {
+ router.push(path)
+ }
+}
const formatPercent = (val) => {
const num = Number(val) || 0
@@ -81,6 +95,14 @@
height: 142px;
}
+.stat-card.clickable {
+ cursor: pointer;
+}
+
+.stat-card.clickable:hover .card-label {
+ color: #43e8fc;
+}
+
.card-icon {
width: 100px;
height: 100px;
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
index 65a72fe..aa27c0e 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="閲囪喘鍝佸垎甯�" />
+ <PanelHeader title="閲囪喘鍝佸垎甯�" to="/procurementManagement/procurementLedger" />
<div class="main-panel panel-item-customers">
<CarouselCards :items="cardItems" :visible-count="3" />
<div class="pie-chart-wrapper" ref="pieWrapperRef">
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
index f5dac31..cf2a234 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="閿�鍞搧鍒嗗竷" />
+ <PanelHeader title="閿�鍞搧鍒嗗竷" to="/salesManagement/salesLedger" />
<div class="main-panel panel-item-customers">
<CarouselCards :items="cardItems" :visible-count="3" />
<div class="pie-chart-wrapper" ref="pieWrapperRef">
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/index.vue b/src/views/reportAnalysis/PSIDataAnalysis/index.vue
index f81e482..3f8d3df 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/index.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/index.vue
@@ -34,8 +34,8 @@
<!-- 鍙充晶鍖哄煙 -->
<div class="right-panel">
- <RightBottom />
- <RightTop />
+ <RightBottom header-to="/salesManagement/receiptPaymentLedger" />
+ <RightTop header-to="/procurementManagement/paymentLedger" />
</div>
</div>
</div>
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/psiNavigation.js b/src/views/reportAnalysis/PSIDataAnalysis/psiNavigation.js
new file mode 100644
index 0000000..425e666
--- /dev/null
+++ b/src/views/reportAnalysis/PSIDataAnalysis/psiNavigation.js
@@ -0,0 +1,15 @@
+export const PSI_ROUTE_MAP = {
+ 閿�鍞搧鍒嗗竷: '/salesManagement/salesLedger',
+ 閲囪喘鍝佸垎甯�: '/procurementManagement/procurementLedger',
+ 閿�鍞骇鍝佹暟: '/salesManagement/salesLedger',
+ 閲囪喘浜у搧鏁�: '/procurementManagement/procurementLedger',
+ 鍌ㄥ瓨浜у搧鏁�: '/inventoryManagement/stockManagement',
+ 瀹㈡埛璐$尞鎺掑悕: '/salesManagement/receiptPaymentLedger',
+ 渚涘簲鍟嗛噰璐帓鍚�: '/procurementManagement/paymentLedger',
+ 鍑哄叆搴撹秼鍔�: '/inventoryManagement/receiptManagement',
+ 浜у搧鍛ㄨ浆澶╂暟: '/inventoryManagement/stockManagement',
+}
+
+export function getPsiRoute(name) {
+ return PSI_ROUTE_MAP[name] || ''
+}
diff --git a/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue b/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue
index 313f1df..fad818d 100644
--- a/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue
@@ -1,17 +1,35 @@
<template>
- <div class="panel-header">
+ <div
+ class="panel-header"
+ :class="{ clickable: !!to }"
+ @click="handleClick"
+ >
<span class="panel-title">{{ title }}</span>
</div>
</template>
<script setup>
-defineProps({
+import { useRouter } from 'vue-router'
+
+const props = defineProps({
title: {
type: String,
required: true,
default: ''
+ },
+ to: {
+ type: String,
+ default: ''
}
})
+
+const router = useRouter()
+
+const handleClick = () => {
+ if (props.to) {
+ router.push(props.to)
+ }
+}
</script>
<style scoped>
@@ -30,4 +48,12 @@
padding-left: 46px;
line-height: 36px;
}
+
+.panel-header.clickable {
+ cursor: pointer;
+}
+
+.panel-header.clickable:hover .panel-title {
+ color: #43e8fc;
+}
</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
index 6fcd80f..9c0ce9a 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="瀹㈡埛璐$尞鎺掑悕" />
+ <PanelHeader title="瀹㈡埛璐$尞鎺掑悕" :to="headerTo" />
<div class="panel-item-customers">
<div class="switch-container">
<DateTypeSwitch v-model="dateType" @change="handleDateTypeChange" />
@@ -28,12 +28,19 @@
import DateTypeSwitch from '../DateTypeSwitch.vue'
import { customerContributionRanking } from '@/api/viewIndex.js'
+defineProps({
+ headerTo: {
+ type: String,
+ default: ''
+ }
+})
+
const chartStyle = {
width: '100%',
height: '100%',
}
-const dateType = ref(1) // 1=鍛� 2=鏈� 3=瀛e害
+const dateType = ref(3) // 1=鍛� 2=鏈� 3=瀛e害
// 椋炴満鍥炬爣 SVG path锛堜笌 right-top 涓�鑷达級
const aircraft =
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
index 96e4548..36741a9 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="渚涘簲鍟嗛噰璐帓鍚�" />
+ <PanelHeader title="渚涘簲鍟嗛噰璐帓鍚�" :to="headerTo" />
<div class="panel-item-customers">
<div class="switch-container">
<DateTypeSwitch v-model="radio1" @change="handleDateTypeChange" />
@@ -27,12 +27,19 @@
import DateTypeSwitch from '../DateTypeSwitch.vue'
import { supplierPurchaseRanking } from '@/api/viewIndex.js'
+defineProps({
+ headerTo: {
+ type: String,
+ default: ''
+ }
+})
+
const chartStyle = {
width: '100%',
height: '100%',
}
-const radio1 = ref(1)
+const radio1 = ref(3)
// 椋炴満鍥炬爣 SVG path
const aircraft =
diff --git a/src/views/reportAnalysis/productionAnalysis/components/PanelHeader.vue b/src/views/reportAnalysis/productionAnalysis/components/PanelHeader.vue
index 313f1df..fad818d 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/PanelHeader.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/PanelHeader.vue
@@ -1,17 +1,35 @@
<template>
- <div class="panel-header">
+ <div
+ class="panel-header"
+ :class="{ clickable: !!to }"
+ @click="handleClick"
+ >
<span class="panel-title">{{ title }}</span>
</div>
</template>
<script setup>
-defineProps({
+import { useRouter } from 'vue-router'
+
+const props = defineProps({
title: {
type: String,
required: true,
default: ''
+ },
+ to: {
+ type: String,
+ default: ''
}
})
+
+const router = useRouter()
+
+const handleClick = () => {
+ if (props.to) {
+ router.push(props.to)
+ }
+}
</script>
<style scoped>
@@ -30,4 +48,12 @@
padding-left: 46px;
line-height: 36px;
}
+
+.panel-header.clickable {
+ cursor: pointer;
+}
+
+.panel-header.clickable:hover .panel-title {
+ color: #43e8fc;
+}
</style>
diff --git a/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue
index f4f4024..ce746c7 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="鐢熶骇璁㈠崟瀹屾垚杩涘害" />
+ <PanelHeader title="鐢熶骇璁㈠崟瀹屾垚杩涘害" to="/productionManagement/productionOrder" />
<div class="main-panel">
<div class="panel-item-customers">
<CarouselCards :items="cardItems" :visible-count="4" />
diff --git a/src/views/reportAnalysis/productionAnalysis/components/center-center.vue b/src/views/reportAnalysis/productionAnalysis/components/center-center.vue
index a65f4f8..c56a4f8 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/center-center.vue
@@ -2,7 +2,7 @@
<div>
<!-- 璁惧缁熻 -->
<div class="equipment-stats">
- <div class="equipment-header">
+ <div class="equipment-header clickable" @click="handleNavigate">
<img
src="@/assets/BI/shujutongjiicon@2x.png"
alt="鍥炬爣"
@@ -10,8 +10,12 @@
/>
<span class="equipment-title">鎶曞叆浜у嚭鍒嗘瀽</span>
</div>
+
+ <div class="filters-row">
+ <DateTypeSwitch v-model="dateType" @change="handleDateTypeChange" />
+ </div>
<Echarts
- ref="chart"
+ ref="chartRef"
:chartStyle="chartStyle"
:grid="grid"
:legend="lineLegend"
@@ -27,11 +31,25 @@
</template>
<script setup>
-import { ref, onMounted, inject, watch } from 'vue'
+import { ref, onMounted, inject, watch, nextTick } from 'vue'
+import { useRouter } from 'vue-router'
import * as echarts from 'echarts'
import Echarts from '@/components/Echarts/echarts.vue'
import { inputOutputAnalysis } from '@/api/viewIndex.js'
+import DateTypeSwitch from "@/views/reportAnalysis/productionAnalysis/components/DateTypeSwitch.vue";
+import { getProductionRoute } from '../productionNavigation.js'
+const router = useRouter()
+
+const handleNavigate = () => {
+ const path = getProductionRoute('鎶曞叆浜у嚭鍒嗘瀽')
+ if (path) {
+ router.push(path)
+ }
+}
+
+const dateType = ref(3) // 1=鍛� 2=鏈� 3=瀛e害
+const chartRef = ref(null)
const chartStyle = { width: '100%', height: '100%' }
const grid = {
left: '3%',
@@ -77,6 +95,10 @@
splitLine: { lineStyle: { color: '#B8C8E0' } },
},
]
+
+const handleDateTypeChange = () => {
+ fetchData()
+}
const lineSeries = ref([
{
@@ -132,18 +154,27 @@
}
const fetchData = () => {
- inputOutputAnalysis()
+ inputOutputAnalysis({ type: dateType.value })
.then((res) => {
if (res.code === 200 && Array.isArray(res.data)) {
const list = res.data
xAxis1.value[0].data = list.map((d) => d.date)
lineSeries.value[0].data = list.map((d) => Number(d.outputSum) || 0)
lineSeries.value[1].data = list.map((d) => Number(d.inputSum) || 0)
+ scheduleChartResize()
}
})
.catch((err) => {
console.error('鑾峰彇鎶曞叆浜у嚭鍒嗘瀽澶辫触:', err)
})
+}
+
+const scheduleChartResize = () => {
+ nextTick(() => {
+ ;[0, 150, 400].forEach((ms) => {
+ setTimeout(() => chartRef.value?.resize?.(), ms)
+ })
+ })
}
const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
@@ -155,6 +186,7 @@
onMounted(() => {
fetchData()
+ scheduleChartResize()
})
</script>
@@ -183,6 +215,14 @@
padding-bottom: 2px;
}
+.equipment-header.clickable {
+ cursor: pointer;
+}
+
+.equipment-header.clickable:hover .equipment-title {
+ opacity: 0.85;
+}
+
.equipment-title {
font-weight: 500;
font-size: 18px;
@@ -197,4 +237,10 @@
width: 50px;
height: 50px;
}
+
+.filters-row {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+}
</style>
diff --git a/src/views/reportAnalysis/productionAnalysis/components/center-top.vue b/src/views/reportAnalysis/productionAnalysis/components/center-top.vue
index a806150..7a3deef 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/center-top.vue
@@ -6,6 +6,8 @@
v-for="item in statItems"
:key="item.name"
class="stat-card"
+ :class="{ clickable: !!getStatRoute(item.name) }"
+ @click="handleStatClick(item.name)"
>
<img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
<div class="card-content">
@@ -25,9 +27,21 @@
<script setup>
import { ref, onMounted, inject, watch } from 'vue'
+import { useRouter } from 'vue-router'
import { orderCount } from '@/api/viewIndex.js'
+import { getProductionRoute } from '../productionNavigation.js'
+const router = useRouter()
const statItems = ref([])
+
+const getStatRoute = (name) => getProductionRoute(name)
+
+const handleStatClick = (name) => {
+ const path = getStatRoute(name)
+ if (path) {
+ router.push(path)
+ }
+}
const formatPercent = (val) => {
const num = Number(val) || 0
@@ -81,6 +95,14 @@
height: 142px;
}
+.stat-card.clickable {
+ cursor: pointer;
+}
+
+.stat-card.clickable:hover .card-label {
+ color: #43e8fc;
+}
+
.card-icon {
width: 100px;
height: 100px;
diff --git a/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
index b7c7358..e6e8189 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="鍦ㄥ埗鍝佺粺璁″垎鏋�" />
+ <PanelHeader title="鍦ㄥ埗鍝佺粺璁″垎鏋�" to="/productionManagement/productionOrder" />
<div class="main-panel panel-item-customers">
<CarouselCards :items="cardItems" :visible-count="3" />
<div class="chart-wrapper">
diff --git a/src/views/reportAnalysis/productionAnalysis/components/left-top.vue b/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
index 37c82f0..c4532ad 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="宸ュ簭浜у嚭鍒嗘瀽" />
+ <PanelHeader title="宸ュ簭浜у嚭鍒嗘瀽" to="/productionManagement/processStatistics" />
<div class="main-panel panel-item-customers">
<div class="filters-row">
<DateTypeSwitch v-model="dateType" @change="handleDateTypeChange" />
@@ -33,7 +33,7 @@
const pieWrapperRef = ref(null)
const pieBackgroundRef = ref(null)
-const dateType = ref(1) // 1=鍛� 2=鏈� 3=瀛e害
+const dateType = ref(3) // 1=鍛� 2=鏈� 3=瀛e害
function array2obj(array, key) {
const resObj = {}
diff --git a/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue
index 62356e7..33c5c20 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="鐢熶骇鏍哥畻鍒嗘瀽" />
+ <PanelHeader title="鐢熶骇鏍哥畻鍒嗘瀽" to="/productionManagement/productionCosting" />
<div class="main-panel panel-item-customers">
<div class="filters-row">
<DateTypeSwitch v-model="dateType" @change="handleDateTypeChange" />
@@ -28,7 +28,7 @@
import DateTypeSwitch from './DateTypeSwitch.vue'
import Echarts from '@/components/Echarts/echarts.vue'
-const dateType = ref(1)
+const dateType = ref(3)
const chartStyle = {
width: '100%',
diff --git a/src/views/reportAnalysis/productionAnalysis/components/right-top.vue b/src/views/reportAnalysis/productionAnalysis/components/right-top.vue
index 5ec836f..8e6ffef 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/right-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/right-top.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <PanelHeader title="宸ュ崟鎵ц鏁堢巼鍒嗘瀽" />
+ <PanelHeader title="宸ュ崟鎵ц鏁堢巼鍒嗘瀽" to="/productionManagement/productionManagement/workOrderEdit/index" />
<div class="main-panel panel-item-customers">
<div class="filters-row">
<DateTypeSwitch v-model="dateType" @change="handleDateTypeChange" />
@@ -28,7 +28,7 @@
import Echarts from '@/components/Echarts/echarts.vue'
import DateTypeSwitch from './DateTypeSwitch.vue'
-const dateType = ref(1) // 1=鍛� 2=鏈� 3=瀛e害
+const dateType = ref(3) // 1=鍛� 2=鏈� 3=瀛e害
const chartStyle = {
width: '100%',
@@ -135,7 +135,7 @@
}
const fetchData = () => {
- workOrderEfficiencyAnalysis({ dateType: dateType.value })
+ workOrderEfficiencyAnalysis({ type: dateType.value })
.then((res) => {
if (res.code !== 200 || !Array.isArray(res.data)) return
const items = res.data
diff --git a/src/views/reportAnalysis/productionAnalysis/productionNavigation.js b/src/views/reportAnalysis/productionAnalysis/productionNavigation.js
new file mode 100644
index 0000000..38b45e8
--- /dev/null
+++ b/src/views/reportAnalysis/productionAnalysis/productionNavigation.js
@@ -0,0 +1,19 @@
+const PRODUCTION_ORDER_ROUTE = '/productionManagement/productionOrder'
+
+export const PRODUCTION_ROUTE_MAP = {
+ 宸ュ簭浜у嚭鍒嗘瀽: '/productionManagement/processStatistics',
+ 鍦ㄥ埗鍝佺粺璁″垎鏋�: PRODUCTION_ORDER_ROUTE,
+ 鐢熶骇璁㈠崟鏁�: PRODUCTION_ORDER_ROUTE,
+ 宸插畬鎴愯鍗曟暟: PRODUCTION_ORDER_ROUTE,
+ 寰呯敓浜ц鍗�: PRODUCTION_ORDER_ROUTE,
+ 寰呯敓浜ц鍗曟暟: PRODUCTION_ORDER_ROUTE,
+ 鐢熶骇璁㈠崟瀹屾垚杩涘害: PRODUCTION_ORDER_ROUTE,
+ 鐢熶骇璁㈠崟瀹屾垚杩涘害鏁�: PRODUCTION_ORDER_ROUTE,
+ 鎶曞叆浜у嚭鍒嗘瀽: '/productionManagement/productionReporting',
+ 宸ュ崟鎵ц鏁堢巼鍒嗘瀽: '/productionManagement/productionManagement/workOrderEdit/index',
+ 鐢熶骇鏍哥畻鍒嗘瀽: '/productionManagement/productionCosting',
+}
+
+export function getProductionRoute(name) {
+ return PRODUCTION_ROUTE_MAP[name] || ''
+}
diff --git a/src/views/reportAnalysis/reportManagement/index.vue b/src/views/reportAnalysis/reportManagement/index.vue
index cd8ddd5..4c9e1ea 100644
--- a/src/views/reportAnalysis/reportManagement/index.vue
+++ b/src/views/reportAnalysis/reportManagement/index.vue
@@ -37,7 +37,7 @@
</div>
</div>
</div>
- <div class="typeNum">
+ <div class="typeNum" v-if="showSemiFinished">
<div class="typeNum-left">
<img src="~@/assets/images/chartCard2.svg" alt="鍥捐〃"
style="width: 40px; height: 40px; object-fit: contain;">
@@ -123,7 +123,7 @@
</div>
</div>
</div>
- <div class="quality-card green-card">
+ <div class="quality-card green-card" v-if="showSemiFinished">
<div class="quality-card-title">
<img src="~@/assets/images/chartCard2.svg" alt="鍗婃垚鍝�"
style="width: 24px; height: 24px; margin-right: 8px;">
@@ -202,7 +202,7 @@
<div class="chart-box-title">鍘熸潗鏂欐�绘暟</div>
<div class="chart-box-num">{{ getYearlyStatValue(0, 'totalCount') }}</div>
</div>
- <div class="inspection-chart-box">
+ <div class="inspection-chart-box" v-if="showSemiFinished">
<div class="chart-box-title">鍗婃垚鍝佹�绘暟</div>
<div class="chart-box-num">{{ getYearlyStatValue(1, 'totalCount') }}</div>
</div>
@@ -266,7 +266,7 @@
<!-- Tab 閫夋嫨鍣� -->
<div class="tab-selector">
<div class="tab-item" :class="{ active: activeTab === 'raw' }" @click="activeTab = 'raw'">鍘熸潗鏂�</div>
- <div class="tab-item" :class="{ active: activeTab === 'semi' }" @click="activeTab = 'semi'">鍗婃垚鍝�</div>
+ <div v-if="showSemiFinished" class="tab-item" :class="{ active: activeTab === 'semi' }" @click="activeTab = 'semi'">鍗婃垚鍝�</div>
<div class="tab-item" :class="{ active: activeTab === 'final' }" @click="activeTab = 'final'">鎴愬搧</div>
</div>
</el-card>
@@ -296,6 +296,9 @@
const topParametersData = ref({ totalCount: 0, list: [] });
const activeTab = ref("raw");
+// 鏄惁鏄剧ず鍗婃垚鍝佺浉鍏冲唴瀹广�傛湁鐨勪紒涓氭病鏈夊崐鎴愬搧锛岃涓� false 鍗冲彲闅愯棌鎵�鏈夊崐鎴愬搧鐩稿叧灞曠ず
+const showSemiFinished = ref(false);
+
const getParameterColor = (index) => {
const colors = ['#165DFF', '#14C9C9', '#F7BA1E', '#722ED1', '#3491FA', '#FF7D00', '#F53F3F'];
return colors[index % colors.length];
@@ -315,7 +318,7 @@
const stat = passRateStatisticsData.value.find(item => item.modelType === type);
if (stat) {
if (field === 'completionRate' || field === 'passRate') {
- return stat[field] ? Number(stat[field]).toFixed(0) + '%' : '0%';
+ return stat[field] ? parseFloat(stat[field]) + '%' : '0%';
}
return stat[field];
}
@@ -526,7 +529,7 @@
containLabel: true,
},
legend: {
- data: ["鍘熸潗鏂�", "鍗婃垚鍝�", "鎴愬搧"], // 鍥句緥鏁版嵁
+ data: showSemiFinished.value ? ["鍘熸潗鏂�", "鍗婃垚鍝�", "鎴愬搧"] : ["鍘熸潗鏂�", "鎴愬搧"], // 鍥句緥鏁版嵁
icon: ["circle", "circle", "circle"],
itemWidth: 10, // 璁剧疆鍥炬爣瀹藉害
itemHeight: 10,
@@ -564,7 +567,7 @@
color: "#409EFF",
},
},
- {
+ ...(showSemiFinished.value ? [{
name: "鍗婃垚鍝�",
type: "bar",
barWidth: "15%",
@@ -573,7 +576,7 @@
itemStyle: {
color: "#67C23A",
},
- },
+ }] : []),
{
name: "鎴愬搧",
type: "bar",
@@ -607,7 +610,7 @@
radius: "70%",
data: [
{ value: getYearlyStatValue(0, 'totalCount'), name: "鍘熸潗鏂�", itemStyle: { color: "#1890FF" } },
- { value: getYearlyStatValue(1, 'totalCount'), name: "鍗婃垚鍝�", itemStyle: { color: "#F7BA1E" } },
+ ...(showSemiFinished.value ? [{ value: getYearlyStatValue(1, 'totalCount'), name: "鍗婃垚鍝�", itemStyle: { color: "#F7BA1E" } }] : []),
{ value: getYearlyStatValue(2, 'totalCount'), name: "鎴愬搧", itemStyle: { color: "#14C9C9" } },
],
label: {
@@ -655,7 +658,7 @@
},
// 鍥句緥閰嶇疆
legend: {
- data: ["鍘熸潗鏂�", "鍗婃垚鍝�", "鎴愬搧"], // 鍥句緥鏁版嵁
+ data: showSemiFinished.value ? ["鍘熸潗鏂�", "鍗婃垚鍝�", "鎴愬搧"] : ["鍘熸潗鏂�", "鎴愬搧"], // 鍥句緥鏁版嵁
icon: ["circle", "circle", "circle"],
itemWidth: 10, // 璁剧疆鍥炬爣瀹藉害
itemHeight: 10,
@@ -697,7 +700,7 @@
},
data: monthlyPassRateData.value.map(item => item.rawMaterial.passRate),
},
- {
+ ...(showSemiFinished.value ? [{
name: "鍗婃垚鍝�", // 绯诲垪鍚嶇О
type: "line", // 鍥捐〃绫诲瀷涓烘姌绾垮浘
// stack: "Total", // 鍫嗗彔鍚嶇О
@@ -706,7 +709,7 @@
color: "#F7BA1E", // 璁剧疆杩欐潯绾跨殑棰滆壊
},
data: monthlyPassRateData.value.map(item => item.process.passRate),
- },
+ }] : []),
{
name: "鎴愬搧", // 绯诲垪鍚嶇О
type: "line", // 鍥捐〃绫诲瀷涓烘姌绾垮浘
@@ -769,16 +772,18 @@
"#52c41a",
getPassRateStatValue(0, 'passRate')
);
- semiCompletionChartInstance = initQualityChart(
- semiCompletionChart,
- "#1890ff",
- getPassRateStatValue(1, 'completionRate')
- );
- semiQualityChartInstance = initQualityChart(
- semiQualityChart,
- "#52c41a",
- getPassRateStatValue(1, 'passRate')
- );
+ if (showSemiFinished.value) {
+ semiCompletionChartInstance = initQualityChart(
+ semiCompletionChart,
+ "#1890ff",
+ getPassRateStatValue(1, 'completionRate')
+ );
+ semiQualityChartInstance = initQualityChart(
+ semiQualityChart,
+ "#52c41a",
+ getPassRateStatValue(1, 'passRate')
+ );
+ }
finalCompletionChartInstance = initQualityChart(
finalCompletionChart,
"#1890ff",
@@ -1161,7 +1166,7 @@
.typeNum {
height: 100%;
- width: 33.33%;
+ flex: 1;
display: flex;
align-items: center;
justify-content: center;
@@ -1297,11 +1302,12 @@
.flex-center {
justify-content: space-evenly;
+ gap: 15px;
}
.quality-card {
- /* flex: 1; */
- width: 32%;
+ flex: 1;
+ min-width: 0;
/* height: 100px; */
border-radius: 8px;
padding: 12px;
diff --git a/src/views/safeProduction/dangerInvestigation/index.vue b/src/views/safeProduction/dangerInvestigation/index.vue
index a278058..cb09e52 100644
--- a/src/views/safeProduction/dangerInvestigation/index.vue
+++ b/src/views/safeProduction/dangerInvestigation/index.vue
@@ -160,7 +160,7 @@
<el-form-item label="闅愭偅缂栧彿锛�"
prop="hiddenCode">
<el-input v-model="form.hiddenCode"
- placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�"
+ placeholder="鑷姩鐢熸垚"
disabled
clearable />
</el-form-item>
diff --git a/src/views/safeProduction/safetyTrainingAssessment/index.vue b/src/views/safeProduction/safetyTrainingAssessment/index.vue
index 38c2172..2c98308 100644
--- a/src/views/safeProduction/safetyTrainingAssessment/index.vue
+++ b/src/views/safeProduction/safetyTrainingAssessment/index.vue
@@ -76,21 +76,7 @@
prop="courseCode">
<el-input v-model="form.courseCode"
disabled
- placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鍒涘缓鏃堕棿"
- prop="createTime">
- <el-date-picker style="width: 100%"
- v-model="formCreateTimeDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable />
+ placeholder="鑷姩鐢熸垚" />
</el-form-item>
</el-col>
</el-row>
@@ -459,19 +445,12 @@
trainingMode: "", // 鍩硅鏂瑰紡
placeTraining: "", // 鍩硅鍦扮偣
classHour: "", // 璇炬椂
- createTime: "", // 鍒涘缓鏃堕棿
},
dialogVisible: false,
dialogTitle: "",
dialogType: "add",
viewDialogVisible: false,
currentKnowledge: {},
- });
- const formCreateTimeDate = computed({
- get: () => (form.value.createTime ? String(form.value.createTime).split(" ")[0] : ""),
- set: (value) => {
- form.value.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
- },
});
const {
@@ -1046,7 +1025,6 @@
trainingMode: "", // 鍩硅鏂瑰紡
placeTraining: "", // 鍩硅鍦扮偣
classHour: "", // 璇炬椂
- createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 鍒涘缓鏃堕棿
});
} else if (type === "edit" && row) {
dialogTitle.value = "缂栬緫鍩硅";
@@ -1064,7 +1042,6 @@
trainingMode: row.trainingMode, // 鍩硅鏂瑰紡
placeTraining: row.placeTraining, // 鍩硅鍦扮偣
classHour: row.classHour, // 璇炬椂
- createTime: row.createTime || "", // 鍒涘缓鏃堕棿
});
}
dialogVisible.value = true;
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index 33fa45f..07cf066 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -139,13 +139,13 @@
@click="openDetail(scope.row)"
>璇︽儏
</el-button>
- <!-- <el-button-->
- <!-- link-->
- <!-- type="danger"-->
- <!-- :disabled="isApproving(scope.row.status)"-->
- <!-- @click="handleDeleteSingle(scope.row)"-->
- <!-- >鍒犻櫎-->
- <!-- </el-button>-->
+ <el-button
+ link
+ type="danger"
+ :disabled="isApproving(scope.row.status)"
+ @click="handleDeleteSingle(scope.row)"
+ >鍒犻櫎
+ </el-button>
</template>
</el-table-column>
</el-table>
@@ -290,9 +290,11 @@
<el-descriptions-item label="蹇�掑崟鍙�" :span="2">{{
detailRow.expressNumber || "--"
}}</el-descriptions-item>
- <el-descriptions-item label="鍑哄簱鍗曞彿" :span="2">{{
- detailRow.outboundBatches || "--"
- }}</el-descriptions-item>
+ <el-descriptions-item label="鍑哄簱鍗曞彿" :span="2">
+ <span class="outbound-batches-text">
+ {{ detailRow.outboundBatches || "--" }}
+ </span>
+ </el-descriptions-item>
</el-descriptions>
<el-table
:data="getDeliveryProductInfoList()"
@@ -892,6 +894,14 @@
padding: 8px 0;
}
+.outbound-batches-text {
+ display: block;
+ white-space: normal;
+ overflow-wrap: anywhere;
+ word-break: break-word;
+ line-height: 1.6;
+}
+
.detail-images {
margin-top: 16px;
}
diff --git a/src/views/salesManagement/indicatorStats/index.vue b/src/views/salesManagement/indicatorStats/index.vue
index 52f1e6b..7e5e5ba 100644
--- a/src/views/salesManagement/indicatorStats/index.vue
+++ b/src/views/salesManagement/indicatorStats/index.vue
@@ -2,7 +2,7 @@
<div class="app-container indicator-stats">
<!-- KPI 姹囨�� -->
<el-row :gutter="20" class="stats-row">
- <el-col :xs="24" :sm="12" :md="12">
+ <el-col :xs="24" :sm="12" :md="6">
<div class="stat-card stat-card-blue">
<div class="stat-icon-wrapper">
<div class="stat-icon">
@@ -16,7 +16,7 @@
<div class="stat-bg-decoration"></div>
</div>
</el-col>
- <el-col :xs="24" :sm="12" :md="12">
+ <el-col :xs="24" :sm="12" :md="6">
<div class="stat-card stat-card-green">
<div class="stat-icon-wrapper">
<div class="stat-icon">
@@ -26,6 +26,34 @@
<div class="stat-content">
<div class="stat-value">楼{{ indicatorKpis.salesAmount.toLocaleString() }}</div>
<div class="stat-label">閿�鍞</div>
+ </div>
+ <div class="stat-bg-decoration"></div>
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="6">
+ <div class="stat-card stat-card-purple">
+ <div class="stat-icon-wrapper">
+ <div class="stat-icon">
+ <el-icon :size="32"><Goods /></el-icon>
+ </div>
+ </div>
+ <div class="stat-content">
+ <div class="stat-value">{{ formatQuantity(indicatorKpis.productSalesQuantity) }}</div>
+ <div class="stat-label">浜у搧閿�鍞暟閲�</div>
+ </div>
+ <div class="stat-bg-decoration"></div>
+ </div>
+ </el-col>
+ <el-col :xs="24" :sm="12" :md="6">
+ <div class="stat-card stat-card-orange">
+ <div class="stat-icon-wrapper">
+ <div class="stat-icon">
+ <el-icon :size="32"><Van /></el-icon>
+ </div>
+ </div>
+ <div class="stat-content">
+ <div class="stat-value">{{ indicatorKpis.shipRate }}</div>
+ <div class="stat-label">鍙戣揣鐜�</div>
</div>
<div class="stat-bg-decoration"></div>
</div>
@@ -118,7 +146,7 @@
<script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
-import { Document, Tickets, Search, Refresh } from '@element-plus/icons-vue'
+import { Document, Van, Tickets, Search, Refresh, Goods } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import { getTotalStatistics, getStatisticsTable } from '@/api/salesManagement/indicatorStats'
import { productTreeList } from '@/api/basicData/product.js'
@@ -128,6 +156,7 @@
const indicatorKpis = reactive({
orderCount: 0,
salesAmount: 0,
+ productSalesQuantity: 0,
shipRate: 0
})
@@ -147,6 +176,11 @@
const productOptions = ref([])
const customerOption = ref([])
+const formatQuantity = (value) => {
+ const num = Number(value)
+ if (Number.isNaN(num)) return '0'
+ return num.toLocaleString(undefined, { maximumFractionDigits: 2 })
+}
// 杞崲浜у搧鏍戞暟鎹紝灏� id 鏀逛负 value
function convertIdToValue(data) {
return data.map((item) => {
@@ -220,7 +254,7 @@
if (res && res.data) {
indicatorKpis.orderCount = res.data.total || 0
indicatorKpis.salesAmount = res.data.contractAmountTotal || 0
- // 鍙戣揣鐜囧鏋滄帴鍙f病鏈夎繑鍥烇紝淇濇寔鍘熷�兼垨璁句负0
+ indicatorKpis.productSalesQuantity = res.data.productQuantityTotal || 0
indicatorKpis.shipRate = res.data.shipRate || 0
}
} catch (error) {
@@ -268,12 +302,19 @@
if (indicatorChart) indicatorChart.dispose()
indicatorChart = echarts.init(indicatorChartRef.value)
- // 鏍规嵁鎺ュ彛杩斿洖鐨勬暟鎹粨鏋勬洿鏂板浘琛�
- // 鎺ュ彛杩斿洖: dateList, orderCountList, salesAmountList
+ // 鎺ュ彛杩斿洖: dateList, orderCountList, salesAmountList, productQuantityList
const option = {
title: { text: '澶氱淮搴﹂攢鍞寚鏍囪秼鍔�', left: 'center' },
tooltip: { trigger: 'axis' },
- legend: { data: ['璁㈠崟鏁�', '閿�鍞'], top: 30 },
+ legend: {
+ data: ['璁㈠崟鏁�', '閿�鍞', '浜у搧閿�鍞暟閲�'],
+ top: 30,
+ selected: {
+ '璁㈠崟鏁�': false,
+ '閿�鍞': true,
+ '浜у搧閿�鍞暟閲�': true
+ }
+ },
grid: { left: '3%', right: '8%', bottom: '3%', containLabel: true },
xAxis: {
type: 'category',
@@ -308,6 +349,13 @@
yAxisIndex: 0,
data: chartData.salesAmountList || [],
itemStyle: { color: '#67c23a' }
+ },
+ {
+ name: '浜у搧閿�鍞暟閲�',
+ type: 'line',
+ yAxisIndex: 1,
+ data: chartData.productQuantityList || [],
+ itemStyle: { color: '#f56c6c' }
}
]
}
@@ -321,7 +369,15 @@
const option = {
title: { text: '澶氱淮搴﹂攢鍞寚鏍囪秼鍔�', left: 'center' },
tooltip: { trigger: 'axis' },
- legend: { data: ['璁㈠崟鏁�', '閿�鍞'], top: 30 },
+ legend: {
+ data: ['璁㈠崟鏁�', '閿�鍞', '浜у搧閿�鍞暟閲�'],
+ top: 30,
+ selected: {
+ '璁㈠崟鏁�': false,
+ '閿�鍞': true,
+ '浜у搧閿�鍞暟閲�': true
+ }
+ },
grid: { left: '3%', right: '8%', bottom: '3%', containLabel: true },
xAxis: { type: 'category', data: [] },
yAxis: [
@@ -341,7 +397,8 @@
],
series: [
{ name: '璁㈠崟鏁�', type: 'line', yAxisIndex: 1, data: [], itemStyle: { color: '#409eff' } },
- { name: '閿�鍞', type: 'bar', yAxisIndex: 0, data: [], itemStyle: { color: '#67c23a' } }
+ { name: '閿�鍞', type: 'bar', yAxisIndex: 0, data: [], itemStyle: { color: '#67c23a' } },
+ { name: '浜у搧閿�鍞暟閲�', type: 'line', yAxisIndex: 1, data: [], itemStyle: { color: '#f56c6c' } }
]
}
indicatorChart.setOption(option)
@@ -509,6 +566,17 @@
background: #e6a23c;
}
}
+
+ &.stat-card-purple {
+ .stat-icon {
+ background: linear-gradient(135deg, #9b59b6 0%, #b37fcc 100%);
+ color: #fff;
+ }
+
+ .stat-bg-decoration {
+ background: #9b59b6;
+ }
+ }
}
.chart-card,
diff --git a/src/views/salesManagement/receiptPaymentLedger/index.vue b/src/views/salesManagement/receiptPaymentLedger/index.vue
index c5e3415..0bc5de3 100644
--- a/src/views/salesManagement/receiptPaymentLedger/index.vue
+++ b/src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -4,7 +4,7 @@
style="margin-bottom: 20px;">
<div>
<span class="search_title">瀹㈡埛鍚嶇О锛�</span>
- <el-input v-model="searchForm.searchText"
+ <el-input v-model="searchForm.customerName"
style="width: 240px"
placeholder="杈撳叆瀹㈡埛鍚嶇О鎼滅储"
@change="handleQuery"
@@ -41,23 +41,18 @@
show-overflow-tooltip
:formatter="formattedNumber"
width="200" />
- <el-table-column label="鍥炴閲戦(鍏�)"
- prop="receiptPaymentAmount"
+ <el-table-column label="宸插嚭搴撻噾棰�(鍏�)"
+ prop="shippedAmount"
show-overflow-tooltip
:formatter="formattedNumber"
width="200" />
- <el-table-column label="閫�璐ч噾棰�(鍏�)"
- prop="returnAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200" />
- <el-table-column label="搴旀敹閲戦(鍏�)"
- prop="receiptableAmount"
+ <el-table-column label="鏈嚭搴撻噾棰�(鍏�)"
+ prop="unshippedAmount"
show-overflow-tooltip
width="200">
<template #default="{ row, column }">
<el-text type="danger">
- {{ formattedNumber(row, column, row.receiptableAmount) }}
+ {{ formattedNumber(row, column, row.unshippedAmount) }}
</el-text>
</template>
</el-table-column>
@@ -96,23 +91,18 @@
show-overflow-tooltip
:formatter="formattedNumber"
width="200" />
- <el-table-column label="鍥炴閲戦(鍏�)"
- prop="receiptPaymentAmount"
+ <el-table-column label="宸插嚭搴撻噾棰�(鍏�)"
+ prop="shippedAmount"
show-overflow-tooltip
:formatter="formattedNumber"
width="200" />
- <el-table-column label="閫�璐ч噾棰�(鍏�)"
- prop="returnAmount"
- show-overflow-tooltip
- :formatter="formattedNumber"
- width="200" />
- <el-table-column label="搴旀敹閲戦(鍏�)"
- prop="receiptableAmount"
+ <el-table-column label="鏈嚭搴撻噾棰�(鍏�)"
+ prop="unshippedAmount"
show-overflow-tooltip
width="200">
<template #default="{ row, column }">
<el-text type="danger">
- {{ formattedNumber(row, column, row.receiptableAmount) }}
+ {{ formattedNumber(row, column, row.unshippedAmount) }}
</el-text>
</template>
</el-table-column>
@@ -136,6 +126,7 @@
customewTransactionsDetails,
} from "@/api/salesManagement/indicatorStats.js";
import Pagination from "../../../components/PIMTable/Pagination.vue";
+ import { tableAmountFormatter, buildAmountSummaryFormat } from "@/utils/numberFormat";
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const receiptRecord = ref([]);
@@ -152,7 +143,7 @@
const recordTotal = ref(0);
const data = reactive({
searchForm: {
- searchText: "",
+ customerName: "",
invoiceDate: "",
},
});
@@ -183,39 +174,33 @@
}
});
};
- const formattedNumber = (row, column, cellValue) => {
- return cellValue ? parseFloat(cellValue).toFixed(2) : "0.00";
- };
+ const formattedNumber = tableAmountFormatter;
// 涓昏〃鍚堣鏂规硶
const summarizeMainTable = param => {
return proxy.summarizeTable(
param,
- [
- "contractAmounts",
- "receiptPaymentAmount",
- "returnAmount",
- "receiptableAmount",
- ],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
+ ["contractAmounts", "shippedAmount", "unshippedAmount"],
+ buildAmountSummaryFormat(
+ ["contractAmounts", "shippedAmount", "unshippedAmount"],
+ {
+ ticketsNum: { noDecimal: true },
+ futureTickets: { noDecimal: true },
+ }
+ )
);
};
// 瀛愯〃鍚堣鏂规硶
const summarizeMainTable1 = param => {
var summarizeTable = proxy.summarizeTable(
param,
- [
- "contractAmount",
- "receiptPaymentAmount",
- "returnAmount",
- "receiptableAmount",
- ],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
+ ["contractAmount", "shippedAmount", "unshippedAmount"],
+ buildAmountSummaryFormat(
+ ["contractAmount", "shippedAmount", "unshippedAmount"],
+ {
+ ticketsNum: { noDecimal: true },
+ futureTickets: { noDecimal: true },
+ }
+ )
);
return summarizeTable;
};
diff --git a/src/views/salesManagement/returnOrder/components/detailDia.vue b/src/views/salesManagement/returnOrder/components/detailDia.vue
index a09149f..ecc663f 100644
--- a/src/views/salesManagement/returnOrder/components/detailDia.vue
+++ b/src/views/salesManagement/returnOrder/components/detailDia.vue
@@ -11,12 +11,6 @@
<el-descriptions-item label="閿�鍞崟鍙�">{{ detail.salesContractNo }}</el-descriptions-item>
<el-descriptions-item label="涓氬姟鍛�">{{ detail.salesman }}</el-descriptions-item>
<el-descriptions-item label="鍏宠仈鍙戣揣鍗曞彿">{{ detail.shippingNo }}</el-descriptions-item>
- <el-descriptions-item label="鍙戣揣绫诲瀷">{{ getShippingTypeText(detail.shippingType) }}</el-descriptions-item>
- <el-descriptions-item v-if="String(detail.shippingType) === '1'" label="鍙戣揣杞︾墝鍙�">{{ detail.truckPlateNo || "--" }}</el-descriptions-item>
- <template v-else-if="String(detail.shippingType) === '2'">
- <el-descriptions-item label="蹇�掑叕鍙�">{{ detail.expressCompany || "--" }}</el-descriptions-item>
- <el-descriptions-item label="蹇�掑崟鍙�">{{ detail.expressNo || "--" }}</el-descriptions-item>
- </template>
<!-- <el-descriptions-item label="椤圭洰鍚嶇О">{{ detail.projectName }}</el-descriptions-item> -->
<el-descriptions-item label="鍒跺崟浜�">{{ detail.maker }}</el-descriptions-item>
<el-descriptions-item label="鍒跺崟鏃堕棿">{{ detail.makeTime }}</el-descriptions-item>
@@ -27,6 +21,9 @@
<div style="padding-top: 20px">
<span class="descriptions">浜у搧鍒楄〃</span>
<PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData">
+ <template #totalReturnNum="{ row }">
+ {{ calcAlreadyReturned(row) }}
+ </template>
</PIMTable>
</div>
</div>
@@ -47,10 +44,6 @@
const detail = ref({});
const tableData = ref([]);
const availableProducts = ref([]);
-const shippingTypeMap = {
- 1: "璐ц溅",
- 2: "蹇��",
-};
const sameKey = (a, b) => a != null && b != null && String(a) === String(b);
@@ -120,8 +113,6 @@
if (!Number.isFinite(total) || !Number.isFinite(un)) return 0;
return Math.max(total - un, 0);
};
-
-const getShippingTypeText = (value) => shippingTypeMap[String(value)] || shippingTypeMap[value] || "--";
/** 璇︽儏琛ㄧ敤 productName / model锛涘悎骞舵椂鍕胯绌轰覆鐩栨帀鍑哄簱琛屽瓧娈� */
const mergeDetailProductRow = (product, normalized) => {
@@ -261,9 +252,8 @@
{align: "center", label: "瑙勬牸鍨嬪彿", prop: "model"},
{align: "center", label: "鍗曚綅", prop: "unit", width: 80},
{align: "center", label: "鎬绘暟閲�", prop: "stockOutNum", width: 120},
- {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120},
+ {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120, dataType: "slot", slot: "totalReturnNum"},
{align: "center", label: "鏈��璐ф暟閲�", prop: "unQuantity", width: 120},
- {align: "center", label: "寰呭鐞嗛��璐ф暟閲�", prop: "pendingReturnNum", width: 120},
{align: "center", label: "閫�璐ф暟閲�", prop: "returnQuantity", width: 120},
{align: "center", label: "閫�璐т骇鍝佸崟浠�", prop: "price", width: 120},
{align: "center", label: "閫�璐т骇鍝侀噾棰�", prop: "amount", width: 120},
@@ -294,7 +284,7 @@
try {
const res = await returnManagementGetById({ returnManagementId: row.id });
detail.value = res?.data ?? res ?? {};
-
+
if (detail.value.shippingId) {
const productRes = await returnManagementGetByShippingId({ shippingId: detail.value.shippingId });
if (productRes.code === 200) {
diff --git a/src/views/salesManagement/returnOrder/components/formDia.vue b/src/views/salesManagement/returnOrder/components/formDia.vue
index 4fc0859..6a6d756 100644
--- a/src/views/salesManagement/returnOrder/components/formDia.vue
+++ b/src/views/salesManagement/returnOrder/components/formDia.vue
@@ -69,31 +69,6 @@
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鍙戣揣绫诲瀷锛�" prop="shippingType">
- <el-select v-model="form.shippingType" placeholder="璇烽�夋嫨鍙戣揣绫诲瀷" @change="handleShippingTypeChange">
- <el-option label="璐ц溅" :value="1" />
- <el-option label="蹇��" :value="2" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="4" v-if="form.shippingType === 1">
- <el-form-item label="鍙戣揣杞︾墝鍙凤細" prop="truckPlateNo">
- <el-input v-model="form.truckPlateNo" placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿" />
- </el-form-item>
- </el-col>
- <template v-else-if="form.shippingType === 2">
- <el-col :span="4">
- <el-form-item label="蹇�掑叕鍙革細" prop="expressCompany">
- <el-input v-model="form.expressCompany" placeholder="璇疯緭鍏ュ揩閫掑叕鍙�" />
- </el-form-item>
- </el-col>
- <el-col :span="4">
- <el-form-item label="蹇�掑崟鍙凤細" prop="expressNo">
- <el-input v-model="form.expressNo" placeholder="璇疯緭鍏ュ揩閫掑崟鍙�" />
- </el-form-item>
- </el-col>
- </template>
- <el-col :span="4">
<el-form-item label="閫�娆炬�婚锛�" prop="refundAmount">
<el-input v-model="form.refundAmount" disabled placeholder="鑷姩璁$畻" />
</el-form-item>
@@ -107,29 +82,32 @@
<el-button type="primary" @click="openProductSelection" :disabled="!form.shippingId">娣诲姞浜у搧</el-button>
</div>
<PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData">
+ <template #totalReturnNum="{ row }">
+ {{ calcAlreadyReturned(row) }}
+ </template>
<template #returnQuantity="{ row }">
- <el-input
- v-model="row.returnQuantity"
- style="width:100px"
- placeholder="璇疯緭鍏�"
+ <el-input
+ v-model="row.returnQuantity"
+ style="width:100px"
+ placeholder="璇疯緭鍏�"
type="number"
@input="(val) => handleReturnQuantityChange(val, row)"
/>
</template>
<template #price="{ row }">
- <el-input
- v-model="row.price"
- style="width:100px"
- placeholder="璇疯緭鍏�"
+ <el-input
+ v-model="row.price"
+ style="width:100px"
+ placeholder="璇疯緭鍏�"
type="number"
@input="(val) => handlePriceChange(val, row)"
/>
</template>
<template #amount="{ row }">
- <el-input
- v-model="row.amount"
- style="width:100px"
- placeholder="鑷姩璁$畻"
+ <el-input
+ v-model="row.amount"
+ style="width:100px"
+ placeholder="鑷姩璁$畻"
type="number"
disabled
/>
@@ -141,10 +119,10 @@
</el-select>
</template>
<template #remark="{ row }">
- <el-input
- v-model="row.remark"
- style="width:130px"
- placeholder="璇疯緭鍏�"
+ <el-input
+ v-model="row.remark"
+ style="width:130px"
+ placeholder="璇疯緭鍏�"
/>
</template>
<template #action="{ index }">
@@ -162,9 +140,9 @@
</el-dialog>
<el-dialog v-model="productSelectionVisible" title="閫夋嫨浜у搧" width="70%" append-to-body>
- <el-table
- :data="availableProducts"
- style="width: 100%"
+ <el-table
+ :data="availableProducts"
+ style="width: 100%"
@selection-change="handleSelectionChange"
ref="productTableRef"
row-key="id"
@@ -176,9 +154,11 @@
<el-table-column align="center" prop="specificationModel" label="瑙勬牸鍨嬪彿" />
<el-table-column align="center" prop="unit" label="鍗曚綅" />
<el-table-column align="center" prop="stockOutNum" label="鎬绘暟閲�" />
- <el-table-column align="center" label="宸查��璐ф暟閲�" prop="totalReturnNum"></el-table-column>
<el-table-column align="center" prop="unQuantity" label="鏈��璐ф暟閲�" />
- <el-table-column align="center" prop="pendingReturnNum" label="寰呭鐞嗛��璐ф暟閲�" />
+ <el-table-column align="center" label="宸查��璐ф暟閲�">
+ <template #default="{ row }">{{ calcAlreadyReturned(row) }}</template>
+ </el-table-column>
+
</el-table>
<template #footer>
<div class="dialog-footer">
@@ -211,10 +191,6 @@
returnNo: "",
customerId: "",
shippingId: "",
- shippingType: "",
- truckPlateNo: "",
- expressCompany: "",
- expressNo: "",
projectId: "",
maker: "",
makeTime: "",
@@ -232,7 +208,6 @@
}],
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
shippingId: [{ required: true, message: "璇烽�夋嫨鍏宠仈鍑哄簱鍗曞彿", trigger: "change" }],
- shippingType: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
}
});
const { form, rules } = toRefs(data);
@@ -251,8 +226,7 @@
{align: "center", label: "瑙勬牸鍨嬪彿", prop: "specificationModel" },
{align: "center", label: "鍗曚綅", prop: "unit", width: 80 },
{align: "center", label: "鎬绘暟閲�", prop: "stockOutNum", width: 120 },
- {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120 },
- {align: "center", label: "寰呭鐞嗛��璐ф暟閲�", prop: "pendingReturnNum", width: 120 },
+ {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120, dataType: "slot", slot: "totalReturnNum" },
{align: "center", label: "鏈��璐ф暟閲�", prop: "unQuantity", width: 120 },
{align: "center", label: "閫�璐ф暟閲�", prop: "returnQuantity", dataType: "slot", slot: "returnQuantity", width: 120 },
{align: "center", label: "閫�璐т骇鍝佸崟浠�", prop: "price", dataType: "slot", slot: "price", width: 120 },
@@ -521,10 +495,6 @@
returnNo: "",
customerId: "",
shippingId: "",
- shippingType: "",
- truckPlateNo: "",
- expressCompany: "",
- expressNo: "",
projectId: "",
maker: "",
makeTime: "",
@@ -541,22 +511,6 @@
const submitForm = () => {
proxy.$refs["formRef"].validate(valid => {
if (!valid) return;
- if (!tableData.value || tableData.value.length === 0) {
- proxy.$modal.msgWarning("璇疯嚦灏戞坊鍔犱竴涓��璐т骇鍝�");
- return;
- }
- for (let i = 0; i < tableData.value.length; i++) {
- const row = tableData.value[i];
- const qty = Number(row.num ?? row.returnQuantity ?? 0);
- if (!qty || qty <= 0) {
- proxy.$modal.msgWarning(`绗�${i + 1}琛岄��璐ф暟閲忓繀椤诲ぇ浜�0`);
- return;
- }
- if (row.price === "" || row.price === null || row.price === undefined || Number(row.price) < 0) {
- proxy.$modal.msgWarning(`绗�${i + 1}琛岄��璐у崟浠蜂笉鑳戒负璐熸暟`);
- return;
- }
- }
const returnSaleProducts = (tableData.value || []).map(el => ({
stockOutRecordId: el.returnSaleLedgerProductId ?? el.id,
productModelId: el.productModelId,
@@ -571,11 +525,6 @@
const payload = { ...form.value, returnSaleProducts };
delete payload.returnNoCheckbox;
if (operationType.value === "add" && form.value.returnNoCheckbox) delete payload.returnNo;
- if (payload.shippingType !== 1) payload.truckPlateNo = "";
- if (payload.shippingType !== 2) {
- payload.expressCompany = "";
- payload.expressNo = "";
- }
if (operationType.value === "add") {
returnManagementAdd(payload).then(() => {
proxy.$modal.msgSuccess("鏂板鎴愬姛");
@@ -594,22 +543,6 @@
proxy.resetForm("formRef");
dialogFormVisible.value = false;
emit('close');
- data.form = {
- returnNoCheckbox: true,
- returnNo: "",
- customerId: "",
- shippingId: "",
- shippingType: "",
- truckPlateNo: "",
- expressCompany: "",
- expressNo: "",
- projectId: "",
- maker: "",
- makeTime: "",
- status: 0,
- returnReason: "",
- refundAmount: "",
- }
};
const initCustomers = async () => {
@@ -646,26 +579,13 @@
formRef.value?.validateField('returnNo');
};
-const handleShippingTypeChange = (val) => {
- if (val === 1) {
- form.value.expressCompany = "";
- form.value.expressNo = "";
- } else if (val === 2) {
- form.value.truckPlateNo = "";
- } else {
- form.value.truckPlateNo = "";
- form.value.expressCompany = "";
- form.value.expressNo = "";
- }
-};
-
const customerNameChange = async (val, clearDownstream = true) => {
// val is customerId now
if (clearDownstream) {
form.value.shippingId = "";
outboundOptions.value = [];
}
-
+
// Find customer name for getSalesLedger if it requires name
const customer = customerNameOptions.value.find(c => c.id === val);
if (!customer) return;
@@ -673,7 +593,7 @@
// Assuming getSalesLedger takes customerName. If it takes ID, adjust accordingly.
// Previous code used customerName. Let's try passing customerName.
getSalesLedger({
- customerName: customer.label,
+ customerName: customer.label,
}).then(res => {
if(res.code === 200){
outboundOptions.value = res.data.map(item => ({
@@ -690,7 +610,7 @@
if(res.code === 200){
// If backend returns project info, set it
if (res.data.projectId) form.value.projectId = res.data.projectId;
-
+
availableProducts.value = mergeShippingProductLists(res.data);
if (clearTable) tableData.value = [];
}
@@ -698,12 +618,9 @@
const handleReturnQuantityChange = (val, row) => {
if (val === "" || val === null) return;
- const unQuantity = row.unQuantity === undefined || row.unQuantity === null ? Infinity : Number(row.unQuantity || 0);//鏈��璐ф暟閲�
- const pendingReturnNum = row.pendingReturnNum === undefined || row.pendingReturnNum === null ? Infinity : Number(row.pendingReturnNum || 0);//寰呭鐞嗛��璐ф暟閲�
- //鏈�澶ч��璐ф暟閲忥紝濡傛灉涓虹紪杈戠姸鎬佸姞涓婂緟澶勭悊閫�璐ф暟閲�
- const max = operationType.value === 'edit' ? unQuantity + pendingReturnNum : unQuantity
+ const max = row.unQuantity === undefined || row.unQuantity === null ? Infinity : Number(row.unQuantity || 0);
const current = Number(val);
-
+
if (current > max) {
proxy.$nextTick(() => {
row.returnQuantity = max;
@@ -769,7 +686,7 @@
// Removed checkSelectable to allow toggling existing items
const confirmProductSelection = () => {
const newTableData = [];
-
+
selectedProducts.value.forEach(product => {
const existing = tableData.value.find(item => item.id === product.id);
if (existing) {
@@ -777,7 +694,7 @@
} else {
newTableData.push({
...product,
- returnSaleLedgerProductId: product.id,
+ returnSaleLedgerProductId: product.id,
productModelId: product.productModelId,
returnQuantity: 0,
num: 0,
@@ -795,7 +712,7 @@
});
}
});
-
+
tableData.value = newTableData;
productSelectionVisible.value = false;
};
diff --git a/src/views/salesManagement/returnOrder/index.vue b/src/views/salesManagement/returnOrder/index.vue
index 1bcda4d..0a8257b 100644
--- a/src/views/salesManagement/returnOrder/index.vue
+++ b/src/views/salesManagement/returnOrder/index.vue
@@ -38,9 +38,6 @@
<template #status="{ row }">
<el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
</template>
- <template #stockInApprovalStatus="{ row }">
- <el-tag :type="getStockInApprovalStatusType(row.stockInApprovalStatus)">{{ getStockInApprovalStatusText(row.stockInApprovalStatus) }}</el-tag>
- </template>
</PIMTable>
</div>
<form-dia ref="formDia" @close="handleQuery" />
@@ -117,21 +114,11 @@
const defaultColumns = [
{ label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: 160 },
{ label: "鍗曟嵁鐘舵��", prop: "status", minWidth: 90, dataType: "slot", slot: "status" },
- { label: "鍏ュ簱瀹℃壒鐘舵��", prop: "stockInApprovalStatus", minWidth: 120, dataType: "slot", slot: "stockInApprovalStatus" },
{ label: "鍒跺崟鏃堕棿", prop: "makeTime", minWidth: 170 },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: 220 },
{ label: "閿�鍞崟鍙�", prop: "salesContractNo", minWidth: 160 },
{ label: "涓氬姟鍛�", prop: "salesman", minWidth: 120 },
{ label: "鍏宠仈鍙戣揣鍗曞彿", prop: "shippingNo", minWidth: 170 },
- {
- label: "鍙戣揣绫诲瀷",
- prop: "shippingType",
- minWidth: 100,
- formatData: (val) => ({ 1: "璐ц溅", 2: "蹇��" }[String(val)] || "--"),
- },
- { label: "鍙戣揣杞︾墝鍙�", prop: "truckPlateDisplay", minWidth: 140 },
- { label: "蹇�掑叕鍙�", prop: "expressCompanyDisplay", minWidth: 140 },
- { label: "蹇�掑崟鍙�", prop: "expressNoDisplay", minWidth: 150 },
{ label: "椤圭洰鍚嶇О", prop: "projectName", minWidth: 180 },
{ label: "鍒跺崟浜�", prop: "maker", minWidth: 120 },
{
@@ -177,12 +164,7 @@
tableLoading.value = true;
returnManagementList({ ...searchForm.value, ...page }).then(res => {
tableLoading.value = false;
- tableData.value = (res?.data?.records || []).map((row) => ({
- ...row,
- truckPlateDisplay: String(row?.shippingType) === "1" ? (row?.truckPlateNo || "--") : "--",
- expressCompanyDisplay: String(row?.shippingType) === "2" ? (row?.expressCompany || "--") : "--",
- expressNoDisplay: String(row?.shippingType) === "2" ? (row?.expressNo || "--") : "--",
- }));
+ tableData.value = res?.data?.records || [];
page.total = res?.data?.total || 0;
}).finally(() => tableLoading.value = false);
};
@@ -221,24 +203,6 @@
const statusMap = {
0: "寰呭鐞�",
1: "宸插鐞�"
- };
- return statusMap[status] || "鏈煡";
-};
-
-const getStockInApprovalStatusType = (status) => {
- const statusMap = {
- 0: "",
- 1: "success",
- 2: "warning"
- };
- return statusMap[status] || "info";
-};
-
-const getStockInApprovalStatusText = (status) => {
- const statusMap = {
- 0: "鏈鎵�",
- 1: "宸插鎵�",
- 2: "瀹℃壒涓�"
};
return statusMap[status] || "鏈煡";
};
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index d2e82b5..9362a18 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -1,47 +1,42 @@
<template>
<div class="app-container">
<div class="search_form">
- <el-form :model="searchForm" :inline="true">
+ <el-form :model="searchForm"
+ :inline="true">
<el-form-item label="瀹㈡埛鍚嶇О锛�">
- <el-input
- v-model="searchForm.customerName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery"
- />
+ <el-input v-model="searchForm.customerName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="閿�鍞悎鍚屽彿锛�">
- <el-input
- v-model="searchForm.salesContractNo"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery"
- />
+ <el-input v-model="searchForm.salesContractNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="椤圭洰鍚嶇О锛�">
- <el-input
- v-model="searchForm.projectName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery"
- />
+ <el-input v-model="searchForm.projectName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
- <el-date-picker
- v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange"
- />
+ <el-date-picker v-model="searchForm.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="daterange"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="changeDaterange" />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
+ <el-button type="primary"
+ @click="handleQuery"> 鎼滅储
+ </el-button>
</el-form-item>
</el-form>
</div>
@@ -49,137 +44,139 @@
<div class="actions">
<div></div>
<div>
- <el-button type="primary" @click="openForm('add')">
+ <el-button type="primary"
+ @click="openForm('add')">
鏂板鍙拌处
</el-button>
- <el-button type="primary" plain @click="handleImport"
- >瀵煎叆
+ <el-button type="primary"
+ plain
+ @click="handleImport">瀵煎叆
</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎 </el-button>
- <el-button type="primary" plain @click="handlePrint">鎵撳嵃 </el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎
+ </el-button>
+ <el-button type="primary"
+ plain
+ @click="handlePrint">鎵撳嵃
+ </el-button>
</div>
</div>
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- :row-class-name="tableRowClassName"
- show-summary
- style="width: 100%"
- :summary-method="summarizeMainTable"
- @expand-change="expandChange"
- height="calc(100vh - 18.5em)"
- >
- <el-table-column
- align="center"
- type="selection"
- width="55"
- fixed="left"
- />
- <el-table-column type="expand" width="60" fixed="left">
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ :row-class-name="tableRowClassName"
+ show-summary
+ style="width: 100%"
+ :summary-method="summarizeMainTable"
+ @expand-change="expandChange"
+ height="calc(100vh - 18.5em)">
+ <el-table-column align="center"
+ type="selection"
+ width="55"
+ fixed="left" />
+ <el-table-column type="expand"
+ width="60"
+ fixed="left">
<template #default="props">
- <el-table
- :data="props.row.children"
- border
- show-summary
- :summary-method="
- (param) => summarizeChildrenTable(param, props.row)
- "
- >
- <el-table-column align="center" label="搴忓彿" type="index" />
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="浜у搧鐘舵��" width="100px" align="center">
+ <el-table :data="props.row.children"
+ border
+ show-summary
+ :summary-method="(param) => summarizeChildrenTable(param, props.row)">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="specificationModel" />
+ <el-table-column label="鍗曚綅"
+ prop="unit" />
+ <el-table-column label="浜у搧鐘舵��"
+ width="100px"
+ align="center">
<template #default="scope">
- <el-tag v-if="scope.row.approveStatus === 1" type="success"
- >鍏呰冻
+ <el-tag v-if="scope.row.approveStatus === 1 "
+ type="success">鍏呰冻
</el-tag>
- <el-tag
- v-else-if="
- scope.row.approveStatus === 0 &&
- scope.row.noQuantity === 0
- "
- type="success"
- >宸插嚭搴�
+ <el-tag v-else-if="scope.row.approveStatus === 0 && scope.row.noQuantity === 0"
+ type="success">宸插嚭搴�
</el-tag>
- <el-tag v-else type="danger">涓嶈冻 </el-tag>
+ <el-tag v-else
+ type="danger">涓嶈冻
+ </el-tag>
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鐘舵��" width="140" align="center">
+ <el-table-column label="鍙戣揣鐘舵��"
+ width="140"
+ align="center">
<template #default="scope">
- <el-tag :type="getShippingStatusType(scope.row)" size="small">
+ <el-tag :type="getShippingStatusType(scope.row)"
+ size="small">
{{ getShippingStatusText(scope.row) }}
</el-tag>
</template>
</el-table-column>
- <el-table-column label="瀹℃壒涓暟閲�" width="120" align="center">
- <template #default="scope">
- <span>{{ scope.row.pendingApprovalQuantity || 0 }}</span>
- </template>
- </el-table-column>
- <el-table-column
- label="蹇�掑叕鍙�"
- prop="expressCompany"
- show-overflow-tooltip
- />
- <el-table-column
- label="蹇�掑崟鍙�"
- prop="expressNumber"
- show-overflow-tooltip
- />
- <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
+ <el-table-column label="蹇�掑叕鍙�"
+ prop="expressCompany"
+ show-overflow-tooltip />
+ <el-table-column label="蹇�掑崟鍙�"
+ prop="expressNumber"
+ show-overflow-tooltip />
+ <el-table-column label="鍙戣揣杞︾墝"
+ minWidth="100px"
+ align="center">
<template #default="scope">
<div>
- <el-tag type="success" v-if="scope.row.shippingCarNumber"
- >{{ scope.row.shippingCarNumber }}
+ <el-tag type="success"
+ v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}
</el-tag>
- <el-tag v-else type="info">- </el-tag>
+ <el-tag v-else
+ type="info">-
+ </el-tag>
</div>
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鏃ユ湡" minWidth="100px" align="center">
+ <el-table-column label="鍙戣揣鏃ユ湡"
+ minWidth="100px"
+ align="center">
<template #default="scope">
<div>
- <div v-if="scope.row.shippingDate">
- {{ scope.row.shippingDate }}
- </div>
- <el-tag v-else type="info">- </el-tag>
+ <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
+ <el-tag v-else
+ type="info">-
+ </el-tag>
</div>
</template>
</el-table-column>
- <el-table-column label="鏁伴噺" prop="quantity" />
- <el-table-column label="閫�璐ф暟閲�" prop="returnQuantity" />
- <el-table-column label="寰呭彂璐ф暟閲�" prop="noQuantity" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" />
- <el-table-column
- label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="sensitiveAmountFormatter"
- />
- <el-table-column
- label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="sensitiveAmountFormatter"
- />
- <el-table-column
- label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="sensitiveAmountFormatter"
- />
+ <el-table-column label="鏁伴噺"
+ prop="quantity" />
+ <el-table-column label="寰呭彂璐ф暟閲�"
+ prop="noQuantity" />
+ <el-table-column label="绋庣巼(%)"
+ prop="taxRate" />
+ <el-table-column label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="sensitiveAmountFormatter" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="sensitiveAmountFormatter" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="sensitiveAmountFormatter" />
<!--鎿嶄綔-->
- <el-table-column Width="60px" label="鎿嶄綔" align="center">
+ <el-table-column Width="60px"
+ label="鎿嶄綔"
+ align="center">
<template #default="scope">
- <el-button
- link
- type="primary"
- :disabled="!canShip(scope.row)"
- @click="openDeliveryForm(scope.row)"
- >
+ <el-button link
+ type="primary"
+ :disabled="!canShip(scope.row)"
+ @click="openDeliveryForm(scope.row)">
鍙戣揣
</el-button>
</template>
@@ -187,696 +184,598 @@
</el-table>
</template>
</el-table-column>
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column
- label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- width="180"
- show-overflow-tooltip
- />
- <el-table-column
- label="瀹㈡埛鍚嶇О"
- prop="customerName"
- width="300"
- show-overflow-tooltip
- />
- <el-table-column
- label="涓氬姟鍛�"
- prop="salesman"
- width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="椤圭洰鍚嶇О"
- prop="projectName"
- width="180"
- show-overflow-tooltip
- />
- <el-table-column
- label="浠樻鏂瑰紡"
- prop="paymentMethod"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍚堝悓閲戦(鍏�)"
- prop="contractAmount"
- width="220"
- show-overflow-tooltip
- :formatter="formattedNumber"
- />
- <el-table-column
- label="瀹為檯鍚堝悓閲戦(鍏�)"
- prop="netContractAmount"
- width="220"
- show-overflow-tooltip
- :formatter="formattedNumber"
- />
- <el-table-column
- label="褰曞叆浜�"
- prop="entryPersonName"
- width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="褰曞叆鏃ユ湡"
- prop="entryDate"
- width="120"
- show-overflow-tooltip
- />
- <el-table-column
- label="绛捐鏃ユ湡"
- prop="executionDate"
- width="120"
- show-overflow-tooltip
- />
- <el-table-column
- label="浜や粯鏃ユ湡"
- prop="deliveryDate"
- width="120"
- show-overflow-tooltip
- />
- <el-table-column
- label="澶囨敞"
- prop="remarks"
- width="200"
- show-overflow-tooltip
- />
- <el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="閿�鍞悎鍚屽彿"
+ prop="salesContractNo"
+ width="180"
+ show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛鍚嶇О"
+ prop="customerName"
+ width="300"
+ show-overflow-tooltip />
+ <el-table-column label="涓氬姟鍛�"
+ prop="salesman"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="椤圭洰鍚嶇О"
+ prop="projectName"
+ width="180"
+ show-overflow-tooltip />
+ <el-table-column label="浠樻鏂瑰紡"
+ prop="paymentMethod"
+ show-overflow-tooltip />
+ <el-table-column label="鍚堝悓閲戦(鍏�)"
+ prop="contractAmount"
+ width="220"
+ show-overflow-tooltip
+ :formatter="formattedNumber" />
+ <el-table-column label="褰曞叆浜�"
+ prop="entryPersonName"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="褰曞叆鏃ユ湡"
+ prop="entryDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="绛捐鏃ユ湡"
+ prop="executionDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="浜や粯鏃ユ湡"
+ prop="deliveryDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="澶囨敞"
+ prop="remarks"
+ width="200"
+ show-overflow-tooltip />
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="220"
+ align="center">
<template #default="scope">
- <el-button link type="primary" @click="openForm('view', scope.row)"
- >璇︽儏
+ <el-button link
+ type="primary"
+ @click="openForm('view', scope.row)">璇︽儏
</el-button>
- <el-button
- link
- type="primary"
- @click="openForm('edit', scope.row)"
- :disabled="
- !scope.row.isEdit ||
- scope.row.hasProductionRecord ||
- !canEditLedger(scope.row)
- "
- >缂栬緫
+ <el-button link
+ type="primary"
+ @click="openForm('edit', scope.row)"
+ :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">缂栬緫
</el-button>
- <el-button link type="primary" @click="openFileDialog(scope.row)"
- >闄勪欢
- </el-button>
+ <el-button link
+ type="primary"
+ @click="openFileDialog(scope.row)">闄勪欢
+ </el-button> <!--downloadOrder(scope.row.id) 涓嬭浇-->
</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"
- />
+ <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="
- operationType === 'add'
- ? '鏂板閿�鍞彴璐﹂〉闈�'
- : operationType === 'edit'
- ? '缂栬緫閿�鍞彴璐﹂〉闈�'
- : '閿�鍞彴璐﹁鎯�'
- "
- :width="'70%'"
- :operation-type="operationType"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia"
- >
- <el-form
- :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef"
- >
+ <FormDialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : (operationType === 'edit' ? '缂栬緫閿�鍞彴璐﹂〉闈�' : '閿�鍞彴璐﹁鎯�')"
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
+ <el-form :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
<!-- 鎶ヤ环鍗曞鍏ュ叆鍙o細鏀惧湪琛ㄥ崟椤堕儴锛岄�夋嫨鍚庡弽鏄惧鎴�/涓氬姟鍛樼瓑 -->
- <el-row v-if="operationType === 'add'" style="margin-bottom: 10px">
- <el-col :span="24" style="text-align: right">
- <el-button type="primary" plain @click="openQuotationDialog">
+ <el-row v-if="operationType === 'add'"
+ style="margin-bottom: 10px;">
+ <el-col :span="24"
+ style="text-align: right;">
+ <el-button type="primary"
+ plain
+ @click="openQuotationDialog">
浠庨攢鍞姤浠峰鍏�
</el-button>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
- <div
- style="
- display: flex;
- align-items: center;
- gap: 12px;
- width: 100%;
- "
- >
- <el-checkbox
- v-model="form.autoGenerateContractNo"
- v-if="operationType === 'add'"
- >鑷姩鐢熸垚
+ <el-form-item label="閿�鍞悎鍚屽彿锛�"
+ prop="salesContractNo">
+ <div style="display: flex; align-items: center; gap: 12px;width: 100%;">
+ <el-checkbox v-model="form.autoGenerateContractNo"
+ v-if="operationType === 'add'">鑷姩鐢熸垚
</el-checkbox>
- <el-input
- v-model="form.salesContractNo"
- :placeholder="
- form.autoGenerateContractNo ? '淇濆瓨鍚庤嚜鍔ㄧ敓鎴�' : '璇疯緭鍏�'
- "
- clearable
- :disabled="
- form.autoGenerateContractNo || operationType === 'view'
- "
- />
+ <el-input v-model="form.salesContractNo"
+ :placeholder="form.autoGenerateContractNo ? '鑷姩鐢熸垚' : '璇疯緭鍏�'"
+ clearable
+ :disabled="form.autoGenerateContractNo || operationType === 'view'" />
</div>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="涓氬姟鍛橈細" prop="salesman">
- <el-select
- v-model="form.salesman"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- filterable
- >
- <el-option
- v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName"
- />
+ <el-form-item label="涓氬姟鍛橈細"
+ prop="salesman">
+ <el-select v-model="form.salesman"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ filterable>
+ <el-option v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerId">
- <el-select
- v-model="form.customerId"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- filterable
- >
- <el-option
- v-for="item in customerOption"
- :key="item.id"
- :label="item.customerName"
- :value="item.id"
- >
+ <el-form-item label="瀹㈡埛鍚嶇О锛�"
+ prop="customerId">
+ <el-select v-model="form.customerId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ filterable>
+ <el-option v-for="item in customerOption"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id">
{{
- item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
+ item.taxpayerIdentificationNumber ? item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber : item.customerName
}}
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
- <el-input
- v-model="form.projectName"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="operationType === 'view'"
- />
+ <el-form-item label="椤圭洰鍚嶇О锛�"
+ prop="projectName">
+ <el-input v-model="form.projectName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.executionDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- />
+ <el-form-item label="绛捐鏃ユ湡锛�"
+ prop="executionDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.executionDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡">
- <el-input
- v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="operationType === 'view'"
- />
+ <el-input v-model="form.paymentMethod"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="褰曞叆浜猴細" prop="entryPerson">
- <el-select
- v-model="form.entryPerson"
- filterable
- default-first-option
- :reserve-keyword="false"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- @change="changs"
- >
- <el-option
- v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId"
- />
+ <el-form-item label="褰曞叆浜猴細"
+ prop="entryPerson">
+ <el-select v-model="form.entryPerson"
+ filterable
+ default-first-option
+ :reserve-keyword="false"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ @change="changs">
+ <el-option v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId" />
</el-select>
</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"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- />
+ <el-form-item label="褰曞叆鏃ユ湡锛�"
+ prop="entryDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="浜よ揣鏃ユ湡锛�" prop="entryDate">
- <el-date-picker
- style="width: 100%"
- v-model="form.deliveryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- />
+ <el-form-item label="浜よ揣鏃ユ湡锛�"
+ prop="entryDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.deliveryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
<el-row>
- <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
- <el-button
- v-if="operationType !== 'view'"
- type="primary"
- @click="openProductForm('add')"
- >娣诲姞
+ <el-form-item label="浜у搧淇℃伅锛�"
+ prop="entryDate">
+ <el-button v-if="operationType !== 'view'"
+ type="primary"
+ @click="openProductForm('add')">娣诲姞
</el-button>
- <el-button
- v-if="operationType !== 'view'"
- plain
- type="danger"
- @click="deleteProduct"
- >鍒犻櫎
+ <el-button v-if="operationType !== 'view'"
+ plain
+ type="danger"
+ @click="deleteProduct">鍒犻櫎
</el-button>
</el-form-item>
</el-row>
- <el-table
- :data="productData"
- border
- @selection-change="productSelected"
- show-summary
- :summary-method="summarizeMainTable"
- >
- <el-table-column
- align="center"
- type="selection"
- width="55"
- v-if="operationType !== 'view'"
- :selectable="(row) => !isProductShipped(row)"
- />
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="鏁伴噺" prop="quantity" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" />
- <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="isProduction" width="150">
+ <el-table :data="productData"
+ border
+ @selection-change="productSelected"
+ show-summary
+ :summary-method="summarizeMainTable">
+ <el-table-column align="center"
+ type="selection"
+ width="55"
+ v-if="operationType !== 'view'"
+ :selectable="(row) => !isProductShipped(row)" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="specificationModel" />
+ <el-table-column label="鍗曚綅"
+ prop="unit" />
+ <el-table-column label="鏁伴噺"
+ prop="quantity" />
+ <el-table-column label="绋庣巼(%)"
+ prop="taxRate" />
+ <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="isProduction"
+ width="150">
<template #default="scope">
<el-tag :type="scope.row.isProduction ? 'success' : 'info'">
- {{ scope.row.isProduction ? "鏄�" : "鍚�" }}
+ {{ scope.row.isProduction ? '鏄�' : '鍚�' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column
- fixed="right"
- label="鎿嶄綔"
- min-width="60"
- align="center"
- v-if="operationType !== 'view'"
- >
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ min-width="60"
+ align="center"
+ v-if="operationType !== 'view'">
<template #default="scope">
- <el-button
- link
- type="primary"
- size="small"
- :disabled="isProductShipped(scope.row)"
- @click="openProductForm('edit', scope.row, scope.$index)"
- >缂栬緫
+ <el-button link
+ type="primary"
+ size="small"
+ :disabled="isProductShipped(scope.row)"
+ @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫
</el-button>
</template>
</el-table-column>
</el-table>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="澶囨敞锛�" prop="remarks">
- <el-input
- v-model="form.remarks"
- placeholder="璇疯緭鍏�"
- clearable
- type="textarea"
- :rows="2"
- :disabled="operationType === 'view'"
- />
+ <el-form-item label="澶囨敞锛�"
+ prop="remarks">
+ <el-input v-model="form.remarks"
+ placeholder="璇疯緭鍏�"
+ clearable
+ type="textarea"
+ :rows="2"
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
- <el-row v-if="operationType !== 'view'" :gutter="30">
+ <el-row v-if="operationType !== 'view'"
+ :gutter="30">
<el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�" prop="salesLedgerFiles">
- <FileUpload
- v-model:file-list="fileList"
- :disabled="operationType === 'view'"
- />
+ <el-form-item label="闄勪欢鏉愭枡锛�"
+ prop="salesLedgerFiles">
+ <FileUpload v-model:file-list="fileList"
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</FormDialog>
<!-- 浠庢姤浠峰崟瀵煎叆锛堜粎瀹℃壒閫氳繃锛� -->
- <el-dialog
- v-model="quotationDialogVisible"
- title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
- width="80%"
- :close-on-click-modal="false"
- >
- <div
- style="
- margin-bottom: 12px;
- display: flex;
- gap: 12px;
- align-items: center;
- "
- >
- <el-input
- v-model="quotationSearchForm.quotationNo"
- placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
- clearable
- style="max-width: 260px"
- @change="fetchQuotationList"
- />
- <el-input
- v-model="quotationSearchForm.customer"
- placeholder="璇疯緭鍏ュ鎴峰悕绉�"
- clearable
- style="max-width: 260px"
- @change="fetchQuotationList"
- />
- <el-button type="primary" @click="fetchQuotationList">鎼滅储 </el-button>
+ <el-dialog v-model="quotationDialogVisible"
+ title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
+ width="80%"
+ :close-on-click-modal="false">
+ <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
+ <el-input v-model="quotationSearchForm.quotationNo"
+ placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
+ clearable
+ style="max-width: 260px;"
+ @change="fetchQuotationList" />
+ <el-input v-model="quotationSearchForm.customer"
+ placeholder="璇疯緭鍏ュ鎴峰悕绉�"
+ clearable
+ style="max-width: 260px;"
+ @change="fetchQuotationList" />
+ <el-button type="primary"
+ @click="fetchQuotationList">鎼滅储
+ </el-button>
<el-button @click="resetQuotationSearch">閲嶇疆</el-button>
</div>
- <el-table
- :data="quotationList"
- border
- stripe
- v-loading="quotationLoading"
- height="420px"
- >
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column
- prop="quotationNo"
- label="鎶ヤ环鍗曞彿"
- width="180"
- show-overflow-tooltip
- />
- <el-table-column
- prop="customer"
- label="瀹㈡埛鍚嶇О"
- min-width="220"
- show-overflow-tooltip
- />
- <el-table-column
- prop="salesperson"
- label="涓氬姟鍛�"
- width="120"
- show-overflow-tooltip
- />
- <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="140" />
- <el-table-column
- prop="status"
- label="瀹℃壒鐘舵��"
- width="120"
- align="center"
- />
- <el-table-column
- prop="totalAmount"
- label="鎶ヤ环閲戦(鍏�)"
- width="160"
- align="right"
- >
+ <el-table :data="quotationList"
+ border
+ stripe
+ v-loading="quotationLoading"
+ height="420px">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column prop="quotationNo"
+ label="鎶ヤ环鍗曞彿"
+ width="180"
+ show-overflow-tooltip />
+ <el-table-column prop="customer"
+ label="瀹㈡埛鍚嶇О"
+ min-width="220"
+ show-overflow-tooltip />
+ <el-table-column prop="salesperson"
+ label="涓氬姟鍛�"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column prop="quotationDate"
+ label="鎶ヤ环鏃ユ湡"
+ width="140" />
+ <el-table-column prop="status"
+ label="瀹℃壒鐘舵��"
+ width="120"
+ align="center" />
+ <el-table-column prop="totalAmount"
+ label="鎶ヤ环閲戦(鍏�)"
+ width="160"
+ align="right">
<template #default="scope">
- {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
+ {{ formatDecimal(scope.row.totalAmount) }}
</template>
</el-table-column>
- <el-table-column fixed="right" label="鎿嶄綔" width="120" align="center">
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="120"
+ align="center">
<template #default="scope">
- <el-button type="primary" link @click="applyQuotation(scope.row)"
- >閫夋嫨
+ <el-button type="primary"
+ link
+ @click="applyQuotation(scope.row)">閫夋嫨
</el-button>
</template>
</el-table-column>
</el-table>
- <pagination
- v-show="quotationPage.total > 0"
- :total="quotationPage.total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="quotationPage.current"
- :limit="quotationPage.size"
- @pagination="quotationPaginationChange"
- />
+ <pagination v-show="quotationPage.total > 0"
+ :total="quotationPage.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="quotationPage.current"
+ :limit="quotationPage.size"
+ @pagination="quotationPaginationChange" />
<template #footer>
<el-button @click="quotationDialogVisible = false">鍏抽棴</el-button>
</template>
</el-dialog>
- <FormDialog
- v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia"
- >
- <el-form
- :model="productForm"
- label-width="140px"
- label-position="top"
- :rules="productRules"
- ref="productFormRef"
- >
+ <FormDialog v-model="productFormVisible"
+ :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
+ :width="'40%'"
+ :operation-type="productOperationType"
+ @close="closeProductDia"
+ @confirm="submitProduct"
+ @cancel="closeProductDia">
+ <el-form :model="productForm"
+ label-width="140px"
+ label-position="top"
+ :rules="productRules"
+ ref="productFormRef">
<el-row :gutter="30">
- <el-col :span="24">
+ <el-col :span="12">
<el-form-item label="浜у搧澶х被锛�" prop="productCategory">
- <el-tree-select
- v-model="productForm.productCategory"
- placeholder="璇烽�夋嫨"
- clearable
- filterable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%"
- />
+ <el-input v-model="productForm.productCategory"
+ placeholder="鐐瑰嚮閫夋嫨"
+ readonly
+ @click="showProductSelectDialog = true"
+ style="cursor:pointer" />
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
+ <el-col :span="12">
<el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
- <el-select
- v-model="productForm.productModelId"
- placeholder="璇烽�夋嫨"
- clearable
- @change="getProductModel"
- filterable
- >
- <el-option
- v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id"
- />
+ <el-input v-model="productForm.specificationModel"
+ placeholder="鐐瑰嚮閫夋嫨"
+ readonly
+ @click="showProductSelectDialog = true"
+ style="cursor:pointer" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�"
+ prop="unit">
+ <el-input v-model="productForm.unit"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绋庣巼(%)锛�"
+ prop="taxRate">
+ <el-select v-model="productForm.taxRate"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="calculateFromTaxRate">
+ <el-option v-for="dict in tax_rate"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍗曚綅锛�" prop="unit">
- <el-input
- v-model="productForm.unit"
- placeholder="璇疯緭鍏�"
- clearable
- />
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
+ prop="taxInclusiveUnitPrice">
+ <el-input-number :step="0.000001"
+ :min="0"
+ v-model="productForm.taxInclusiveUnitPrice"
+ style="width: 100%"
+ :precision="6"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromUnitPrice" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绋庣巼(%)锛�" prop="taxRate">
- <el-select
- v-model="productForm.taxRate"
- placeholder="璇烽�夋嫨"
- clearable
- @change="calculateFromTaxRate"
- >
- <el-option
- v-for="dict in tax_rate"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
+ <el-form-item label="鏁伴噺锛�"
+ prop="quantity">
+ <el-input-number :step="0.1"
+ :min="0"
+ v-model="productForm.quantity"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :precision="2"
+ @change="calculateFromQuantity"
+ style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
- <el-input-number
- :step="0.01"
- :min="0"
- v-model="productForm.taxInclusiveUnitPrice"
- style="width: 100%"
- :precision="2"
- placeholder="璇疯緭鍏�"
- clearable
- @change="calculateFromUnitPrice"
- />
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�"
+ prop="taxInclusiveTotalPrice">
+ <el-input v-model="productForm.taxInclusiveTotalPrice"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromTotalPrice" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏁伴噺锛�" prop="quantity">
- <el-input-number
- :step="0.1"
- :min="0"
- v-model="productForm.quantity"
- placeholder="璇疯緭鍏�"
- clearable
- :precision="2"
- @change="calculateFromQuantity"
- style="width: 100%"
- />
+ <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
+ prop="taxExclusiveTotalPrice">
+ <el-input v-model="productForm.taxExclusiveTotalPrice"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromExclusiveTotalPrice" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
- <el-input
- v-model="productForm.taxInclusiveTotalPrice"
- placeholder="璇疯緭鍏�"
- clearable
- @change="calculateFromTotalPrice"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item
- label="涓嶅惈绋庢�讳环(鍏�)锛�"
- prop="taxExclusiveTotalPrice"
- >
- <el-input
- v-model="productForm.taxExclusiveTotalPrice"
- placeholder="璇疯緭鍏�"
- clearable
- @change="calculateFromExclusiveTotalPrice"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
- <el-select
- v-model="productForm.invoiceType"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
- <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
+ <el-form-item label="鍙戠エ绫诲瀷锛�"
+ prop="invoiceType">
+ <el-select v-model="productForm.invoiceType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="澧炴櫘绁�"
+ value="澧炴櫘绁�" />
+ <el-option label="澧炰笓绁�"
+ value="澧炰笓绁�" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏄惁鐢熶骇锛�" prop="isProduction">
+ <el-form-item label="鏄惁鐢熶骇锛�"
+ prop="isProduction">
+ <div style="display: flex; align-items: center; width: 100%;">
<el-radio-group v-model="productForm.isProduction">
- <el-radio label="鏄�" :value="true" />
- <el-radio label="鍚�" :value="false" />
+ <el-radio label="鏄�"
+ :value="true" />
+ <el-radio label="鍚�"
+ :value="false" />
</el-radio-group>
+ <div
+ v-if="currentStock !== null"
+ :style="{
+ marginLeft: '20px',
+ padding: '0 12px',
+ height: '28px',
+ lineHeight: '28px',
+ borderRadius: '4px',
+ fontSize: '13px',
+ fontWeight: '500',
+ display: 'inline-block',
+ whiteSpace: 'nowrap',
+ backgroundColor: (productForm.quantity || 0) > currentStock ? '#fff0f0' : '#f0f9eb',
+ border: (productForm.quantity || 0) > currentStock ? '1px solid #ffcccc' : '1px solid #e1f3d8',
+ color: (productForm.quantity || 0) > currentStock ? '#f56c6c' : '#67c23a'
+ }"
+ >
+ <span>褰撳墠搴撳瓨锛歿{ currentStock }} {{ productForm.unit || '' }}</span>
+ </div>
+ </div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</FormDialog>
+ <ProductSelectDialog v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single />
<!-- 瀵煎叆寮圭獥 -->
- <FormDialog
- v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false"
- >
- <el-upload
- ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag
- >
+ <FormDialog v-model="importUpload.open"
+ :title="importUpload.title"
+ :width="'600px'"
+ @close="importUpload.open = false"
+ @confirm="submitImportFile"
+ @cancel="importUpload.open = false">
+ <el-upload ref="importUploadRef"
+ :limit="1"
+ accept=".xlsx,.xls"
+ :action="importUpload.url"
+ :headers="importUpload.headers"
+ :before-upload="importUpload.beforeUpload"
+ :on-success="importUpload.onSuccess"
+ :on-error="importUpload.onError"
+ :on-progress="importUpload.onProgress"
+ :on-change="importUpload.onChange"
+ :auto-upload="false"
+ drag>
<i class="el-icon-upload"></i>
- <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+ <div class="el-upload__text">
+ 灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
+ </div>
<template #tip>
<div class="el-upload__tip">
浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link type="primary" @click="downloadTemplate"
- >涓嬭浇瀵煎叆妯℃澘
+ <el-button link
+ type="primary"
+ @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘
</el-button>
</div>
</template>
@@ -884,50 +783,35 @@
</FormDialog>
<!-- // todo 闄勪欢棰勮鐩稿叧 -->
<!-- 闄勪欢鍒楄〃寮圭獥 -->
- <FileList
- v-if="fileDialogVisible"
- v-model:visible="fileDialogVisible"
- record-type="sales_ledger"
- :record-id="recordId"
- />
+ <FileList v-if="fileDialogVisible"
+ v-model:visible="fileDialogVisible"
+ record-type="sales_ledger"
+ :record-id="recordId" />
<!-- 鎵撳嵃棰勮寮圭獥 -->
- <el-dialog
- v-model="printPreviewVisible"
- title="鎵撳嵃棰勮"
- width="90%"
- :close-on-click-modal="false"
- class="print-preview-dialog"
- >
+ <el-dialog v-model="printPreviewVisible"
+ title="鎵撳嵃棰勮"
+ width="90%"
+ :close-on-click-modal="false"
+ class="print-preview-dialog">
<div class="print-preview-container">
<div class="print-preview-header">
- <el-button type="primary" @click="executePrint">鎵ц鎵撳嵃 </el-button>
+ <el-button type="primary"
+ @click="executePrint">鎵ц鎵撳嵃
+ </el-button>
<el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
</div>
<div class="print-preview-content">
- <div
- v-if="printData.length === 0"
- style="text-align: center; padding: 50px; color: #999"
- >
+ <div v-if="printData.length === 0"
+ style="text-align: center; padding: 50px; color: #999;">
鏆傛棤鎵撳嵃鏁版嵁
</div>
- <div
- v-else
- style="
- text-align: center;
- padding: 10px;
- color: #666;
- font-size: 14px;
- background: #e8f4fd;
- margin-bottom: 10px;
- "
- >
+ <div v-else
+ style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
</div>
- <div
- v-for="(item, index) in printData"
- :key="index"
- class="print-page"
- >
+ <div v-for="(item, index) in printData"
+ :key="index"
+ class="print-page">
<div class="delivery-note">
<div class="header">
<div class="document-title">闆跺敭鍙戣揣鍗�</div>
@@ -965,17 +849,18 @@
</tr>
</thead>
<tbody>
- <tr v-for="product in item.products" :key="product.id">
- <td>{{ product.productCategory || "" }}</td>
- <td>{{ product.specificationModel || "" }}</td>
- <td>{{ product.unit || "" }}</td>
- <td>{{ product.taxInclusiveUnitPrice || "0" }}</td>
- <td>{{ product.quantity || "0" }}</td>
- <td>{{ product.taxInclusiveTotalPrice || "0" }}</td>
+ <tr v-for="product in item.products"
+ :key="product.id">
+ <td>{{ product.productCategory || '' }}</td>
+ <td>{{ product.specificationModel || '' }}</td>
+ <td>{{ product.unit || '' }}</td>
+ <td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
+ <td>{{ product.quantity || '0' }}</td>
+ <td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
</tr>
<tr v-if="!item.products || item.products.length === 0">
- <td colspan="6" style="text-align: center; color: #999">
- 鏆傛棤浜у搧鏁版嵁
+ <td colspan="6"
+ style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁
</td>
</tr>
</tbody>
@@ -985,12 +870,8 @@
<td class="total-value"></td>
<td class="total-value"></td>
<td class="total-value"></td>
- <td class="total-value">
- {{ getTotalQuantity(item.products) }}
- </td>
- <td class="total-value">
- {{ getTotalAmount(item.products) }}
- </td>
+ <td class="total-value">{{ getTotalQuantity(item.products) }}</td>
+ <td class="total-value">{{ getTotalAmount(item.products) }}</td>
</tr>
</tfoot>
</table>
@@ -1013,9 +894,7 @@
<div class="footer-row">
<div class="footer-item">
<span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">{{
- userStore.nickName || "鎾曞紑鍓�"
- }}</span>
+ <span class="value">{{ userStore.nickName || '鎾曞紑鍓�' }}</span>
</div>
<div class="footer-item">
<span class="label">鎵撳嵃鏃ユ湡锛�</span>
@@ -1029,127 +908,116 @@
</div>
</el-dialog>
<!-- 鍙戣揣寮规 -->
- <el-dialog
- v-model="deliveryFormVisible"
- title="鍙戣揣淇℃伅"
- width="40%"
- @close="closeDeliveryDia"
- >
- <el-form
- :model="deliveryForm"
- label-width="120px"
- label-position="top"
- :rules="deliveryRules"
- ref="deliveryFormRef"
- >
+ <el-dialog v-model="deliveryFormVisible"
+ title="鍙戣揣淇℃伅"
+ width="40%"
+ @close="closeDeliveryDia">
+ <el-form :model="deliveryForm"
+ label-width="120px"
+ label-position="top"
+ :rules="deliveryRules"
+ ref="deliveryFormRef">
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="鍙戣揣绫诲瀷锛�" prop="type">
- <el-select
- v-model="deliveryForm.type"
- placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 100%"
- @change="handleDeliveryTypeChange"
- >
- <el-option label="璐ц溅" value="璐ц溅" />
- <el-option label="蹇��" value="蹇��" />
+ <el-form-item label="鍙戣揣绫诲瀷锛�"
+ prop="type">
+ <el-select v-model="deliveryForm.type"
+ placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
+ style="width: 100%"
+ @change="handleDeliveryTypeChange">
+ <el-option label="璐ц溅"
+ value="璐ц溅" />
+ <el-option label="蹇��"
+ value="蹇��" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="寰呭彂璐ф暟閲忥細">
- <el-input
- :model-value="currentDeliveryRow?.noQuantity"
- disabled
- />
+ <el-input :model-value="currentDeliveryRow?.noQuantity"
+ disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="24" v-if="deliveryForm.type === '璐ц溅'">
- <el-form-item label="鍙戣揣杞︾墝鍙凤細" prop="shippingCarNumber">
- <el-input
- v-model="deliveryForm.shippingCarNumber"
- placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
- clearable
- />
+ <el-col :span="24"
+ v-if="deliveryForm.type === '璐ц溅'">
+ <el-form-item label="鍙戣揣杞︾墝鍙凤細"
+ prop="shippingCarNumber">
+ <el-input v-model="deliveryForm.shippingCarNumber"
+ placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
+ clearable />
</el-form-item>
</el-col>
- <el-col :span="24" v-else>
- <el-form-item label="蹇�掑叕鍙革細" prop="expressCompany">
- <el-input
- v-model="deliveryForm.expressCompany"
- placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
- clearable
- />
+ <el-col :span="24"
+ v-else>
+ <el-form-item label="蹇�掑叕鍙革細"
+ prop="expressCompany">
+ <el-input v-model="deliveryForm.expressCompany"
+ placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
+ clearable />
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30" v-if="deliveryForm.type === '蹇��'">
+ <el-row :gutter="30"
+ v-if="deliveryForm.type === '蹇��'">
<el-col :span="24">
- <el-form-item label="蹇�掑崟鍙凤細" prop="expressNumber">
- <el-input
- v-model="deliveryForm.expressNumber"
- placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
- clearable
- />
+ <el-form-item label="蹇�掑崟鍙凤細"
+ prop="expressNumber">
+ <el-input v-model="deliveryForm.expressNumber"
+ placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+ clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="鍙戣揣鍥剧墖锛�">
- <ImageUpload v-model:file-list="deliveryFileList" :limit="9" />
+ <ImageUpload v-model:file-list="deliveryFileList"
+ :limit="9" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="搴撳瓨锛�" prop="batchNo">
- <el-table
- :data="deliveryForm.batchNoList"
- border
- size="small"
- max-height="260"
- style="width: 100%"
- >
- <el-table-column label="鎵瑰彿" prop="batchNo" min-width="180" />
- <el-table-column
- label="浜у搧澶х被"
- prop="productName"
- min-width="100"
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="model"
- min-width="100"
- />
- <el-table-column label="鍗曚綅" prop="unit" min-width="100" />
- <el-table-column
- label="搴撳瓨鏁伴噺"
- min-width="120"
- align="center"
- >
+ <el-form-item label="搴撳瓨锛�"
+ prop="batchNo">
+ <el-table :data="deliveryForm.batchNoList"
+ border
+ size="small"
+ max-height="260"
+ style="width: 100%;">
+ <el-table-column label="鎵瑰彿"
+ prop="batchNo"
+ min-width="180" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productName"
+ min-width="100" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="model"
+ min-width="100" />
+ <el-table-column label="鍗曚綅"
+ prop="unit"
+ min-width="100" />
+ <el-table-column label="搴撳瓨鏁伴噺"
+ min-width="120"
+ align="center">
<template #default="scope">
{{ getDeliveryBatchQuantity(scope.row) }}
</template>
</el-table-column>
- <el-table-column
- label="鍙戣揣鏁伴噺"
- min-width="160"
- align="center"
- >
+ <el-table-column label="鍙戣揣鏁伴噺"
+ min-width="160"
+ align="center">
<template #default="scope">
- <el-input-number
- v-model="scope.row.deliveryQuantity"
- :min="0"
- :max="getDeliveryBatchDeliveryMax(scope.row)"
- :precision="2"
- :step="0.01"
- controls-position="right"
- @change="handleDeliveryBatchQuantityChange(scope.row)"
- style="width: 100%"
- />
+ <el-input-number v-model="scope.row.deliveryQuantity"
+ :min="0"
+ :max="getDeliveryBatchDeliveryMax(scope.row)"
+ :precision="2"
+ :step="0.01"
+ controls-position="right"
+ @change="handleDeliveryBatchQuantityChange(scope.row)"
+ style="width: 100%;" />
</template>
</el-table-column>
</el-table>
@@ -1159,8 +1027,9 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitDelivery"
- >纭鍙戣揣
+ <el-button type="primary"
+ :loading="deliveryLoading"
+ @click="submitDelivery">纭鍙戣揣
</el-button>
<el-button @click="closeDeliveryDia">鍙栨秷</el-button>
</div>
@@ -1170,2035 +1039,1772 @@
</template>
<script setup>
-import { getToken } from "@/utils/auth";
-import pagination from "@/components/PIMTable/Pagination.vue";
-import { onMounted, ref, getCurrentInstance } from "vue";
-import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
-import { ElMessageBox, ElMessage } from "element-plus";
-import useUserStore from "@/store/modules/user";
-import { userListNoPage } from "@/api/system/user.js";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
-import {
- ledgerListPage,
- productList,
- customerList,
- addOrUpdateSalesLedger,
- getSalesLedgerWithProducts,
- delLedger,
- addOrUpdateSalesLedgerProduct,
- delProduct,
- delLedgerFile,
- getProductInventory,
-} from "@/api/salesManagement/salesLedger.js";
-import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
-import { modelList, productTreeList } from "@/api/basicData/product.js";
-import useFormData from "@/hooks/useFormData.js";
-import dayjs from "dayjs";
-import FileUpload from "@/components/AttachmentUpload/file/index.vue";
-import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
-import { getCurrentDate } from "@/utils/index.js";
-import { listCustomer } from "@/api/basicData/customer.js";
+ import { getToken } from "@/utils/auth";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import { onMounted, ref, getCurrentInstance } from "vue";
+ import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
+ import { ElMessageBox, ElMessage } from "element-plus";
+ import useUserStore from "@/store/modules/user";
+ import { userListNoPage } from "@/api/system/user.js";
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
+ import {
+ ledgerListPage,
+ productList,
+ customerList,
+ addOrUpdateSalesLedger,
+ getSalesLedgerWithProducts,
+ delLedger,
+ addOrUpdateSalesLedgerProduct,
+ delProduct,
+ delLedgerFile,
+ getProductInventory,
+ getPrintData,
+ } from "@/api/salesManagement/salesLedger.js";
+ import { downloadSalesJpg, printSalesMulti } from "@/utils/documentPrint.js";
+ import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
+ import { modelList, productTreeList } from "@/api/basicData/product.js";
+ import useFormData from "@/hooks/useFormData.js";
+ import dayjs from "dayjs";
+ import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+ import {
+ tableAmountFormatter,
+ formatDecimal,
+ buildAmountSummaryFormat,
+ } from "@/utils/numberFormat";
+ import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
+ import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+ import { getCurrentDate } from "@/utils/index.js";
+ import { listCustomer } from "@/api/basicData/customer.js";
-const FileList = defineAsyncComponent(() =>
- import("@/components/Dialog/FileList.vue")
-);
+ const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+ );
-const router = useRouter();
-const route = useRoute();
-const userStore = useUserStore();
-const { proxy } = getCurrentInstance();
-const { tax_rate } = proxy.useDict("tax_rate");
-const tableData = ref([]);
-const productData = ref([]);
-const selectedRows = ref([]);
-const productSelectedRows = ref([]);
-const userList = ref([]);
-const customerOption = ref([]);
-const productOptions = ref([]);
-const modelOptions = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const fileList = ref([]);
-const deliveryFileList = ref([]);
+ const router = useRouter();
+ const route = useRoute();
+ const userStore = useUserStore();
+ const { proxy } = getCurrentInstance();
+ const { tax_rate } = proxy.useDict("tax_rate");
+ const tableData = ref([]);
+ const productData = ref([]);
+ const selectedRows = ref([]);
+ const productSelectedRows = ref([]);
+ const userList = ref([]);
+ const customerOption = ref([]);
+ const productOptions = ref([]);
+ const modelOptions = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ });
+ const total = ref(0);
+ const fileList = ref([]);
+ const deliveryFileList = ref([]);
+ const showProductSelectDialog = ref(false);
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- customerName: "", // 瀹㈡埛鍚嶇О
- salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- form: {
- salesContractNo: "",
- autoGenerateContractNo: true,
- salesman: "",
- customerId: "",
- entryPerson: "",
- entryDate: "",
- deliveryDate: "",
- maintenanceTime: "",
- productData: [],
- executionDate: "",
- hasProductionRecord: false,
- createTime: "",
- },
- rules: {
- salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { form, rules } = toRefs(data);
-const { form: searchForm } = useFormData(data.searchForm);
-// 浜у搧琛ㄥ崟寮规鏁版嵁
-const productFormVisible = ref(false);
-const productOperationType = ref("");
-const currentId = ref("");
-const productFormData = reactive({
- productForm: {
- productCategory: "",
- specificationModel: "",
- unit: "",
- quantity: "",
- taxInclusiveUnitPrice: "",
- taxRate: "",
- taxInclusiveTotalPrice: "",
- taxExclusiveTotalPrice: "",
- invoiceType: "",
- isProduction: false,
- },
- productRules: {
- productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- specificationModel: [
- { required: true, message: "璇烽�夋嫨", trigger: "change" },
- ],
- unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- isProduction: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { productForm, productRules } = toRefs(productFormData);
-// 闃叉寰幆璁$畻鐨勬爣蹇�
-const isCalculating = ref(false);
-// 鎵撳嵃鐩稿叧
-const printPreviewVisible = ref(false);
-const printData = ref([]);
-
-// 鎶ヤ环鍗曞鍏ョ浉鍏�
-const quotationDialogVisible = ref(false);
-const quotationLoading = ref(false);
-const quotationList = ref([]);
-const quotationSearchForm = reactive({
- quotationNo: "",
- customer: "",
-});
-// 鎶ヤ环鍗曞脊妗嗗垎椤�
-const quotationPage = reactive({
- current: 1,
- size: 10,
- total: 0,
-});
-const selectedQuotation = ref(null);
-
-// 鍙戣揣鐩稿叧
-const deliveryFormVisible = ref(false);
-const currentDeliveryRow = ref(null);
-const getDeliveryBatchQuantity = (item) => {
- const quantity =
- item?.qualitity ??
- item?.quantity ??
- item?.unLockedQuantity ??
- item?.qualifiedUnLockedQuantity ??
- item?.qualifiedQuantity ??
- item?.stockQuantity;
- return quantity ?? 0;
-};
-const getCurrentDeliveryRowQuantity = () => {
- return Number(currentDeliveryRow.value?.noQuantity || 0);
-};
-const getDeliveryBatchDeliveryMax = (row) => {
- const productQuantity = getCurrentDeliveryRowQuantity();
- const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
- const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
- (sum, item) => {
- if (item?.id === row?.id) return sum;
- return sum + Number(item?.deliveryQuantity || 0);
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const data = reactive({
+ searchForm: {
+ customerName: "", // 瀹㈡埛鍚嶇О
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
},
- 0
- );
- const remainingProductQuantity = Math.max(
- 0,
- productQuantity - otherBatchTotal
- );
- return Math.max(0, Math.min(batchQuantity, remainingProductQuantity));
-};
-const handleDeliveryBatchQuantityChange = (row) => {
- const productQuantity = getCurrentDeliveryRowQuantity();
- const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
- const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
- (sum, item) => {
- if (item?.id === row?.id) return sum;
- return sum + Number(item?.deliveryQuantity || 0);
+ form: {
+ salesContractNo: "",
+ autoGenerateContractNo: true,
+ salesman: "",
+ customerId: "",
+ entryPerson: "",
+ entryDate: "",
+ deliveryDate: "",
+ maintenanceTime: "",
+ productData: [],
+ executionDate: "",
+ hasProductionRecord: false,
},
- 0
- );
- const remainingProductQuantity = Math.max(
- 0,
- productQuantity - otherBatchTotal
- );
- const currentValue = Number(row?.deliveryQuantity || 0);
+ rules: {
+ salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+ });
+ const { form, rules } = toRefs(data);
+ const { form: searchForm } = useFormData(data.searchForm);
+ // 浜у搧琛ㄥ崟寮规鏁版嵁
+ const productFormVisible = ref(false);
+ const productOperationType = ref("");
+ const currentId = ref("");
+ const productFormData = reactive({
+ productForm: {
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ isProduction: false,
+ },
+ productRules: {
+ productCategory: [{ required: true, message: "璇烽�夋嫨浜у搧澶х被", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨瑙勬牸鍨嬪彿", trigger: "change" }],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ isProduction: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+ });
+ const { productForm, productRules } = toRefs(productFormData);
+ // 闃叉寰幆璁$畻鐨勬爣蹇�
+ const isCalculating = ref(false);
+ // 鎵撳嵃鐩稿叧
+ const printPreviewVisible = ref(false);
+ const printData = ref([]);
- if (currentValue > batchQuantity) {
- row.deliveryQuantity = batchQuantity;
- proxy.$modal.msgWarning("鍙戣揣鏁伴噺涓嶈兘澶т簬搴撳瓨鏁伴噺");
- } else if (currentValue > remainingProductQuantity) {
- row.deliveryQuantity = remainingProductQuantity;
- proxy.$modal.msgWarning("鎵�鏈夋壒娆″彂璐ф暟閲忎箣鍜屼笉鑳藉ぇ浜庡緟鍙戣揣鏁伴噺");
- }
-};
-const getSelectedDeliveryBatchRows = () => {
- return (deliveryForm.value.batchNoList || []).filter(
- (item) => Number(item?.deliveryQuantity || 0) > 0
- );
-};
-const getDeliveryBatchNoList = async (productModelId) => {
- if (!productModelId) return [];
- const res = await getStockInventoryByModelId(productModelId);
- const rawList = Array.isArray(res?.data)
- ? res.data
- : res?.data?.records || res?.data?.rows || [];
- const seenIds = new Set();
- return rawList
- .filter((item) => {
- if (!item?.id || !item?.batchNo || seenIds.has(item.id)) {
+ // 鎶ヤ环鍗曞鍏ョ浉鍏�
+ const quotationDialogVisible = ref(false);
+ const quotationLoading = ref(false);
+ const quotationList = ref([]);
+ const quotationSearchForm = reactive({
+ quotationNo: "",
+ customer: "",
+ });
+ // 鎶ヤ环鍗曞脊妗嗗垎椤�
+ const quotationPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+ const selectedQuotation = ref(null);
+
+ // 鍙戣揣鐩稿叧
+ const deliveryFormVisible = ref(false);
+ const deliveryLoading = ref(false);
+ const currentDeliveryRow = ref(null);
+ const getDeliveryBatchQuantity = item => {
+ const quantity =
+ item?.qualitity ??
+ item?.quantity ??
+ item?.unLockedQuantity ??
+ item?.qualifiedUnLockedQuantity ??
+ item?.qualifiedQuantity ??
+ item?.stockQuantity;
+ return quantity ?? 0;
+ };
+ const currentStock = ref(null);
+ const fetchCurrentStock = async (productModelId) => {
+ if (!productModelId) {
+ currentStock.value = null;
+ return;
+ }
+ try {
+ const res = await getStockInventoryByModelId(productModelId);
+ const rawList = Array.isArray(res?.data)
+ ? res.data
+ : res?.data?.records || res?.data?.rows || [];
+ let total = 0;
+ rawList.forEach(item => {
+ total += Number(getDeliveryBatchQuantity(item) || 0);
+ });
+ currentStock.value = total;
+ } catch (e) {
+ console.error(e);
+ currentStock.value = 0;
+ }
+ };
+ const getCurrentDeliveryRowQuantity = () => {
+ return Number(currentDeliveryRow.value?.noQuantity || 0);
+ };
+ const getDeliveryBatchDeliveryMax = row => {
+ const productQuantity = getCurrentDeliveryRowQuantity();
+ const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
+ const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
+ (sum, item) => {
+ if (item?.id === row?.id) return sum;
+ return sum + Number(item?.deliveryQuantity || 0);
+ },
+ 0
+ );
+ const remainingProductQuantity = Math.max(
+ 0,
+ productQuantity - otherBatchTotal
+ );
+ return Math.max(0, Math.min(batchQuantity, remainingProductQuantity));
+ };
+ const handleDeliveryBatchQuantityChange = row => {
+ const productQuantity = getCurrentDeliveryRowQuantity();
+ const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
+ const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
+ (sum, item) => {
+ if (item?.id === row?.id) return sum;
+ return sum + Number(item?.deliveryQuantity || 0);
+ },
+ 0
+ );
+ const remainingProductQuantity = Math.max(
+ 0,
+ productQuantity - otherBatchTotal
+ );
+ const currentValue = Number(row?.deliveryQuantity || 0);
+
+ if (currentValue > batchQuantity) {
+ row.deliveryQuantity = batchQuantity;
+ proxy.$modal.msgWarning("鍙戣揣鏁伴噺涓嶈兘澶т簬搴撳瓨鏁伴噺");
+ } else if (currentValue > remainingProductQuantity) {
+ row.deliveryQuantity = remainingProductQuantity;
+ proxy.$modal.msgWarning("鎵�鏈夋壒娆″彂璐ф暟閲忎箣鍜屼笉鑳藉ぇ浜庡緟鍙戣揣鏁伴噺");
+ }
+ };
+ const getSelectedDeliveryBatchRows = () => {
+ return (deliveryForm.value.batchNoList || []).filter(
+ item => Number(item?.deliveryQuantity || 0) > 0
+ );
+ };
+ const getDeliveryBatchNoList = async productModelId => {
+ if (!productModelId) return [];
+ const res = await getStockInventoryByModelId(productModelId);
+ const rawList = Array.isArray(res?.data)
+ ? res.data
+ : res?.data?.records || res?.data?.rows || [];
+ const seenIds = new Set();
+ return rawList
+ .filter(item => {
+ if (!item?.id || !item?.batchNo || seenIds.has(item.id)) {
+ return false;
+ }
+ seenIds.add(item.id);
+ return true;
+ })
+ .map(item => ({
+ ...item,
+ deliveryQuantity: 0,
+ }));
+ };
+ const validateDeliveryShippingCarNumber = (_rule, value, callback) => {
+ if (deliveryForm.value.type === "璐ц溅" && !value) {
+ return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
+ }
+ callback();
+ };
+ const validateDeliveryExpressCompany = (_rule, value, callback) => {
+ if (deliveryForm.value.type === "蹇��" && !value) {
+ return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
+ }
+ callback();
+ };
+ const deliveryFormData = reactive({
+ deliveryForm: {
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "",
+ type: "璐ц溅", // 璐ц溅, 蹇��
+ },
+ deliveryRules: {
+ shippingCarNumber: [
+ { validator: validateDeliveryShippingCarNumber, trigger: "blur" },
+ ],
+ expressCompany: [
+ { validator: validateDeliveryExpressCompany, trigger: "blur" },
+ ],
+ type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
+ },
+ });
+ const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
+
+ // 瀵煎叆鐩稿叧
+ const importUploadRef = ref(null);
+ const importUpload = reactive({
+ title: "瀵煎叆閿�鍞彴璐�",
+ open: false,
+ url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
+ headers: { Authorization: "Bearer " + getToken() },
+ isUploading: false,
+ beforeUpload: file => {
+ const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isExcel) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
return false;
}
- seenIds.add(item.id);
+ if (!isLt10M) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
+ }
return true;
- })
- .map((item) => ({
- ...item,
- deliveryQuantity: 0,
- }));
-};
-const validateDeliveryShippingCarNumber = (_rule, value, callback) => {
- if (deliveryForm.value.type === "璐ц溅" && !value) {
- return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
- }
- callback();
-};
-const validateDeliveryExpressCompany = (_rule, value, callback) => {
- if (deliveryForm.value.type === "蹇��" && !value) {
- return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
- }
- callback();
-};
-const deliveryFormData = reactive({
- deliveryForm: {
- shippingCarNumber: "",
- expressCompany: "",
- expressNumber: "",
- type: "璐ц溅", // 璐ц溅, 蹇��
- },
- deliveryRules: {
- shippingCarNumber: [
- { validator: validateDeliveryShippingCarNumber, trigger: "blur" },
- ],
- expressCompany: [
- { validator: validateDeliveryExpressCompany, trigger: "blur" },
- ],
- type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
- },
-});
-const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
+ },
+ onChange: (file, fileList) => {
+ console.log("鏂囦欢鐘舵�佹敼鍙�", file, fileList);
+ },
+ onProgress: (event, file, fileList) => {
+ console.log("涓婁紶涓�...", event.percent);
+ },
+ onSuccess: (response, file, fileList) => {
+ console.log("涓婁紶鎴愬姛", response, file, fileList);
+ importUpload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+ importUpload.open = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles();
+ }
+ getList();
+ } else {
+ proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
+ }
+ },
+ onError: (error, file, fileList) => {
+ console.error("涓婁紶澶辫触", error, file, fileList);
+ importUpload.isUploading = false;
+ proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+ },
+ });
-// 瀵煎叆鐩稿叧
-const importUploadRef = ref(null);
-const importUpload = reactive({
- title: "瀵煎叆閿�鍞彴璐�",
- open: false,
- url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
- headers: { Authorization: "Bearer " + getToken() },
- isUploading: false,
- beforeUpload: (file) => {
- const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
- const isLt10M = file.size / 1024 / 1024 < 10;
- if (!isExcel) {
- proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
- return false;
+ const changeDaterange = value => {
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
}
- if (!isLt10M) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
- return false;
+ handleQuery();
+ };
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
+ // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
+ if (arguments.length === 0) {
+ page.current = 1;
+ }
+ expandedRowKeys.value = [];
+ getList();
+ };
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ tableLoading.value = true;
+ const { entryDate, ...rest } = searchForm;
+ // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
+ const params = { ...rest, ...page };
+ // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
+ delete params.entryDate;
+ return ledgerListPage(params)
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.records;
+ tableData.value.map(item => {
+ item.children = [];
+ });
+ total.value = res.total;
+ return res;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+ };
+ // 鑾峰彇浜у搧澶х被tree鏁版嵁
+ const getProductOptions = () => {
+ // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
+ return productTreeList().then(res => {
+ productOptions.value = convertIdToValue(res);
+ return productOptions.value;
+ });
+ };
+ const formattedNumber = tableAmountFormatter;
+ const findLedgerRecordByRow = row => {
+ if (!row) return null;
+ if (
+ row.maintainer !== undefined ||
+ row.maintainerName !== undefined ||
+ row.entryPerson !== undefined ||
+ row.entryPersonName !== undefined
+ ) {
+ return row;
+ }
+ if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) {
+ return (
+ tableData.value.find(
+ item => String(item.id) === String(row.salesLedgerId)
+ ) || null
+ );
+ }
+ return null;
+ };
+ const isCurrentUserMaintainer = row => {
+ const ledgerRecord = findLedgerRecordByRow(row);
+ if (!ledgerRecord) return true;
+ const currentUserId = String(userStore.id ?? "");
+ const currentNickName = String(userStore.nickName ?? "").trim();
+ const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson;
+ const maintainerName =
+ ledgerRecord.maintainerName ??
+ ledgerRecord.maintainer ??
+ ledgerRecord.entryPersonName;
+ if (
+ maintainerId !== undefined &&
+ maintainerId !== null &&
+ String(maintainerId) !== ""
+ ) {
+ return String(maintainerId) === currentUserId;
+ }
+ if (
+ maintainerName !== undefined &&
+ maintainerName !== null &&
+ String(maintainerName).trim() !== ""
+ ) {
+ return String(maintainerName).trim() === currentNickName;
}
return true;
- },
- onChange: (file, fileList) => {
- console.log("鏂囦欢鐘舵�佹敼鍙�", file, fileList);
- },
- onProgress: (event, file, fileList) => {
- console.log("涓婁紶涓�...", event.percent);
- },
- onSuccess: (response, file, fileList) => {
- console.log("涓婁紶鎴愬姛", response, file, fileList);
- importUpload.isUploading = false;
- if (response.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importUpload.open = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
- getList();
+ };
+ const canEditLedger = row => isCurrentUserMaintainer(row);
+ const canDeleteLedger = row => isCurrentUserMaintainer(row);
+ const sensitiveAmountFormatter = (row, column, cellValue) => {
+ if (!isCurrentUserMaintainer(row)) {
+ return "*****";
+ }
+ return formattedNumber(row, column, cellValue);
+ };
+ // ProductSelectDialog 閫変腑鍥炶皟
+ const handleProductSelect = (products) => {
+ if (!products || !products.length) return;
+ const p = products[0];
+ productForm.value.productId = p.productId;
+ productForm.value.productCategory = p.productName || '';
+ productForm.value.productModelId = p.id;
+ productForm.value.specificationModel = p.model || '';
+ productForm.value.unit = p.unit || '';
+ fetchCurrentStock(productForm.value.productModelId);
+ showProductSelectDialog.value = false;
+ };
+ // 鑾峰彇tree瀛愭暟鎹�
+ const getModels = value => {
+ productForm.value.productCategory = findNodeById(productOptions.value, value);
+ currentStock.value = null;
+ modelList({ id: value }).then(res => {
+ modelOptions.value = res;
+ });
+ };
+ const getProductModel = value => {
+ const index = modelOptions.value.findIndex(item => item.id === value);
+ if (index !== -1) {
+ productForm.value.specificationModel = modelOptions.value[index].model;
+ productForm.value.unit = modelOptions.value[index].unit;
+ fetchCurrentStock(value);
} else {
- proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
+ productForm.value.specificationModel = null;
+ productForm.value.unit = null;
+ currentStock.value = null;
}
- },
- onError: (error, file, fileList) => {
- console.error("涓婁紶澶辫触", error, file, fileList);
- importUpload.isUploading = false;
- proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
- },
-});
-
-const changeDaterange = (value) => {
- if (value) {
- searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- searchForm.entryDateStart = undefined;
- searchForm.entryDateEnd = undefined;
- }
- handleQuery();
-};
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
- // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
- if (arguments.length === 0) {
- page.current = 1;
- }
- expandedRowKeys.value = [];
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const { entryDate, ...rest } = searchForm;
- // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
- const params = { ...rest, ...page };
- // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
- delete params.entryDate;
- return ledgerListPage(params)
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.records;
- tableData.value.map((item) => {
- item.children = [];
- });
- total.value = res.total;
- return res;
- })
- .catch(() => {
- tableLoading.value = false;
- });
-};
-// 鑾峰彇浜у搧澶х被tree鏁版嵁
-const getProductOptions = () => {
- // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
- return productTreeList().then((res) => {
- productOptions.value = convertIdToValue(res);
- return productOptions.value;
- });
-};
-const formattedNumber = (row, column, cellValue) => {
- if (cellValue === undefined || cellValue === null || cellValue === "") {
- return "0.00";
- }
- return parseFloat(cellValue).toFixed(2);
-};
-const findLedgerRecordByRow = (row) => {
- if (!row) return null;
- if (
- row.maintainer !== undefined ||
- row.maintainerName !== undefined ||
- row.entryPerson !== undefined ||
- row.entryPersonName !== undefined
- ) {
- return row;
- }
- if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) {
- return (
- tableData.value.find(
- (item) => String(item.id) === String(row.salesLedgerId)
- ) || null
- );
- }
- return null;
-};
-const isCurrentUserMaintainer = (row) => {
- const ledgerRecord = findLedgerRecordByRow(row);
- if (!ledgerRecord) return true;
- const currentUserId = String(userStore.id ?? "");
- const currentNickName = String(userStore.nickName ?? "").trim();
- const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson;
- const maintainerName =
- ledgerRecord.maintainerName ??
- ledgerRecord.maintainer ??
- ledgerRecord.entryPersonName;
- if (
- maintainerId !== undefined &&
- maintainerId !== null &&
- String(maintainerId) !== ""
- ) {
- return String(maintainerId) === currentUserId;
- }
- if (
- maintainerName !== undefined &&
- maintainerName !== null &&
- String(maintainerName).trim() !== ""
- ) {
- return String(maintainerName).trim() === currentNickName;
- }
- return true;
-};
-const canEditLedger = (row) => isCurrentUserMaintainer(row);
-const canDeleteLedger = (row) => isCurrentUserMaintainer(row);
-const sensitiveAmountFormatter = (row, column, cellValue) => {
- if (!isCurrentUserMaintainer(row)) {
- return "*****";
- }
- return formattedNumber(row, column, cellValue);
-};
-// 鑾峰彇tree瀛愭暟鎹�
-const getModels = (value) => {
- productForm.value.productCategory = findNodeById(productOptions.value, value);
- modelList({ id: value }).then((res) => {
- modelOptions.value = res;
- });
-};
-const getProductModel = (value) => {
- const index = modelOptions.value.findIndex((item) => item.id === value);
- if (index !== -1) {
- productForm.value.specificationModel = modelOptions.value[index].model;
- productForm.value.unit = modelOptions.value[index].unit;
- } else {
- productForm.value.specificationModel = null;
- productForm.value.unit = null;
- }
-};
-const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ };
+ const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
}
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
-};
-
-function convertIdToValue(data) {
- return data.map((item) => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
-}
-
-// 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
-function findNodeIdByLabel(nodes, label) {
- if (!label) return null;
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (node.label === label) return node.value;
- if (node.children && node.children.length > 0) {
- const found = findNodeIdByLabel(node.children, label);
- if (found !== null && found !== undefined) return found;
- }
- }
- return null;
-}
-
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.children !== undefined);
- console.log("selection", selectedRows.value);
-};
-const productSelected = (selectedRows) => {
- productSelectedRows.value = selectedRows;
-};
-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;
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
}
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- console.log(error);
+ }
}
- } else {
- expandedRowKeys.value = [];
- }
-};
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+ };
-// 娣诲姞琛ㄨ绫诲悕鏂规硶
-const tableRowClassName = ({ row }) => {
- if (!row.deliveryDate) return "";
- if (row.isFh) return "";
+ function convertIdToValue(data) {
+ return data.map(item => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
- const diff = row.deliveryDaysDiff;
- if (diff === 15) {
- return "yellow";
- } else if (diff === 10) {
- return "pink";
- } else if (diff === 2) {
- return "purple";
- } else if (diff < 2) {
- return "red";
- }
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, [
- "contractAmount",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param, parentRow) => {
- if (!isCurrentUserMaintainer(parentRow)) {
- const { columns } = param;
- return columns.map((column, index) => {
- if (index === 0) {
- return "鍚堣";
- }
- if (
- [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ].includes(column.property)
- ) {
- return "*****";
- }
- return "";
+ return newItem;
});
}
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
-};
-// 鎵撳紑寮规
-const openForm = async (type, row) => {
- if (type === "edit" && row && !canEditLedger(row)) {
- proxy.$modal.msgWarning("褰撳墠绯荤粺鐧诲綍浜轰笉鏄淮鎶や汉锛屼笉鑳界紪杈戞暟鎹�");
- return;
+
+ // 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
+ function findNodeIdByLabel(nodes, label) {
+ if (!label) return null;
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ if (node.label === label) return node.value;
+ if (node.children && node.children.length > 0) {
+ const found = findNodeIdByLabel(node.children, label);
+ if (found !== null && found !== undefined) return found;
+ }
+ }
+ return null;
}
- operationType.value = type;
- form.value = {};
- productData.value = [];
- selectedQuotation.value = null;
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- listCustomer({ current: -1, size: -1, type: 0 }).then((res) => {
- customerOption.value = res.data.records;
- });
- form.value.entryPerson = userStore.id;
- if (type === "add") {
- // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
- form.value.entryDate = getCurrentDate();
- // 绛捐鏃ユ湡榛樿涓哄綋澶�
- form.value.executionDate = getCurrentDate();
- // 鍒涘缓鏃堕棿榛樿涓哄綋澶�
- form.value.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
- // 榛樿鑷姩鐢熸垚閿�鍞悎鍚屽彿
- form.value.autoGenerateContractNo = true;
- } else {
- currentId.value = row.id;
- getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
- form.value = { ...res };
- form.value.entryPerson = Number(res.entryPerson);
- productData.value = form.value.productData;
- fileList.value = form.value.storageBlobVOs;
- // 缂栬緫鏃惰缃嚜鍔ㄧ敓鎴愪负false锛屽厑璁告墜鍔ㄤ慨鏀�
- form.value.autoGenerateContractNo = false;
+
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter(item => item.children !== undefined);
+ console.log("selection", selectedRows.value);
+ };
+ const productSelected = selectedRows => {
+ productSelectedRows.value = selectedRows;
+ };
+ 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 tableRowClassName = ({ row }) => {
+ if (!row.deliveryDate) return "";
+ if (row.isFh) return "";
+
+ const diff = row.deliveryDaysDiff;
+ if (diff === 15) {
+ return "yellow";
+ } else if (diff === 10) {
+ return "pink";
+ } else if (diff === 2) {
+ return "purple";
+ } else if (diff < 2) {
+ return "red";
+ }
+ };
+ // 涓昏〃鍚堣鏂规硶
+ const summarizeMainTable = param => {
+ return proxy.summarizeTable(
+ param,
+ ["contractAmount", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"],
+ buildAmountSummaryFormat([
+ "contractAmount",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ])
+ );
+ };
+ // 瀛愯〃鍚堣鏂规硶
+ const summarizeChildrenTable = (param, parentRow) => {
+ if (!isCurrentUserMaintainer(parentRow)) {
+ const { columns } = param;
+ return columns.map((column, index) => {
+ if (index === 0) {
+ return "鍚堣";
+ }
+ if (
+ [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ].includes(column.property)
+ ) {
+ return "*****";
+ }
+ return "";
+ });
+ }
+ return proxy.summarizeTable(
+ param,
+ [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ],
+ buildAmountSummaryFormat([
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ])
+ );
+ };
+ // 鎵撳紑寮规
+ const openForm = async (type, row) => {
+ if (type === "edit" && row && !canEditLedger(row)) {
+ proxy.$modal.msgWarning("褰撳墠绯荤粺鐧诲綍浜轰笉鏄淮鎶や汉锛屼笉鑳界紪杈戞暟鎹�");
+ return;
+ }
+ operationType.value = type;
+ form.value = {};
+ productData.value = [];
+ selectedQuotation.value = null;
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ listCustomer({ current: -1, size: -1, type: 0 }).then(res => {
+ customerOption.value = res.data.records;
});
- }
- // let userAll = await userStore.getInfo()
- // userList.value.forEach(element => {
- // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
- // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
- // }
- // });
- form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
- dialogFormVisible.value = true;
-};
-
-// 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
-const openQuotationDialog = async () => {
- if (operationType.value === "view") return;
- quotationDialogVisible.value = true;
- // 鎵撳紑寮圭獥鏃堕噸缃垎椤靛埌绗竴椤�
- quotationPage.current = 1;
- // 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
- if (!customerOption.value || customerOption.value.length === 0) {
- try {
- listCustomer({ current: -1, size: -1 }).then((res) => {
- customerOption.value = res.data.records;
- });
- } catch (e) {
- // ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
- }
- }
- await fetchQuotationList();
-};
-
-const fetchQuotationList = async () => {
- quotationLoading.value = true;
- try {
- const params = {
- // 鍚庣鍒嗛〉瀛楁锛歝urrent / size
- current: quotationPage.current,
- size: quotationPage.size,
- ...quotationSearchForm,
- status: "閫氳繃",
- };
- const res = await getQuotationList(params);
- quotationList.value = res?.data?.records || [];
- quotationPage.total = res?.data?.total || 0;
- } finally {
- quotationLoading.value = false;
- }
-};
-
-const resetQuotationSearch = async () => {
- quotationSearchForm.quotationNo = "";
- quotationSearchForm.customer = "";
- quotationPage.current = 1;
- await fetchQuotationList();
-};
-
-// 鎶ヤ环鍗曞脊妗嗗垎椤靛垏鎹�
-const quotationPaginationChange = (obj) => {
- quotationPage.current = obj.page;
- quotationPage.size = obj.limit;
- fetchQuotationList();
-};
-
-// 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
-const applyQuotation = (row) => {
- if (!row) return;
- selectedQuotation.value = row;
-
- // 涓氬姟鍛�
- form.value.salesman = (row.salesperson || "").trim();
-
- // 瀹㈡埛鍚嶇О -> customerId
- const qCustomerName = String(row.customer || "").trim();
- const customer = (customerOption.value || []).find((c) => {
- const name = String(c.customerName || "").trim();
- return (
- name === qCustomerName ||
- name.includes(qCustomerName) ||
- qCustomerName.includes(name)
- );
- });
- if (customer?.id) {
- form.value.customerId = customer.id;
- } else {
- // 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
- form.value.customerId = form.value.customerId || "";
- }
-
- // 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
- const products = Array.isArray(row.products) ? row.products : [];
- productData.value = products.map((p) => {
- const quantity = Number(p.quantity ?? 0) || 0;
- const unitPrice = Number(p.unitPrice ?? 0) || 0;
- const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
- const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
- const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(
- taxInclusiveTotalPrice,
- taxRate
- );
- return {
- // 鍙拌处瀛楁
- productCategory: p.product || p.productName || "",
- specificationModel: p.specification || "",
- unit: p.unit || "",
- quantity: quantity,
- taxRate: taxRate,
- taxInclusiveUnitPrice: unitPrice.toFixed(2),
- taxInclusiveTotalPrice: taxInclusiveTotalPrice,
- taxExclusiveTotalPrice: taxExclusiveTotalPrice,
- invoiceType: "澧炴櫘绁�",
- isProduction: true,
- productId: p.productId,
- productModelId: p.productModelId,
- };
- });
-
- quotationDialogVisible.value = false;
-};
-
-function changs(val) {
- console.log(val);
-}
-
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- console.log("productData.value--", productData.value);
- if (productData.value !== null && productData.value.length > 0) {
- form.value.productData = proxy.HaveJson(productData.value);
- } else {
- proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
- return;
- }
- form.value.storageBlobDTOs = fileList;
- form.value.type = 1;
- if (form.value.autoGenerateContractNo) {
- form.value.salesContractNo = "";
- }
- addOrUpdateSalesLedger(form.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- expandedRowKeys.value = [];
- getList();
+ form.value.entryPerson = userStore.id;
+ if (type === "add") {
+ // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
+ form.value.entryDate = getCurrentDate();
+ // 绛捐鏃ユ湡榛樿涓哄綋澶�
+ form.value.executionDate = getCurrentDate();
+ // 榛樿鑷姩鐢熸垚閿�鍞悎鍚屽彿
+ form.value.autoGenerateContractNo = true;
+ } else {
+ currentId.value = row.id;
+ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
+ form.value = { ...res };
+ form.value.entryPerson = Number(res.entryPerson);
+ productData.value = form.value.productData;
+ fileList.value = form.value.storageBlobVOs;
+ // 缂栬緫鏃惰缃嚜鍔ㄧ敓鎴愪负false锛屽厑璁告墜鍔ㄤ慨鏀�
+ form.value.autoGenerateContractNo = false;
});
}
- });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
-};
+ // let userAll = await userStore.getInfo()
+ // userList.value.forEach(element => {
+ // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
+ // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
+ // }
+ // });
+ form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
+ dialogFormVisible.value = true;
+ };
-const productIndex = ref(0);
-// 鎵撳紑浜у搧寮规
-const openProductForm = async (type, row, index) => {
- // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
- if (type === "edit" && isProductShipped(row)) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
- return;
- }
+ // 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
+ const openQuotationDialog = async () => {
+ if (operationType.value === "view") return;
+ quotationDialogVisible.value = true;
+ // 鎵撳紑寮圭獥鏃堕噸缃垎椤靛埌绗竴椤�
+ quotationPage.current = 1;
+ // 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
+ if (!customerOption.value || customerOption.value.length === 0) {
+ try {
+ listCustomer({ current: -1, size: -1 }).then(res => {
+ customerOption.value = res.data.records;
+ });
+ } catch (e) {
+ // ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
+ }
+ }
+ await fetchQuotationList();
+ };
- productOperationType.value = type;
- productForm.value = {};
- if (type === "add") {
- productForm.value.isProduction = true;
- }
- proxy.resetForm("productFormRef");
- if (type === "edit") {
- productForm.value = { ...row };
- productIndex.value = index;
- // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
+ const fetchQuotationList = async () => {
+ quotationLoading.value = true;
try {
- const options =
- productOptions.value && productOptions.value.length > 0
- ? productOptions.value
- : await getProductOptions();
- const categoryId = findNodeIdByLabel(
- options,
- productForm.value.productCategory
+ const params = {
+ // 鍚庣鍒嗛〉瀛楁锛歝urrent / size
+ current: quotationPage.current,
+ size: quotationPage.size,
+ ...quotationSearchForm,
+ status: "閫氳繃",
+ };
+ const res = await getQuotationList(params);
+ quotationList.value = res?.data?.records || [];
+ quotationPage.total = res?.data?.total || 0;
+ } finally {
+ quotationLoading.value = false;
+ }
+ };
+
+ const resetQuotationSearch = async () => {
+ quotationSearchForm.quotationNo = "";
+ quotationSearchForm.customer = "";
+ quotationPage.current = 1;
+ await fetchQuotationList();
+ };
+
+ // 鎶ヤ环鍗曞脊妗嗗垎椤靛垏鎹�
+ const quotationPaginationChange = obj => {
+ quotationPage.current = obj.page;
+ quotationPage.size = obj.limit;
+ fetchQuotationList();
+ };
+
+ // 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
+ const applyQuotation = row => {
+ if (!row) return;
+ selectedQuotation.value = row;
+
+ // 涓氬姟鍛�
+ form.value.salesman = (row.salesperson || "").trim();
+
+ // 瀹㈡埛鍚嶇О -> customerId
+ const qCustomerName = String(row.customer || "").trim();
+ const customer = (customerOption.value || []).find(c => {
+ const name = String(c.customerName || "").trim();
+ return (
+ name === qCustomerName ||
+ name.includes(qCustomerName) ||
+ qCustomerName.includes(name)
);
- if (categoryId) {
- const models = await modelList({ id: categoryId });
- modelOptions.value = models || [];
- // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
- const currentModel = (modelOptions.value || []).find(
- (m) => m.model === productForm.value.specificationModel
- );
- if (currentModel) {
- productForm.value.productModelId = currentModel.id;
- }
- }
- } catch (e) {
- // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
- console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
- }
- } else {
- getProductOptions();
- }
- productFormVisible.value = true;
-};
-// 鎻愪氦浜у搧琛ㄥ崟
-const submitProduct = () => {
- proxy.$refs["productFormRef"].validate((valid) => {
- if (valid) {
- if (operationType.value === "edit") {
- submitProductEdit();
- } else {
- if (productOperationType.value === "add") {
- productData.value.push({ ...productForm.value });
- } else {
- productData.value[productIndex.value] = { ...productForm.value };
- }
- closeProductDia();
- }
- }
- });
-};
-const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 1;
- addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
- productData.value = res.productData;
});
- });
-};
-// 鍒犻櫎浜у搧
-const deleteProduct = () => {
- if (productSelectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
- const shippedProducts = productSelectedRows.value.filter((row) =>
- isProductShipped(row)
- );
- if (shippedProducts.length > 0) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
- return;
- }
-
- // 妫�鏌ユ槸鍚﹀彧鍓╀竴鏉℃暟鎹紝閿�鍞彴璐﹁嚦灏戜繚鐣欎竴鏉′骇鍝�
- if (productData.value.length <= 1) {
- proxy.$modal.msgWarning("閿�鍞彴璐﹁嚦灏戦渶瑕佷繚鐣欎竴鏉′骇鍝佹暟鎹�");
- return;
- }
-
- if (operationType.value === "add") {
- productData.value = productData.value.filter(
- (item) => !productSelectedRows.value.includes(item)
- );
- productSelectedRows.value = [];
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map((item) => item.id);
+ if (customer?.id) {
+ form.value.customerId = customer.id;
+ } else {
+ // 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
+ form.value.customerId = form.value.customerId || "";
}
+
+ // 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
+ const products = Array.isArray(row.products) ? row.products : [];
+ productData.value = products.map(p => {
+ const quantity = Number(p.quantity ?? 0) || 0;
+ const unitPrice = Number(p.unitPrice ?? 0) || 0;
+ const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
+ const taxInclusiveTotalPrice = formatDecimal(unitPrice * quantity);
+ const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(
+ taxInclusiveTotalPrice,
+ taxRate
+ );
+ return {
+ // 鍙拌处瀛楁
+ productCategory: p.product || p.productName || "",
+ specificationModel: p.specification || "",
+ unit: p.unit || "",
+ quantity: quantity,
+ taxRate: taxRate,
+ taxInclusiveUnitPrice: formatDecimal(unitPrice),
+ taxInclusiveTotalPrice: taxInclusiveTotalPrice,
+ taxExclusiveTotalPrice: taxExclusiveTotalPrice,
+ invoiceType: "澧炴櫘绁�",
+ isProduction: true,
+ productId: p.productId,
+ productModelId: p.productModelId,
+ };
+ });
+
+ quotationDialogVisible.value = false;
+ };
+
+ function changs(val) {
+ console.log(val);
+ }
+
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ console.log("productData.value--", productData.value);
+ if (productData.value !== null && productData.value.length > 0) {
+ form.value.productData = proxy.HaveJson(productData.value);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
+ }
+ form.value.storageBlobDTOs = fileList;
+ form.value.type = 1;
+ if (form.value.autoGenerateContractNo) {
+ form.value.salesContractNo = "";
+ }
+ addOrUpdateSalesLedger(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ expandedRowKeys.value = [];
+ getList();
+ });
+ }
+ });
+ };
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+
+ const productIndex = ref(0);
+ // 鎵撳紑浜у搧寮规
+ const openProductForm = async (type, row, index) => {
+ // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
+ if (type === "edit" && isProductShipped(row)) {
+ proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
+ return;
+ }
+
+ productOperationType.value = type;
+ productForm.value = {};
+ currentStock.value = null;
+ if (type === "add") {
+ productForm.value.isProduction = true;
+ }
+ proxy.resetForm("productFormRef");
+ if (type === "edit") {
+ productForm.value = { ...row };
+ productIndex.value = index;
+ // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
+ try {
+ const options =
+ productOptions.value && productOptions.value.length > 0
+ ? productOptions.value
+ : await getProductOptions();
+ const categoryId = findNodeIdByLabel(
+ options,
+ productForm.value.productCategory
+ );
+ if (categoryId) {
+ const models = await modelList({ id: categoryId });
+ modelOptions.value = models || [];
+ // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
+ const currentModel = (modelOptions.value || []).find(
+ m => m.model === productForm.value.specificationModel
+ );
+ if (currentModel) {
+ productForm.value.productModelId = currentModel.id;
+ fetchCurrentStock(currentModel.id);
+ }
+ }
+ } catch (e) {
+ // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
+ console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
+ }
+ } else {
+ getProductOptions();
+ }
+ productFormVisible.value = true;
+ };
+ // 鎻愪氦浜у搧琛ㄥ崟
+ const submitProduct = () => {
+ proxy.$refs["productFormRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitProductEdit();
+ } else {
+ if (productOperationType.value === "add") {
+ productData.value.push({ ...productForm.value });
+ } else {
+ productData.value[productIndex.value] = { ...productForm.value };
+ }
+ closeProductDia();
+ }
+ }
+ });
+ };
+ const submitProductEdit = () => {
+ productForm.value.salesLedgerId = currentId.value;
+ productForm.value.type = 1;
+ addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(res => {
+ productData.value = res.productData;
+ });
+ });
+ };
+ // 鍒犻櫎浜у搧
+ const deleteProduct = () => {
+ if (productSelectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+
+ // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
+ const shippedProducts = productSelectedRows.value.filter(row =>
+ isProductShipped(row)
+ );
+ if (shippedProducts.length > 0) {
+ proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
+ return;
+ }
+
+ if (operationType.value === "add") {
+ productData.value = productData.value.filter(
+ item => !productSelectedRows.value.includes(item)
+ );
+ productSelectedRows.value = [];
+ } else {
+ let ids = [];
+ if (productSelectedRows.value.length > 0) {
+ ids = productSelectedRows.value.map(item => item.id);
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delProduct(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
+ res => {
+ productData.value = res.productData;
+ }
+ );
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ }
+ };
+ // 鍏抽棴浜у搧寮规
+ const closeProductDia = () => {
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = false;
+ };
+ // 瀵煎叆
+ const handleImport = () => {
+ importUpload.title = "瀵煎叆閿�鍞彴璐�";
+ importUpload.open = true;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles();
+ }
+ };
+
+ // 涓嬭浇瀵煎叆妯℃澘
+ const downloadTemplate = () => {
+ proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
+ };
+
+ // 鎻愪氦瀵煎叆鏂囦欢
+ const submitImportFile = () => {
+ importUpload.isUploading = true;
+ proxy.$refs["importUploadRef"].submit();
+ };
+
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+ /** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
+ const isProductShipped = product => {
+ if (!product) return false;
+ const status = String(product.shippingStatus || "").trim();
+ // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
+ return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
+ };
+
+ /** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
+ const hasShippedProducts = products => {
+ if (!products || !products.length) return false;
+ return products.some(p => {
+ const status = String(p.shippingStatus || "").trim();
+ // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
+ if (p.shippingDate || p.shippingCarNumber) return true;
+ // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
+ return (
+ status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�"
+ );
+ });
+ };
+
+ // 鍒犻櫎
+ const handleDelete = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const unauthorizedRows = selectedRows.value.filter(
+ row => !canDeleteLedger(row)
+ );
+ if (unauthorizedRows.length > 0) {
+ proxy.$modal.msgWarning("褰撳墠鐧诲綍鐢ㄦ埛涓嶆槸褰曞叆浜猴紝涓嶈兘鍒犻櫎璇ユ暟鎹�");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+
+ // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
+ const cannotDeleteNames = [];
+ for (const row of selectedRows.value) {
+ let products =
+ row.children && row.children.length > 0 ? row.children : null;
+ if (!products) {
+ try {
+ const res = await productList({ salesLedgerId: row.id, type: 1 });
+ products = res.data || [];
+ } catch {
+ products = [];
+ }
+ }
+ if (hasShippedProducts(products)) {
+ cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
+ }
+ }
+ if (cannotDeleteNames.length > 0) {
+ proxy.$modal.msgWarning(
+ "宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�")
+ );
+ return;
+ }
+
ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
})
.then(() => {
- delProduct(ids).then((res) => {
+ delLedger(ids).then(res => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
- (res) => {
- productData.value = res.productData;
- }
- );
+ getList();
});
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- }
-};
-// 鍏抽棴浜у搧寮规
-const closeProductDia = () => {
- proxy.resetForm("productFormRef");
- productFormVisible.value = false;
-};
-// 瀵煎叆
-const handleImport = () => {
- importUpload.title = "瀵煎叆閿�鍞彴璐�";
- importUpload.open = true;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
-};
+ };
-// 涓嬭浇瀵煎叆妯℃澘
-const downloadTemplate = () => {
- proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
-};
-
-// 鎻愪氦瀵煎叆鏂囦欢
-const submitImportFile = () => {
- importUpload.isUploading = true;
- proxy.$refs["importUploadRef"].submit();
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-/** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
-const isProductShipped = (product) => {
- if (!product) return false;
- const status = String(product.shippingStatus || "").trim();
- // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
- return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
-};
-
-/** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
-const hasShippedProducts = (products) => {
- if (!products || !products.length) return false;
- return products.some((p) => {
- const status = String(p.shippingStatus || "").trim();
- // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
- if (p.shippingDate || p.shippingCarNumber) return true;
- // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
- return (
- status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�"
- );
- });
-};
-
-// 鍒犻櫎
-const handleDelete = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const unauthorizedRows = selectedRows.value.filter(
- (row) => !canDeleteLedger(row)
- );
- if (unauthorizedRows.length > 0) {
- proxy.$modal.msgWarning("褰撳墠鐧诲綍鐢ㄦ埛涓嶆槸褰曞叆浜猴紝涓嶈兘鍒犻櫎璇ユ暟鎹�");
- return;
- }
- const ids = selectedRows.value.map((item) => item.id);
-
- // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
- const cannotDeleteNames = [];
- for (const row of selectedRows.value) {
- let products =
- row.children && row.children.length > 0 ? row.children : null;
- if (!products) {
- try {
- const res = await productList({ salesLedgerId: row.id, type: 1 });
- products = res.data || [];
- } catch {
- products = [];
- }
- }
- if (hasShippedProducts(products)) {
- cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
- }
- }
- if (cannotDeleteNames.length > 0) {
- proxy.$modal.msgWarning(
- "宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�")
- );
- return;
- }
-
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delLedger(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 鎵撳嵃鍔熻兘
+ // 鎵撳嵃鍔熻兘 - 澶氶�夊悎骞堕瑙�
const handlePrint = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
- return;
- }
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+ proxy.$modal.loading("姝e湪鍔犺浇鎵撳嵃鏁版嵁...");
+ try {
+ const orders = [];
+ let companyName = '';
+ for (const row of selectedRows.value) {
+ const res = await getPrintData(row.id);
+ const data = res.data || res;
+ companyName = data.companyName || companyName;
+ orders.push(data.ledger);
+ }
+ printSalesMulti(companyName, orders);
+ } catch (e) {
+ console.error('鎵撳嵃澶辫触:', e);
+ proxy.$modal.msgError("鎵撳嵃澶辫触");
+ } finally {
+ proxy.$modal.closeLoading();
+ }
+ };
- // 鏄剧ず鍔犺浇鐘舵��
- proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
+ // 鏍煎紡鍖栨棩鏈�
+ const formatDate = dateString => {
+ if (!dateString) return getCurrentDate();
+ const date = new Date(dateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ return `${year}/${month}/${day}`;
+ };
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ const formatDateTime = date => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ const seconds = String(date.getSeconds()).padStart(2, "0");
+ return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+ };
+ // 璁$畻浜у搧鎬绘暟閲�
+ const getTotalQuantity = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.quantity) || 0);
+ }, 0);
+ return total.toFixed(2);
+ };
- try {
- // 涓烘瘡涓�変腑鐨勯攢鍞彴璐﹁褰曟煡璇㈠搴旂殑浜у搧鏁版嵁
- const printDataWithProducts = [];
+ // 璁$畻浜у搧鎬婚噾棰�
+ const getTotalAmount = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+ }, 0);
+ return formatDecimal(total);
+ };
- for (const row of selectedRows.value) {
- try {
- // 璋冪敤productList鎺ュ彛鏌ヨ浜у搧鏁版嵁
- const productRes = await productList({
- salesLedgerId: row.id,
- type: 1,
- });
+ // 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
+ const getTotalQuantityForPrint = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.quantity) || 0);
+ }, 0);
+ return total.toFixed(2);
+ };
- // 灏嗕骇鍝佹暟鎹暣鍚堝埌閿�鍞彴璐﹁褰曚腑
- const rowWithProducts = {
- ...row,
- products: productRes.data || [],
- };
+ const getTotalAmountForPrint = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+ }, 0);
+ return formatDecimal(total);
+ };
- printDataWithProducts.push(rowWithProducts);
- } catch (error) {
- console.error(`鑾峰彇閿�鍞彴璐� ${row.id} 鐨勪骇鍝佹暟鎹け璐�:`, error);
- // 鍗充娇鏌愪釜璁板綍鐨勪骇鍝佹暟鎹幏鍙栧け璐ワ紝涔熻鍖呭惈璇ヨ褰�
- printDataWithProducts.push({
- ...row,
- products: [],
- });
- }
+ const mathNum = () => {
+ console.log("productForm.value", productForm.value);
+ if (!productForm.value.taxInclusiveUnitPrice) {
+ return;
+ }
+ if (!productForm.value.quantity) {
+ return;
+ }
+ // 鍚◣鎬讳环璁$畻
+ productForm.value.taxInclusiveTotalPrice =
+ proxy.calculateTaxIncludeTotalPrice(
+ productForm.value.taxInclusiveUnitPrice,
+ productForm.value.quantity
+ );
+ if (productForm.value.taxRate) {
+ // 涓嶅惈绋庢�讳环璁$畻
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+ };
+
+ // 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+ const calculateFromTotalPrice = () => {
+ if (isCalculating.value) return;
+
+ const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+ const quantity = parseFloat(productForm.value.quantity);
+
+ if (!totalPrice || !quantity || quantity <= 0) {
+ return;
}
- printData.value = printDataWithProducts;
- console.log("鎵撳嵃鏁版嵁锛堝寘鍚骇鍝侊級:", printData.value);
- printPreviewVisible.value = true;
- } catch (error) {
- console.error("鑾峰彇浜у搧鏁版嵁澶辫触:", error);
- proxy.$modal.msgError("鑾峰彇浜у搧鏁版嵁澶辫触锛岃閲嶈瘯");
- } finally {
- proxy.$modal.closeLoading();
- }
-};
-// 鎵ц鎵撳嵃
-const executePrint = () => {
- console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
- console.log("鎵撳嵃鏁版嵁:", printData.value);
+ isCalculating.value = true;
- // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
- const printWindow = window.open("", "_blank", "width=800,height=600");
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = formatDecimal(totalPrice / quantity);
- // 鏋勫缓鎵撳嵃鍐呭
- let printContent = `
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>鎵撳嵃棰勮</title>
- <style>
- body {
- margin: 0;
- padding: 0;
- font-family: "SimSun", serif;
- background: white;
- }
- .print-page {
- width: 200mm;
- height: 75mm;
- padding: 10mm;
- padding-left: 20mm;
- background: white;
- box-sizing: border-box;
- page-break-after: always;
- page-break-inside: avoid;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
- .delivery-note {
- width: 100%;
- height: 100%;
- font-size: 12px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
- color: #000;
- }
- .header {
- text-align: center;
- margin-bottom: 8px;
- }
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
- .info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .info-row {
- line-height: 20px;
- }
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 12px;
- }
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 12px;
- }
- .table-section {
- margin-bottom: 40px;
- // flex: 0.6;
- }
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
- }
- .product-table th, .product-table td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 12px;
- line-height: 1.4;
- }
- .product-table th {
- font-weight: bold;
- }
- .total-value {
- font-weight: bold;
- }
- .footer-section {
- margin-top: auto;
- }
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 22px;
- justify-content: space-between;
- }
- .footer-item {
- display: flex;
- margin-right: 20px;
- }
- .footer-item .label {
- font-weight: bold;
- width: 80px;
- font-size: 12px;
- }
- .footer-item .value {
- min-width: 80px;
- font-size: 12px;
- }
- .address-item .address-value {
- min-width: 200px;
- }
- @media print {
- body {
- margin: 0;
- padding: 0;
- }
- .print-page {
- margin: 0;
- padding: 10mm;
- /* padding-left: 20mm; */
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
- }
- </style>
- </head>
- <body>
- `;
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ totalPrice,
+ productForm.value.taxRate
+ );
+ }
- // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
- printData.value.forEach((item, index) => {
- printContent += `
- <div class="print-page">
- <div class="delivery-note">
- <div class="header">
- <div class="document-title">闆跺敭鍙戣揣鍗�</div>
- </div>
-
- <div class="info-section">
- <div class="info-row">
- <div>
- <span class="label">鍙戣揣鏃ユ湡锛�</span>
- <span class="value">${formatDate(
- item.createTime
- )}</span>
- </div>
- <div>
- <span class="label">瀹㈡埛鍚嶇О锛�</span>
- <span class="value">${
- item.customerName
- }</span>
- </div>
- </div>
- <div class="info-row">
- <span class="label">鍗曞彿锛�</span>
- <span class="value">${
- item.salesContractNo ||
- ""
- }</span>
- </div>
- </div>
-
- <div class="table-section">
- <table class="product-table">
- <thead>
- <tr>
- <th>浜у搧鍚嶇О</th>
- <th>瑙勬牸鍨嬪彿</th>
- <th>鍗曚綅</th>
- <th>鍗曚环</th>
- <th>闆跺敭鏁伴噺</th>
- <th>闆跺敭閲戦</th>
- </tr>
- </thead>
- <tbody>
- ${
- item.products &&
- item
- .products
- .length >
- 0
- ? item.products
- .map(
- (
- product
- ) => `
- <tr>
- <td>${
- product.productCategory ||
- ""
- }</td>
- <td>${
- product.specificationModel ||
- ""
- }</td>
- <td>${
- product.unit ||
- ""
- }</td>
- <td>${
- product.taxInclusiveUnitPrice ||
- "0"
- }</td>
- <td>${
- product.quantity ||
- "0"
- }</td>
- <td>${
- product.taxInclusiveTotalPrice ||
- "0"
- }</td>
- </tr>
- `
- )
- .join(
- ""
- )
- : '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
- }
- </tbody>
- <tfoot>
- <tr>
- <td class="label">鍚堣</td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value">${getTotalQuantityForPrint(
- item.products
- )}</td>
- <td class="total-value">${getTotalAmountForPrint(
- item.products
- )}</td>
- </tr>
- </tfoot>
- </table>
- </div>
-
- <div class="footer-section">
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鏀惰揣鐢佃瘽锛�</span>
- <span class="value"></span>
- </div>
- <div class="footer-item">
- <span class="label">鏀惰揣浜猴細</span>
- <span class="value"></span>
- </div>
- <div class="footer-item address-item">
- <span class="label">鏀惰揣鍦板潃锛�</span>
- <span class="value address-value"></span>
- </div>
- </div>
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">${
- userStore.nickName ||
- "鎾曞紑鍓�"
- }</span>
- </div>
- <div class="footer-item">
- <span class="label">鎵撳嵃鏃ユ湡锛�</span>
- <span class="value">${formatDateTime(
- new Date()
- )}</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- `;
- });
-
- printContent += `
- </body>
- </html>
- `;
-
- // 鍐欏叆鍐呭鍒版柊绐楀彛
- printWindow.document.write(printContent);
- printWindow.document.close();
-
- // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
- printWindow.onload = () => {
- setTimeout(() => {
- printWindow.print();
- printWindow.close();
- printPreviewVisible.value = false;
- }, 500);
+ isCalculating.value = false;
};
-};
-// 鏍煎紡鍖栨棩鏈�
-const formatDate = (dateString) => {
- if (!dateString) return getCurrentDate();
- return dayjs(dateString).format("YYYY/MM/DD HH:mm:ss");
-};
-// 鏍煎紡鍖栨棩鏈熸椂闂�
-const formatDateTime = (date) => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const seconds = String(date.getSeconds()).padStart(2, "0");
- return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
-};
-// 璁$畻浜у搧鎬绘暟閲�
-const getTotalQuantity = (products) => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.quantity) || 0);
- }, 0);
- return total.toFixed(2);
-};
-// 璁$畻浜у搧鎬婚噾棰�
-const getTotalAmount = (products) => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
- }, 0);
- return total.toFixed(2);
-};
+ // 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+ const calculateFromExclusiveTotalPrice = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
-// 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
-const getTotalQuantityForPrint = (products) => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.quantity) || 0);
- }, 0);
- return total.toFixed(2);
-};
-
-const getTotalAmountForPrint = (products) => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
- }, 0);
- return total.toFixed(2);
-};
-
-const mathNum = () => {
- console.log("productForm.value", productForm.value);
- if (!productForm.value.taxInclusiveUnitPrice) {
- return;
- }
- if (!productForm.value.quantity) {
- return;
- }
- // 鍚◣鎬讳环璁$畻
- productForm.value.taxInclusiveTotalPrice =
- proxy.calculateTaxIncludeTotalPrice(
- productForm.value.taxInclusiveUnitPrice,
- productForm.value.quantity
+ const exclusiveTotalPrice = parseFloat(
+ productForm.value.taxExclusiveTotalPrice
);
- if (productForm.value.taxRate) {
- // 涓嶅惈绋庢�讳环璁$畻
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-};
+ const quantity = parseFloat(productForm.value.quantity);
+ const taxRate = parseFloat(productForm.value.taxRate);
-// 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
-const calculateFromTotalPrice = () => {
- if (isCalculating.value) return;
+ if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
+ return;
+ }
- const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
- const quantity = parseFloat(productForm.value.quantity);
+ isCalculating.value = true;
- if (!totalPrice || !quantity || quantity <= 0) {
- return;
- }
+ // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
+ const taxRateDecimal = taxRate / 100;
+ const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
+ productForm.value.taxInclusiveTotalPrice = formatDecimal(inclusiveTotalPrice);
- isCalculating.value = true;
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- totalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
-const calculateFromExclusiveTotalPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const exclusiveTotalPrice = parseFloat(
- productForm.value.taxExclusiveTotalPrice
- );
- const quantity = parseFloat(productForm.value.quantity);
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
- const taxRateDecimal = taxRate / 100;
- const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
- productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (
- inclusiveTotalPrice / quantity
- ).toFixed(2);
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
-const calculateFromQuantity = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
-const calculateFromUnitPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
-const calculateFromTaxRate = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const inclusiveTotalPrice = parseFloat(
- productForm.value.taxInclusiveTotalPrice
- );
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!inclusiveTotalPrice || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻涓嶅惈绋庢�讳环
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate);
-
- isCalculating.value = false;
-};
-/**
- * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
- * @param row 琛屾暟鎹�
- */
-const getShippingStatusText = (row) => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
- // if (row.shippingDate || row.shippingCarNumber) {
- // return "宸插彂璐�";
- // }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
- if (status === null || status === undefined || status === "") {
- return "寰呭彂璐�";
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const statusTextMap = {
- 寰呭彂璐�: "寰呭彂璐�",
- 寰呭鏍�: "寰呭鏍�",
- 瀹℃牳涓�: "瀹℃牳涓�",
- 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
- 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
- 宸插彂璐�: "宸插彂璐�",
- 閮ㄥ垎鍙戣揣: "閮ㄥ垎鍙戣揣",
- };
- return statusTextMap[statusStr] || "寰呭彂璐�";
-};
-
-/**
- * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
- * @param row 琛屾暟鎹�
- */
-const getShippingStatusType = (row) => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
- if (row.shippingStatus === "宸插彂璐�") {
- return "success";
- }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
- if (status === null || status === undefined || status === "") {
- return "info";
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const typeTextMap = {
- 寰呭彂璐�: "info",
- 寰呭鏍�: "info",
- 瀹℃牳涓�: "warning",
- 瀹℃牳鎷掔粷: "danger",
- 瀹℃牳閫氳繃: "success",
- 宸插彂璐�: "success",
- 閮ㄥ垎鍙戣揣: "warning",
- };
- return typeTextMap[statusStr] || "info";
-};
-
-/**
- * 鍒ゆ柇鏄惁鍙互鍙戣揣
- * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐с�佸鎵逛腑銆佸鏍告嫆缁濄�侀儴鍒嗗彂璐х殑鏃跺�欐墠鍙互鍙戣揣
- * @param row 琛屾暟鎹�
- */
-const canShip = (row) => {
- // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
- if (row.approveStatus !== 1) {
- return false;
- }
-
- // 鑾峰彇鍙戣揣鐘舵��
- const shippingStatus = row.shippingStatus;
-
- // 濡傛灉宸插彂璐э紝涓嶈兘鍐嶆鍙戣揣
- if (shippingStatus === "宸插彂璐�") {
- return false;
- }
-
- // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"銆�"瀹℃壒涓�"銆�"瀹℃牳鎷掔粷"鎴�"閮ㄥ垎鍙戣揣"
- const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
- return (
- statusStr === "寰呭彂璐�" ||
- statusStr === "瀹℃壒涓�" ||
- statusStr === "瀹℃牳鎷掔粷" ||
- statusStr === "閮ㄥ垎鍙戣揣"
- );
-};
-
-// 鎵撳紑闄勪欢寮圭獥
-const recordId = ref(0);
-const fileDialogVisible = ref(false);
-
-// 鎵撳紑闄勪欢寮规
-const openFileDialog = async (row) => {
- recordId.value = row.id;
- fileDialogVisible.value = true;
-};
-
-// 鎵撳紑鍙戣揣寮规
-const openDeliveryForm = async (row) => {
- // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
- if (!canShip(row)) {
- proxy.$modal.msgWarning(
- "鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐с�佸鎵逛腑銆佸鏍告嫆缁濇垨閮ㄥ垎鍙戣揣鐨勬椂鍊欐墠鍙互鍙戣揣"
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = formatDecimal(
+ inclusiveTotalPrice / quantity
);
- return;
- }
- // 瀹℃壒涓椂鎻愮ず鐢ㄦ埛宸叉湁寰呭鎵圭殑鍙戣揣璁板綍
- const statusStr = row.shippingStatus ? String(row.shippingStatus).trim() : "";
- if (statusStr === "瀹℃壒涓�") {
- proxy.$modal.msgWarning("璇ヤ骇鍝佸瓨鍦ㄥ緟瀹℃壒鐨勫彂璐ц褰曪紝璇锋敞鎰忛伩鍏嶉噸澶嶆彁浜�");
- }
-
- currentDeliveryRow.value = row;
- const batchNoList = await getDeliveryBatchNoList(
- row.productModelId || row.modelId
- );
- deliveryForm.value = {
- shippingCarNumber: "",
- expressCompany: "",
- expressNumber: "",
- type: "璐ц溅",
- batchNo: [],
- batchNoList,
+ isCalculating.value = false;
};
- deliveryFileList.value = [];
- deliveryFormVisible.value = true;
-};
-// 鎻愪氦鍙戣揣琛ㄥ崟
-const submitDelivery = () => {
- proxy.$refs["deliveryFormRef"].validate((valid) => {
- if (valid) {
- const selectedBatchRows = getSelectedDeliveryBatchRows();
- if (selectedBatchRows.length === 0) {
- proxy.$modal.msgWarning("璇疯嚦灏戝~鍐欎竴涓壒鍙风殑鍙戣揣鏁伴噺");
- return;
- }
- const totalDeliveryQuantity = selectedBatchRows.reduce(
- (sum, item) => sum + Number(item.deliveryQuantity || 0),
- 0
+ // 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
+ const calculateFromQuantity = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = formatDecimal(unitPrice * quantity);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+ };
+
+ // 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
+ const calculateFromUnitPrice = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = formatDecimal(unitPrice * quantity);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+ };
+
+ // 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
+ const calculateFromTaxRate = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const inclusiveTotalPrice = parseFloat(
+ productForm.value.taxInclusiveTotalPrice
+ );
+ const taxRate = parseFloat(productForm.value.taxRate);
+
+ if (!inclusiveTotalPrice || !taxRate) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate);
+
+ isCalculating.value = false;
+ };
+ /**
+ * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
+ * @param row 琛屾暟鎹�
+ */
+ const getShippingStatusText = row => {
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
+ // if (row.shippingDate || row.shippingCarNumber) {
+ // return "宸插彂璐�";
+ // }
+
+ // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+ const status = row.shippingStatus;
+
+ // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
+ if (status === null || status === undefined || status === "") {
+ return "寰呭彂璐�";
+ }
+
+ // 鐘舵�佹槸瀛楃涓�
+ const statusStr = String(status).trim();
+ const statusTextMap = {
+ 寰呭彂璐�: "寰呭彂璐�",
+ 寰呭鏍�: "寰呭鏍�",
+ 瀹℃牳涓�: "瀹℃牳涓�",
+ 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
+ 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
+ 宸插彂璐�: "宸插彂璐�",
+ 閮ㄥ垎鍙戣揣: "閮ㄥ垎鍙戣揣",
+ };
+ return statusTextMap[statusStr] || "寰呭彂璐�";
+ };
+
+ /**
+ * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
+ * @param row 琛屾暟鎹�
+ */
+ const getShippingStatusType = row => {
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
+ if (row.shippingStatus === "宸插彂璐�") {
+ return "success";
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+ const status = row.shippingStatus;
+
+ // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
+ if (status === null || status === undefined || status === "") {
+ return "info";
+ }
+
+ // 鐘舵�佹槸瀛楃涓�
+ const statusStr = String(status).trim();
+ const typeTextMap = {
+ 寰呭彂璐�: "info",
+ 寰呭鏍�: "info",
+ 瀹℃牳涓�: "warning",
+ 瀹℃牳鎷掔粷: "danger",
+ 瀹℃牳閫氳繃: "success",
+ 宸插彂璐�: "success",
+ 閮ㄥ垎鍙戣揣: "warning",
+ };
+ return typeTextMap[statusStr] || "info";
+ };
+
+ /**
+ * 鍒ゆ柇鏄惁鍙互鍙戣揣
+ * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
+ * @param row 琛屾暟鎹�
+ */
+ const canShip = row => {
+ // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
+ if (row.approveStatus !== 1) {
+ return false;
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵��
+ const shippingStatus = row.shippingStatus;
+
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
+ if (shippingStatus === "宸插彂璐�") {
+ return false;
+ }
+
+ // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
+ const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
+ return (
+ statusStr === "寰呭彂璐�" ||
+ statusStr === "瀹℃牳鎷掔粷" ||
+ statusStr === "閮ㄥ垎鍙戣揣"
+ );
+ };
+
+ // 鎵撳紑闄勪欢寮圭獥
+ const recordId = ref(0);
+ const fileDialogVisible = ref(false);
+
+ // 鎵撳紑闄勪欢寮规
+ const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileDialogVisible.value = true;
+ };
+
+ // 涓嬭浇閿�鍞崟
+ const downloadOrder = async (id) => {
+ try {
+ const res = await getPrintData(id);
+ const data = res.data || res;
+ downloadSalesJpg(data.companyName, data.ledger, '閿�鍞崟_' + (data.ledger.salesContractNo || id) + '.jpg');
+ } catch (e) {
+ console.error('涓嬭浇澶辫触:', e);
+ }
+ };
+
+ // 鎵撳嵃閿�鍞崟
+ const printOrder = async (id) => {
+ try {
+ const res = await getPrintData(id);
+ const data = res.data || res;
+ printSales(data.companyName, data.ledger);
+ } catch (e) {
+ console.error('鎵撳嵃澶辫触:', e);
+ }
+ };
+
+ // 鎵撳紑鍙戣揣寮规
+ const openDeliveryForm = async row => {
+ // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
+ if (!canShip(row)) {
+ proxy.$modal.msgWarning(
+ "鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
);
- const currentRowNoQuantity = Number(
- currentDeliveryRow.value?.noQuantity || 0
- );
- if (
- currentRowNoQuantity > 0 &&
- totalDeliveryQuantity > currentRowNoQuantity
- ) {
- proxy.$modal.msgWarning("鎵瑰彿鍙戣揣鎬绘暟涓嶈兘瓒呰繃寰呭彂璐ф暟閲�");
- return;
- }
- // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
- const currentExpandedKeys = [...expandedRowKeys.value];
- const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
- deliveryForm.value.batchNo = selectedBatchRows.map((item) => item.id);
- const productModelId =
- currentDeliveryRow.value.productModelId ||
- currentDeliveryRow.value.modelId;
- addShippingInfo({
- salesLedgerId: salesLedgerId,
- salesLedgerProductId: currentDeliveryRow.value.id,
- type: deliveryForm.value.type,
- shippingCarNumber:
- deliveryForm.value.type === "璐ц溅"
- ? deliveryForm.value.shippingCarNumber
- : "",
- expressCompany:
- deliveryForm.value.type === "蹇��"
- ? deliveryForm.value.expressCompany
- : "",
- expressNumber:
- deliveryForm.value.type === "蹇��"
- ? deliveryForm.value.expressNumber
- : "",
- storageBlobDTOs: deliveryFileList.value || [],
- batchNo: deliveryForm.value.batchNo,
- batchNoDetailList: selectedBatchRows.map((item) => ({
- stockInventoryId: item.id,
- batchNo: item.batchNo,
- quantity: Number(item.deliveryQuantity || 0),
- productModelId: productModelId,
- })),
- }).then(() => {
- proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
- closeDeliveryDia();
- // 鍒锋柊涓昏〃鏁版嵁
- getList().then(() => {
- // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
- if (currentExpandedKeys.length > 0) {
- // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
- const loadPromises = currentExpandedKeys.map((ledgerId) => {
- return productList({ salesLedgerId: ledgerId, type: 1 }).then(
- (res) => {
- const index = tableData.value.findIndex(
- (item) => item.id === ledgerId
- );
- if (index > -1) {
- tableData.value[index].children = res.data;
+ return;
+ }
+
+ currentDeliveryRow.value = row;
+ const batchNoList = await getDeliveryBatchNoList(
+ row.productModelId || row.modelId
+ );
+ deliveryForm.value = {
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "",
+ type: "璐ц溅",
+ batchNo: [],
+ batchNoList,
+ };
+ deliveryFileList.value = [];
+ deliveryFormVisible.value = true;
+ };
+
+ // 鎻愪氦鍙戣揣琛ㄥ崟
+ const submitDelivery = () => {
+ proxy.$refs["deliveryFormRef"].validate(valid => {
+ if (valid) {
+ const selectedBatchRows = getSelectedDeliveryBatchRows();
+ if (selectedBatchRows.length === 0) {
+ proxy.$modal.msgWarning("璇疯嚦灏戝~鍐欎竴涓壒鍙风殑鍙戣揣鏁伴噺");
+ return;
+ }
+ const totalDeliveryQuantity = selectedBatchRows.reduce(
+ (sum, item) => sum + Number(item.deliveryQuantity || 0),
+ 0
+ );
+ const currentRowNoQuantity = Number(
+ currentDeliveryRow.value?.noQuantity || 0
+ );
+ if (
+ currentRowNoQuantity > 0 &&
+ totalDeliveryQuantity > currentRowNoQuantity
+ ) {
+ proxy.$modal.msgWarning("鎵瑰彿鍙戣揣鎬绘暟涓嶈兘瓒呰繃寰呭彂璐ф暟閲�");
+ return;
+ }
+ // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
+ const currentExpandedKeys = [...expandedRowKeys.value];
+ const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
+ deliveryForm.value.batchNo = selectedBatchRows.map(item => item.id);
+ const productModelId =
+ currentDeliveryRow.value.productModelId ||
+ currentDeliveryRow.value.modelId;
+ deliveryLoading.value = true;
+ addShippingInfo({
+ salesLedgerId: salesLedgerId,
+ salesLedgerProductId: currentDeliveryRow.value.id,
+ type: deliveryForm.value.type,
+ shippingCarNumber:
+ deliveryForm.value.type === "璐ц溅"
+ ? deliveryForm.value.shippingCarNumber
+ : "",
+ expressCompany:
+ deliveryForm.value.type === "蹇��"
+ ? deliveryForm.value.expressCompany
+ : "",
+ expressNumber:
+ deliveryForm.value.type === "蹇��"
+ ? deliveryForm.value.expressNumber
+ : "",
+ storageBlobDTOs: deliveryFileList.value || [],
+ batchNo: deliveryForm.value.batchNo,
+ batchNoDetailList: selectedBatchRows.map(item => ({
+ stockInventoryId: item.id,
+ batchNo: item.batchNo,
+ quantity: Number(item.deliveryQuantity || 0),
+ productModelId: productModelId,
+ })),
+ }).then(() => {
+ proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
+ closeDeliveryDia();
+ // 鍒锋柊涓昏〃鏁版嵁
+ getList().then(() => {
+ // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
+ if (currentExpandedKeys.length > 0) {
+ // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
+ const loadPromises = currentExpandedKeys.map(ledgerId => {
+ return productList({ salesLedgerId: ledgerId, type: 1 }).then(
+ res => {
+ const index = tableData.value.findIndex(
+ item => item.id === ledgerId
+ );
+ if (index > -1) {
+ tableData.value[index].children = res.data;
+ }
}
- }
- );
- });
- Promise.all(loadPromises).then(() => {
- // 鎭㈠灞曞紑鐘舵��
- expandedRowKeys.value = currentExpandedKeys;
- });
- }
+ );
+ });
+ Promise.all(loadPromises).then(() => {
+ // 鎭㈠灞曞紑鐘舵��
+ expandedRowKeys.value = currentExpandedKeys;
+ });
+ }
+ });
+ }).finally(() => {
+ deliveryLoading.value = false;
});
- });
+ }
+ });
+ };
+
+ // 鍏抽棴鍙戣揣寮规
+ const handleDeliveryTypeChange = val => {
+ if (val === "璐ц溅") {
+ deliveryForm.value.expressCompany = "";
+ deliveryForm.value.expressNumber = "";
+ } else {
+ deliveryForm.value.shippingCarNumber = "";
}
- });
-};
+ };
-// 鍏抽棴鍙戣揣寮规
-const handleDeliveryTypeChange = (val) => {
- if (val === "璐ц溅") {
- deliveryForm.value.expressCompany = "";
- deliveryForm.value.expressNumber = "";
- } else {
- deliveryForm.value.shippingCarNumber = "";
- }
-};
-
-const closeDeliveryDia = () => {
- proxy.resetForm("deliveryFormRef");
- deliveryFileList.value = [];
- deliveryFormVisible.value = false;
- currentDeliveryRow.value = null;
-};
-const currentFactoryName = ref("");
-const getCurrentFactoryName = async () => {
- let res = await userStore.getInfo();
- currentFactoryName.value = res.user.currentFactoryName;
-};
-onMounted(() => {
- searchForm.salesContractNo = route.query.salesContractNo;
- getList();
- userListNoPage().then((res) => {
- userList.value = res.data;
+ const closeDeliveryDia = () => {
+ proxy.resetForm("deliveryFormRef");
+ deliveryFileList.value = [];
+ deliveryFormVisible.value = false;
+ currentDeliveryRow.value = null;
+ };
+ const currentFactoryName = ref("");
+ const getCurrentFactoryName = async () => {
+ let res = await userStore.getInfo();
+ currentFactoryName.value = res.user.currentFactoryName;
+ };
+ onMounted(() => {
+ searchForm.salesContractNo = route.query.salesContractNo;
+ getList();
+ userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ getCurrentFactoryName();
});
- getCurrentFactoryName();
-});
</script>
<style scoped lang="scss">
-.ml-10 {
- margin-left: 10px;
-}
-
-:deep(.yellow) {
- background-color: #faf0de;
-}
-
-:deep(.pink) {
- background-color: #fae1de;
-}
-
-:deep(.red) {
- background-color: #fae1de;
-}
-
-:deep(.purple) {
- background-color: #f4defa;
-}
-
-.table_list {
- margin-top: unset;
-}
-
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-
-.print-preview-dialog {
- .el-dialog__body {
- padding: 0;
- max-height: 80vh;
- overflow-y: auto;
- }
-}
-
-.print-preview-container {
- .print-preview-header {
- padding: 15px;
- border-bottom: 1px solid #e4e7ed;
- text-align: center;
-
- .el-button {
- margin: 0 10px;
- }
+ .ml-10 {
+ margin-left: 10px;
}
- .print-preview-content {
- padding: 20px;
- background-color: #f5f5f5;
- min-height: 400px;
- }
-}
-
-.print-page {
- width: 220mm;
- height: 90mm;
- padding: 10mm;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin-bottom: 10px;
- box-sizing: border-box;
-}
-
-.delivery-note {
- width: 100%;
- height: 100%;
- font-family: "SimSun", serif;
- font-size: 10px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
-}
-
-.header {
- text-align: center;
- margin-bottom: 8px;
-
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
+ :deep(.yellow) {
+ background-color: #faf0de;
}
- .document-title {
- font-size: 16px;
- font-weight: bold;
+ :deep(.pink) {
+ background-color: #fae1de;
}
-}
-.info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- .info-row {
- line-height: 20px;
-
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 14px;
- }
-
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 14px;
- }
+ :deep(.red) {
+ background-color: #fae1de;
}
-}
-.table-section {
- margin-bottom: 4px;
- flex: 1;
-
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
-
- th,
- td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 14px;
- line-height: 1.4;
- }
-
- th {
- font-weight: bold;
- }
-
- .total-label {
- text-align: right;
- font-weight: bold;
- }
-
- .total-value {
- font-weight: bold;
- }
+ :deep(.purple) {
+ background-color: #f4defa;
}
-}
-.footer-section {
- .footer-row {
+ .table_list {
+ margin-top: unset;
+ }
+
+ .actions {
display: flex;
- margin-bottom: 3px;
- line-height: 20px;
justify-content: space-between;
+ margin-bottom: 10px;
+ }
- .footer-item {
- display: flex;
- margin-right: 20px;
+ .print-preview-dialog {
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
+ }
+ }
+
+ .print-preview-container {
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
+ text-align: center;
+
+ .el-button {
+ margin: 0 10px;
+ }
+ }
+
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
+ }
+
+ .print-page {
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
+ }
+
+ .delivery-note {
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .header {
+ text-align: center;
+ margin-bottom: 8px;
+
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+ }
+
+ .info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .info-row {
+ line-height: 20px;
.label {
font-weight: bold;
- width: 80px;
+ width: 60px;
font-size: 14px;
}
.value {
+ margin-right: 20px;
min-width: 80px;
font-size: 14px;
}
+ }
+ }
- &.address-item {
- .address-value {
- min-width: 200px;
+ .table-section {
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th,
+ td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
+ }
+
+ .footer-section {
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 14px;
+ }
+
+ .value {
+ min-width: 80px;
+ font-size: 14px;
+ }
+
+ &.address-item {
+ .address-value {
+ min-width: 200px;
+ }
}
}
}
}
-}
-@media print {
- .app-container {
- display: none;
- }
+ @media print {
+ .app-container {
+ display: none;
+ }
- .print-page {
- box-shadow: none;
- margin: 0;
- padding: 10mm;
- padding-left: 20mm;
- page-break-inside: avoid;
- page-break-after: always;
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
}
- .print-page:last-child {
- page-break-after: avoid;
- }
-}
</style>
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
index fce764f..455f686 100644
--- a/src/views/salesManagement/salesQuotation/index.vue
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -65,7 +65,7 @@
</el-table-column>
<el-table-column prop="totalAmount" label="鎶ヤ环閲戦" width="120">
<template #default="scope">
- 楼{{ scope.row.totalAmount.toFixed(2) }}
+ 楼{{ formatDecimal(scope.row.totalAmount) }}
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
@@ -215,7 +215,7 @@
<el-table-column prop="unitPrice" label="鍗曚环">
<template #default="scope">
<el-form-item :prop="`products.${scope.$index}.unitPrice`" class="product-table-form-item">
- <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" />
+ <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="6" :step="0.000001" style="width: 100%" />
</el-form-item>
</template>
</el-table-column>
@@ -267,7 +267,7 @@
<!-- <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="鎶ヤ环鎬婚" :span="2">
- <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">楼{{ currentQuotation.totalAmount?.toFixed(2) }}</span>
+ <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">楼{{ formatDecimal(currentQuotation.totalAmount) }}</span>
</el-descriptions-item>
</el-descriptions>
@@ -279,7 +279,7 @@
<el-table-column prop="unit" label="鍗曚綅" />
<el-table-column prop="unitPrice" label="鍗曚环">
<template #default="scope">
- 楼{{ scope.row.unitPrice.toFixed(2) }}
+ 楼{{ formatDecimal(scope.row.unitPrice) }}
</template>
</el-table-column>
</el-table>
@@ -303,6 +303,7 @@
import {modelList, productTreeList} from "@/api/basicData/product.js";
import {listCustomer} from "@/api/basicData/customer.js";
import { userListNoPage } from "@/api/system/user.js";
+import { formatDecimal, roundAmount } from '@/utils/numberFormat';
// 鍝嶅簲寮忔暟鎹�
const loading = ref(false)
@@ -346,6 +347,7 @@
const baseRules = {
customer: [{ required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change' }],
+ customerId: [{ required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change' }],
salesperson: [{ required: true, message: '璇烽�夋嫨涓氬姟鍛�', trigger: 'change' }],
quotationDate: [{ required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change' }],
validDate: [{ required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'change' }],
@@ -686,11 +688,11 @@
return
}
- // 璁$畻鎵�鏈変骇鍝佺殑鍗曚环鎬诲拰
- form.totalAmount = form.products.reduce((sum, product) => {
+ // 璁$畻鎵�鏈変骇鍝佺殑鍗曚环鎬诲拰锛屼繚鐣欏叚浣嶅皬鏁�
+ form.totalAmount = roundAmount(form.products.reduce((sum, product) => {
const price = Number(product.unitPrice) || 0
return sum + price
- }, 0)
+ }, 0))
form.customer = customerOption.value.find(item => item.id === form.customerId)?.customerName || ''
if (isEdit.value) {
diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue
index a177314..0b7601b 100644
--- a/src/views/system/dept/index.vue
+++ b/src/views/system/dept/index.vue
@@ -63,7 +63,7 @@
</el-table-column>
<el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="200">
<template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
+ <span>{{ parseTime(scope.row.createTime,'{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue
index f4e2c6f..6d860f5 100644
--- a/src/views/system/dict/data.vue
+++ b/src/views/system/dict/data.vue
@@ -105,7 +105,7 @@
<el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
<el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
<template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" align="center" width="160" class-name="small-padding fixed-width">
diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue
index 6c67e1b..ff38b58 100644
--- a/src/views/system/dict/index.vue
+++ b/src/views/system/dict/index.vue
@@ -120,7 +120,7 @@
<el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
<el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
<template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" align="center" width="160" class-name="small-padding fixed-width">
diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue
index 3bea122..ecf1ebf 100644
--- a/src/views/system/menu/index.vue
+++ b/src/views/system/menu/index.vue
@@ -71,7 +71,7 @@
</el-table-column>
<el-table-column label="鍒涘缓鏃堕棿" align="center" width="160" prop="createTime">
<template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
+ <span>{{ parseTime(scope.row.createTime,'{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" align="center" width="210" class-name="small-padding fixed-width">
diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue
index 0e80652..bb6b1d7 100644
--- a/src/views/system/post/index.vue
+++ b/src/views/system/post/index.vue
@@ -82,7 +82,7 @@
<el-table-column label="宀椾綅缂栧彿" align="center" prop="postId" />
<el-table-column label="宀椾綅缂栫爜" align="center" prop="postCode" />
<el-table-column label="宀椾綅鍚嶇О" align="center" prop="postName" />
- <el-table-column label="宀椾綅鎺掑簭" align="center" prop="postSort" />
+ <!-- <el-table-column label="宀椾綅鎺掑簭" align="center" prop="postSort" /> -->
<el-table-column label="鐘舵��" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
@@ -90,7 +90,7 @@
</el-table-column>
<el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
<template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
+ <span>{{ parseTime(scope.row.createTime,'{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" width="180" align="center" class-name="small-padding fixed-width">
diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue
index 85ecf28..495141c 100644
--- a/src/views/system/role/index.vue
+++ b/src/views/system/role/index.vue
@@ -110,7 +110,7 @@
</el-table-column>
<el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime">
<template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
diff --git a/src/views/systemArchitecture/index.vue b/src/views/systemArchitecture/index.vue
index a070122..334194f 100644
--- a/src/views/systemArchitecture/index.vue
+++ b/src/views/systemArchitecture/index.vue
@@ -9,7 +9,9 @@
<section class="section-card section-card--top">
<article class="module-title module-title--basic">
<div class="module-title__icon">
- <img :src="jichupeizhi" alt="鍩虹閰嶇疆" />
+ <span class="module-title__icon-shape">
+ <svg-icon icon-class="system" />
+ </span>
</div>
<div class="module-title__text">
<h2>鍩虹閰嶇疆</h2>
@@ -20,9 +22,9 @@
<div class="flow-row flow-row--top">
<template v-for="item in basicFlow" :key="item.key">
<div class="flow-item">
- <article class="flow-node">
+ <article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon">
- <img :src="item.icon" :alt="item.name" />
+ <svg-icon :icon-class="item.icon" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -35,7 +37,9 @@
<div class="panel-card panel-card--sale">
<article class="module-title module-title--sale">
<div class="module-title__icon">
- <img :src="xiaoshoupeizhi" alt="閿�鍞厤缃�" />
+ <span class="module-title__icon-shape">
+ <svg-icon icon-class="chart" />
+ </span>
</div>
<div class="module-title__text">
<h2>閿�鍞厤缃�</h2>
@@ -46,9 +50,9 @@
<div class="flow-grid flow-grid--sale">
<template v-for="(item, index) in saleFlow" :key="item.key">
<div class="grid-cell">
- <article class="flow-node">
+ <article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon" :class="{ 'flow-node__icon--accent': item.accent }">
- <img :src="item.icon" :alt="item.name" />
+ <svg-icon :icon-class="item.icon" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -66,6 +70,11 @@
</div>
<div class="ai-stage">
+ <div class="ai-stage__connector ai-stage__connector--top"></div>
+ <div class="ai-stage__connector ai-stage__connector--left"></div>
+ <div class="ai-stage__connector ai-stage__connector--right"></div>
+ <div class="ai-stage__connector ai-stage__connector--bottom"></div>
+
<div class="ai-stage__ring">
<div class="ai-stage__core">
<img :src="aiHead" alt="AI 鏍稿績寮曟搸" />
@@ -76,7 +85,9 @@
<div class="panel-card panel-card--purchase">
<article class="module-title module-title--purchase">
<div class="module-title__icon">
- <img :src="caigoupeizhi" alt="閲囪喘閰嶇疆" />
+ <span class="module-title__icon-shape">
+ <svg-icon icon-class="shopping" />
+ </span>
</div>
<div class="module-title__text">
<h2>閲囪喘閰嶇疆</h2>
@@ -87,9 +98,9 @@
<div class="flow-grid flow-grid--purchase">
<template v-for="(item, index) in purchaseFlow" :key="item.key">
<div class="grid-cell">
- <article class="flow-node">
+ <article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon" :class="{ 'flow-node__icon--accent': item.accent }">
- <img :src="item.icon" :alt="item.name" />
+ <svg-icon :icon-class="item.icon" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -110,7 +121,9 @@
<section class="section-card section-card--bottom">
<article class="module-title module-title--produce">
<div class="module-title__icon">
- <img :src="shengchanpeizhi" alt="鐢熶骇閰嶇疆" />
+ <span class="module-title__icon-shape">
+ <svg-icon icon-class="build" />
+ </span>
</div>
<div class="module-title__text">
<h2>鐢熶骇閰嶇疆</h2>
@@ -121,9 +134,9 @@
<div class="flow-row flow-row--wide">
<template v-for="(item, index) in produceFlow" :key="item.key">
<div class="flow-item">
- <article class="flow-node">
+ <article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon" :class="{ 'flow-node__icon--green': item.green, 'flow-node__icon--accent': item.accent }">
- <img :src="item.icon" :alt="item.name" />
+ <svg-icon :icon-class="item.icon" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -136,7 +149,9 @@
<section class="section-card section-card--bottom">
<article class="module-title module-title--store">
<div class="module-title__icon">
- <img :src="cangchuwuliu" alt="浠撳偍鐗╂祦" />
+ <span class="module-title__icon-shape">
+ <svg-icon icon-class="redis" />
+ </span>
</div>
<div class="module-title__text">
<h2>浠撳偍鐗╂祦</h2>
@@ -147,9 +162,9 @@
<div class="flow-row flow-row--store">
<template v-for="(item, index) in storeFlow" :key="item.key">
<div class="flow-item">
- <article class="flow-node">
+ <article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon">
- <img :src="item.icon" :alt="item.name" />
+ <svg-icon :icon-class="item.icon" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -163,77 +178,88 @@
</template>
<script setup>
-import aiHead from '@/assets/system/ai.svg'
-import jichupeizhi from '@/assets/system/jichupeizhi.svg'
-import xiaoshoupeizhi from '@/assets/system/xiaoshoupeizhi.svg'
-import caigoupeizhi from '@/assets/system/caigoupeizhi.svg'
-import shengchanpeizhi from '@/assets/system/shengchanpeizhi.svg'
-import cangchuwuliu from '@/assets/system/cangchuwuliu.svg'
+import { useRouter } from 'vue-router'
+import aiHead from '@/assets/images/head.svg'
-import yonghuguanli from '@/assets/system/yonghuguanli.svg'
-import shenpiguanli from '@/assets/system/shenpiguanli.svg'
-import chanpinweihu from '@/assets/system/chanpinweihu.svg'
+const router = useRouter()
-import kehudangan from '@/assets/system/kehudangan.svg'
-import xiaoshoubaojia from '@/assets/system/xiaoshoubaojia.svg'
-import xiaoshoutaizhang from '@/assets/system/xiaoshoutaizhang.svg'
-import fahuotaizhang from '@/assets/system/fahuotaizhang.svg'
-import xiaoshoutuihuo from '@/assets/system/xiaoshoutuihuo.svg'
+const routeMap = {
+ 'basic-role': '/system/role',
+ 'basic-user': '/system/user',
+ 'basic-post': '/system/post',
+ 'basic-dept': '/system/dept',
+ 'basic-product': '/basicData/product',
+ 'basic-approval': '/collaborativeApproval/approvalManagement',
+ 'sale-customer': '/salesManagement/customerFile',
+ 'sale-quote': '/salesManagement/salesQuotation',
+ 'sale-ledger': '/salesManagement/salesLedger',
+ 'sale-delivery': '/salesManagement/deliveryLedger',
+ 'sale-return': '/salesManagement/returnOrder',
+ 'purchase-supplier': '/procurementManagement/supplierManage',
+ 'purchase-ledger': '/procurementManagement/procurementLedger',
+ 'purchase-return': '/procurementManagement/purchaseReturnOrder',
+ 'purchase-contact': '/procurementManagement/paymentLedger',
+ 'purchase-report': '/procurementManagement/procurementReport',
+ 'produce-process': '/processDesign/productionManagement/productionProcess/index',
+ 'produce-bom': '/processDesign/productionManagement/productStructure/index',
+ 'produce-route': '/processDesign/processRoute',
+ 'produce-order': '/productionManagement/productionOrder',
+ 'produce-schedule': '/productionManagement/productionManagement/workOrderEdit/index',
+ 'produce-work': '/productionManagement/workOrderManagement',
+ 'produce-ledger': '/productionManagement/productionReporting',
+ 'produce-cost': '/productionManagement/productionCosting',
+ 'store-in': '/inventoryManagement/receiptManagement',
+ 'store-out': '/inventoryManagement/dispatchLog',
+ 'store-stock': '/inventoryManagement/stockManagement'
+}
-import gongyingshangdangan from '@/assets/system/gongyingshangdangan.svg'
-import caigoutaizhang from '@/assets/system/caigoutaizhang.svg'
-import caigoutuihuo from '@/assets/system/caigoutuihuo.svg'
-import gongyingshangwanglai from '@/assets/system/gongyingshangwanglai.svg'
-import caigoubaobiao from '@/assets/system/caigoubaobiao.svg'
-
-import gongxu from '@/assets/system/gongxu.svg'
-import BOM from '@/assets/system/BOM.svg'
-import shengchandingdan from '@/assets/system/shengchandingdan.svg'
-import shengchanpaichan from '@/assets/system/shengchanpaichan.svg'
-import baogong from '@/assets/system/baogong.svg'
-import baogongtaizhang from '@/assets/system/baogongtaizhang.svg'
-import shengchanheduan from '@/assets/system/shengchanheduan.svg'
-
-import rukuguanli from '@/assets/system/rukuguanli.svg'
-import chukuguanli from '@/assets/system/chukuguanli.svg'
-import kucunguanli from '@/assets/system/kucunguanli.svg'
+function goPage(key) {
+ const path = routeMap[key]
+ if (path) {
+ router.push(path)
+ }
+}
const basicFlow = [
- { key: 'basic-user', name: '鐢ㄦ埛绠$悊', icon: yonghuguanli },
- { key: 'basic-approval', name: '瀹℃壒绠$悊', icon: shenpiguanli },
- { key: 'basic-product', name: '浜у搧缁存姢', icon: chanpinweihu }
+ { key: 'basic-role', name: '瑙掕壊绠$悊', icon: 'user' },
+ { key: 'basic-user', name: '鐢ㄦ埛绠$悊', icon: 'peoples' },
+ { key: 'basic-post', name: '宀椾綅绠$悊', icon: 'tree' },
+ { key: 'basic-dept', name: '閮ㄩ棬绠$悊', icon: 'tree' },
+ { key: 'basic-product', name: '浜у搧缁存姢', icon: 'table' },
+ { key: 'basic-approval', name: '瀹℃壒绠$悊', icon: 'form' }
]
const saleFlow = [
- { key: 'sale-customer', name: '瀹㈡埛妗f', icon: kehudangan, arrow: 'right' },
- { key: 'sale-quote', name: '閿�鍞姤浠�', icon: xiaoshoubaojia, arrow: 'right' },
- { key: 'sale-ledger', name: '閿�鍞彴璐�', icon: xiaoshoutaizhang, arrow: 'right' },
- { key: 'sale-delivery', name: '鍙戣揣鍙拌处', icon: fahuotaizhang, arrow: 'right' },
- { key: 'sale-return', name: '閿�鍞��璐�', icon: xiaoshoutuihuo, accent: true }
+ { key: 'sale-customer', name: '瀹㈡埛妗f', icon: 'peoples', arrow: 'right' },
+ { key: 'sale-quote', name: '閿�鍞姤浠�', icon: 'form', arrow: 'right' },
+ { key: 'sale-ledger', name: '閿�鍞彴璐�', icon: 'monitor', arrow: 'right' },
+ { key: 'sale-delivery', name: '鍙戣揣鍙拌处', icon: 'clipboard', arrow: 'right' },
+ { key: 'sale-return', name: '閿�鍞��璐�', icon: 'nested', accent: true }
]
const purchaseFlow = [
- { key: 'purchase-supplier', name: '渚涘簲鍟嗘。妗�', icon: gongyingshangdangan, arrow: 'right' },
- { key: 'purchase-ledger', name: '閲囪喘鍙拌处', icon: caigoutaizhang, arrow: 'right' },
- { key: 'purchase-return', name: '閲囪喘閫�璐�', icon: caigoutuihuo, accent: true },
- { key: 'purchase-contact', name: '渚涘簲鍟嗗線鏉�', icon: gongyingshangwanglai, arrow: 'right' },
- { key: 'purchase-report', name: '閲囪喘鎶ヨ〃', icon: caigoubaobiao }
+ { key: 'purchase-supplier', name: '渚涘簲鍟嗘。妗�', icon: 'people', arrow: 'right' },
+ { key: 'purchase-ledger', name: '閲囪喘鍙拌处', icon: 'monitor', arrow: 'right' },
+ { key: 'purchase-return', name: '閲囪喘閫�璐�', icon: 'nested', accent: true },
+ { key: 'purchase-contact', name: '渚涘簲鍟嗗線鏉�', icon: 'peoples', arrow: 'right' },
+ { key: 'purchase-report', name: '閲囪喘鎶ヨ〃', icon: 'chart' }
]
const produceFlow = [
- { key: 'produce-process', name: '宸ュ簭', icon: gongxu },
- { key: 'produce-bom', name: 'BOM', icon: BOM },
- { key: 'produce-order', name: '鐢熶骇璁㈠崟', icon: shengchandingdan, green: true },
- { key: 'produce-schedule', name: '鐢熶骇鎺掍骇', icon: shengchanpaichan },
- { key: 'produce-work', name: '鐢熶骇鎶ュ伐', icon: baogong },
- { key: 'produce-ledger', name: '鎶ュ伐鍙拌处', icon: baogongtaizhang },
- { key: 'produce-cost', name: '鐢熶骇鏍哥畻', icon: shengchanheduan, accent: true }
+ { key: 'produce-process', name: '宸ュ簭', icon: 'list' },
+ { key: 'produce-bom', name: 'BOM', icon: 'monitor' },
+ { key: 'produce-route', name: '宸ヨ壓璺嚎', icon: 'tree', green: true },
+ { key: 'produce-order', name: '鐢熶骇璁㈠崟', icon: 'peoples', green: true },
+ { key: 'produce-schedule', name: '鐢熶骇鎺掍骇', icon: 'time' },
+ { key: 'produce-work', name: '鐢熶骇鎶ュ伐', icon: 'edit' },
+ { key: 'produce-ledger', name: '鎶ュ伐鍙拌处', icon: 'form' },
+ { key: 'produce-cost', name: '鐢熶骇鏍哥畻', icon: 'money', accent: true }
]
const storeFlow = [
- { key: 'store-in', name: '鍏ュ簱绠$悊', icon: rukuguanli },
- { key: 'store-out', name: '鍑哄簱绠$悊', icon: chukuguanli },
- { key: 'store-stock', name: '搴撳瓨绠$悊', icon: kucunguanli }
+ { key: 'store-in', name: '鍏ュ簱绠$悊', icon: 'download' },
+ { key: 'store-out', name: '鍑哄簱绠$悊', icon: 'guide' },
+ { key: 'store-stock', name: '搴撳瓨绠$悊', icon: 'redis-list' }
]
</script>
@@ -314,15 +340,24 @@
}
.module-title__icon {
- width: 72px;
- height: 72px;
+ width: 44px;
+ height: 50px;
+ position: relative;
display: grid;
place-items: center;
+ transform: translateY(-1px);
+ filter: drop-shadow(0 10px 14px rgba(82, 125, 211, 0.28))
+ drop-shadow(0 4px 8px rgba(82, 125, 211, 0.18));
}
-.module-title__icon img {
+.module-title__icon-shape {
width: 100%;
height: 100%;
+ clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
+ display: grid;
+ place-items: center;
+ color: #fff;
+ font-size: 18px;
}
.module-title__text h2 {
@@ -338,7 +373,50 @@
color: #7f8ba3;
}
+.module-title--basic .module-title__icon {
+ filter: drop-shadow(0 10px 14px rgba(47, 110, 236, 0.28))
+ drop-shadow(0 4px 8px rgba(47, 110, 236, 0.18));
+}
+.module-title--basic .module-title__icon-shape {
+ background: linear-gradient(135deg, #2069ff 0%, #5bb0ff 100%);
+}
+
+.module-title--sale .module-title__icon {
+ filter: drop-shadow(0 10px 14px rgba(123, 66, 255, 0.24))
+ drop-shadow(0 4px 8px rgba(123, 66, 255, 0.16));
+}
+
+.module-title--sale .module-title__icon-shape {
+ background: linear-gradient(135deg, #7b42ff 0%, #a172ff 100%);
+}
+
+.module-title--purchase .module-title__icon {
+ filter: drop-shadow(0 10px 14px rgba(52, 161, 255, 0.24))
+ drop-shadow(0 4px 8px rgba(52, 161, 255, 0.16));
+}
+
+.module-title--purchase .module-title__icon-shape {
+ background: linear-gradient(135deg, #34a1ff 0%, #66c6ff 100%);
+}
+
+.module-title--produce .module-title__icon {
+ filter: drop-shadow(0 10px 14px rgba(36, 183, 118, 0.24))
+ drop-shadow(0 4px 8px rgba(36, 183, 118, 0.16));
+}
+
+.module-title--produce .module-title__icon-shape {
+ background: linear-gradient(135deg, #24b776 0%, #62d49d 100%);
+}
+
+.module-title--store .module-title__icon {
+ filter: drop-shadow(0 10px 14px rgba(119, 81, 255, 0.24))
+ drop-shadow(0 4px 8px rgba(119, 81, 255, 0.16));
+}
+
+.module-title--store .module-title__icon-shape {
+ background: linear-gradient(135deg, #7751ff 0%, #9b76ff 100%);
+}
.flow-row {
display: flex;
@@ -374,6 +452,7 @@
align-items: center;
gap: 8px;
text-align: center;
+ cursor: pointer;
}
.flow-node__icon {
@@ -383,12 +462,6 @@
place-items: center;
color: #3f76f3;
font-size: 24px;
-}
-
-.flow-node__icon img {
- width: 100%;
- height: 100%;
- object-fit: contain;
}
.flow-node__icon--accent {
@@ -543,6 +616,47 @@
box-shadow: 0 10px 20px rgba(118, 147, 204, 0.08);
}
+.ai-stage__connector {
+ position: absolute;
+ border-color: rgba(145, 181, 247, 0.5);
+ border-style: dashed;
+ border-width: 1px;
+ pointer-events: none;
+}
+
+.ai-stage__connector--top {
+ top: 24px;
+ left: 50%;
+ width: 0;
+ height: 64px;
+ border-left-width: 1px;
+ transform: translateX(-50%);
+}
+
+.ai-stage__connector--left,
+.ai-stage__connector--right {
+ top: 148px;
+ width: 74px;
+ border-top-width: 1px;
+}
+
+.ai-stage__connector--left {
+ left: 18px;
+}
+
+.ai-stage__connector--right {
+ right: 18px;
+}
+
+.ai-stage__connector--bottom {
+ bottom: 32px;
+ left: 50%;
+ width: 0;
+ height: 64px;
+ border-left-width: 1px;
+ transform: translateX(-50%);
+}
+
@media (max-width: 1440px) {
.middle-layout {
grid-template-columns: 1fr 360px 1fr;
diff --git a/vite.config.js b/vite.config.js
index 6b267a7..14a32ce 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -6,14 +6,8 @@
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd());
const { VITE_APP_ENV } = env;
- const baseUrl =
- env.VITE_APP_ENV === "development"
- ? "http://localhost:7005"
- : env.VITE_BASE_API;
- const javaUrl =
- env.VITE_APP_ENV === "development"
- ? "http://1.15.17.182:9049"
- : env.VITE_JAVA_API;
+ const baseUrl = env.VITE_BASE_API;
+ const javaUrl = env.VITE_JAVA_API;
return {
define:{
__BASE_API__: JSON.stringify(javaUrl)
--
Gitblit v1.9.3