From 5a520798abc9bef73c308edaa5d606ecdd7ce72a Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期四, 14 五月 2026 09:11:41 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_西宁_青铝绿行

---
 src/views/index.vue                                                  |    2 
 src/views/financialManagement/receivable/salesOut.vue                |  272 -
 multiple/config.json                                                 |   40 
 src/views/basicData/product/index.vue                                |   38 
 src/api/financialManagement/voucher.js                               |   54 
 src/views/financialManagement/generalLedger/index.vue                |  172 +
 src/views/salesManagement/returnOrder/components/detailDia.vue       |  260 ++
 src/api/procurementManagement/purchase_return_order.js               |    9 
 src/views/financialManagement/voucher/index.vue                      |  439 +++-
 src/views/salesManagement/salesLedger/index.vue                      |    2 
 src/api/financialManagement/ledger.js                                |   19 
 src/views/salesManagement/returnOrder/index.vue                      |   24 
 multiple/assets/favicon/KYHGfavicon.ico                              |    0 
 src/views/basicData/customerFile/index.vue                           |   35 
 src/views/salesManagement/returnOrder/components/formDia.vue         |  228 ++
 src/views/procurementManagement/purchaseReturnOrder/index.vue        |  487 +++-
 src/views/financialManagement/assets/intangibleAssets.vue            |  190 +
 public/favicon.ico                                                   |    0 
 src/views/procurementManagement/purchaseReturnOrder/ProductList.vue  |   91 
 src/views/financialManagement/voucher/detailLedger.vue               |  434 ++--
 src/api/financialManagement/accountPurchase.js                       |   19 
 src/views/financialManagement/voucher/generalLedger.vue              |  382 ++-
 src/views/inventoryManagement/receiptManagement/Record.vue           |   11 
 src/views/qualityManagement/processInspection/components/formDia.vue |  844 ++++----
 src/views/salesManagement/deliveryLedger/index.vue                   |   16 
 multiple/assets/logo/HYZCLogo.png                                    |    0 
 src/api/financialManagement/fixedAsset.js                            |   50 
 FINANCIAL_MANAGEMENT_BACKEND_SPEC.md                                 |  233 ++
 src/assets/logo/logo.png                                             |    0 
 multiple/assets/favicon/WTXCfavicon.ico                              |    0 
 src/api/basicData/customer.js                                        |    8 
 src/router/index.js                                                  |    7 
 src/views/financialManagement/assets/fixedAssets.vue                 |  182 +
 src/views/financialManagement/receivable/salesReturn.vue             |  308 --
 multiple/assets/logo/DYKJLogo.png                                    |    0 
 multiple/assets/logo/WTXCLogo.png                                    |    0 
 src/views/financialManagement/payable/purchaseIn.vue                 |  326 --
 src/api/financialManagement/intangibleAsset.js                       |   50 
 multiple/assets/favicon/DYKJfavicon.ico                              |    0 
 src/views/procurementManagement/purchaseReturnOrder/New.vue          |   92 
 multiple/assets/logo/KYHGLogo.png                                    |    0 
 src/api/financialManagement/accountSales.js                          |   19 
 src/views/inventoryManagement/stockReport/index.vue                  |   14 
 src/views/financialManagement/payable/purchaseReturn.vue             |  239 ++
 multiple/assets/favicon/HYZCfavicon.ico                              |    0 
 45 files changed, 3,566 insertions(+), 2,030 deletions(-)

diff --git a/FINANCIAL_MANAGEMENT_BACKEND_SPEC.md b/FINANCIAL_MANAGEMENT_BACKEND_SPEC.md
new file mode 100644
index 0000000..ee7e5b7
--- /dev/null
+++ b/FINANCIAL_MANAGEMENT_BACKEND_SPEC.md
@@ -0,0 +1,233 @@
+# 璐㈠姟绠$悊鍚庣鏂囨。锛堜粎璐熻矗妯″潡锛�
+
+鏇存柊鏃堕棿锛�2026-05-12  
+閫傜敤鑼冨洿锛堜粎浠ヤ笅 6 涓ā鍧楋級锛�
+1. 鍥哄畾璧勪骇锛坄/financial/fixed-assets`锛�
+2. 鏃犲舰璧勪骇锛坄/financial/intangible-assets`锛�
+3. 鎬昏处绉戠洰锛坄/financial/general-ledger`锛�
+4. 鍑瘉锛坄/financial/voucher`锛�
+5. 绉戠洰鎬昏处锛坄/financial/voucher-general-ledger`锛�
+6. 绉戠洰鏄庣粏璐︼紙`/financial/voucher-detail-ledger`锛�
+
+---
+
+## 1. 缁熶竴绾﹀畾
+
+### 1.1 鍝嶅簲缁撴瀯
+```json
+{
+  "code": 200,
+  "msg": "success",
+  "data": {}
+}
+```
+
+### 1.2 鍒嗛〉缁撴瀯锛堝鏋滄槸鍒嗛〉鎺ュ彛锛�
+璇锋眰鍙傛暟寤鸿锛�
+- `current`锛堥〉鐮侊級
+- `size`锛堟瘡椤垫潯鏁帮級
+
+鍝嶅簲寤鸿锛�
+```json
+{
+  "code": 200,
+  "data": {
+    "records": [],
+    "total": 0
+  }
+}
+```
+
+### 1.3 閲戦涓庣簿搴�
+- 閲戦瀛楁寤鸿 `decimal(18,2)`銆�
+- 鍓嶅悗绔粺涓�淇濈暀涓や綅灏忔暟銆�
+
+---
+
+## 2. 妯″潡涓�锛氭�昏处绉戠洰锛堝凡鎺ョ湡瀹� API锛�
+
+鍓嶇鏂囦欢锛歚src/views/financialManagement/generalLedger/index.vue`  
+API 鏂囦欢锛歚src/api/financialManagement/accountSubject.js`
+
+### 2.1 鎺ュ彛鐜扮姸
+- `GET /accountSubject/list`
+- `POST /accountSubject/add`
+- `PUT /accountSubject/edit`
+- `DELETE /accountSubject/remove/{ids}`
+- `POST /accountSubject/export`
+
+### 2.2 瀛楁妯″瀷
+- `id`
+- `subjectCode`锛堢鐩紪鐮侊級
+- `subjectName`锛堢鐩悕绉帮級
+- `subjectType`锛堢鐩被鍨嬶級
+- `balanceDirection`锛堜綑棰濇柟鍚戯細鍊熸柟/璐锋柟锛�
+- `status`锛�0 鍚敤锛�1 绂佺敤锛�
+- `remark`
+
+### 2.3 涓氬姟瑙勫垯
+- `subjectCode`銆乣subjectName`銆乣subjectType` 蹇呭~銆�
+- 鍒犻櫎闇�瑕佸仛寮曠敤鏍¢獙锛堣嫢宸茶鍑瘉鍒嗗綍寮曠敤锛屼笉鍏佽鍒犻櫎锛夈��
+
+---
+
+## 3. 妯″潡浜岋細鍥哄畾璧勪骇锛堝綋鍓嶅墠绔负 mock锛屽緟鍚庣瀹炵幇锛�
+
+鍓嶇鏂囦欢锛歚src/views/financialManagement/assets/fixedAssets.vue`
+
+### 3.1 寤鸿鎺ュ彛
+- `GET /financial/fixedAsset/page`
+- `POST /financial/fixedAsset/add`
+- `PUT /financial/fixedAsset/update`
+- `DELETE /financial/fixedAsset/delete`
+- `POST /financial/fixedAsset/depreciate`锛堟寜鏈堣鎻愶級
+
+### 3.2 瀛楁妯″瀷
+- `id, assetCode, assetName, category, specification`
+- `purchaseDate, originalValue, usefulLife, residualRate`
+- `accumulatedDepreciation, netValue`
+- `location, department, keeper, status, remark`
+
+### 3.3 鏍稿績鍏紡锛堝繀椤讳竴鑷达級
+- `monthlyDepreciation = originalValue * (1 - residualRate/100) / (usefulLife*12)`
+- `accumulatedDepreciation += monthlyDepreciation`
+- `netValue = originalValue - accumulatedDepreciation`
+
+### 3.4 鐘舵�佸缓璁�
+- `in_use`锛堝湪鐢級
+- `idle`锛堥棽缃級
+- `repair`锛堢淮淇腑锛�
+- `scrapped`锛堟姤搴燂級
+
+---
+
+## 4. 妯″潡涓夛細鏃犲舰璧勪骇锛堝綋鍓嶅墠绔负 mock锛屽緟鍚庣瀹炵幇锛�
+
+鍓嶇鏂囦欢锛歚src/views/financialManagement/assets/intangibleAssets.vue`
+
+### 4.1 寤鸿鎺ュ彛
+- `GET /financial/intangibleAsset/page`
+- `POST /financial/intangibleAsset/add`
+- `PUT /financial/intangibleAsset/update`
+- `DELETE /financial/intangibleAsset/delete`
+- `POST /financial/intangibleAsset/amortize`锛堟寜鏈堟憡閿�锛�
+
+### 4.2 瀛楁妯″瀷
+- `id, assetCode, assetName, category, certificateNo`
+- `acquisitionDate, originalValue, amortizationPeriod, residualRate`
+- `accumulatedAmortization, netValue`
+- `validityDate, status, description, remark`
+
+### 4.3 鏍稿績鍏紡锛堝繀椤讳竴鑷达級
+- `monthlyAmortization = originalValue * (1 - residualRate/100) / (amortizationPeriod*12)`
+- `accumulatedAmortization += monthlyAmortization`
+- `netValue = originalValue - accumulatedAmortization`
+- 褰� `netValue <= 0`锛�
+  - `netValue = 0`
+  - `status = amortized`
+
+### 4.4 鐘舵�佸缓璁�
+- `in_use`锛堝湪鐢級
+- `expired`锛堝埌鏈燂級
+- `amortized`锛堝凡鎽婇攢瀹岋級
+
+---
+
+## 5. 妯″潡鍥涳細鍑瘉锛堝綋鍓嶅墠绔负 mock锛屽緟鍚庣瀹炵幇锛�
+
+鍓嶇鏂囦欢锛歚src/views/financialManagement/voucher/index.vue`
+
+### 5.1 寤鸿鎺ュ彛
+- `GET /financial/voucher/page`
+- `POST /financial/voucher/add`
+- `PUT /financial/voucher/update`
+- `POST /financial/voucher/post`锛堣繃璐︼級
+- `POST /financial/voucher/cancel`锛堜綔搴燂級
+- `GET /financial/voucher/detail/{id}`
+
+### 5.2 涓昏〃瀛楁
+- `id, voucherNo, voucherDate, summary`
+- `debit, credit, creator, status, attachmentCount, remark`
+
+### 5.3 鍒嗗綍瀛楁
+- `subjectCode, subjectName, summary, debit, credit`
+
+### 5.4 鍏抽敭鏍¢獙
+- 鍒嗗綍鑷冲皯涓�鏉℃湁鏁堣锛堢鐩笉绌猴紝涓斿�熸柟鎴栬捶鏂� > 0锛夈��
+- 鍊熻捶骞宠 锛歚sum(debit) == sum(credit)` 涓� > 0锛屼笉婊¤冻绂佹淇濆瓨銆�
+
+### 5.5 鐘舵�佹祦杞�
+- `unposted -> posted`
+- `unposted -> cancelled`
+
+---
+
+## 6. 妯″潡浜旓細绉戠洰鎬昏处锛堝綋鍓嶅墠绔负 mock锛屽緟鍚庣瀹炵幇锛�
+
+鍓嶇鏂囦欢锛歚src/views/financialManagement/voucher/generalLedger.vue`
+
+### 6.1 寤鸿鎺ュ彛
+- `GET /financial/ledger/general`
+
+### 6.2 璇锋眰鍙傛暟
+- `subjectCode`锛堟湯绾ф垨鎸囧畾绉戠洰锛�
+- `startMonth`锛圷YYY-MM锛�
+- `endMonth`锛圷YYY-MM锛�
+
+### 6.3 鍝嶅簲瀛楁
+- `date, voucherNo, summary`
+- `debit, credit, direction, balance`
+
+### 6.4 瑙勫垯
+- 浠呭湪閫夋嫨绉戠洰鍚庤繑鍥炴暟鎹��
+- 鏀寔鈥滄湡鍒濅綑棰� / 鏈湀鍚堣 / 鏈勾绱鈥濊锛堝彲閫氳繃 `rowType` 瀛楁鍖哄垎锛夈��
+
+---
+
+## 7. 妯″潡鍏細绉戠洰鏄庣粏璐︼紙褰撳墠鍓嶇涓� mock锛屽緟鍚庣瀹炵幇锛�
+
+鍓嶇鏂囦欢锛歚src/views/financialManagement/voucher/detailLedger.vue`
+
+### 7.1 寤鸿鎺ュ彛
+- `GET /financial/ledger/detail`
+
+### 7.2 璇锋眰鍙傛暟
+- `subjectCode`
+- `auxiliaryType`锛坈ustomer/supplier/department/employee/project锛�
+- `auxiliaryId`
+- `startMonth`锛圷YYY-MM锛�
+- `endMonth`锛圷YYY-MM锛�
+
+### 7.3 鍝嶅簲瀛楁
+- `date, voucherNo, summary`
+- `debit, credit, direction, balance`
+
+### 7.4 瑙勫垯
+- 鍏堥�夌鐩紝鍐嶆煡鏄庣粏銆�
+- 杈呭姪鏍哥畻鏉′欢涓哄彲閫夛紝浣嗗缓璁悗绔敮鎸佺淮搴﹁繃婊ゃ��
+
+---
+
+## 8. 鎺ㄨ崘鏈�灏忚〃璁捐锛堜粎鏈寖鍥达級
+
+- `fin_account_subject`
+- `fin_fixed_asset`
+- `fin_intangible_asset`
+- `fin_voucher`
+- `fin_voucher_entry`
+- `fin_ledger_snapshot_general`锛堝彲閫夛紝鍋氭�ц兘浼樺寲锛�
+- `fin_ledger_snapshot_detail`锛堝彲閫夛紝鍋氭�ц兘浼樺寲锛�
+
+---
+
+## 9. AI 鐢熸垚鍚庣浠诲姟椤哄簭锛堝缓璁級
+
+1. 鍏堝畬鎴� **鎬昏处绉戠洰**锛堝凡鏈� API锛屾渶绋冲畾锛夈��  
+2. 瀹屾垚 **鍑瘉 + 鍒嗗綍 + 鍊熻捶骞宠 鏍¢獙 + 鐘舵�佹祦杞�**銆�  
+3. 瀹炵幇 **绉戠洰鎬昏处 / 绉戠洰鏄庣粏璐�** 鏌ヨ銆�  
+4. 瀹炵幇 **鍥哄畾璧勪骇鎶樻棫** 涓� **鏃犲舰璧勪骇鎽婇攢**銆�  
+5. 琛ユ祴璇曪細  
+   - 鍊熻捶骞宠 鏍¢獙  
+   - 鎶樻棫/鎽婇攢鍏紡  
+   - 绉戠洰琚紩鐢ㄧ姝㈠垹闄�  
+
diff --git a/multiple/assets/favicon/DYKJfavicon.ico b/multiple/assets/favicon/DYKJfavicon.ico
new file mode 100644
index 0000000..8437010
--- /dev/null
+++ b/multiple/assets/favicon/DYKJfavicon.ico
Binary files differ
diff --git a/multiple/assets/favicon/HYZCfavicon.ico b/multiple/assets/favicon/HYZCfavicon.ico
new file mode 100644
index 0000000..996ab43
--- /dev/null
+++ b/multiple/assets/favicon/HYZCfavicon.ico
Binary files differ
diff --git a/multiple/assets/favicon/KYHGfavicon.ico b/multiple/assets/favicon/KYHGfavicon.ico
new file mode 100644
index 0000000..8178896
--- /dev/null
+++ b/multiple/assets/favicon/KYHGfavicon.ico
Binary files differ
diff --git a/multiple/assets/favicon/WTXCfavicon.ico b/multiple/assets/favicon/WTXCfavicon.ico
new file mode 100644
index 0000000..ce783dc
--- /dev/null
+++ b/multiple/assets/favicon/WTXCfavicon.ico
Binary files differ
diff --git a/multiple/assets/logo/DYKJLogo.png b/multiple/assets/logo/DYKJLogo.png
new file mode 100644
index 0000000..b96b61c
--- /dev/null
+++ b/multiple/assets/logo/DYKJLogo.png
Binary files differ
diff --git a/multiple/assets/logo/HYZCLogo.png b/multiple/assets/logo/HYZCLogo.png
new file mode 100644
index 0000000..e8e4cad
--- /dev/null
+++ b/multiple/assets/logo/HYZCLogo.png
Binary files differ
diff --git a/multiple/assets/logo/KYHGLogo.png b/multiple/assets/logo/KYHGLogo.png
new file mode 100644
index 0000000..0186c87
--- /dev/null
+++ b/multiple/assets/logo/KYHGLogo.png
Binary files differ
diff --git a/multiple/assets/logo/WTXCLogo.png b/multiple/assets/logo/WTXCLogo.png
new file mode 100644
index 0000000..0a486cd
--- /dev/null
+++ b/multiple/assets/logo/WTXCLogo.png
Binary files differ
diff --git a/multiple/config.json b/multiple/config.json
index e6d47ef..802ef67 100644
--- a/multiple/config.json
+++ b/multiple/config.json
@@ -45,8 +45,8 @@
   "BTYX": {
     "env": {
       "VITE_APP_TITLE": "娌冲崡甯お浼橀�夎繘鍑哄彛鏈夐檺鍏徃",
-      "VITE_BASE_API": "http://127.0.0.1:9001",
-      "VITE_JAVA_API": "http://127.0.0.1:9000"
+      "VITE_BASE_API": "http://1.15.17.182:9056",
+      "VITE_JAVA_API": "http://1.15.17.182:9057"
     },
     "logo": "logo/BTYXLogo.png",
     "favicon": "favicon/BTYXfavicon.ico"
@@ -60,6 +60,42 @@
     "logo": "logo/ZXZNLogo.png",
     "favicon": "favicon/ZXZNfavicon.ico"
   },
+  "HYZC": {
+    "env": {
+      "VITE_APP_TITLE": "灞辫タ鍗庝嚎浼楁垚寤烘潗鏈夐檺鍏徃",
+      "VITE_BASE_API": "http://36.137.13.103:9001",
+      "VITE_JAVA_API": "http://36.137.13.103:9000"
+    },
+    "logo": "logo/HYZCLogo.png",
+    "favicon": "favicon/HYZCfavicon.ico"
+  },
+  "WTXC": {
+    "env": {
+      "VITE_APP_TITLE": "瀹佸涓囬�氭柊鏉�",
+      "VITE_BASE_API": "http://42.63.71.140:9001",
+      "VITE_JAVA_API": "http://42.63.71.140:9000"
+    },
+    "logo": "logo/WTXCLogo.png",
+    "favicon": "favicon/WTXCfavicon.ico"
+  },
+  "KYHG": {
+    "env": {
+      "VITE_APP_TITLE": "灞辫タ鍧ゆ簮鍖栧伐鏈夐檺鍏徃",
+      "VITE_BASE_API": "http://36.137.13.29:9001",
+      "VITE_JAVA_API": "http://36.137.13.29:9000"
+    },
+    "logo": "logo/KYHGLogo.png",
+    "favicon": "favicon/KYHGfavicon.ico"
+  },
+  "DYKJ": {
+    "env": {
+      "VITE_APP_TITLE": "灞辫タ寰风泭绉戞妧鏈夐檺鍏徃",
+      "VITE_BASE_API": "http://36.137.12.37:9001",
+      "VITE_JAVA_API": "http://36.137.12.37:9000"
+    },
+    "logo": "logo/DYKJLogo.png",
+    "favicon": "favicon/DYKJfavicon.ico"
+  },
   "logo": "/src/assets/logo/logo.png",
   "favicon": "/public/favicon.ico"
 }
diff --git a/public/favicon.ico b/public/favicon.ico
index 2fa05d5..ce783dc 100644
--- a/public/favicon.ico
+++ b/public/favicon.ico
Binary files differ
diff --git a/src/api/basicData/customer.js b/src/api/basicData/customer.js
index 28f2eab..0934193 100644
--- a/src/api/basicData/customer.js
+++ b/src/api/basicData/customer.js
@@ -26,6 +26,14 @@
     })
 }
 
+// 娴佸叆鍏捣
+export function backCustomer(id) {
+    return request({
+        url: '/basic/customer/back/' + id,
+        method: 'post'
+    })
+}
+
 export function shareCustomer(data) {
     return request({
         url: '/basic/customer/together',
diff --git a/src/api/financialManagement/accountPurchase.js b/src/api/financialManagement/accountPurchase.js
new file mode 100644
index 0000000..9e2d508
--- /dev/null
+++ b/src/api/financialManagement/accountPurchase.js
@@ -0,0 +1,19 @@
+import request from "@/utils/request";
+
+/** 閲囪喘鍏ュ簱鍒嗛〉鍒楄〃 */
+export const listPageAccountPurchase = (params) => {
+  return request({
+    url: "/accountPurchase/listPageAccountPurchase",
+    method: "get",
+    params,
+  });
+};
+
+/** 閲囪喘閫�璐у垎椤靛垪琛� */
+export const listPageAccountPurchaseReturn = (params) => {
+  return request({
+    url: "/accountPurchase/listPageAccountPurchaseReturn",
+    method: "get",
+    params,
+  });
+};
diff --git a/src/api/financialManagement/accountSales.js b/src/api/financialManagement/accountSales.js
new file mode 100644
index 0000000..e56d50f
--- /dev/null
+++ b/src/api/financialManagement/accountSales.js
@@ -0,0 +1,19 @@
+import request from "@/utils/request";
+
+/** 閿�鍞嚭搴撳垎椤靛垪琛� */
+export const listPageAccountSales = (params) => {
+  return request({
+    url: "/accountSales/listPageAccountSales",
+    method: "get",
+    params,
+  });
+};
+
+/** 閿�鍞��璐у垎椤靛垪琛� */
+export const listPageAccountSalesReturn = (params) => {
+  return request({
+    url: "/accountSales/listPageAccountSalesReturn",
+    method: "get",
+    params,
+  });
+};
diff --git a/src/api/financialManagement/fixedAsset.js b/src/api/financialManagement/fixedAsset.js
new file mode 100644
index 0000000..5c28db4
--- /dev/null
+++ b/src/api/financialManagement/fixedAsset.js
@@ -0,0 +1,50 @@
+import request from "@/utils/request";
+
+// 鍥哄畾璧勪骇鍒嗛〉鏌ヨ锛坈urrent/size锛�
+export function listFixedAssetPage(params) {
+  return request({
+    url: "/financial/fixedAsset/page",
+    method: "get",
+    params,
+  });
+}
+
+// 鏂板鍥哄畾璧勪骇
+export function addFixedAsset(data) {
+  return request({
+    url: "/financial/fixedAsset/add",
+    method: "post",
+    data,
+  });
+}
+
+// 淇敼鍥哄畾璧勪骇
+export function updateFixedAsset(data) {
+  return request({
+    url: "/financial/fixedAsset/update",
+    method: "put",
+    data,
+  });
+}
+
+// 鍒犻櫎鍥哄畾璧勪骇锛堝悗绔姹� ids=1&ids=2 褰㈠紡锛�
+export function deleteFixedAsset(ids) {
+  const idList = Array.isArray(ids) ? ids : [ids];
+  const query = idList
+    .filter(id => id !== undefined && id !== null && id !== "")
+    .map(id => `ids=${encodeURIComponent(id)}`)
+    .join("&");
+  return request({
+    url: `/financial/fixedAsset/delete?${query}`,
+    method: "delete",
+  });
+}
+
+// 鎶樻棫璁℃彁锛坽} 琛ㄧず鍏ㄩ儴鍦ㄧ敤璧勪骇锛�
+export function depreciateFixedAsset(data = {}) {
+  return request({
+    url: "/financial/fixedAsset/depreciate",
+    method: "post",
+    data,
+  });
+}
diff --git a/src/api/financialManagement/intangibleAsset.js b/src/api/financialManagement/intangibleAsset.js
new file mode 100644
index 0000000..802e649
--- /dev/null
+++ b/src/api/financialManagement/intangibleAsset.js
@@ -0,0 +1,50 @@
+import request from "@/utils/request";
+
+// 鏃犲舰璧勪骇鍒嗛〉鏌ヨ锛坈urrent/size锛�
+export function listIntangibleAssetPage(params) {
+  return request({
+    url: "/financial/intangibleAsset/page",
+    method: "get",
+    params,
+  });
+}
+
+// 鏂板鏃犲舰璧勪骇
+export function addIntangibleAsset(data) {
+  return request({
+    url: "/financial/intangibleAsset/add",
+    method: "post",
+    data,
+  });
+}
+
+// 淇敼鏃犲舰璧勪骇
+export function updateIntangibleAsset(data) {
+  return request({
+    url: "/financial/intangibleAsset/update",
+    method: "put",
+    data,
+  });
+}
+
+// 鍒犻櫎鏃犲舰璧勪骇锛堝悗绔姹� ids=1&ids=2 褰㈠紡锛�
+export function deleteIntangibleAsset(ids) {
+  const idList = Array.isArray(ids) ? ids : [ids];
+  const query = idList
+    .filter(id => id !== undefined && id !== null && id !== "")
+    .map(id => `ids=${encodeURIComponent(id)}`)
+    .join("&");
+  return request({
+    url: `/financial/intangibleAsset/delete?${query}`,
+    method: "delete",
+  });
+}
+
+// 鎽婇攢璁℃彁锛坽} 琛ㄧず鍏ㄩ儴鍦ㄧ敤璧勪骇锛�
+export function amortizeIntangibleAsset(data = {}) {
+  return request({
+    url: "/financial/intangibleAsset/amortize",
+    method: "post",
+    data,
+  });
+}
diff --git a/src/api/financialManagement/ledger.js b/src/api/financialManagement/ledger.js
new file mode 100644
index 0000000..17e62fc
--- /dev/null
+++ b/src/api/financialManagement/ledger.js
@@ -0,0 +1,19 @@
+import request from "@/utils/request";
+
+// 绉戠洰鎬昏处
+export function getGeneralLedger(params) {
+  return request({
+    url: "/financial/ledger/general",
+    method: "get",
+    params,
+  });
+}
+
+// 绉戠洰鏄庣粏璐�
+export function getDetailLedger(params) {
+  return request({
+    url: "/financial/ledger/detail",
+    method: "get",
+    params,
+  });
+}
diff --git a/src/api/financialManagement/voucher.js b/src/api/financialManagement/voucher.js
new file mode 100644
index 0000000..ccb0908
--- /dev/null
+++ b/src/api/financialManagement/voucher.js
@@ -0,0 +1,54 @@
+import request from "@/utils/request";
+
+// 鍑瘉鍒嗛〉鏌ヨ锛坈urrent/size + 杩囨护鏉′欢锛�
+export function listVoucherPage(params) {
+  return request({
+    url: "/financial/voucher/page",
+    method: "get",
+    params,
+  });
+}
+
+// 鏂板鍑瘉
+export function addVoucher(data) {
+  return request({
+    url: "/financial/voucher/add",
+    method: "post",
+    data,
+  });
+}
+
+// 淇敼鍑瘉锛堜粎鏈繃璐︼級
+export function updateVoucher(data) {
+  return request({
+    url: "/financial/voucher/update",
+    method: "put",
+    data,
+  });
+}
+
+// 杩囪处
+export function postVoucher(data) {
+  return request({
+    url: "/financial/voucher/post",
+    method: "post",
+    data,
+  });
+}
+
+// 浣滃簾
+export function cancelVoucher(data) {
+  return request({
+    url: "/financial/voucher/cancel",
+    method: "post",
+    data,
+  });
+}
+
+// 璇︽儏
+export function getVoucherDetail(id) {
+  return request({
+    url: `/financial/voucher/detail/${id}`,
+    method: "get",
+  });
+}
diff --git a/src/api/procurementManagement/purchase_return_order.js b/src/api/procurementManagement/purchase_return_order.js
index aeb380d..2705dde 100644
--- a/src/api/procurementManagement/purchase_return_order.js
+++ b/src/api/procurementManagement/purchase_return_order.js
@@ -19,6 +19,15 @@
     });
 }
 
+// 鏍规嵁閲囪喘鍙拌处 ID 鏌ヨ鍙��浜у搧绛変俊鎭�
+export function getPurchaseReturnOrderByPurchaseLedgerId(query) {
+    return request({
+        url: "/purchaseReturnOrders/getByPurchaseLedgerId",
+        method: "get",
+        params: query,
+    });
+}
+
 // 鏌ョ湅璇︽儏
 // purchaseReturnOrders/selectById/xxx
 export function getPurchaseReturnOrderDetail(id) {
diff --git a/src/assets/logo/logo.png b/src/assets/logo/logo.png
index a5831b8..0a486cd 100644
--- a/src/assets/logo/logo.png
+++ b/src/assets/logo/logo.png
Binary files differ
diff --git a/src/router/index.js b/src/router/index.js
index aea22ca..d809a63 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -183,7 +183,12 @@
         name: "PurchaseIn",
         meta: { title: "閲囪喘鍏ュ簱" },
       },
-      
+      {
+        path: "purchase-return",
+        component: () => import("@/views/financialManagement/payable/purchaseReturn.vue"),
+        name: "PurchaseReturn",
+        meta: { title: "閲囪喘閫�璐�" },
+      },
       {
         path: "input-invoice",
         component: () => import("@/views/financialManagement/payable/input-invoice.vue"),
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index 97ea3e6..7091a02 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -27,6 +27,9 @@
       <div>
         <el-button type="primary"
                    @click="openForm('add')">鏂板瀹㈡埛</el-button>
+        <el-button type="primary"
+                   plain
+                   @click="back">娴佸叆鍏捣</el-button>
         <el-button @click="handleOut">瀵煎嚭</el-button>
         <el-button type="info"
                    plain
@@ -619,7 +622,7 @@
     addReturnVisit,
     getReturnVisit,
   } from "@/api/basicData/customerFile.js";
-  import {listCustomer, getCustomer, addCustomer, updateCustomer, delCustomer} 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";
@@ -1126,6 +1129,36 @@
       });
   };
 
+  const back = () => {
+    if (selectedRows.value.length === 0) {
+      proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+      return;
+    }
+    const ids = selectedRows.value.map(item => item.id);
+    ElMessageBox.confirm("閫変腑鐨勫鎴峰皢娴佸叆鍏捣锛屾槸鍚︾‘璁わ紵", "娴佸叆鍏捣鎻愮ず", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        tableLoading.value = true;
+        return Promise.all(ids.map(id => backCustomer(id)))
+          .then(() => {
+            proxy.$modal.msgSuccess("娴佸叆鍏捣鎴愬姛");
+            selectedRows.value = [];
+            getList();
+          })
+          .finally(() => {
+            tableLoading.value = false;
+          });
+      })
+      .catch(error => {
+        if (error === "cancel" || error === "close") {
+          proxy.$modal.msg("宸插彇娑�");
+        }
+      });
+  };
+
   // 鎵撳紑鍥炶鎻愰啋寮圭獥
   const openReminderDialog = row => {
     currentCustomerId.value = row.id;
diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index 99ab028..07da49b 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -43,12 +43,12 @@
                 <el-button type="primary"
                            link
                            :disabled="isTopLevelNode(data, node)"
-                           @click="openProDia('edit', data)">
+                           @click="openProDia('edit', data, node)">
                   缂栬緫
                 </el-button>
                 <el-button type="primary"
                            link
-                           @click="openProDia('add', data)">
+                           @click="openProDia('add', data, node)">
                   娣诲姞浜у搧
                 </el-button>
                 <el-button v-if="!node.childNodes.length"
@@ -285,6 +285,8 @@
   const search = ref("");
   const currentId = ref("");
   const currentParentId = ref("");
+  /** 浜у搧寮圭獥锛歛dd 瀛樼埗鑺傜偣 id锛沞dit 瀛樺綋鍓嶈妭鐐� id 涓� parentId锛堜笉渚濊禆鏍戦�変腑椤癸級 */
+  const productDialogTarget = ref(null);
   const operationType = ref("");
   const treeLoad = ref(false);
   const list = ref([]);
@@ -388,17 +390,28 @@
     return [null, undefined, "", 0, "0"].includes(data?.parentId);
   };
   // 鎵撳紑浜у搧寮规
-  const openProDia = (type, data) => {
-    if (data && type === "edit" && isTopLevelNode(data)) {
+  const openProDia = (type, data, node) => {
+    if (data && type === "edit" && isTopLevelNode(data, node)) {
       proxy.$modal.msgWarning("涓�绾ц妭鐐逛笉鑳界紪杈戞垨鍒犻櫎");
       return;
     }
     operationType.value = type;
-    productDia.value = true;
-    form.value.productName = "";
-    if (type === "edit") {
-      form.value.productName = data.productName;
+    productDialogTarget.value = null;
+    if (type === "add" && data) {
+      productDialogTarget.value = { parentId: data.id };
+    } else if (type === "edit" && data) {
+      let parentId = data.parentId;
+      if (
+        [null, undefined, ""].includes(parentId) &&
+        node?.parent?.data?.id != null
+      ) {
+        parentId = node.parent.data.id;
+      }
+      productDialogTarget.value = { id: data.id, parentId };
     }
+    productDia.value = true;
+    form.value.productName =
+      type === "edit" && data ? data.productName : "";
   };
   // 鎵撳紑瑙勬牸鍨嬪彿寮规
   const openModelDia = (type, data) => {
@@ -417,14 +430,16 @@
     proxy.$refs.formRef.validate(valid => {
       if (valid) {
         if (operationType.value === "add") {
-          form.value.parentId = currentId.value;
+          form.value.parentId =
+            productDialogTarget.value?.parentId ?? currentId.value;
           form.value.id = "";
         } else if (operationType.value === "addOne") {
           form.value.id = "";
           form.value.parentId = "";
         } else {
-          form.value.id = currentId.value;
-          form.value.parentId = "";
+          form.value.id =
+            productDialogTarget.value?.id ?? currentId.value;
+          form.value.parentId = productDialogTarget.value?.parentId ?? "";
         }
         addOrEditProduct(form.value).then(res => {
           proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
@@ -437,6 +452,7 @@
   // 鍏抽棴浜у搧寮规
   const closeProDia = () => {
     proxy.$refs.formRef.resetFields();
+    productDialogTarget.value = null;
     productDia.value = false;
   };
 
diff --git a/src/views/financialManagement/assets/fixedAssets.vue b/src/views/financialManagement/assets/fixedAssets.vue
index 61eb245..c6241c8 100644
--- a/src/views/financialManagement/assets/fixedAssets.vue
+++ b/src/views/financialManagement/assets/fixedAssets.vue
@@ -43,6 +43,7 @@
       </div>
       <PIMTable
         rowKey="id"
+        isSelection
         :column="columns"
         :tableData="dataList"
         :page="{
@@ -50,6 +51,7 @@
           size: pagination.pageSize,
           total: pagination.total,
         }"
+        @selection-change="handleSelectionChange"
         @pagination="changePage"
       >
         <template #originalValue="{ row }">
@@ -76,7 +78,7 @@
     </div>
 
     <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
-      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+      <el-form :model="form" :rules="rules" :disabled="isView" ref="formRef" label-width="120px">
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="璧勪骇缂栧彿" prop="assetCode">
@@ -178,7 +180,7 @@
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button type="primary" @click="submitForm">纭畾</el-button>
+        <el-button v-if="!isView" type="primary" @click="submitForm">纭畾</el-button>
         <el-button @click="dialogVisible = false">鍙栨秷</el-button>
       </template>
     </FormDialog>
@@ -189,6 +191,13 @@
 import { ref, reactive, onMounted, computed } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import FormDialog from "@/components/Dialog/FormDialog.vue";
+import {
+  listFixedAssetPage,
+  addFixedAsset,
+  updateFixedAsset,
+  deleteFixedAsset,
+  depreciateFixedAsset,
+} from "@/api/financialManagement/fixedAsset";
 
 defineOptions({
   name: "鍥哄畾璧勪骇",
@@ -210,23 +219,30 @@
 const columns = [
   { label: "璧勪骇缂栧彿", prop: "assetCode", width: "130" },
   { label: "璧勪骇鍚嶇О", prop: "assetName", width: "150" },
-  { label: "璧勪骇绫诲埆", prop: "category", slot: "category" },
+  { label: "璧勪骇绫诲埆", prop: "category", dataType: "slot", slot: "category" },
   { label: "瑙勬牸鍨嬪彿", prop: "specification", width: "120" },
-  { label: "璧勪骇鍘熷��", prop: "originalValue", slot: "originalValue" },
-  { label: "绱鎶樻棫", prop: "accumulatedDepreciation", slot: "accumulatedDepreciation" },
-  { label: "璧勪骇鍑�鍊�", prop: "netValue", slot: "netValue" },
-  { label: "鐘舵��", prop: "status", slot: "status" },
-  { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "180", fixed: "right" },
+  { label: "璧勪骇鍘熷��", prop: "originalValue", dataType: "slot", slot: "originalValue" },
+  { label: "绱鎶樻棫", prop: "accumulatedDepreciation", dataType: "slot", slot: "accumulatedDepreciation" },
+  { label: "璧勪骇鍑�鍊�", prop: "netValue", dataType: "slot", slot: "netValue" },
+  { label: "鐘舵��", prop: "status", dataType: "slot", slot: "status" },
+  { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "180", fixed: "right" },
 ];
 
 const dataList = ref([]);
+const multipleList = ref([]);
 const dialogVisible = ref(false);
 const dialogTitle = ref("");
 const formRef = ref(null);
 const isEdit = ref(false);
+const isView = ref(false);
 const currentId = ref(null);
+const selectedIds = computed(() =>
+  multipleList.value
+    .map(item => item?.id)
+    .filter(id => id !== undefined && id !== null && id !== "")
+);
 
-const form = reactive({
+const createDefaultForm = () => ({
   assetCode: "",
   assetName: "",
   category: "",
@@ -244,6 +260,10 @@
   remark: "",
 });
 
+const form = reactive({
+  ...createDefaultForm(),
+});
+
 const rules = {
   assetName: [{ required: true, message: "璇疯緭鍏ヨ祫浜у悕绉�", trigger: "blur" }],
   category: [{ required: true, message: "璇烽�夋嫨璧勪骇绫诲埆", trigger: "change" }],
@@ -251,13 +271,6 @@
   originalValue: [{ required: true, message: "璇疯緭鍏ヨ祫浜у師鍊�", trigger: "blur" }],
   usefulLife: [{ required: true, message: "璇疯緭鍏ヤ娇鐢ㄥ勾闄�", trigger: "blur" }],
 };
-
-const mockData = [
-  { id: 1, assetCode: "GD2024001", assetName: "鍔炲叕鐢佃剳", category: "electronic", specification: "鑱旀兂ThinkPad X1", purchaseDate: "2023-01-15", originalValue: 8000, usefulLife: 5, residualRate: 5, accumulatedDepreciation: 1520, netValue: 6480, location: "鍔炲叕瀹�", department: "璐㈠姟閮�", keeper: "寮犱笁", status: "in_use", remark: "" },
-  { id: 2, assetCode: "GD2024002", assetName: "鎵撳嵃鏈�", category: "electronic", specification: "鎯犳櫘M479fdw", purchaseDate: "2023-03-20", originalValue: 3500, usefulLife: 5, residualRate: 5, accumulatedDepreciation: 532, netValue: 2968, location: "鏂囧嵃瀹�", department: "琛屾斂閮�", keeper: "鏉庡洓", status: "in_use", remark: "" },
-  { id: 3, assetCode: "GD2024003", assetName: "鍔炲叕妗屾", category: "furniture", specification: "瀹炴湪鍔炲叕妗�", purchaseDate: "2023-06-10", originalValue: 2500, usefulLife: 10, residualRate: 5, accumulatedDepreciation: 118.75, netValue: 2381.25, location: "鍔炲叕瀹�", department: "閿�鍞儴", keeper: "鐜嬩簲", status: "in_use", remark: "" },
-  { id: 4, assetCode: "GD2024004", assetName: "鍟嗗姟杞�", category: "vehicle", specification: "鍒厠GL8", purchaseDate: "2022-08-01", originalValue: 280000, usefulLife: 10, residualRate: 5, accumulatedDepreciation: 53200, netValue: 226800, location: "鍋滆溅鍦�", department: "琛屾斂閮�", keeper: "璧靛叚", status: "in_use", remark: "" },
-];
 
 const totalOriginalValue = computed(() => {
   return dataList.value.reduce((sum, item) => sum + Number(item.originalValue), 0);
@@ -288,35 +301,44 @@
 };
 
 const getStatusLabel = (status) => {
-  const map = { in_use: "鍦ㄧ敤", idle: "闂茬疆", scrapped: "鎶ュ簾" };
-  return map[status] || status;
+  const key = String(status || "").toLowerCase();
+  const map = { in_use: "鍦ㄧ敤", idle: "闂茬疆", repair: "缁翠慨涓�", scrapped: "鎶ュ簾" };
+  return map[key] || status;
 };
 
 const getStatusType = (status) => {
-  const map = { in_use: "success", idle: "warning", scrapped: "info" };
-  return map[status] || "";
+  const key = String(status || "").toLowerCase();
+  const map = { in_use: "success", idle: "warning", repair: "warning", scrapped: "info" };
+  return map[key] || "";
 };
 
 const calculateNetValue = () => {
-  form.netValue = Number((form.originalValue - form.accumulatedDepreciation).toFixed(2));
+  const originalValue = Number(form.originalValue || 0);
+  const accumulatedDepreciation = Number(form.accumulatedDepreciation || 0);
+  form.netValue = Number((originalValue - accumulatedDepreciation).toFixed(2));
 };
 
-const getTableData = () => {
-  let result = [...mockData];
-  if (filters.assetCode) {
-    result = result.filter(item => item.assetCode.includes(filters.assetCode));
+// 鑱旇皟绾﹀畾锛氬垎椤靛弬鏁板浐瀹氫负 current/size锛岃繑鍥� data.records/data.total
+const getTableData = async () => {
+  try {
+    const { data } = await listFixedAssetPage({
+      current: pagination.currentPage,
+      size: pagination.pageSize,
+      assetCode: filters.assetCode,
+      assetName: filters.assetName,
+      category: filters.category,
+      status: filters.status,
+    });
+    dataList.value = data?.records || [];
+    multipleList.value = [];
+    pagination.total = Number(data?.total || 0);
+  } catch (error) {
+    // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
   }
-  if (filters.assetName) {
-    result = result.filter(item => item.assetName.includes(filters.assetName));
-  }
-  if (filters.category) {
-    result = result.filter(item => item.category === filters.category);
-  }
-  if (filters.status) {
-    result = result.filter(item => item.status === filters.status);
-  }
-  pagination.total = result.length;
-  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+};
+
+const handleSelectionChange = (selectionList) => {
+  multipleList.value = selectionList;
 };
 
 const resetFilters = () => {
@@ -334,39 +356,32 @@
   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, {
-    assetCode: "GD" + Date.now().toString().slice(-8),
-    assetName: "",
-    category: "",
-    specification: "",
+  Object.assign(form, createDefaultForm(), {
+    assetCode: buildAssetCode(),
     purchaseDate: new Date().toISOString().split('T')[0],
-    originalValue: 0,
-    usefulLife: 5,
-    residualRate: 5,
-    accumulatedDepreciation: 0,
-    netValue: 0,
-    location: "",
-    department: "",
-    keeper: "",
-    status: "in_use",
-    remark: "",
   });
   dialogVisible.value = true;
 };
 
 const edit = (row) => {
   isEdit.value = true;
+  isView.value = false;
   currentId.value = row.id;
   dialogTitle.value = "缂栬緫鍥哄畾璧勪骇";
-  Object.assign(form, row);
+  Object.assign(form, createDefaultForm(), row);
   dialogVisible.value = true;
 };
 
 const view = (row) => {
-  ElMessage.info(`鏌ョ湅璧勪骇: ${row.assetName}`);
+  edit(row);
+  isView.value = true;
 };
 
 const handleDelete = (row) => {
@@ -374,31 +389,30 @@
     confirmButtonText: "纭畾",
     cancelButtonText: "鍙栨秷",
     type: "warning",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData.splice(index, 1);
+  }).then(async () => {
+    // 鑱旇皟绾﹀畾锛氬垹闄ゆ帴鍙d娇鐢� ids=1&ids=2
+    await deleteFixedAsset([row.id]);
+    if (dataList.value.length === 1 && pagination.currentPage > 1) {
+      pagination.currentPage -= 1;
     }
     ElMessage.success("鍒犻櫎鎴愬姛");
-    getTableData();
+    await getTableData();
   });
 };
 
 const handleDepreciation = () => {
-  ElMessageBox.confirm("纭杩涜鏈湀鎶樻棫璁℃彁鍚楋紵", "鎻愮ず", {
+  const ids = selectedIds.value;
+  const confirmText = ids.length
+    ? `纭瀵归�変腑鐨� ${ids.length} 鏉¤祫浜ц繘琛屾湰鏈堟姌鏃ц鎻愬悧锛焋
+    : "纭杩涜鏈湀鎶樻棫璁℃彁鍚楋紵";
+  ElMessageBox.confirm(confirmText, "鎻愮ず", {
     confirmButtonText: "纭",
     cancelButtonText: "鍙栨秷",
     type: "info",
-  }).then(() => {
-    mockData.forEach(item => {
-      if (item.status === "in_use") {
-        const monthlyDepreciation = (item.originalValue * (1 - item.residualRate / 100)) / (item.usefulLife * 12);
-        item.accumulatedDepreciation = Number((item.accumulatedDepreciation + monthlyDepreciation).toFixed(2));
-        item.netValue = Number((item.originalValue - item.accumulatedDepreciation).toFixed(2));
-      }
-    });
+  }).then(async () => {
+    await depreciateFixedAsset({ ids });
     ElMessage.success("鎶樻棫璁℃彁瀹屾垚");
-    getTableData();
+    await getTableData();
   });
 };
 
@@ -407,22 +421,28 @@
 };
 
 const submitForm = () => {
-  formRef.value.validate((valid) => {
+  if (isView.value) {
+    dialogVisible.value = false;
+    return;
+  }
+  formRef.value.validate(async valid => {
     if (valid) {
-      calculateNetValue();
-      if (isEdit.value) {
-        const index = mockData.findIndex(item => item.id === currentId.value);
-        if (index !== -1) {
-          mockData[index] = { ...mockData[index], ...form };
+      try {
+        calculateNetValue();
+        const payload = { ...form };
+        if (isEdit.value) {
+          payload.id = currentId.value;
+          await updateFixedAsset(payload);
+          ElMessage.success("缂栬緫鎴愬姛");
+        } else {
+          await addFixedAsset(payload);
+          ElMessage.success("鏂板鎴愬姛");
         }
-        ElMessage.success("缂栬緫鎴愬姛");
-      } else {
-        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
-        mockData.push({ id: newId, ...form });
-        ElMessage.success("鏂板鎴愬姛");
+        dialogVisible.value = false;
+        await getTableData();
+      } catch (error) {
+        // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
       }
-      dialogVisible.value = false;
-      getTableData();
     }
   });
 };
diff --git a/src/views/financialManagement/assets/intangibleAssets.vue b/src/views/financialManagement/assets/intangibleAssets.vue
index 14dae55..47820c2 100644
--- a/src/views/financialManagement/assets/intangibleAssets.vue
+++ b/src/views/financialManagement/assets/intangibleAssets.vue
@@ -44,6 +44,7 @@
       </div>
       <PIMTable
         rowKey="id"
+        isSelection
         :column="columns"
         :tableData="dataList"
         :page="{
@@ -51,6 +52,7 @@
           size: pagination.pageSize,
           total: pagination.total,
         }"
+        @selection-change="handleSelectionChange"
         @pagination="changePage"
       >
         <template #originalValue="{ row }">
@@ -77,7 +79,7 @@
     </div>
 
     <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
-      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+      <el-form :model="form" :rules="rules" :disabled="isView" ref="formRef" label-width="120px">
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="璧勪骇缂栧彿" prop="assetCode">
@@ -171,7 +173,7 @@
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button type="primary" @click="submitForm">纭畾</el-button>
+        <el-button v-if="!isView" type="primary" @click="submitForm">纭畾</el-button>
         <el-button @click="dialogVisible = false">鍙栨秷</el-button>
       </template>
     </FormDialog>
@@ -182,6 +184,13 @@
 import { ref, reactive, onMounted, computed } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import FormDialog from "@/components/Dialog/FormDialog.vue";
+import {
+  listIntangibleAssetPage,
+  addIntangibleAsset,
+  updateIntangibleAsset,
+  deleteIntangibleAsset,
+  amortizeIntangibleAsset,
+} from "@/api/financialManagement/intangibleAsset";
 
 defineOptions({
   name: "鏃犲舰璧勪骇",
@@ -203,23 +212,30 @@
 const columns = [
   { label: "璧勪骇缂栧彿", prop: "assetCode", width: "130" },
   { label: "璧勪骇鍚嶇О", prop: "assetName", width: "150" },
-  { label: "璧勪骇绫诲埆", prop: "category", slot: "category" },
+  { label: "璧勪骇绫诲埆", prop: "category", dataType: "slot", slot: "category" },
   { label: "璇佷功缂栧彿", prop: "certificateNo", width: "150" },
-  { label: "璧勪骇鍘熷��", prop: "originalValue", slot: "originalValue" },
-  { label: "绱鎽婇攢", prop: "accumulatedAmortization", slot: "accumulatedAmortization" },
-  { label: "璧勪骇鍑�鍊�", prop: "netValue", slot: "netValue" },
-  { label: "鐘舵��", prop: "status", slot: "status" },
-  { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "180", fixed: "right" },
+  { label: "璧勪骇鍘熷��", prop: "originalValue", dataType: "slot", slot: "originalValue" },
+  { label: "绱鎽婇攢", prop: "accumulatedAmortization", dataType: "slot", slot: "accumulatedAmortization" },
+  { label: "璧勪骇鍑�鍊�", prop: "netValue", dataType: "slot", slot: "netValue" },
+  { label: "鐘舵��", prop: "status", dataType: "slot", slot: "status" },
+  { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "180", fixed: "right" },
 ];
 
 const dataList = ref([]);
+const multipleList = ref([]);
 const dialogVisible = ref(false);
 const dialogTitle = ref("");
 const formRef = ref(null);
 const isEdit = ref(false);
+const isView = ref(false);
 const currentId = ref(null);
+const selectedIds = computed(() =>
+  multipleList.value
+    .map(item => item?.id)
+    .filter(id => id !== undefined && id !== null && id !== "")
+);
 
-const form = reactive({
+const createDefaultForm = () => ({
   assetCode: "",
   assetName: "",
   category: "",
@@ -236,6 +252,10 @@
   remark: "",
 });
 
+const form = reactive({
+  ...createDefaultForm(),
+});
+
 const rules = {
   assetName: [{ required: true, message: "璇疯緭鍏ヨ祫浜у悕绉�", trigger: "blur" }],
   category: [{ required: true, message: "璇烽�夋嫨璧勪骇绫诲埆", trigger: "change" }],
@@ -243,13 +263,6 @@
   originalValue: [{ required: true, message: "璇疯緭鍏ヨ祫浜у師鍊�", trigger: "blur" }],
   amortizationPeriod: [{ required: true, message: "璇疯緭鍏ユ憡閿�骞撮檺", trigger: "blur" }],
 };
-
-const mockData = [
-  { id: 1, assetCode: "WX2024001", assetName: "ERP杞欢璁稿彲", category: "software", certificateNo: "SW-2023-001", acquisitionDate: "2023-01-01", originalValue: 50000, amortizationPeriod: 10, residualRate: 0, accumulatedAmortization: 5000, netValue: 45000, validityDate: "2033-01-01", status: "in_use", description: "浼佷笟璧勬簮璁″垝绠$悊绯荤粺", remark: "" },
-  { id: 2, assetCode: "WX2024002", assetName: "鍙戞槑涓撳埄", category: "patent", certificateNo: "ZL202210123456.7", acquisitionDate: "2022-06-15", originalValue: 100000, amortizationPeriod: 20, residualRate: 0, accumulatedAmortization: 3750, netValue: 96250, validityDate: "2042-06-15", status: "in_use", description: "涓�绉嶆柊鍨嬬敓浜у伐鑹�", remark: "" },
-  { id: 3, assetCode: "WX2024003", assetName: "鍟嗘爣鏉�", category: "trademark", certificateNo: "TM-2023-008", acquisitionDate: "2023-03-10", originalValue: 20000, amortizationPeriod: 10, residualRate: 0, accumulatedAmortization: 1500, netValue: 18500, validityDate: "2033-03-10", status: "in_use", description: "鍏徃鍝佺墝鍟嗘爣", remark: "" },
-  { id: 4, assetCode: "WX2024004", assetName: "鍦熷湴浣跨敤鏉�", category: "land", certificateNo: "鍦熷浗鐢�(2023)绗�001鍙�", acquisitionDate: "2023-07-01", originalValue: 500000, amortizationPeriod: 50, residualRate: 0, accumulatedAmortization: 5000, netValue: 495000, validityDate: "2073-07-01", status: "in_use", description: "宸ヤ笟鐢ㄥ湴浣跨敤鏉�", remark: "" },
-];
 
 const totalOriginalValue = computed(() => {
   return dataList.value.reduce((sum, item) => sum + Number(item.originalValue), 0);
@@ -281,35 +294,49 @@
 };
 
 const getStatusLabel = (status) => {
-  const map = { in_use: "鍦ㄧ敤", idle: "闂茬疆", amortized: "宸叉憡閿�瀹屾瘯" };
-  return map[status] || status;
+  const key = String(status || "").toLowerCase();
+  const map = {
+    in_use: "鍦ㄧ敤",
+    idle: "闂茬疆",
+    expired: "宸插埌鏈�",
+    amortized: "宸叉憡閿�瀹屾瘯",
+  };
+  return map[key] || status;
 };
 
 const getStatusType = (status) => {
-  const map = { in_use: "success", idle: "warning", amortized: "info" };
-  return map[status] || "";
+  const key = String(status || "").toLowerCase();
+  const map = { in_use: "success", idle: "warning", expired: "warning", amortized: "info" };
+  return map[key] || "";
 };
 
 const calculateNetValue = () => {
-  form.netValue = Number((form.originalValue - form.accumulatedAmortization).toFixed(2));
+  const originalValue = Number(form.originalValue || 0);
+  const accumulatedAmortization = Number(form.accumulatedAmortization || 0);
+  form.netValue = Number((originalValue - accumulatedAmortization).toFixed(2));
 };
 
-const getTableData = () => {
-  let result = [...mockData];
-  if (filters.assetCode) {
-    result = result.filter(item => item.assetCode.includes(filters.assetCode));
+// 鑱旇皟绾﹀畾锛氬垎椤靛弬鏁板浐瀹氫负 current/size锛岃繑鍥� data.records/data.total
+const getTableData = async () => {
+  try {
+    const { data } = await listIntangibleAssetPage({
+      current: pagination.currentPage,
+      size: pagination.pageSize,
+      assetCode: filters.assetCode,
+      assetName: filters.assetName,
+      category: filters.category,
+      status: filters.status,
+    });
+    dataList.value = data?.records || [];
+    multipleList.value = [];
+    pagination.total = Number(data?.total || 0);
+  } catch (error) {
+    // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
   }
-  if (filters.assetName) {
-    result = result.filter(item => item.assetName.includes(filters.assetName));
-  }
-  if (filters.category) {
-    result = result.filter(item => item.category === filters.category);
-  }
-  if (filters.status) {
-    result = result.filter(item => item.status === filters.status);
-  }
-  pagination.total = result.length;
-  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+};
+
+const handleSelectionChange = (selectionList) => {
+  multipleList.value = selectionList;
 };
 
 const resetFilters = () => {
@@ -327,38 +354,32 @@
   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, {
-    assetCode: "WX" + Date.now().toString().slice(-8),
-    assetName: "",
-    category: "",
-    certificateNo: "",
+  Object.assign(form, createDefaultForm(), {
+    assetCode: buildAssetCode(),
     acquisitionDate: new Date().toISOString().split('T')[0],
-    originalValue: 0,
-    amortizationPeriod: 10,
-    residualRate: 0,
-    accumulatedAmortization: 0,
-    netValue: 0,
-    validityDate: "",
-    status: "in_use",
-    description: "",
-    remark: "",
   });
   dialogVisible.value = true;
 };
 
 const edit = (row) => {
   isEdit.value = true;
+  isView.value = false;
   currentId.value = row.id;
   dialogTitle.value = "缂栬緫鏃犲舰璧勪骇";
-  Object.assign(form, row);
+  Object.assign(form, createDefaultForm(), row);
   dialogVisible.value = true;
 };
 
 const view = (row) => {
-  ElMessage.info(`鏌ョ湅璧勪骇: ${row.assetName}`);
+  edit(row);
+  isView.value = true;
 };
 
 const handleDelete = (row) => {
@@ -366,35 +387,30 @@
     confirmButtonText: "纭畾",
     cancelButtonText: "鍙栨秷",
     type: "warning",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData.splice(index, 1);
+  }).then(async () => {
+    // 鑱旇皟绾﹀畾锛氬垹闄ゆ帴鍙d娇鐢� ids=1&ids=2
+    await deleteIntangibleAsset([row.id]);
+    if (dataList.value.length === 1 && pagination.currentPage > 1) {
+      pagination.currentPage -= 1;
     }
     ElMessage.success("鍒犻櫎鎴愬姛");
-    getTableData();
+    await getTableData();
   });
 };
 
 const handleAmortization = () => {
-  ElMessageBox.confirm("纭杩涜鏈湀鎽婇攢璁℃彁鍚楋紵", "鎻愮ず", {
+  const ids = selectedIds.value;
+  const confirmText = ids.length
+    ? `纭瀵归�変腑鐨� ${ids.length} 鏉¤祫浜ц繘琛屾湰鏈堟憡閿�璁℃彁鍚楋紵`
+    : "纭杩涜鏈湀鎽婇攢璁℃彁鍚楋紵";
+  ElMessageBox.confirm(confirmText, "鎻愮ず", {
     confirmButtonText: "纭",
     cancelButtonText: "鍙栨秷",
     type: "info",
-  }).then(() => {
-    mockData.forEach(item => {
-      if (item.status === "in_use") {
-        const monthlyAmortization = (item.originalValue * (1 - item.residualRate / 100)) / (item.amortizationPeriod * 12);
-        item.accumulatedAmortization = Number((item.accumulatedAmortization + monthlyAmortization).toFixed(2));
-        item.netValue = Number((item.originalValue - item.accumulatedAmortization).toFixed(2));
-        if (item.netValue <= 0) {
-          item.status = "amortized";
-          item.netValue = 0;
-        }
-      }
-    });
+  }).then(async () => {
+    await amortizeIntangibleAsset({ ids });
     ElMessage.success("鎽婇攢璁℃彁瀹屾垚");
-    getTableData();
+    await getTableData();
   });
 };
 
@@ -403,22 +419,28 @@
 };
 
 const submitForm = () => {
-  formRef.value.validate((valid) => {
+  if (isView.value) {
+    dialogVisible.value = false;
+    return;
+  }
+  formRef.value.validate(async valid => {
     if (valid) {
-      calculateNetValue();
-      if (isEdit.value) {
-        const index = mockData.findIndex(item => item.id === currentId.value);
-        if (index !== -1) {
-          mockData[index] = { ...mockData[index], ...form };
+      try {
+        calculateNetValue();
+        const payload = { ...form };
+        if (isEdit.value) {
+          payload.id = currentId.value;
+          await updateIntangibleAsset(payload);
+          ElMessage.success("缂栬緫鎴愬姛");
+        } else {
+          await addIntangibleAsset(payload);
+          ElMessage.success("鏂板鎴愬姛");
         }
-        ElMessage.success("缂栬緫鎴愬姛");
-      } else {
-        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
-        mockData.push({ id: newId, ...form });
-        ElMessage.success("鏂板鎴愬姛");
+        dialogVisible.value = false;
+        await getTableData();
+      } catch (error) {
+        // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
       }
-      dialogVisible.value = false;
-      getTableData();
     }
   });
 };
diff --git a/src/views/financialManagement/generalLedger/index.vue b/src/views/financialManagement/generalLedger/index.vue
index fbe2210..556567b 100644
--- a/src/views/financialManagement/generalLedger/index.vue
+++ b/src/views/financialManagement/generalLedger/index.vue
@@ -48,16 +48,58 @@
                      icon="Download">瀵煎嚭</el-button>
         </div>
       </div>
-      <PIMTable rowKey="id"
-                :column="columns"
-                :tableData="dataList"
-                :page="{
-          current: pagination.currentPage,
-          size: pagination.pageSize,
-          total: pagination.total,
-        }"
-                @pagination="changePage">
-      </PIMTable>
+      <el-table ref="tableRef"
+                v-loading="loading"
+                :data="dataList"
+                row-key="id"
+                :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+                height="calc(100vh - 280px)"
+                border
+                stripe
+                highlight-current-row
+                class="subject-table">
+        <el-table-column label="绉戠洰缂栫爜" prop="subjectCode" width="140">
+          <template #default="scope">
+            <span class="subject-code">{{ scope.row.subjectCode }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="绉戠洰鍚嶇О" prop="subjectName" min-width="180">
+          <template #default="scope">
+            <span class="subject-name" :class="{ 'is-parent': scope.row.children?.length > 0 }">
+              {{ scope.row.subjectName }}
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column label="绉戠洰绫诲瀷" prop="subjectType" width="100" align="center">
+          <template #default="scope">
+            <el-tag size="small" :type="getSubjectTypeType(scope.row.subjectType)">
+              {{ scope.row.subjectType }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="浣欓鏂瑰悜" prop="balanceDirection" width="100" align="center">
+          <template #default="scope">
+            <el-tag size="small" :type="scope.row.balanceDirection === '鍊熸柟' ? 'primary' : 'danger'">
+              {{ scope.row.balanceDirection }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐘舵��" prop="status" width="80" align="center">
+          <template #default="scope">
+            <el-tag size="small" :type="scope.row.status === 0 || scope.row.status === '0' ? 'success' : 'info'">
+              {{ scope.row.status === 0 || scope.row.status === '0' ? '鍚敤' : '绂佺敤' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="澶囨敞" prop="remark" show-overflow-tooltip min-width="150" />
+        <el-table-column label="鎿嶄綔" align="center" fixed="right" width="240">
+          <template #default="scope">
+            <el-button link type="primary" icon="Plus" @click="addChild(scope.row)">鏂板</el-button>
+            <el-button link type="primary" icon="Edit" @click="edit(scope.row)">缂栬緫</el-button>
+            <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
     </div>
     <FormDialog :title="dialogTitle"
                 v-model="dialogVisible"
@@ -68,6 +110,10 @@
                :rules="rules"
                ref="formRef"
                label-width="100px">
+        <el-form-item label="鐖剁骇绉戠洰">
+          <el-input :model-value="parentSubjectLabel"
+                    disabled />
+        </el-form-item>
         <el-form-item label="绉戠洰缂栫爜"
                       prop="subjectCode">
           <el-input v-model="form.subjectCode"
@@ -127,7 +173,7 @@
 </template>
 
 <script setup>
-  import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+  import { ref, reactive, onMounted, getCurrentInstance, nextTick } from "vue";
   import { ElMessage, ElMessageBox } from "element-plus";
   import FormDialog from "@/components/Dialog/FormDialog.vue";
   import {
@@ -201,8 +247,15 @@
       label: "鎿嶄綔",
       align: "center",
       fixed: "right",
-      width: "150",
+      width: "220",
       operation: [
+        {
+          name: "鏂板",
+          type: "primary",
+          clickFun: row => {
+            addChild(row);
+          },
+        },
         {
           name: "缂栬緫",
           type: "primary",
@@ -224,11 +277,15 @@
   const dataList = ref([]);
   const dialogVisible = ref(false);
   const dialogTitle = ref("");
+  const parentSubjectLabel = ref("椤剁骇绉戠洰");
   const formRef = ref(null);
+  const tableRef = ref(null);
   const isEdit = ref(false);
+  const loading = ref(false);
 
   const form = reactive({
     id: undefined,
+    parentId: null,
     subjectCode: "",
     subjectName: "",
     subjectType: "",
@@ -257,14 +314,17 @@
   };
 
   const getTableData = () => {
+    loading.value = true;
     const query = {
-      pageNum: pagination.currentPage,
-      pageSize: pagination.pageSize,
+      current: pagination.currentPage,
+      size: pagination.pageSize,
       ...filters,
     };
     listAccountSubject(query).then(response => {
-      dataList.value = response.data.records;
-      pagination.total = response.data.total;
+      dataList.value = response.data.records || [];
+      loading.value = false;
+    }).catch(() => {
+      loading.value = false;
     });
   };
 
@@ -282,11 +342,19 @@
     getTableData();
   };
 
-  const add = () => {
-    isEdit.value = false;
-    dialogTitle.value = "鏂板绉戠洰";
+  const buildParentSubjectLabel = parentRow => {
+    if (!parentRow) {
+      return "椤剁骇绉戠洰";
+    }
+    const code = parentRow.subjectCode || "";
+    const name = parentRow.subjectName || "";
+    return `${code} ${name}`.trim();
+  };
+
+  const resetForm = ({ parentId = null, parentRow = null } = {}) => {
     Object.assign(form, {
       id: undefined,
+      parentId,
       subjectCode: "",
       subjectName: "",
       subjectType: "",
@@ -294,13 +362,54 @@
       status: 0,
       remark: "",
     });
+    parentSubjectLabel.value = buildParentSubjectLabel(parentRow);
+  };
+
+  const add = () => {
+    isEdit.value = false;
+    dialogTitle.value = "鏂板绉戠洰";
+    resetForm({ parentId: null, parentRow: null });
     dialogVisible.value = true;
+  };
+
+  const addChild = row => {
+    isEdit.value = false;
+    dialogTitle.value = "鏂板瀛愮鐩�";
+    resetForm({ parentId: row.id, parentRow: row });
+    form.subjectType = row.subjectType || "";
+    form.balanceDirection = row.balanceDirection || "鍊熸柟";
+    dialogVisible.value = true;
+  };
+
+  const findSubjectById = (nodes, id) => {
+    for (const item of nodes || []) {
+      if (item.id === id) {
+        return item;
+      }
+      if (item.children && item.children.length > 0) {
+        const found = findSubjectById(item.children, id);
+        if (found) {
+          return found;
+        }
+      }
+    }
+    return null;
   };
 
   const edit = row => {
     isEdit.value = true;
     dialogTitle.value = "缂栬緫绉戠洰";
     Object.assign(form, row);
+    form.parentId = row.parentId ?? null;
+    const parentRow =
+      row.parentId === null || row.parentId === undefined
+        ? null
+        : findSubjectById(dataList.value, row.parentId);
+    parentSubjectLabel.value = parentRow
+      ? buildParentSubjectLabel(parentRow)
+      : row.parentId
+      ? `涓婄骇ID: ${row.parentId}`
+      : buildParentSubjectLabel(null);
     dialogVisible.value = true;
   };
 
@@ -361,4 +470,29 @@
     justify-content: space-between;
     margin-bottom: 15px;
   }
+
+  .subject-table {
+    border-radius: 8px;
+    overflow: hidden;
+
+    :deep(.el-table__row) {
+      transition: background-color 0.3s;
+    }
+
+    :deep(.el-table__row:hover) {
+      background-color: #f5f7fa;
+    }
+
+    .subject-code {
+      color: #606266;
+    }
+
+    .subject-name {
+      font-weight: 500;
+
+      &.is-parent {
+        color: #409eff;
+      }
+    }
+  }
 </style>
diff --git a/src/views/financialManagement/payable/purchaseIn.vue b/src/views/financialManagement/payable/purchaseIn.vue
index 4813159..4fadcbb 100644
--- a/src/views/financialManagement/payable/purchaseIn.vue
+++ b/src/views/financialManagement/payable/purchaseIn.vue
@@ -1,19 +1,27 @@
 <template>
+  <!-- 閲囪喘鍏ュ簱 -->
   <div class="app-container">
     <el-form :model="filters" :inline="true">
       <el-form-item label="鍏ュ簱鍗曞彿:">
-        <el-input v-model="filters.inCode" placeholder="璇疯緭鍏ュ叆搴撳崟鍙�" clearable style="width: 200px;" />
+        <el-input v-model="filters.inboundBatches" placeholder="璇疯緭鍏ュ叆搴撳崟鍙�" clearable style="width: 200px;" />
       </el-form-item>
       <el-form-item label="渚涘簲鍟�:">
-        <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px;">
-          <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
-        </el-select>
+        <el-input v-model="filters.supplierName" 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="getTableData">鎼滅储</el-button>
+        <el-button type="primary" @click="onSearch">鎼滅储</el-button>
         <el-button @click="resetFilters">閲嶇疆</el-button>
       </el-form-item>
     </el-form>
@@ -28,6 +36,7 @@
         rowKey="id"
         :column="columns"
         :tableData="dataList"
+        :tableLoading="tableLoading"
         :page="{
           current: pagination.currentPage,
           size: pagination.pageSize,
@@ -35,107 +44,28 @@
         }"
         @pagination="changePage"
       >
-        <template #amount="{ row }">
-          <span class="text-primary">楼{{ formatMoney(row.amount) }}</span>
-        </template>
-        <template #status="{ row }">
-          <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
-        </template>
-        <template #operation="{ row }">
-          <el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
-          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
-          <el-button type="danger" link @click="handleDelete(row)" v-if="row.status === 'pending'">鍒犻櫎</el-button>
+        <template #inboundDate="{ row }">
+          {{ row.InboundDate || row.inboundDate || "" }}
         </template>
       </PIMTable>
     </div>
-
-    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
-      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="鍏ュ簱鍗曞彿" prop="inCode">
-              <el-input v-model="form.inCode" placeholder="璇疯緭鍏ュ叆搴撳崟鍙�" :disabled="isEdit" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="渚涘簲鍟�" prop="supplierId">
-              <el-select v-model="form.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%;" :disabled="isEdit">
-                <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="鍏ュ簱鏃ユ湡" prop="inDate">
-              <el-date-picker v-model="form.inDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="鍏ュ簱閲戦" prop="amount">
-              <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-form-item label="鍏ュ簱鏄庣粏" prop="details">
-          <el-table :data="form.details" border style="width: 100%">
-            <el-table-column prop="materialName" label="鐗╂枡鍚嶇О" width="150">
-              <template #default="{ $index }">
-                <el-input v-model="form.details[$index].materialName" placeholder="鐗╂枡鍚嶇О" />
-              </template>
-            </el-table-column>
-            <el-table-column prop="spec" label="瑙勬牸" width="120">
-              <template #default="{ $index }">
-                <el-input v-model="form.details[$index].spec" placeholder="瑙勬牸" />
-              </template>
-            </el-table-column>
-            <el-table-column prop="quantity" label="鏁伴噺" width="100">
-              <template #default="{ $index }">
-                <el-input-number v-model="form.details[$index].quantity" :min="0" style="width: 100%;" />
-              </template>
-            </el-table-column>
-            <el-table-column prop="unitPrice" label="鍗曚环" width="120">
-              <template #default="{ $index }">
-                <el-input-number v-model="form.details[$index].unitPrice" :min="0" :precision="2" style="width: 100%;" />
-              </template>
-            </el-table-column>
-            <el-table-column prop="total" label="閲戦" width="120">
-              <template #default="{ row }">
-                <span>楼{{ formatMoney(row.quantity * row.unitPrice) }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="鎿嶄綔" width="80">
-              <template #default="{ $index }">
-                <el-button type="danger" link @click="removeDetail($index)">鍒犻櫎</el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-          <el-button type="primary" link @click="addDetail" style="margin-top: 10px;">+ 娣诲姞鏄庣粏</el-button>
-        </el-form-item>
-        <el-form-item label="澶囨敞" prop="remark">
-          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button type="primary" @click="submitForm">纭畾</el-button>
-        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
-      </template>
-    </FormDialog>
   </div>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ElMessage } from "element-plus";
+import { listPageAccountPurchase } from "@/api/financialManagement/accountPurchase";
 
 defineOptions({
   name: "閲囪喘鍏ュ簱",
 });
 
+const { proxy } = getCurrentInstance();
+
 const filters = reactive({
-  inCode: "",
-  supplierId: "",
+  inboundBatches: "",
+  supplierName: "",
   dateRange: [],
 });
 
@@ -146,170 +76,85 @@
 });
 
 const columns = [
-  { label: "鍏ュ簱鍗曞彿", prop: "inCode", width: "150" },
-  { label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
-  { label: "鍏ュ簱鏃ユ湡", prop: "inDate", width: "120" },
-  { label: "鍏ュ簱閲戦", prop: "amount", slot: "amount" },
-  { label: "鐘舵��", prop: "status", slot: "status" },
-  { label: "澶囨敞", prop: "remark", showOverflowTooltip: true },
-  { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "200", fixed: "right" },
+  { label: "鍏ュ簱鍗曞彿", prop: "inboundBatches", minWidth: "150" },
+  { label: "渚涘簲鍟�", prop: "supplierName", minWidth: "180" },
+  {
+    label: "鍏ュ簱鏃ユ湡",
+    prop: "InboundDate",
+    minWidth: "170",
+    dataType: "slot",
+    slot: "inboundDate",
+  },
+  { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
+  { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
+  { label: "閲囪喘璁㈠崟鍙�", prop: "purchaseContractNumber", minWidth: "150" },
 ];
 
 const dataList = ref([]);
-const dialogVisible = ref(false);
-const dialogTitle = ref("");
-const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
+const tableLoading = ref(false);
 
-const supplierList = [
-  { id: 1, name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
-  { id: 2, name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
-  { id: 3, name: "骞垮窞鍖呰鏉愭枡鍘�" },
-  { id: 4, name: "娣卞湷浜旈噾閰嶄欢鍏徃" },
-];
+function buildFilterParams() {
+  const params = {
+    inboundBatches: filters.inboundBatches || undefined,
+    supplierName: filters.supplierName || undefined,
+  };
+  if (filters.dateRange && filters.dateRange.length === 2) {
+    params.startDate = filters.dateRange[0];
+    params.endDate = filters.dateRange[1];
+  }
+  return params;
+}
 
-const form = reactive({
-  inCode: "",
-  supplierId: "",
-  inDate: "",
-  amount: 0,
-  details: [],
-  remark: "",
-});
-
-const rules = {
-  inCode: [{ required: true, message: "璇疯緭鍏ュ叆搴撳崟鍙�", trigger: "blur" }],
-  supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
-  inDate: [{ required: true, message: "璇烽�夋嫨鍏ュ簱鏃ユ湡", trigger: "change" }],
-  amount: [{ required: true, message: "璇疯緭鍏ュ叆搴撻噾棰�", trigger: "blur" }],
-};
-
-const mockData = [
-  { id: 1, inCode: "RK2024001", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", inDate: "2024-01-10", amount: 8000, status: "approved", details: [{ materialName: "閽㈡潗", spec: "Q235", quantity: 10, unitPrice: 500 }], remark: "" },
-  { id: 2, inCode: "RK2024002", supplierId: 2, supplierName: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�", inDate: "2024-01-12", amount: 12000, status: "pending", details: [{ materialName: "鑺墖", spec: "STM32", quantity: 100, unitPrice: 80 }], remark: "" },
-  { id: 3, inCode: "RK2024003", supplierId: 3, supplierName: "骞垮窞鍖呰鏉愭枡鍘�", inDate: "2024-01-15", amount: 3500, status: "approved", details: [{ materialName: "绾哥", spec: "50*40*30", quantity: 500, unitPrice: 5 }], remark: "" },
-];
-
-const formatMoney = (value) => {
-  if (value === undefined || value === null) return "0.00";
-  return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
-};
-
-const getStatusLabel = (status) => {
-  const map = { pending: "寰呭鏍�", approved: "宸插鏍�", rejected: "宸查┏鍥�" };
-  return map[status] || status;
-};
-
-const getStatusType = (status) => {
-  const map = { pending: "warning", approved: "success", rejected: "danger" };
-  return map[status] || "";
+const onSearch = () => {
+  pagination.currentPage = 1;
+  getTableData();
 };
 
 const getTableData = () => {
-  let result = [...mockData];
-  if (filters.inCode) {
-    result = result.filter(item => item.inCode.includes(filters.inCode));
-  }
-  if (filters.supplierId) {
-    result = result.filter(item => item.supplierId === filters.supplierId);
-  }
-  if (filters.dateRange && filters.dateRange.length === 2) {
-    result = result.filter(item => item.inDate >= filters.dateRange[0] && item.inDate <= filters.dateRange[1]);
-  }
-  pagination.total = result.length;
-  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+  tableLoading.value = true;
+  listPageAccountPurchase({
+    ...buildFilterParams(),
+    current: pagination.currentPage,
+    size: pagination.pageSize,
+  })
+    .then((res) => {
+      const ok = res.code === 200 || res.code === 0;
+      if (ok && res.data) {
+        pagination.total = res.data.total ?? 0;
+        dataList.value = res.data.records ?? [];
+      } else {
+        ElMessage.error(res.msg || "鏌ヨ澶辫触");
+        dataList.value = [];
+      }
+    })
+    .catch(() => {
+      dataList.value = [];
+    })
+    .finally(() => {
+      tableLoading.value = false;
+    });
 };
 
 const resetFilters = () => {
-  filters.inCode = "";
-  filters.supplierId = "";
+  filters.inboundBatches = "";
+  filters.supplierName = "";
   filters.dateRange = [];
   pagination.currentPage = 1;
   getTableData();
 };
 
-const changePage = ({ current, size }) => {
-  pagination.currentPage = current;
-  pagination.pageSize = size;
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+  pagination.pageSize = limit;
   getTableData();
 };
 
-const addDetail = () => {
-  form.details.push({ materialName: "", spec: "", quantity: 0, unitPrice: 0 });
-};
-
-const removeDetail = (index) => {
-  form.details.splice(index, 1);
-};
-
-const add = () => {
-  isEdit.value = false;
-  dialogTitle.value = "鏂板鍏ュ簱";
-  Object.assign(form, {
-    inCode: "RK" + Date.now().toString().slice(-8),
-    supplierId: "",
-    inDate: new Date().toISOString().split('T')[0],
-    amount: 0,
-    details: [{ materialName: "", spec: "", quantity: 0, unitPrice: 0 }],
-    remark: "",
-  });
-  dialogVisible.value = true;
-};
-
-const edit = (row) => {
-  isEdit.value = true;
-  currentId.value = row.id;
-  dialogTitle.value = "缂栬緫鍏ュ簱";
-  Object.assign(form, row);
-  if (!form.details || form.details.length === 0) {
-    form.details = [{ materialName: "", spec: "", quantity: 0, unitPrice: 0 }];
-  }
-  dialogVisible.value = true;
-};
-
-const view = (row) => {
-  ElMessage.info(`鏌ョ湅鍏ュ簱鍗�: ${row.inCode}`);
-};
-
-const handleDelete = (row) => {
-  ElMessageBox.confirm("纭鍒犻櫎璇ュ叆搴撳崟鍚楋紵", "鎻愮ず", {
-    confirmButtonText: "纭畾",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData.splice(index, 1);
-    }
-    ElMessage.success("鍒犻櫎鎴愬姛");
-    getTableData();
-  });
-};
-
 const handleOut = () => {
-  ElMessage.success("瀵煎嚭鎴愬姛");
-};
-
-const submitForm = () => {
-  formRef.value.validate((valid) => {
-    if (valid) {
-      const supplier = supplierList.find(item => item.id === form.supplierId);
-      if (isEdit.value) {
-        const index = mockData.findIndex(item => item.id === currentId.value);
-        if (index !== -1) {
-          mockData[index] = { ...mockData[index], ...form, supplierName: supplier?.name };
-        }
-        ElMessage.success("缂栬緫鎴愬姛");
-      } else {
-        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
-        mockData.push({ id: newId, ...form, supplierName: supplier?.name, status: "pending" });
-        ElMessage.success("鏂板鎴愬姛");
-      }
-      dialogVisible.value = false;
-      getTableData();
-    }
-  });
+  proxy.download(
+    "/accountPurchase/exportAccountPurchaseInbound",
+    buildFilterParams(),
+    `閲囪喘鍏ュ簱_${new Date().getTime()}.xlsx`
+  );
 };
 
 onMounted(() => {
@@ -322,10 +167,5 @@
   display: flex;
   justify-content: space-between;
   margin-bottom: 15px;
-}
-
-.text-primary {
-  color: #409eff;
-  font-weight: bold;
 }
 </style>
diff --git a/src/views/financialManagement/payable/purchaseReturn.vue b/src/views/financialManagement/payable/purchaseReturn.vue
new file mode 100644
index 0000000..e7ca665
--- /dev/null
+++ b/src/views/financialManagement/payable/purchaseReturn.vue
@@ -0,0 +1,239 @@
+<template>
+  <!-- 閲囪喘閫�璐� -->
+
+  <div class="app-container">
+    <el-form :model="filters" :inline="true">
+      <el-form-item label="閫�璐у崟鍙�:">
+        <el-input
+          v-model="filters.returnNo"
+          placeholder="璇疯緭鍏ラ��璐у崟鍙�"
+          clearable
+          style="width: 200px"
+        />
+      </el-form-item>
+
+      <el-form-item label="渚涘簲鍟�:">
+        <el-input
+          v-model="filters.supplierName"
+          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-form-item>
+
+      <el-form-item>
+        <el-button type="primary" @click="onSearch">鎼滅储</el-button>
+
+        <el-button @click="resetFilters">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <div class="table_list">
+      <div class="actions">
+        <div></div>
+
+        <div>
+          <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+        </div>
+      </div>
+
+      <PIMTable
+        rowKey="id"
+        :column="columns"
+        :tableData="dataList"
+        :tableLoading="tableLoading"
+        :page="{
+          current: pagination.currentPage,
+
+          size: pagination.pageSize,
+
+          total: pagination.total,
+        }"
+        @pagination="changePage"
+      />
+    </div>
+  </div>
+</template>
+
+
+
+<script setup>
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+
+import { ElMessage } from "element-plus";
+
+import { listPageAccountPurchaseReturn } from "@/api/financialManagement/accountPurchase";
+
+defineOptions({
+  name: "閲囪喘閫�璐�",
+});
+
+const { proxy } = getCurrentInstance();
+
+const filters = reactive({
+  returnNo: "",
+
+  supplierName: "",
+
+  dateRange: [],
+});
+
+const pagination = reactive({
+  currentPage: 1,
+
+  pageSize: 10,
+
+  total: 0,
+});
+
+const columns = [
+  { label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: "150" },
+
+  { label: "渚涘簲鍟�", prop: "supplierName", minWidth: "180" },
+
+  { label: "鍏宠仈鍏ュ簱鍗曞彿", prop: "inboundBatches", minWidth: "150" },
+
+  { label: "閫�璐ф棩鏈�", prop: "preparedAt", minWidth: "170" },
+
+  {
+    label: "閫�娆炬�婚",
+
+    prop: "totalAmount",
+
+    minWidth: "150",
+
+    align: "right",
+
+    formatData: (val) =>
+      val === null || val === undefined || val === ""
+        ? ""
+        : Number(val).toLocaleString("zh-CN", {
+            minimumFractionDigits: 2,
+            maximumFractionDigits: 2,
+          }),
+  },
+
+  { label: "閫�璐ф柟寮�", prop: "returnType", minWidth: "150" },
+
+  { label: "閲囪喘璁㈠崟鍙�", prop: "purchaseContractNumber", minWidth: "150" },
+];
+
+const dataList = ref([]);
+
+const tableLoading = ref(false);
+
+function buildFilterParams() {
+  const params = {
+    returnNo: filters.returnNo || undefined,
+
+    supplierName: filters.supplierName || 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 getTableData = () => {
+  tableLoading.value = true;
+
+  listPageAccountPurchaseReturn({
+    ...buildFilterParams(),
+
+    current: pagination.currentPage,
+
+    size: pagination.pageSize,
+  })
+    .then((res) => {
+      const ok = res.code === 200 || res.code === 0;
+
+      if (ok && res.data) {
+        pagination.total = res.data.total ?? 0;
+
+        dataList.value = res.data.records ?? [];
+      } else {
+        ElMessage.error(res.msg || "鏌ヨ澶辫触");
+
+        dataList.value = [];
+      }
+    })
+
+    .catch(() => {
+      dataList.value = [];
+    })
+
+    .finally(() => {
+      tableLoading.value = false;
+    });
+};
+
+const resetFilters = () => {
+  filters.returnNo = "";
+
+  filters.supplierName = "";
+
+  filters.dateRange = [];
+
+  pagination.currentPage = 1;
+
+  getTableData();
+};
+
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+
+  pagination.pageSize = limit;
+
+  getTableData();
+};
+
+const handleOut = () => {
+  proxy.download(
+    "/accountPurchase/exportAccountPurchaseReturn",
+
+    buildFilterParams(),
+
+    `閲囪喘閫�璐${new Date().getTime()}.xlsx`
+  );
+};
+
+onMounted(() => {
+  getTableData();
+});
+</script>
+
+
+
+<style lang="scss" scoped>
+.actions {
+  display: flex;
+
+  justify-content: space-between;
+
+  margin-bottom: 15px;
+}
+</style>
+
diff --git a/src/views/financialManagement/receivable/salesOut.vue b/src/views/financialManagement/receivable/salesOut.vue
index fce0c20..297a82c 100644
--- a/src/views/financialManagement/receivable/salesOut.vue
+++ b/src/views/financialManagement/receivable/salesOut.vue
@@ -1,19 +1,27 @@
 <template>
+<!-- 閿�鍞嚭搴� -->
   <div class="app-container">
     <el-form :model="filters" :inline="true">
       <el-form-item label="鍑哄簱鍗曞彿:">
-        <el-input v-model="filters.outCode" placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�" clearable style="width: 200px;" />
+        <el-input v-model="filters.outboundBatches" placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�" clearable style="width: 200px;" />
       </el-form-item>
-      <el-form-item label="瀹㈡埛:">
-        <el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable style="width: 200px;">
-          <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
-        </el-select>
+      <el-form-item label="瀹㈡埛鍚嶇О:">
+        <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="getTableData">鎼滅储</el-button>
+        <el-button type="primary" @click="onSearch">鎼滅储</el-button>
         <el-button @click="resetFilters">閲嶇疆</el-button>
       </el-form-item>
     </el-form>
@@ -28,76 +36,32 @@
         rowKey="id"
         :column="columns"
         :tableData="dataList"
+        :tableLoading="tableLoading"
         :page="{
           current: pagination.currentPage,
           size: pagination.pageSize,
           total: pagination.total,
         }"
         @pagination="changePage"
-      >
-        <template #status="{ row }">
-          <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
-        </template>
-        <template #operation="{ row }">
-          <el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
-          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
-          <el-button type="danger" link @click="handleDelete(row)" v-if="row.status === 'pending'">鍒犻櫎</el-button>
-        </template>
-      </PIMTable>
+      />
     </div>
-
-    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
-      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="鍑哄簱鍗曞彿" prop="outCode">
-              <el-input v-model="form.outCode" placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�" :disabled="isEdit" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="瀹㈡埛" prop="customerId">
-              <el-select v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" :disabled="isEdit">
-                <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="鍑哄簱鏃ユ湡" prop="outDate">
-              <el-date-picker v-model="form.outDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="閲戦" prop="amount">
-              <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-form-item label="澶囨敞" prop="remark">
-          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button type="primary" @click="submitForm">纭畾</el-button>
-        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
-      </template>
-    </FormDialog>
   </div>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ElMessage } from "element-plus";
+import { listPageAccountSales } from "@/api/financialManagement/accountSales";
 
 defineOptions({
   name: "閿�鍞嚭搴�",
 });
 
+const { proxy } = getCurrentInstance();
+
 const filters = reactive({
-  outCode: "",
-  customerId: "",
+  outboundBatches: "",
+  customerName: "",
   dateRange: [],
 });
 
@@ -108,153 +72,87 @@
 });
 
 const columns = [
-  { label: "鍑哄簱鍗曞彿", prop: "outCode", width: "150" },
-  { label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
-  { label: "鍑哄簱鏃ユ湡", prop: "outDate", width: "120" },
-  { label: "閲戦", prop: "amount", width: "120" },
-  { label: "鐘舵��", prop: "status", slot: "status" },
-  { label: "澶囨敞", prop: "remark", showOverflowTooltip: true },
-  { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "200", fixed: "right" },
+  { 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 dialogVisible = ref(false);
-const dialogTitle = ref("");
-const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
+const tableLoading = ref(false);
 
-const customerList = [
-  { id: 1, name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
-  { id: 2, name: "涓婃捣璐告槗鍏徃" },
-  { id: 3, name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
-  { id: 4, name: "娣卞湷鐢靛瓙鍏徃" },
-];
+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 form = reactive({
-  outCode: "",
-  customerId: "",
-  outDate: "",
-  amount: 0,
-  remark: "",
-});
-
-const rules = {
-  outCode: [{ required: true, message: "璇疯緭鍏ュ嚭搴撳崟鍙�", trigger: "blur" }],
-  customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
-  outDate: [{ required: true, message: "璇烽�夋嫨鍑哄簱鏃ユ湡", trigger: "change" }],
-  amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
-};
-
-const mockData = [
-  { id: 1, outCode: "CK2024001", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", outDate: "2024-01-15", amount: 5000, status: "approved", remark: "" },
-  { id: 2, outCode: "CK2024002", customerId: 2, customerName: "涓婃捣璐告槗鍏徃", outDate: "2024-01-16", amount: 8000, status: "pending", remark: "" },
-  { id: 3, outCode: "CK2024003", customerId: 3, customerName: "骞垮窞瀹炰笟鏈夐檺鍏徃", outDate: "2024-01-18", amount: 12000, status: "approved", remark: "" },
-  { id: 4, outCode: "CK2024004", customerId: 4, customerName: "娣卞湷鐢靛瓙鍏徃", outDate: "2024-01-20", amount: 3500, status: "pending", remark: "" },
-];
-
-const getStatusLabel = (status) => {
-  const map = { pending: "寰呭鏍�", approved: "宸插鏍�", rejected: "宸查┏鍥�" };
-  return map[status] || status;
-};
-
-const getStatusType = (status) => {
-  const map = { pending: "warning", approved: "success", rejected: "danger" };
-  return map[status] || "";
+const onSearch = () => {
+  pagination.currentPage = 1;
+  getTableData();
 };
 
 const getTableData = () => {
-  let result = [...mockData];
-  if (filters.outCode) {
-    result = result.filter(item => item.outCode.includes(filters.outCode));
-  }
-  if (filters.customerId) {
-    result = result.filter(item => item.customerId === filters.customerId);
-  }
-  if (filters.dateRange && filters.dateRange.length === 2) {
-    result = result.filter(item => item.outDate >= filters.dateRange[0] && item.outDate <= filters.dateRange[1]);
-  }
-  pagination.total = result.length;
-  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+  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.outCode = "";
-  filters.customerId = "";
+  filters.outboundBatches = "";
+  filters.customerName = "";
   filters.dateRange = [];
   pagination.currentPage = 1;
   getTableData();
 };
 
-const changePage = ({ current, size }) => {
-  pagination.currentPage = current;
-  pagination.pageSize = size;
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+  pagination.pageSize = limit;
   getTableData();
 };
 
-const add = () => {
-  isEdit.value = false;
-  dialogTitle.value = "鏂板鍑哄簱";
-  Object.assign(form, {
-    outCode: "CK" + Date.now(),
-    customerId: "",
-    outDate: "",
-    amount: 0,
-    remark: "",
-  });
-  dialogVisible.value = true;
-};
-
-const edit = (row) => {
-  isEdit.value = true;
-  currentId.value = row.id;
-  dialogTitle.value = "缂栬緫鍑哄簱";
-  Object.assign(form, row);
-  dialogVisible.value = true;
-};
-
-const view = (row) => {
-  ElMessage.info(`鏌ョ湅鍑哄簱鍗�: ${row.outCode}`);
-};
-
-const submitForm = () => {
-  formRef.value.validate((valid) => {
-    if (valid) {
-      const customer = customerList.find(item => item.id === form.customerId);
-      if (isEdit.value) {
-        const index = mockData.findIndex(item => item.id === currentId.value);
-        if (index !== -1) {
-          mockData[index] = { ...mockData[index], ...form, customerName: customer?.name };
-        }
-        ElMessage.success("缂栬緫鎴愬姛");
-      } else {
-        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
-        mockData.push({ id: newId, ...form, customerName: customer?.name, status: "pending" });
-        ElMessage.success("鏂板鎴愬姛");
-      }
-      dialogVisible.value = false;
-      getTableData();
-    }
-  });
-};
-
-const handleDelete = (row) => {
-  ElMessageBox.confirm("纭鍒犻櫎璇ュ嚭搴撳崟鍚楋紵", "鎻愮ず", {
-    confirmButtonText: "纭畾",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData.splice(index, 1);
-    }
-    ElMessage.success("鍒犻櫎鎴愬姛");
-    getTableData();
-  });
-};
-
 const handleOut = () => {
-  ElMessage.success("瀵煎嚭鎴愬姛");
+  proxy.download(
+    "/accountSales/exportAccountSalesOutbound",
+    buildFilterParams(),
+    `閿�鍞嚭搴揰${new Date().getTime()}.xlsx`
+  );
 };
 
 onMounted(() => {
diff --git a/src/views/financialManagement/receivable/salesReturn.vue b/src/views/financialManagement/receivable/salesReturn.vue
index 4cf54d6..c58d330 100644
--- a/src/views/financialManagement/receivable/salesReturn.vue
+++ b/src/views/financialManagement/receivable/salesReturn.vue
@@ -1,19 +1,27 @@
 <template>
+  <!-- 閿�鍞��璐� -->
   <div class="app-container">
     <el-form :model="filters" :inline="true">
       <el-form-item label="閫�璐у崟鍙�:">
-        <el-input v-model="filters.returnCode" placeholder="璇疯緭鍏ラ��璐у崟鍙�" clearable style="width: 200px;" />
+        <el-input v-model="filters.returnNo" placeholder="璇疯緭鍏ラ��璐у崟鍙�" clearable style="width: 200px;" />
       </el-form-item>
-      <el-form-item label="瀹㈡埛:">
-        <el-select v-model="filters.customerId" placeholder="璇烽�夋嫨瀹㈡埛" clearable style="width: 200px;">
-          <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
-        </el-select>
+      <el-form-item label="瀹㈡埛鍚嶇О:">
+        <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="getTableData">鎼滅储</el-button>
+        <el-button type="primary" @click="onSearch">鎼滅储</el-button>
         <el-button @click="resetFilters">閲嶇疆</el-button>
       </el-form-item>
     </el-form>
@@ -28,90 +36,32 @@
         rowKey="id"
         :column="columns"
         :tableData="dataList"
+        :tableLoading="tableLoading"
         :page="{
           current: pagination.currentPage,
           size: pagination.pageSize,
           total: pagination.total,
         }"
         @pagination="changePage"
-      >
-        <template #status="{ row }">
-          <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
-        </template>
-        <template #operation="{ row }">
-          <el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
-          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">缂栬緫</el-button>
-          <el-button type="success" link @click="handleAudit(row)" v-if="row.status === 'pending'">瀹℃牳</el-button>
-        </template>
-      </PIMTable>
+      />
     </div>
-
-    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
-      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="閫�璐у崟鍙�" prop="returnCode">
-              <el-input v-model="form.returnCode" placeholder="璇疯緭鍏ラ��璐у崟鍙�" :disabled="isEdit" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="鍏宠仈鍑哄簱鍗�" prop="outCode">
-              <el-select v-model="form.outCode" placeholder="璇烽�夋嫨鍑哄簱鍗�" style="width: 100%;" :disabled="isEdit">
-                <el-option v-for="item in outList" :key="item.outCode" :label="item.outCode" :value="item.outCode" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="瀹㈡埛" prop="customerId">
-              <el-select v-model="form.customerId" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%;" :disabled="isEdit">
-                <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="閫�璐ф棩鏈�" prop="returnDate">
-              <el-date-picker v-model="form.returnDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="閫�璐ч噾棰�" prop="amount">
-              <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="閫�璐у師鍥�" prop="reason">
-              <el-input v-model="form.reason" placeholder="璇疯緭鍏ラ��璐у師鍥�" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-form-item label="澶囨敞" prop="remark">
-          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button type="primary" @click="submitForm">纭畾</el-button>
-        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
-      </template>
-    </FormDialog>
   </div>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ElMessage } from "element-plus";
+import { listPageAccountSalesReturn } from "@/api/financialManagement/accountSales";
 
 defineOptions({
   name: "閿�鍞��璐�",
 });
 
+const { proxy } = getCurrentInstance();
+
 const filters = reactive({
-  returnCode: "",
-  customerId: "",
+  returnNo: "",
+  customerName: "",
   dateRange: [],
 });
 
@@ -122,173 +72,89 @@
 });
 
 const columns = [
-  { label: "閫�璐у崟鍙�", prop: "returnCode", width: "150" },
-  { label: "瀹㈡埛鍚嶇О", prop: "customerName", width: "180" },
-  { label: "鍏宠仈鍑哄簱鍗�", prop: "outCode", width: "150" },
-  { label: "閫�璐ф棩鏈�", prop: "returnDate", width: "120" },
-  { label: "閫�璐ч噾棰�", prop: "amount", width: "120" },
-  { label: "閫�璐у師鍥�", prop: "reason", width: "150", showOverflowTooltip: true },
-  { label: "鐘舵��", prop: "status", slot: "status" },
-  { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "200", fixed: "right" },
+  { label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: "150" },
+  { label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: "180" },
+  { label: "鍏宠仈鍙戣揣鍗曞彿", prop: "shippingNo", minWidth: "150" },
+  { label: "閫�璐ф棩鏈�", prop: "makeTime", minWidth: "170" },
+  {
+    label: "閫�娆炬�婚",
+    prop: "refundAmount",
+    minWidth: "120",
+    align: "right",
+    formatData: (val) =>
+      val === null || val === undefined || val === ""
+        ? ""
+        : Number(val).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
+  },
+  { label: "閫�璐у師鍥�", prop: "returnReason", minWidth: "150", showOverflowTooltip: true },
+  { label: "閿�鍞鍗曞彿", prop: "salesContractNo", minWidth: "150" },
 ];
 
 const dataList = ref([]);
-const dialogVisible = ref(false);
-const dialogTitle = ref("");
-const formRef = ref(null);
-const isEdit = ref(false);
-const currentId = ref(null);
+const tableLoading = ref(false);
 
-const customerList = [
-  { id: 1, name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
-  { id: 2, name: "涓婃捣璐告槗鍏徃" },
-  { id: 3, name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
-  { id: 4, name: "娣卞湷鐢靛瓙鍏徃" },
-];
+function buildFilterParams() {
+  const params = {
+    returnNo: filters.returnNo || 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 outList = [
-  { outCode: "CK2024001", customerId: 1 },
-  { outCode: "CK2024002", customerId: 2 },
-  { outCode: "CK2024003", customerId: 3 },
-];
-
-const form = reactive({
-  returnCode: "",
-  outCode: "",
-  customerId: "",
-  returnDate: "",
-  amount: 0,
-  reason: "",
-  remark: "",
-});
-
-const rules = {
-  returnCode: [{ required: true, message: "璇疯緭鍏ラ��璐у崟鍙�", trigger: "blur" }],
-  outCode: [{ required: true, message: "璇烽�夋嫨鍏宠仈鍑哄簱鍗�", trigger: "change" }],
-  customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
-  returnDate: [{ required: true, message: "璇烽�夋嫨閫�璐ф棩鏈�", trigger: "change" }],
-  amount: [{ required: true, message: "璇疯緭鍏ラ��璐ч噾棰�", trigger: "blur" }],
-};
-
-const mockData = [
-  { id: 1, returnCode: "TH2024001", outCode: "CK2024001", customerId: 1, customerName: "鍖椾含绉戞妧鏈夐檺鍏徃", returnDate: "2024-01-20", amount: 1000, reason: "璐ㄩ噺闂", status: "approved", remark: "" },
-  { id: 2, returnCode: "TH2024002", outCode: "CK2024002", customerId: 2, customerName: "涓婃捣璐告槗鍏徃", returnDate: "2024-01-22", amount: 500, reason: "瑙勬牸涓嶇", status: "pending", remark: "" },
-];
-
-const getStatusLabel = (status) => {
-  const map = { pending: "寰呭鏍�", approved: "宸插鏍�", rejected: "宸查┏鍥�" };
-  return map[status] || status;
-};
-
-const getStatusType = (status) => {
-  const map = { pending: "warning", approved: "success", rejected: "danger" };
-  return map[status] || "";
+const onSearch = () => {
+  pagination.currentPage = 1;
+  getTableData();
 };
 
 const getTableData = () => {
-  let result = [...mockData];
-  if (filters.returnCode) {
-    result = result.filter(item => item.returnCode.includes(filters.returnCode));
-  }
-  if (filters.customerId) {
-    result = result.filter(item => item.customerId === filters.customerId);
-  }
-  if (filters.dateRange && filters.dateRange.length === 2) {
-    result = result.filter(item => item.returnDate >= filters.dateRange[0] && item.returnDate <= filters.dateRange[1]);
-  }
-  pagination.total = result.length;
-  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+  tableLoading.value = true;
+  listPageAccountSalesReturn({
+    ...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.returnCode = "";
-  filters.customerId = "";
+  filters.returnNo = "";
+  filters.customerName = "";
   filters.dateRange = [];
   pagination.currentPage = 1;
   getTableData();
 };
 
-const changePage = ({ current, size }) => {
-  pagination.currentPage = current;
-  pagination.pageSize = size;
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+  pagination.pageSize = limit;
   getTableData();
 };
 
-const add = () => {
-  isEdit.value = false;
-  dialogTitle.value = "鏂板閫�璐�";
-  Object.assign(form, {
-    returnCode: "TH" + Date.now(),
-    outCode: "",
-    customerId: "",
-    returnDate: "",
-    amount: 0,
-    reason: "",
-    remark: "",
-  });
-  dialogVisible.value = true;
-};
-
-const edit = (row) => {
-  isEdit.value = true;
-  currentId.value = row.id;
-  dialogTitle.value = "缂栬緫閫�璐�";
-  Object.assign(form, row);
-  dialogVisible.value = true;
-};
-
-const view = (row) => {
-  ElMessage.info(`鏌ョ湅閫�璐у崟: ${row.returnCode}`);
-};
-
-const handleAudit = (row) => {
-  ElMessageBox.confirm("纭瀹℃牳閫氳繃璇ラ��璐у崟鍚楋紵", "鎻愮ず", {
-    confirmButtonText: "閫氳繃",
-    cancelButtonText: "椹冲洖",
-    distinguishCancelAndClose: true,
-    type: "warning",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData[index].status = "approved";
-    }
-    ElMessage.success("瀹℃牳閫氳繃");
-    getTableData();
-  }).catch((action) => {
-    if (action === "cancel") {
-      const index = mockData.findIndex(item => item.id === row.id);
-      if (index !== -1) {
-        mockData[index].status = "rejected";
-      }
-      ElMessage.warning("宸查┏鍥�");
-      getTableData();
-    }
-  });
-};
-
-const submitForm = () => {
-  formRef.value.validate((valid) => {
-    if (valid) {
-      const customer = customerList.find(item => item.id === form.customerId);
-      if (isEdit.value) {
-        const index = mockData.findIndex(item => item.id === currentId.value);
-        if (index !== -1) {
-          mockData[index] = { ...mockData[index], ...form, customerName: customer?.name };
-        }
-        ElMessage.success("缂栬緫鎴愬姛");
-      } else {
-        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
-        mockData.push({ id: newId, ...form, customerName: customer?.name, status: "pending" });
-        ElMessage.success("鏂板鎴愬姛");
-      }
-      dialogVisible.value = false;
-      getTableData();
-    }
-  });
-};
-
 const handleOut = () => {
-  ElMessage.success("瀵煎嚭鎴愬姛");
+  proxy.download(
+    "/accountSales/exportAccountSalesReturn",
+    buildFilterParams(),
+    `閿�鍞��璐${new Date().getTime()}.xlsx`
+  );
 };
 
 onMounted(() => {
diff --git a/src/views/financialManagement/voucher/detailLedger.vue b/src/views/financialManagement/voucher/detailLedger.vue
index 7f85790..1909d0e 100644
--- a/src/views/financialManagement/voucher/detailLedger.vue
+++ b/src/views/financialManagement/voucher/detailLedger.vue
@@ -1,165 +1,126 @@
 <template>
-  <div class="app-container">
-    <el-form :model="filters" :inline="true">
-      <el-form-item label="浼氳绉戠洰:">
-        <el-cascader v-model="filters.subject" :options="subjectOptions" :props="{ label: 'name', value: 'code' }" placeholder="璇烽�夋嫨浼氳绉戠洰" clearable style="width: 250px;" filterable />
-      </el-form-item>
-      <el-form-item label="杈呭姪鏍哥畻:">
-        <el-select v-model="filters.auxiliary" placeholder="璇烽�夋嫨杈呭姪鏍哥畻" clearable style="width: 180px;">
-          <el-option label="瀹㈡埛" value="customer" />
-          <el-option label="渚涘簲鍟�" value="supplier" />
-          <el-option label="閮ㄩ棬" value="department" />
-          <el-option label="鍛樺伐" value="employee" />
-          <el-option label="椤圭洰" value="project" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="鏍哥畻瀵硅薄:">
-        <el-select v-model="filters.auxiliaryItem" placeholder="璇烽�夋嫨鏍哥畻瀵硅薄" clearable style="width: 200px;" :disabled="!filters.auxiliary">
-          <el-option v-for="item in auxiliaryItems" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="鏈熼棿:">
-        <el-date-picker v-model="filters.startMonth" type="month" placeholder="寮�濮嬫湀浠�" value-format="YYYY-MM" style="width: 140px;" />
-        <span style="margin: 0 10px;">鑷�</span>
-        <el-date-picker v-model="filters.endMonth" type="month" placeholder="缁撴潫鏈堜唤" value-format="YYYY-MM" style="width: 140px;" />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" @click="getTableData">鏌ヨ</el-button>
-        <el-button @click="resetFilters">閲嶇疆</el-button>
-        <el-button @click="handlePrint" icon="Printer">鎵撳嵃</el-button>
-        <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
-      </el-form-item>
-    </el-form>
+  <div class="app-container ledger-page">
+    <div class="ledger-layout">
+      <aside class="subject-panel">
+        <el-input v-model="subjectKeyword" placeholder="璇疯緭鍏ョ鐩悕绉�/缂栧彿" clearable prefix-icon="Search" />
+        <el-scrollbar class="subject-tree-scroll">
+          <el-tree
+            ref="subjectTreeRef"
+            :data="subjectOptions"
+            node-key="code"
+            :props="{ label: 'name', children: 'children' }"
+            highlight-current
+            default-expand-all
+            :expand-on-click-node="false"
+            :filter-node-method="filterSubjectNode"
+            @node-click="handleSubjectClick"
+          >
+            <template #default="{ data }">
+              <span class="subject-node">{{ data.code }} {{ data.name }}</span>
+            </template>
+          </el-tree>
+        </el-scrollbar>
+      </aside>
 
-    <div class="ledger-header" v-if="currentSubject">
-      <h2>绉戠洰鏄庣粏璐�</h2>
-      <p>绉戠洰: {{ currentSubject.code }} {{ currentSubject.name }}</p>
-      <p v-if="filters.auxiliary && filters.auxiliaryItem">杈呭姪鏍哥畻: {{ getAuxiliaryLabel() }}</p>
-      <p>鏈熼棿: {{ filters.startMonth }} 鑷� {{ filters.endMonth }}</p>
+      <section class="ledger-content">
+        <el-form :model="filters" :inline="true" class="filter-form">
+          <el-form-item label="鏈熼棿:">
+            <el-date-picker v-model="filters.startMonth" type="month" placeholder="寮�濮嬫湀浠�" value-format="YYYY-MM" style="width: 140px;" />
+            <span style="margin: 0 10px;">鑷�</span>
+            <el-date-picker v-model="filters.endMonth" type="month" placeholder="缁撴潫鏈堜唤" value-format="YYYY-MM" style="width: 140px;" />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="getTableData">鏌ヨ</el-button>
+            <el-button @click="resetFilters">閲嶇疆</el-button>
+            <el-button @click="handlePrint" icon="Printer">鎵撳嵃</el-button>
+            <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+          </el-form-item>
+        </el-form>
+
+        <div class="table_list">
+          <el-table :data="dataList" border style="width: 100%">
+            <el-table-column prop="date" label="鏃ユ湡" width="120" />
+            <el-table-column prop="voucherNo" label="鍑瘉瀛楀彿" width="120" />
+            <el-table-column prop="summary" label="鎽樿" min-width="200" show-overflow-tooltip />
+            <el-table-column prop="debit" label="鍊熸柟" width="150">
+              <template #default="{ row }">
+                <span v-if="row.debit > 0" class="text-danger">楼{{ formatMoney(row.debit) }}</span>
+                <span v-else>-</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="credit" label="璐锋柟" width="150">
+              <template #default="{ row }">
+                <span v-if="row.credit > 0" class="text-success">楼{{ formatMoney(row.credit) }}</span>
+                <span v-else>-</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="鏂瑰悜" width="80">
+              <template #default="{ row }">
+                <el-tag :type="row.direction === '鍊�' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="浣欓" width="150">
+              <template #default="{ row }">
+                <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">楼{{ formatMoney(Math.abs(row.balance)) }}</span>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+
+        <el-empty v-if="!currentSubject" description="璇烽�夋嫨浼氳绉戠洰鏌ヨ" style="margin-top: 50px;" />
+      </section>
     </div>
-
-    <div class="table_list">
-      <el-table :data="dataList" border style="width: 100%" show-summary :summary-method="getSummaries">
-        <el-table-column prop="date" label="鏃ユ湡" width="120" />
-        <el-table-column prop="voucherNo" label="鍑瘉瀛楀彿" width="120" />
-        <el-table-column prop="summary" label="鎽樿" min-width="200" show-overflow-tooltip />
-        <el-table-column label="鍊熸柟" width="150">
-          <template #default="{ row }">
-            <span v-if="row.debit > 0" class="text-danger">楼{{ formatMoney(row.debit) }}</span>
-            <span v-else>-</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="璐锋柟" width="150">
-          <template #default="{ row }">
-            <span v-if="row.credit > 0" class="text-success">楼{{ formatMoney(row.credit) }}</span>
-            <span v-else>-</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="鏂瑰悜" width="80">
-          <template #default="{ row }">
-            <el-tag :type="row.direction === '鍊�' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="浣欓" width="150">
-          <template #default="{ row }">
-            <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">楼{{ formatMoney(Math.abs(row.balance)) }}</span>
-          </template>
-        </el-table-column>
-      </el-table>
-    </div>
-
-    <el-empty v-if="!currentSubject" description="璇烽�夋嫨浼氳绉戠洰鏌ヨ" style="margin-top: 50px;" />
   </div>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, computed, watch } from "vue";
+import { ref, reactive, onMounted, computed, watch, nextTick } from "vue";
 import { ElMessage } from "element-plus";
+import { listAccountSubject } from "@/api/financialManagement/accountSubject";
+import { getDetailLedger } from "@/api/financialManagement/ledger";
 
 defineOptions({
   name: "绉戠洰鏄庣粏璐�",
 });
 
 const filters = reactive({
-  subject: [],
-  auxiliary: "",
-  auxiliaryItem: "",
-  startMonth: "2024-01",
-  endMonth: "2024-03",
+  subject: "",
+  startMonth: "",
+  endMonth: "",
 });
 
 const dataList = ref([]);
+const subjectOptions = ref([]);
+const subjectKeyword = ref("");
+const subjectTreeRef = ref();
 
-const subjectOptions = [
-  {
-    code: "1122",
-    name: "搴旀敹璐︽",
-    children: [
-      { code: "112201", name: "鍖椾含绉戞妧鏈夐檺鍏徃" },
-      { code: "112202", name: "涓婃捣璐告槗鍏徃" },
-      { code: "112203", name: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
-    ],
-  },
-  {
-    code: "2202",
-    name: "搴斾粯璐︽",
-    children: [
-      { code: "220201", name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
-      { code: "220202", name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
-      { code: "220203", name: "骞垮窞鍖呰鏉愭枡鍘�" },
-    ],
-  },
-  {
-    code: "6602",
-    name: "绠$悊璐圭敤",
-    children: [
-      { code: "660201", name: "鍔炲叕璐�" },
-      { code: "660202", name: "宸梾璐�" },
-      { code: "660203", name: "涓氬姟鎷涘緟璐�" },
-    ],
-  },
+const getPreviousMonth = () => {
+  const date = new Date();
+  date.setDate(1);
+  date.setMonth(date.getMonth() - 1);
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  return `${year}-${month}`;
+};
+
+const defaultMonth = getPreviousMonth();
+filters.startMonth = defaultMonth;
+filters.endMonth = defaultMonth;
+
+const fallbackSubjects = [
+  { code: "1122", name: "搴旀敹璐︽" },
+  { code: "2202", name: "搴斾粯璐︽" },
+  { code: "6602", name: "绠$悊璐圭敤" },
 ];
 
-const auxiliaryItems = computed(() => {
-  const map = {
-    customer: [
-      { value: "1", label: "鍖椾含绉戞妧鏈夐檺鍏徃" },
-      { value: "2", label: "涓婃捣璐告槗鍏徃" },
-      { value: "3", label: "骞垮窞瀹炰笟鏈夐檺鍏徃" },
-    ],
-    supplier: [
-      { value: "1", label: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
-      { value: "2", label: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
-      { value: "3", label: "骞垮窞鍖呰鏉愭枡鍘�" },
-    ],
-    department: [
-      { value: "1", label: "璐㈠姟閮�" },
-      { value: "2", label: "閿�鍞儴" },
-      { value: "3", label: "閲囪喘閮�" },
-    ],
-    employee: [
-      { value: "1", label: "寮犱笁" },
-      { value: "2", label: "鏉庡洓" },
-      { value: "3", label: "鐜嬩簲" },
-    ],
-    project: [
-      { value: "1", label: "椤圭洰A" },
-      { value: "2", label: "椤圭洰B" },
-      { value: "3", label: "椤圭洰C" },
-    ],
-  };
-  return map[filters.auxiliary] || [];
-});
-
-watch(() => filters.auxiliary, () => {
-  filters.auxiliaryItem = "";
-});
-
-const currentSubject = computed(() => {
-  if (!filters.subject || filters.subject.length === 0) return null;
-  const code = filters.subject[filters.subject.length - 1];
-  return findSubject(subjectOptions, code);
-});
+const toTree = (nodes = []) =>
+  nodes
+    .filter(item => item.subjectCode && item.subjectName)
+    .map(item => ({
+      code: item.subjectCode,
+      name: item.subjectName,
+      children: toTree(item.children || []),
+    }));
 
 const findSubject = (options, code) => {
   for (const item of options) {
@@ -172,9 +133,68 @@
   return null;
 };
 
-const getAuxiliaryLabel = () => {
-  const item = auxiliaryItems.value.find(i => i.value === filters.auxiliaryItem);
-  return item ? item.label : "";
+const currentSubject = computed(() => {
+  if (!filters.subject) return null;
+  return findSubject(subjectOptions.value, filters.subject);
+});
+
+const getFirstSubjectCode = (nodes = []) => {
+  for (const item of nodes) {
+    if (item.code) return item.code;
+    if (item.children && item.children.length > 0) {
+      const childCode = getFirstSubjectCode(item.children);
+      if (childCode) return childCode;
+    }
+  }
+  return "";
+};
+
+const setDefaultSubjectSelection = async () => {
+  const firstCode = getFirstSubjectCode(subjectOptions.value);
+  if (!firstCode) {
+    filters.subject = "";
+    subjectTreeRef.value?.setCurrentKey(null);
+    return;
+  }
+  filters.subject = firstCode;
+  await nextTick();
+  subjectTreeRef.value?.setCurrentKey(firstCode);
+};
+
+const filterSubjectNode = (value, data) => {
+  const keyword = value?.trim();
+  if (!keyword) return true;
+  return `${data.code}${data.name}`.includes(keyword);
+};
+
+watch(subjectKeyword, (value) => {
+  subjectTreeRef.value?.filter(value || "");
+});
+
+const handleSubjectClick = async (data) => {
+  filters.subject = data.code;
+  await getTableData();
+};
+
+const loadSubjectOptions = async () => {
+  let options = [];
+  try {
+    const { data } = await listAccountSubject({
+      current: 1,
+      size: 1000,
+    });
+    options = toTree(data?.records || []);
+  } catch (error) {
+    // 鍏ㄥ眬鎷︽埅鍣ㄥ凡鎻愮ず锛屼笅闈㈣蛋鍏滃簳绉戠洰
+  }
+  if (options.length === 0) {
+    options = fallbackSubjects.map(item => ({ ...item, children: [] }));
+  }
+  subjectOptions.value = options;
+  await setDefaultSubjectSelection();
+  if (filters.subject) {
+    await getTableData();
+  }
 };
 
 const formatMoney = (value) => {
@@ -182,63 +202,34 @@
   return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 };
 
-const mockData = [
-  { date: "2024-01-01", voucherNo: "-", summary: "鏈熷垵浣欓", debit: 0, credit: 0, direction: "鍊�", balance: 10000 },
-  { date: "2024-01-05", voucherNo: "璁�-0001", summary: "閿�鍞嚭搴�", debit: 5000, credit: 0, direction: "鍊�", balance: 15000 },
-  { date: "2024-01-10", voucherNo: "璁�-0002", summary: "鏀跺埌璐ф", debit: 0, credit: 3000, direction: "鍊�", balance: 12000 },
-  { date: "2024-01-15", voucherNo: "璁�-0003", summary: "閿�鍞嚭搴�", debit: 8000, credit: 0, direction: "鍊�", balance: 20000 },
-  { date: "2024-01-20", voucherNo: "璁�-0004", summary: "閿�鍞��璐�", debit: 0, credit: 2000, direction: "鍊�", balance: 18000 },
-  { date: "2024-01-25", voucherNo: "璁�-0005", summary: "鏀跺埌璐ф", debit: 0, credit: 5000, direction: "鍊�", balance: 13000 },
-  { date: "2024-01-31", voucherNo: "-", summary: "鏈湀鍚堣", debit: 13000, credit: 10000, direction: "鍊�", balance: 13000 },
-  { date: "2024-02-01", voucherNo: "-", summary: "鏈熷垵浣欓", debit: 0, credit: 0, direction: "鍊�", balance: 13000 },
-  { date: "2024-02-10", voucherNo: "璁�-0006", summary: "閿�鍞嚭搴�", debit: 6000, credit: 0, direction: "鍊�", balance: 19000 },
-  { date: "2024-02-15", voucherNo: "璁�-0007", summary: "鏀跺埌璐ф", debit: 0, credit: 4000, direction: "鍊�", balance: 15000 },
-  { date: "2024-02-28", voucherNo: "-", summary: "鏈湀鍚堣", debit: 6000, credit: 4000, direction: "鍊�", balance: 15000 },
-  { date: "2024-03-01", voucherNo: "-", summary: "鏈熷垵浣欓", debit: 0, credit: 0, direction: "鍊�", balance: 15000 },
-  { date: "2024-03-05", voucherNo: "璁�-0008", summary: "閿�鍞嚭搴�", debit: 7000, credit: 0, direction: "鍊�", balance: 22000 },
-  { date: "2024-03-10", voucherNo: "璁�-0009", summary: "鏀跺埌璐ф", debit: 0, credit: 6000, direction: "鍊�", balance: 16000 },
-  { date: "2024-03-31", voucherNo: "-", summary: "鏈湀鍚堣", debit: 7000, credit: 6000, direction: "鍊�", balance: 16000 },
-  { date: "2024-03-31", voucherNo: "-", summary: "鏈勾绱", debit: 26000, credit: 20000, direction: "鍊�", balance: 16000 },
-];
-
-const getTableData = () => {
+// 鑱旇皟绾﹀畾锛氭槑缁嗚处鎸夌鐩笌鏈熼棿杩囨护
+const getTableData = async () => {
   if (!currentSubject.value) {
     dataList.value = [];
     return;
   }
-  dataList.value = [...mockData];
+  try {
+    const { data } = await getDetailLedger({
+      subjectCode: currentSubject.value.code,
+      startMonth: filters.startMonth,
+      endMonth: filters.endMonth,
+    });
+    dataList.value = Array.isArray(data) ? data : data?.records || [];
+  } catch (error) {
+    // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
+  }
 };
 
-const resetFilters = () => {
-  filters.subject = [];
-  filters.auxiliary = "";
-  filters.auxiliaryItem = "";
-  filters.startMonth = "2024-01";
-  filters.endMonth = "2024-03";
+const resetFilters = async () => {
+  filters.startMonth = defaultMonth;
+  filters.endMonth = defaultMonth;
   dataList.value = [];
-};
-
-const getSummaries = (param) => {
-  const { columns, data } = param;
-  const sums = [];
-  columns.forEach((column, index) => {
-    if (index === 0) {
-      sums[index] = "鍚堣";
-      return;
-    }
-    if (column.property === "debit") {
-      const values = data.map(item => Number(item.debit));
-      const sum = values.reduce((prev, curr) => prev + curr, 0);
-      sums[index] = "楼" + formatMoney(sum);
-    } else if (column.property === "credit") {
-      const values = data.map(item => Number(item.credit));
-      const sum = values.reduce((prev, curr) => prev + curr, 0);
-      sums[index] = "楼" + formatMoney(sum);
-    } else {
-      sums[index] = "";
-    }
-  });
-  return sums;
+  subjectKeyword.value = "";
+  subjectTreeRef.value?.filter("");
+  await setDefaultSubjectSelection();
+  if (filters.subject) {
+    await getTableData();
+  }
 };
 
 const handlePrint = () => {
@@ -249,22 +240,43 @@
   ElMessage.success("瀵煎嚭鎴愬姛");
 };
 
-onMounted(() => {
-  // 榛樿涓嶅姞杞芥暟鎹紝闇�瑕侀�夋嫨绉戠洰
+onMounted(async () => {
+  await loadSubjectOptions();
 });
 </script>
 
 <style lang="scss" scoped>
-.ledger-header {
-  text-align: center;
-  margin-bottom: 20px;
-  h2 {
-    margin: 0 0 10px 0;
-  }
-  p {
-    color: #606266;
-    margin: 5px 0;
-  }
+.ledger-layout {
+  display: flex;
+  gap: 16px;
+}
+
+.subject-panel {
+  width: 260px;
+  flex-shrink: 0;
+  padding: 12px;
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  background-color: #fff;
+}
+
+.subject-tree-scroll {
+  height: 600px;
+  margin-top: 12px;
+}
+
+.subject-node {
+  display: inline-flex;
+  align-items: center;
+}
+
+.ledger-content {
+  flex: 1;
+  min-width: 0;
+}
+
+.filter-form {
+  margin-bottom: 12px;
 }
 
 .text-primary {
@@ -286,4 +298,12 @@
   color: #e6a23c;
   font-weight: bold;
 }
+
+.subject-panel :deep(.el-tree-node__content) {
+  height: 34px;
+}
+
+.subject-panel :deep(.el-tree-node.is-current > .el-tree-node__content) {
+  background-color: #f0f7ff;
+}
 </style>
diff --git a/src/views/financialManagement/voucher/generalLedger.vue b/src/views/financialManagement/voucher/generalLedger.vue
index 5da2d70..9683487 100644
--- a/src/views/financialManagement/voucher/generalLedger.vue
+++ b/src/views/financialManagement/voucher/generalLedger.vue
@@ -1,114 +1,128 @@
 <template>
-  <div class="app-container">
-    <el-form :model="filters" :inline="true">
-      <el-form-item label="浼氳绉戠洰:">
-        <el-cascader v-model="filters.subject" :options="subjectOptions" :props="{ label: 'name', value: 'code' }" placeholder="璇烽�夋嫨浼氳绉戠洰" clearable style="width: 250px;" filterable />
-      </el-form-item>
-      <el-form-item label="鏈熼棿:">
-        <el-date-picker v-model="filters.startMonth" type="month" placeholder="寮�濮嬫湀浠�" value-format="YYYY-MM" style="width: 140px;" />
-        <span style="margin: 0 10px;">鑷�</span>
-        <el-date-picker v-model="filters.endMonth" type="month" placeholder="缁撴潫鏈堜唤" value-format="YYYY-MM" style="width: 140px;" />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" @click="getTableData">鏌ヨ</el-button>
-        <el-button @click="resetFilters">閲嶇疆</el-button>
-        <el-button @click="handlePrint" icon="Printer">鎵撳嵃</el-button>
-        <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
-      </el-form-item>
-    </el-form>
+  <div class="app-container ledger-page">
+    <div class="ledger-layout">
+      <aside class="subject-panel">
+        <el-input v-model="subjectKeyword" placeholder="璇疯緭鍏ョ鐩悕绉�/缂栧彿" clearable prefix-icon="Search" />
+        <el-scrollbar class="subject-tree-scroll">
+          <el-tree
+            ref="subjectTreeRef"
+            :data="subjectOptions"
+            node-key="code"
+            :props="{ label: 'name', children: 'children' }"
+            highlight-current
+            default-expand-all
+            :expand-on-click-node="false"
+            :filter-node-method="filterSubjectNode"
+            @node-click="handleSubjectClick"
+          >
+            <template #default="{ data }">
+              <span class="subject-node">{{ data.code }} {{ data.name }}</span>
+            </template>
+          </el-tree>
+        </el-scrollbar>
+      </aside>
 
-    <div class="ledger-header" v-if="currentSubject">
-      <h2>绉戠洰鎬昏处</h2>
-      <p>绉戠洰: {{ currentSubject.code }} {{ currentSubject.name }}</p>
-      <p>鏈熼棿: {{ filters.startMonth }} 鑷� {{ filters.endMonth }}</p>
+      <section class="ledger-content">
+        <el-form :model="filters" :inline="true" class="filter-form">
+          <el-form-item label="鏈熼棿:">
+            <el-date-picker v-model="filters.startMonth" type="month" placeholder="寮�濮嬫湀浠�" value-format="YYYY-MM" style="width: 140px;" />
+            <span style="margin: 0 10px;">鑷�</span>
+            <el-date-picker v-model="filters.endMonth" type="month" placeholder="缁撴潫鏈堜唤" value-format="YYYY-MM" style="width: 140px;" />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="getTableData">鏌ヨ</el-button>
+            <el-button @click="resetFilters">閲嶇疆</el-button>
+            <el-button @click="handlePrint" icon="Printer">鎵撳嵃</el-button>
+            <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+          </el-form-item>
+        </el-form>
+
+        <div class="table_list">
+          <el-table :data="dataList" border style="width: 100%">
+            <el-table-column prop="date" label="鏃ユ湡" width="120" />
+            <el-table-column prop="voucherNo" label="鍑瘉瀛楀彿" width="120" />
+            <el-table-column prop="summary" label="鎽樿" min-width="200" show-overflow-tooltip />
+            <el-table-column prop="debit" label="鍊熸柟" width="150">
+              <template #default="{ row }">
+                <span v-if="row.debit > 0" class="text-danger">楼{{ formatMoney(row.debit) }}</span>
+                <span v-else>-</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="credit" label="璐锋柟" width="150">
+              <template #default="{ row }">
+                <span v-if="row.credit > 0" class="text-success">楼{{ formatMoney(row.credit) }}</span>
+                <span v-else>-</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="鏂瑰悜" width="80">
+              <template #default="{ row }">
+                <el-tag :type="row.direction === '鍊�' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="浣欓" width="150">
+              <template #default="{ row }">
+                <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">楼{{ formatMoney(Math.abs(row.balance)) }}</span>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+
+        <el-empty v-if="!currentSubject" description="璇烽�夋嫨浼氳绉戠洰鏌ヨ" style="margin-top: 50px;" />
+      </section>
     </div>
-
-    <div class="table_list">
-      <el-table :data="dataList" border style="width: 100%" show-summary :summary-method="getSummaries">
-        <el-table-column prop="date" label="鏃ユ湡" width="120" />
-        <el-table-column prop="voucherNo" label="鍑瘉瀛楀彿" width="120" />
-        <el-table-column prop="summary" label="鎽樿" min-width="200" show-overflow-tooltip />
-        <el-table-column label="鍊熸柟" width="150">
-          <template #default="{ row }">
-            <span v-if="row.debit > 0" class="text-danger">楼{{ formatMoney(row.debit) }}</span>
-            <span v-else>-</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="璐锋柟" width="150">
-          <template #default="{ row }">
-            <span v-if="row.credit > 0" class="text-success">楼{{ formatMoney(row.credit) }}</span>
-            <span v-else>-</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="鏂瑰悜" width="80">
-          <template #default="{ row }">
-            <el-tag :type="row.direction === '鍊�' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="浣欓" width="150">
-          <template #default="{ row }">
-            <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">楼{{ formatMoney(Math.abs(row.balance)) }}</span>
-          </template>
-        </el-table-column>
-      </el-table>
-    </div>
-
-    <el-empty v-if="!currentSubject" description="璇烽�夋嫨浼氳绉戠洰鏌ヨ" style="margin-top: 50px;" />
   </div>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, computed } from "vue";
+import { ref, reactive, onMounted, computed, watch, nextTick } from "vue";
 import { ElMessage } from "element-plus";
+import { listAccountSubject } from "@/api/financialManagement/accountSubject";
+import { getGeneralLedger } from "@/api/financialManagement/ledger";
 
 defineOptions({
   name: "绉戠洰鎬昏处",
 });
 
 const filters = reactive({
-  subject: [],
-  startMonth: "2024-01",
-  endMonth: "2024-03",
+  subject: "",
+  startMonth: "",
+  endMonth: "",
 });
 
 const dataList = ref([]);
+const subjectOptions = ref([]);
+const subjectKeyword = ref("");
+const subjectTreeRef = ref();
 
-const subjectOptions = [
-  {
-    code: "1001",
-    name: "搴撳瓨鐜伴噾",
-    children: [],
-  },
-  {
-    code: "1002",
-    name: "閾惰瀛樻",
-    children: [
-      { code: "100201", name: "宸ュ晢閾惰" },
-      { code: "100202", name: "寤鸿閾惰" },
-    ],
-  },
-  {
-    code: "1122",
-    name: "搴旀敹璐︽",
-    children: [],
-  },
-  {
-    code: "2202",
-    name: "搴斾粯璐︽",
-    children: [],
-  },
-  {
-    code: "6001",
-    name: "涓昏惀涓氬姟鏀跺叆",
-    children: [],
-  },
+const getPreviousMonth = () => {
+  const date = new Date();
+  date.setDate(1);
+  date.setMonth(date.getMonth() - 1);
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  return `${year}-${month}`;
+};
+
+const defaultMonth = getPreviousMonth();
+filters.startMonth = defaultMonth;
+filters.endMonth = defaultMonth;
+
+const fallbackSubjects = [
+  { code: "1001", name: "搴撳瓨鐜伴噾" },
+  { code: "1002", name: "閾惰瀛樻" },
+  { code: "1122", name: "搴旀敹璐︽" },
+  { code: "2202", name: "搴斾粯璐︽" },
+  { code: "6001", name: "涓昏惀涓氬姟鏀跺叆" },
 ];
 
-const currentSubject = computed(() => {
-  if (!filters.subject || filters.subject.length === 0) return null;
-  const code = filters.subject[filters.subject.length - 1];
-  return findSubject(subjectOptions, code);
-});
+const toTree = (nodes = []) =>
+  nodes
+    .filter(item => item.subjectCode && item.subjectName)
+    .map(item => ({
+      code: item.subjectCode,
+      name: item.subjectName,
+      children: toTree(item.children || []),
+    }));
 
 const findSubject = (options, code) => {
   for (const item of options) {
@@ -121,65 +135,104 @@
   return null;
 };
 
+const currentSubject = computed(() => {
+  if (!filters.subject) return null;
+  return findSubject(subjectOptions.value, filters.subject);
+});
+
+const getFirstSubjectCode = (nodes = []) => {
+  for (const item of nodes) {
+    if (item.code) return item.code;
+    if (item.children && item.children.length > 0) {
+      const childCode = getFirstSubjectCode(item.children);
+      if (childCode) return childCode;
+    }
+  }
+  return "";
+};
+
+const setDefaultSubjectSelection = async () => {
+  const firstCode = getFirstSubjectCode(subjectOptions.value);
+  if (!firstCode) {
+    filters.subject = "";
+    subjectTreeRef.value?.setCurrentKey(null);
+    return;
+  }
+  filters.subject = firstCode;
+  await nextTick();
+  subjectTreeRef.value?.setCurrentKey(firstCode);
+};
+
+const filterSubjectNode = (value, data) => {
+  const keyword = value?.trim();
+  if (!keyword) return true;
+  return `${data.code}${data.name}`.includes(keyword);
+};
+
+watch(subjectKeyword, (value) => {
+  subjectTreeRef.value?.filter(value || "");
+});
+
+const handleSubjectClick = async (data) => {
+  filters.subject = data.code;
+  await getTableData();
+};
+
+const loadSubjectOptions = async () => {
+  let options = [];
+  try {
+    const { data } = await listAccountSubject({
+      current: 1,
+      size: 1000,
+      status: 0,
+    });
+    options = toTree(data?.records || []);
+  } catch (error) {
+    // 鍏ㄥ眬鎷︽埅鍣ㄥ凡鎻愮ず锛屼笅闈㈣蛋鍏滃簳绉戠洰
+  }
+  if (options.length === 0) {
+    options = fallbackSubjects.map(item => ({ ...item, children: [] }));
+  }
+  subjectOptions.value = options;
+  await setDefaultSubjectSelection();
+  if (filters.subject) {
+    await getTableData();
+  }
+};
+
 const formatMoney = (value) => {
   if (value === undefined || value === null) return "0.00";
   return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 };
 
-const mockData = [
-  { date: "2024-01-01", voucherNo: "-", summary: "鏈熷垵浣欓", debit: 0, credit: 0, direction: "鍊�", balance: 100000 },
-  { date: "2024-01-05", voucherNo: "璁�-0001", summary: "閿�鍞敹鍏�", debit: 5650, credit: 0, direction: "鍊�", balance: 105650 },
-  { date: "2024-01-10", voucherNo: "璁�-0002", summary: "閲囪喘鏀嚭", debit: 0, credit: 8000, direction: "鍊�", balance: 97650 },
-  { date: "2024-01-15", voucherNo: "璁�-0003", summary: "鏀跺埌璐ф", debit: 10000, credit: 0, direction: "鍊�", balance: 107650 },
-  { date: "2024-01-20", voucherNo: "璁�-0004", summary: "鏀粯璐圭敤", debit: 0, credit: 5000, direction: "鍊�", balance: 102650 },
-  { date: "2024-01-31", voucherNo: "-", summary: "鏈湀鍚堣", debit: 15650, credit: 13000, direction: "鍊�", balance: 102650 },
-  { date: "2024-02-01", voucherNo: "-", summary: "鏈熷垵浣欓", debit: 0, credit: 0, direction: "鍊�", balance: 102650 },
-  { date: "2024-02-10", voucherNo: "璁�-0005", summary: "閿�鍞敹鍏�", debit: 8000, credit: 0, direction: "鍊�", balance: 110650 },
-  { date: "2024-02-15", voucherNo: "璁�-0006", summary: "閲囪喘鏀嚭", debit: 0, credit: 12000, direction: "鍊�", balance: 98650 },
-  { date: "2024-02-28", voucherNo: "-", summary: "鏈湀鍚堣", debit: 8000, credit: 12000, direction: "鍊�", balance: 98650 },
-  { date: "2024-03-01", voucherNo: "-", summary: "鏈熷垵浣欓", debit: 0, credit: 0, direction: "鍊�", balance: 98650 },
-  { date: "2024-03-05", voucherNo: "璁�-0007", summary: "閿�鍞敹鍏�", debit: 12000, credit: 0, direction: "鍊�", balance: 110650 },
-  { date: "2024-03-10", voucherNo: "璁�-0008", summary: "鏀粯宸ヨ祫", debit: 0, credit: 15000, direction: "鍊�", balance: 95650 },
-  { date: "2024-03-31", voucherNo: "-", summary: "鏈湀鍚堣", debit: 12000, credit: 15000, direction: "鍊�", balance: 95650 },
-  { date: "2024-03-31", voucherNo: "-", summary: "鏈勾绱", debit: 35650, credit: 40000, direction: "鍊�", balance: 95650 },
-];
-
-const getTableData = () => {
+// 鑱旇皟绾﹀畾锛氭�昏处鎺ュ彛杩斿洖琛屾暟缁勶紙rowType/date/voucherNo/summary/debit/credit/direction/balance锛�
+const getTableData = async () => {
   if (!currentSubject.value) {
     dataList.value = [];
     return;
   }
-  dataList.value = [...mockData];
+  try {
+    const { data } = await getGeneralLedger({
+      subjectCode: currentSubject.value.code,
+      startMonth: filters.startMonth,
+      endMonth: filters.endMonth,
+    });
+    dataList.value = Array.isArray(data) ? data : data?.records || [];
+  } catch (error) {
+    // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
+  }
 };
 
-const resetFilters = () => {
-  filters.subject = [];
-  filters.startMonth = "2024-01";
-  filters.endMonth = "2024-03";
+const resetFilters = async () => {
+  filters.startMonth = defaultMonth;
+  filters.endMonth = defaultMonth;
   dataList.value = [];
-};
-
-const getSummaries = (param) => {
-  const { columns, data } = param;
-  const sums = [];
-  columns.forEach((column, index) => {
-    if (index === 0) {
-      sums[index] = "鍚堣";
-      return;
-    }
-    if (column.property === "debit") {
-      const values = data.map(item => Number(item.debit));
-      const sum = values.reduce((prev, curr) => prev + curr, 0);
-      sums[index] = "楼" + formatMoney(sum);
-    } else if (column.property === "credit") {
-      const values = data.map(item => Number(item.credit));
-      const sum = values.reduce((prev, curr) => prev + curr, 0);
-      sums[index] = "楼" + formatMoney(sum);
-    } else {
-      sums[index] = "";
-    }
-  });
-  return sums;
+  subjectKeyword.value = "";
+  subjectTreeRef.value?.filter("");
+  await setDefaultSubjectSelection();
+  if (filters.subject) {
+    await getTableData();
+  }
 };
 
 const handlePrint = () => {
@@ -190,22 +243,43 @@
   ElMessage.success("瀵煎嚭鎴愬姛");
 };
 
-onMounted(() => {
-  // 榛樿涓嶅姞杞芥暟鎹紝闇�瑕侀�夋嫨绉戠洰
+onMounted(async () => {
+  await loadSubjectOptions();
 });
 </script>
 
 <style lang="scss" scoped>
-.ledger-header {
-  text-align: center;
-  margin-bottom: 20px;
-  h2 {
-    margin: 0 0 10px 0;
-  }
-  p {
-    color: #606266;
-    margin: 5px 0;
-  }
+.ledger-layout {
+  display: flex;
+  gap: 16px;
+}
+
+.subject-panel {
+  width: 260px;
+  flex-shrink: 0;
+  padding: 12px;
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  background-color: #fff;
+}
+
+.subject-tree-scroll {
+  height: 600px;
+  margin-top: 12px;
+}
+
+.subject-node {
+  display: inline-flex;
+  align-items: center;
+}
+
+.ledger-content {
+  flex: 1;
+  min-width: 0;
+}
+
+.filter-form {
+  margin-bottom: 12px;
 }
 
 .text-primary {
@@ -227,4 +301,12 @@
   color: #e6a23c;
   font-weight: bold;
 }
+
+.subject-panel :deep(.el-tree-node__content) {
+  height: 34px;
+}
+
+.subject-panel :deep(.el-tree-node.is-current > .el-tree-node__content) {
+  background-color: #f0f7ff;
+}
 </style>
diff --git a/src/views/financialManagement/voucher/index.vue b/src/views/financialManagement/voucher/index.vue
index 817185c..03c0856 100644
--- a/src/views/financialManagement/voucher/index.vue
+++ b/src/views/financialManagement/voucher/index.vue
@@ -9,9 +9,12 @@
       </el-form-item>
       <el-form-item label="鍒跺崟浜�:">
         <el-select v-model="filters.creator" placeholder="璇烽�夋嫨鍒跺崟浜�" clearable style="width: 150px;">
-          <el-option label="寮犱笁" value="寮犱笁" />
-          <el-option label="鏉庡洓" value="鏉庡洓" />
-          <el-option label="鐜嬩簲" value="鐜嬩簲" />
+          <el-option
+            v-for="item in creatorOptions"
+            :key="item"
+            :label="item"
+            :value="item"
+          />
         </el-select>
       </el-form-item>
       <el-form-item label="鐘舵��:">
@@ -62,9 +65,9 @@
         </template>
         <template #operation="{ row }">
           <el-button type="primary" link @click="view(row)">鏌ョ湅</el-button>
-          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'unposted'">缂栬緫</el-button>
-          <el-button type="success" link @click="handlePost(row)" v-if="row.status === 'unposted'">杩囪处</el-button>
-          <el-button type="danger" link @click="handleCancel(row)" v-if="row.status === 'unposted'">浣滃簾</el-button>
+          <el-button type="primary" link @click="edit(row)" v-if="canEditVoucher(row.status)">缂栬緫</el-button>
+          <el-button type="success" link @click="handlePost(row)" v-if="canEditVoucher(row.status)">杩囪处</el-button>
+          <el-button type="danger" link @click="handleCancel(row)" v-if="canEditVoucher(row.status)">浣滃簾</el-button>
         </template>
       </PIMTable>
     </div>
@@ -75,25 +78,25 @@
           <h2 class="voucher-title">璁拌处鍑瘉</h2>
           <div class="voucher-period">{{ form.voucherDate ? form.voucherDate.substring(0, 7) + '鏈�' : '' }}</div>
         </div>
-        <el-form :model="form" :rules="rules" ref="formRef" label-width="0">
+        <el-form :model="form" :rules="rules" :disabled="isViewMode" ref="formRef" label-width="0">
           <div class="voucher-info">
             <div class="voucher-no-section">
               <span class="label">鍑瘉瀛楋細</span>
-              <el-select v-model="form.voucherPrefix" style="width: 70px;">
+              <el-select v-model="form.voucherPrefix" :disabled="isViewMode" style="width: 70px;">
                 <el-option label="璁�" value="璁�" />
               </el-select>
-              <el-input v-model="form.voucherNum" style="width: 60px;" />
+              <el-input v-model="form.voucherNum" :disabled="isViewMode" style="width: 60px;" />
               <span class="label" style="margin-left: 5px;">鍙�</span>
             </div>
             <div class="voucher-date-section">
               <span class="label">鏃ユ湡锛�</span>
-              <el-date-picker v-model="form.voucherDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 140px;" />
+              <el-date-picker v-model="form.voucherDate" :disabled="isViewMode" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 140px;" />
             </div>
             <div class="voucher-attachment-section">
               <span class="label">闄勪欢锛�</span>
-              <el-input-number v-model="form.attachmentCount" :min="0" :controls="false" style="width: 60px;" />
+              <el-input-number v-model="form.attachmentCount" :disabled="isViewMode" :min="0" :controls="false" style="width: 60px;" />
               <span class="label" style="margin-left: 5px;">寮�</span>
-              <el-button type="primary" link style="margin-left: 10px;">涓婁紶鏂囦欢</el-button>
+              <el-button type="primary" link :disabled="isViewMode" style="margin-left: 10px;">涓婁紶鏂囦欢</el-button>
             </div>
           </div>
           <div class="voucher-table">
@@ -134,18 +137,28 @@
               <tbody>
                 <tr v-for="(entry, rowIndex) in form.entries" :key="rowIndex" @click="selectRow(rowIndex)" :class="{ 'selected-row': selectedRowIndex === rowIndex }">
                   <td class="col-summary">
-                    <el-input v-model="entry.summary" placeholder="璇疯緭鍏ユ憳瑕�" @focus="selectRow(rowIndex)" />
+                    <el-input v-model="entry.summary" :disabled="isViewMode" placeholder="璇疯緭鍏ユ憳瑕�" @focus="selectRow(rowIndex)" />
                   </td>
                   <td class="col-subject">
-                    <el-select v-model="entry.subjectCode" placeholder="閫夋嫨绉戠洰" filterable @change="(val) => handleSubjectChange(val, rowIndex)" @focus="selectRow(rowIndex)">
-                      <el-option v-for="item in subjectList" :key="item.code" :label="item.code + item.name" :value="item.code" />
-                    </el-select>
+                    <el-tree-select
+                      v-model="entry.subjectCode"
+                      :data="subjectTreeOptions"
+                      :props="subjectTreeSelectProps"
+                      :disabled="isViewMode"
+                      placeholder="閫夋嫨绉戠洰"
+                      filterable
+                      check-strictly
+                      clearable
+                      :render-after-expand="false"
+                      @change="(val) => handleSubjectChange(val, rowIndex)"
+                      @focus="selectRow(rowIndex)"
+                    />
                     <div class="subject-name">{{ entry.subjectName }}</div>
                   </td>
                   <!-- 鍊熸柟11鍒� -->
                   <template v-if="editingCell.row === rowIndex && editingCell.type === 'debit'">
                     <td colspan="11" class="debit-input-cell">
-                      <el-input-number ref="amountInputRef" v-model="entry.debit" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" />
+                      <el-input-number ref="amountInputRef" v-model="entry.debit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" />
                     </td>
                   </template>
                   <template v-else>
@@ -156,7 +169,7 @@
                   <!-- 璐锋柟11鍒� -->
                   <template v-if="editingCell.row === rowIndex && editingCell.type === 'credit'">
                     <td colspan="11" class="credit-input-cell">
-                      <el-input-number ref="amountInputRef" v-model="entry.credit" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" />
+                      <el-input-number ref="amountInputRef" v-model="entry.credit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" />
                     </td>
                   </template>
                   <template v-else>
@@ -165,7 +178,7 @@
                     </td>
                   </template>
                   <td class="col-action">
-                    <el-button type="danger" link size="small" @click="removeEntry(rowIndex)" icon="Delete" :disabled="form.entries.length <= 2">鍒犻櫎</el-button>
+                    <el-button type="danger" link size="small" @click="removeEntry(rowIndex)" icon="Delete" :disabled="isViewMode || form.entries.length <= 2">鍒犻櫎</el-button>
                   </td>
                 </tr>
                 <tr class="total-row">
@@ -182,19 +195,34 @@
             </table>
           </div>
           <div class="voucher-toolbar">
-            <el-button type="primary" link @click="addEntry" icon="Plus">鏂板琛�</el-button>
+            <el-button type="primary" link @click="addEntry" icon="Plus" :disabled="isViewMode">鏂板琛�</el-button>
           </div>
           <div class="voucher-footer">
             <div class="creator-section">
-              <span class="label">鍒跺崟浜猴細{{ form.creator }}</span>
+              <span class="label">鍒跺崟浜猴細</span>
+              <el-select
+                v-model="form.creator"
+                :disabled="isViewMode"
+                placeholder="璇烽�夋嫨鍒跺崟浜�"
+                filterable
+                clearable
+                style="width: 200px;"
+              >
+                <el-option
+                  v-for="item in creatorOptions"
+                  :key="item"
+                  :label="item"
+                  :value="item"
+                />
+              </el-select>
             </div>
           </div>
         </el-form>
       </div>
       <template #footer>
         <div>
-          <el-button type="primary" @click="submitForm" :disabled="!isBalanced">淇濆瓨</el-button>
-          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+          <el-button v-if="!isViewMode" type="primary" @click="submitForm" :disabled="!isBalanced">淇濆瓨</el-button>
+          <el-button @click="dialogVisible = false">{{ isViewMode ? '鍏抽棴' : '鍙栨秷' }}</el-button>
         </div>
       </template>
     </FormDialog>
@@ -205,10 +233,24 @@
 import { ref, reactive, onMounted, computed, nextTick } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import FormDialog from "@/components/Dialog/FormDialog.vue";
+import useUserStore from "@/store/modules/user";
+import { userListNoPageByTenantId } from "@/api/system/user";
+import { listAccountSubject } from "@/api/financialManagement/accountSubject";
+import {
+  listVoucherPage,
+  addVoucher,
+  updateVoucher,
+  postVoucher,
+  cancelVoucher,
+  getVoucherDetail,
+} from "@/api/financialManagement/voucher";
 
 defineOptions({
   name: "鍑瘉绠$悊",
 });
+
+const userStore = useUserStore();
+const getDefaultCreator = () => userStore.nickName || userStore.name || "寮犱笁";
 
 const filters = reactive({
   voucherNo: "",
@@ -227,39 +269,92 @@
   { label: "鍑瘉瀛楀彿", prop: "voucherNo", width: "120" },
   { label: "鍑瘉鏃ユ湡", prop: "voucherDate", width: "120" },
   { label: "鎽樿", prop: "summary", showOverflowTooltip: true },
-  { label: "鍊熸柟閲戦", prop: "debit", slot: "debit" },
-  { label: "璐锋柟閲戦", prop: "credit", slot: "credit" },
+  { label: "鍊熸柟閲戦", prop: "debit", dataType: "slot", slot: "debit" },
+  { label: "璐锋柟閲戦", prop: "credit", dataType: "slot", slot: "credit" },
   { label: "鍒跺崟浜�", prop: "creator", width: "100" },
-  { label: "鐘舵��", prop: "status", slot: "status" },
-  { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "220", fixed: "right" },
+  { label: "鐘舵��", prop: "status", dataType: "slot", slot: "status" },
+  { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "220", fixed: "right" },
 ];
 
 const dataList = ref([]);
 const dialogVisible = ref(false);
 const dialogTitle = ref("");
 const formRef = ref(null);
+const dialogMode = ref("add");
 const isEdit = ref(false);
 const currentId = ref(null);
+const isViewMode = computed(() => dialogMode.value === "view");
 
-const subjectList = [
-  { code: "1001", name: "搴撳瓨鐜伴噾" },
-  { code: "1002", name: "閾惰瀛樻" },
-  { code: "1122", name: "搴旀敹璐︽" },
-  { code: "2202", name: "搴斾粯璐︽" },
-  { code: "5001", name: "鐢熶骇鎴愭湰" },
-  { code: "6001", name: "涓昏惀涓氬姟鏀跺叆" },
-  { code: "6401", name: "涓昏惀涓氬姟鎴愭湰" },
+const fallbackSubjectTree = [
+  { subjectCode: "1001", subjectName: "搴撳瓨鐜伴噾", balanceDirection: "鍊熸柟", children: [] },
+  { subjectCode: "1002", subjectName: "閾惰瀛樻", balanceDirection: "鍊熸柟", children: [] },
+  { subjectCode: "1122", subjectName: "搴旀敹璐︽", balanceDirection: "鍊熸柟", children: [] },
+  { subjectCode: "2202", subjectName: "搴斾粯璐︽", balanceDirection: "璐锋柟", children: [] },
+  { subjectCode: "5001", subjectName: "鐢熶骇鎴愭湰", balanceDirection: "鍊熸柟", children: [] },
+  { subjectCode: "6001", subjectName: "涓昏惀涓氬姟鏀跺叆", balanceDirection: "璐锋柟", children: [] },
+  { subjectCode: "6401", subjectName: "涓昏惀涓氬姟鎴愭湰", balanceDirection: "鍊熸柟", children: [] },
 ];
 
-const form = reactive({
+const subjectTreeOptions = ref([]);
+const subjectList = ref([]);
+const subjectTreeSelectProps = {
+  children: "children",
+  label: "label",
+  value: "value",
+};
+
+const buildSubjectTreeOptions = (nodes = [], flatList = []) =>
+  (nodes || [])
+    .filter(item => item.subjectCode && item.subjectName)
+    .map(item => {
+      const balanceDirection = item.balanceDirection || "";
+      const flatItem = {
+        code: item.subjectCode,
+        name: item.subjectName,
+        balanceDirection,
+      };
+      flatList.push(flatItem);
+      return {
+        value: flatItem.code,
+        label: `${flatItem.code} ${flatItem.name}${balanceDirection ? ` [${balanceDirection}]` : ""}`,
+        children: buildSubjectTreeOptions(item.children || [], flatList),
+      };
+    });
+
+const createEmptyEntry = () => ({
+  subjectCode: "",
+  subjectName: "",
+  balanceDirection: "",
+  summary: "",
+  debit: 0,
+  credit: 0,
+});
+
+const createDefaultForm = () => ({
   voucherNo: "",
   voucherPrefix: "璁�",
   voucherNum: "",
   voucherDate: "",
   attachmentCount: 0,
-  entries: [],
-  creator: "寮犱笁",
+  entries: [createEmptyEntry(), createEmptyEntry()],
+  creator: getDefaultCreator(),
   remark: "",
+});
+
+const form = reactive({
+  ...createDefaultForm(),
+});
+
+const userOptions = ref([]);
+
+const creatorOptions = computed(() => {
+  const source = [
+    ...userOptions.value.map(item => item.nickName || item.userName || item.name),
+    getDefaultCreator(),
+    form.creator,
+    filters.creator,
+  ];
+  return [...new Set(source.filter(Boolean))];
 });
 
 const selectedRowIndex = ref(-1);
@@ -276,12 +371,6 @@
 const rules = {
   voucherDate: [{ required: true, message: "璇烽�夋嫨鍑瘉鏃ユ湡", trigger: "change" }],
 };
-
-const mockData = [
-  { id: 1, voucherNo: "璁�-0001", voucherDate: "2024-01-15", summary: "閿�鍞敹鍏�", debit: 5650, credit: 5650, creator: "寮犱笁", status: "posted", entries: [{ subjectCode: "1002", subjectName: "閾惰瀛樻", summary: "閿�鍞敹鍏�", debit: 5650, credit: 0 }, { subjectCode: "6001", subjectName: "涓昏惀涓氬姟鏀跺叆", summary: "閿�鍞敹鍏�", debit: 0, credit: 5000 }, { subjectCode: "2221", subjectName: "搴斾氦绋庤垂", summary: "閿�椤圭◣棰�", debit: 0, credit: 650 }] },
-  { id: 2, voucherNo: "璁�-0002", voucherDate: "2024-01-16", summary: "閲囪喘鍘熸潗鏂�", debit: 9040, credit: 9040, creator: "鏉庡洓", status: "unposted", entries: [{ subjectCode: "5001", subjectName: "鐢熶骇鎴愭湰", summary: "閲囪喘鍘熸潗鏂�", debit: 8000, credit: 0 }, { subjectCode: "2221", subjectName: "搴斾氦绋庤垂", summary: "杩涢」绋庨", debit: 1040, credit: 0 }, { subjectCode: "2202", subjectName: "搴斾粯璐︽", summary: "閲囪喘鍘熸潗鏂�", debit: 0, credit: 9040 }] },
-  { id: 3, voucherNo: "璁�-0003", voucherDate: "2024-01-18", summary: "鏀粯璐ф", debit: 5000, credit: 5000, creator: "寮犱笁", status: "posted", entries: [{ subjectCode: "2202", subjectName: "搴斾粯璐︽", summary: "鏀粯璐ф", debit: 5000, credit: 0 }, { subjectCode: "1002", subjectName: "閾惰瀛樻", summary: "鏀粯璐ф", debit: 0, credit: 5000 }] },
-];
 
 const totalDebit = computed(() => {
   return dataList.value.reduce((sum, item) => sum + Number(item.debit), 0);
@@ -304,32 +393,79 @@
   return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 };
 
+const normalizeVoucherStatus = status => String(status || "").toLowerCase();
+
+const canEditVoucher = status => {
+  const key = normalizeVoucherStatus(status);
+  return key === "unposted" || status === "鏈繃璐�";
+};
+
 const getStatusLabel = (status) => {
+  const key = normalizeVoucherStatus(status);
   const map = { unposted: "鏈繃璐�", posted: "宸茶繃璐�", cancelled: "宸蹭綔搴�" };
-  return map[status] || status;
+  return map[key] || status;
 };
 
 const getStatusType = (status) => {
+  const key = normalizeVoucherStatus(status);
   const map = { unposted: "warning", posted: "success", cancelled: "info" };
-  return map[status] || "";
+  return map[key] || "";
 };
 
-const getTableData = () => {
-  let result = [...mockData];
-  if (filters.voucherNo) {
-    result = result.filter(item => item.voucherNo.includes(filters.voucherNo));
+// 鑱旇皟绾﹀畾锛氬垎椤靛弬鏁颁娇鐢� current/size锛屾棩鏈熻寖鍥存媶鍒嗕负 startDate/endDate
+const getTableData = async () => {
+  try {
+    const [startDate, endDate] =
+      filters.dateRange && filters.dateRange.length === 2 ? filters.dateRange : ["", ""];
+    const { data } = await listVoucherPage({
+      current: pagination.currentPage,
+      size: pagination.pageSize,
+      voucherNo: filters.voucherNo,
+      creator: filters.creator,
+      status: filters.status,
+      startDate,
+      endDate,
+    });
+    dataList.value = data?.records || [];
+    pagination.total = Number(data?.total || 0);
+  } catch (error) {
+    // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
   }
-  if (filters.dateRange && filters.dateRange.length === 2) {
-    result = result.filter(item => item.voucherDate >= filters.dateRange[0] && item.voucherDate <= filters.dateRange[1]);
+};
+
+// 鍑瘉鍒嗗綍閲岀殑绉戠洰涓嬫媺涓庢�昏处绉戠洰淇濇寔涓�鑷达紝閬垮厤鎻愪氦涓嶅瓨鍦ㄧ鐩�
+const loadSubjectList = async () => {
+  try {
+    const { data } = await listAccountSubject({
+      current: 1,
+      size: 1000,
+      status: 0
+    });
+    const flatList = [];
+    const treeOptions = buildSubjectTreeOptions(data?.records || [], flatList);
+    if (treeOptions.length > 0) {
+      subjectTreeOptions.value = treeOptions;
+      subjectList.value = flatList;
+      return;
+    }
+    const fallbackFlatList = [];
+    subjectTreeOptions.value = buildSubjectTreeOptions(fallbackSubjectTree, fallbackFlatList);
+    subjectList.value = fallbackFlatList;
+  } catch (error) {
+    // 鍏ㄥ眬鎷︽埅鍣ㄥ凡鎻愮ず閿欒锛岃繖閲屼繚鐣欓粯璁ょ鐩綔涓哄厹搴�
+    const fallbackFlatList = [];
+    subjectTreeOptions.value = buildSubjectTreeOptions(fallbackSubjectTree, fallbackFlatList);
+    subjectList.value = fallbackFlatList;
   }
-  if (filters.creator) {
-    result = result.filter(item => item.creator === filters.creator);
+};
+
+const loadUserOptions = async () => {
+  try {
+    const { data } = await userListNoPageByTenantId();
+    userOptions.value = Array.isArray(data) ? data : [];
+  } catch (error) {
+    userOptions.value = [];
   }
-  if (filters.status) {
-    result = result.filter(item => item.status === filters.status);
-  }
-  pagination.total = result.length;
-  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
 };
 
 const resetFilters = () => {
@@ -348,7 +484,10 @@
 };
 
 const addEntry = () => {
-  form.entries.push({ subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 });
+  if (isViewMode.value) {
+    return;
+  }
+  form.entries.push(createEmptyEntry());
 };
 
 const selectRow = (index) => {
@@ -356,6 +495,9 @@
 };
 
 const openAmountInput = (index, type) => {
+  if (isViewMode.value) {
+    return;
+  }
   editingCell.row = index;
   editingCell.type = type;
   nextTick(() => {
@@ -402,65 +544,83 @@
 };
 
 const removeEntry = (index) => {
+  if (isViewMode.value) {
+    return;
+  }
+  if (form.entries.length <= 2) {
+    return;
+  }
   form.entries.splice(index, 1);
-  calculateTotal();
 };
 
 const handleSubjectChange = (val, index) => {
-  const subject = subjectList.find(item => item.code === val);
+  const subject = subjectList.value.find(item => item.code === val);
   if (subject) {
     form.entries[index].subjectName = subject.name;
+    form.entries[index].balanceDirection = subject.balanceDirection || "";
+  } else {
+    form.entries[index].subjectName = "";
+    form.entries[index].balanceDirection = "";
   }
-};
-
-const calculateTotal = () => {
-  // 鑷姩璁$畻锛岀敱computed灞炴�у鐞�
 };
 
 const add = () => {
+  dialogMode.value = "add";
   isEdit.value = false;
+  currentId.value = null;
   dialogTitle.value = "鏂板鍑瘉";
-  const nextNum = String(mockData.length + 1).padStart(2, "0");
-  Object.assign(form, {
-    voucherNo: "璁�-" + nextNum,
+  const nextNum = String((pagination.total || 0) + 1).padStart(4, "0");
+  Object.assign(form, createDefaultForm(), {
     voucherPrefix: "璁�",
     voucherNum: nextNum,
+    voucherNo: `璁�-${nextNum}`,
     voucherDate: new Date().toISOString().split('T')[0],
-    attachmentCount: 0,
-    entries: [
-      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
-      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
-      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
-      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
-    ],
-    creator: "寮犱笁",
-    remark: "",
   });
   selectedRowIndex.value = 0;
   dialogVisible.value = true;
 };
 
-const edit = (row) => {
-  isEdit.value = true;
-  currentId.value = row.id;
-  dialogTitle.value = "缂栬緫鍑瘉";
-  const parts = row.voucherNo.split('-');
-  Object.assign(form, {
-    ...row,
-    voucherPrefix: parts[0] || '璁�',
-    voucherNum: parts[1] || '',
-  });
-  if (form.entries.length < 4) {
-    while (form.entries.length < 4) {
-      form.entries.push({ subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 });
+const openVoucherDialog = async (row, mode = "edit") => {
+  try {
+    dialogMode.value = mode;
+    isEdit.value = mode === "edit";
+    currentId.value = row.id;
+    dialogTitle.value = mode === "view" ? "鏌ョ湅鍑瘉" : "缂栬緫鍑瘉";
+    const { data } = await getVoucherDetail(row.id);
+    const detail = data || row;
+    const parts = (detail.voucherNo || "").split("-");
+    Object.assign(form, createDefaultForm(), detail, {
+      voucherPrefix: parts[0] || "璁�",
+      voucherNum: parts[1] || "",
+      creator: detail.creator || getDefaultCreator(),
+      entries:
+        detail.entries?.map(item => ({
+          subjectCode: item.subjectCode || "",
+          subjectName: item.subjectName || "",
+          balanceDirection: item.balanceDirection || "",
+          summary: item.summary || "",
+          debit: Number(item.debit || 0),
+          credit: Number(item.credit || 0),
+        })) || [],
+    });
+    if (form.entries.length < 2) {
+      while (form.entries.length < 2) {
+        form.entries.push(createEmptyEntry());
+      }
     }
+    selectedRowIndex.value = 0;
+    dialogVisible.value = true;
+  } catch (error) {
+    // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
   }
-  selectedRowIndex.value = 0;
-  dialogVisible.value = true;
 };
 
-const view = (row) => {
-  ElMessage.info(`鏌ョ湅鍑瘉: ${row.voucherNo}`);
+const edit = async row => {
+  await openVoucherDialog(row, "edit");
+};
+
+const view = async row => {
+  await openVoucherDialog(row, "view");
 };
 
 const handlePost = (row) => {
@@ -468,13 +628,10 @@
     confirmButtonText: "纭",
     cancelButtonText: "鍙栨秷",
     type: "info",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData[index].status = "posted";
-    }
+  }).then(async () => {
+    await postVoucher({ id: row.id });
     ElMessage.success("杩囪处鎴愬姛");
-    getTableData();
+    await getTableData();
   });
 };
 
@@ -483,13 +640,10 @@
     confirmButtonText: "纭",
     cancelButtonText: "鍙栨秷",
     type: "warning",
-  }).then(() => {
-    const index = mockData.findIndex(item => item.id === row.id);
-    if (index !== -1) {
-      mockData[index].status = "cancelled";
-    }
+  }).then(async () => {
+    await cancelVoucher({ id: row.id });
     ElMessage.success("浣滃簾鎴愬姛");
-    getTableData();
+    await getTableData();
   });
 };
 
@@ -502,45 +656,79 @@
 };
 
 const submitForm = () => {
-  formRef.value.validate((valid) => {
+  if (isViewMode.value) {
+    dialogVisible.value = false;
+    return;
+  }
+  formRef.value.validate(async valid => {
     if (valid) {
+      // 鍓嶇疆鏍¢獙锛氫笌鍚庣瑙勫垯瀵归綈锛屽噺灏戞棤鏁堣姹�
       if (!isBalanced.value) {
         ElMessage.error("鍊熻捶涓嶅钩琛★紝璇锋鏌ュ垎褰�");
         return;
       }
 
-      const validEntries = form.entries.filter(e => e.subjectCode && (e.debit > 0 || e.credit > 0));
+      const validEntries = form.entries.filter(
+        entry => entry.subjectCode && (Number(entry.debit) > 0 || Number(entry.credit) > 0)
+      );
+      if (validEntries.length === 0) {
+        ElMessage.error("璇疯嚦灏戝~鍐欎竴鏉℃湁鏁堝垎褰�");
+        return;
+      }
+
+      const invalidEntry = validEntries.find(
+        entry => Number(entry.debit) > 0 && Number(entry.credit) > 0
+      );
+      if (invalidEntry) {
+        ElMessage.error("鍚屼竴鍒嗗綍涓嶈兘鍚屾椂濉啓鍊熸柟鍜岃捶鏂�");
+        return;
+      }
+
       const summary = validEntries.find(e => e.debit > 0)?.summary || "";
 
       const voucherNo = `${form.voucherPrefix}-${form.voucherNum}`;
       const dataToSave = {
-        ...form,
         voucherNo,
+        voucherDate: form.voucherDate,
         summary,
+        creator: form.creator,
+        attachmentCount: Number(form.attachmentCount || 0),
+        remark: form.remark,
         debit: totalDebitEntry.value,
         credit: totalCreditEntry.value,
-        entries: validEntries,
+        entries: validEntries.map(entry => ({
+          subjectCode: entry.subjectCode,
+          subjectName: entry.subjectName,
+          summary: entry.summary,
+          debit: Number(entry.debit || 0),
+          credit: Number(entry.credit || 0),
+        })),
       };
 
-      if (isEdit.value) {
-        const index = mockData.findIndex(item => item.id === currentId.value);
-        if (index !== -1) {
-          mockData[index] = { ...mockData[index], ...dataToSave };
+      try {
+        if (isEdit.value) {
+          await updateVoucher({
+            id: currentId.value,
+            ...dataToSave,
+          });
+          ElMessage.success("缂栬緫鎴愬姛");
+        } else {
+          await addVoucher(dataToSave);
+          ElMessage.success("鏂板鎴愬姛");
         }
-        ElMessage.success("缂栬緫鎴愬姛");
-      } else {
-        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
-        mockData.push({ id: newId, ...dataToSave, status: "unposted" });
-        ElMessage.success("鏂板鎴愬姛");
+        dialogVisible.value = false;
+        await getTableData();
+      } catch (error) {
+        // 鎻愮ず鐢卞叏灞�璇锋眰鎷︽埅鍣ㄥ鐞嗭紝杩欓噷浠呴槻姝㈡湭鎹曡幏寮傚父
       }
-      dialogVisible.value = false;
-      getTableData();
     }
   });
 };
 
-onMounted(() => {
-  getTableData();
+onMounted(async () => {
+  await loadUserOptions();
+  await loadSubjectList();
+  await getTableData();
 });
 </script>
 
@@ -780,7 +968,8 @@
     .col-subject {
       position: relative;
 
-      .el-select {
+      .el-select,
+      .el-tree-select {
         .el-input input {
           font-size: 12px;
         }
diff --git a/src/views/index.vue b/src/views/index.vue
index 00d4312..6c0b729 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -479,7 +479,7 @@
 // 鑾峰彇宸ュ簭鍒楄〃
 const getProcessList = () => {
   list().then(res => {
-    processOptions.value = res.data
+    processOptions.value = res.data.records
   })
 }
 
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 78ba5bb..9485188 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -124,7 +124,8 @@
   batchApproveStockInRecords,
 } from "@/api/inventoryManagement/stockInRecord.js";
 import {
-  findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions,
+  findAllQualifiedStockInRecordTypeOptions, 
+  // findAllUnQualifiedStockInRecordTypeOptions,
 } from "@/api/basicData/enum.js";
 
 const {proxy} = getCurrentInstance();
@@ -236,10 +237,10 @@
         })
     return
   }
-  findAllUnQualifiedStockInRecordTypeOptions()
-      .then(res => {
-        stockRecordTypeOptions.value = res.data;
-      })
+  // findAllUnQualifiedStockInRecordTypeOptions()
+  //     .then(res => {
+  //       stockRecordTypeOptions.value = res.data;
+  //     })
 }
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
diff --git a/src/views/inventoryManagement/stockReport/index.vue b/src/views/inventoryManagement/stockReport/index.vue
index 8139508..26bc8a0 100644
--- a/src/views/inventoryManagement/stockReport/index.vue
+++ b/src/views/inventoryManagement/stockReport/index.vue
@@ -223,7 +223,7 @@
   } from "@/api/inventoryManagement/stockInventory.js";
   import {
     findAllQualifiedStockInRecordTypeOptions,
-    findAllUnQualifiedStockInRecordTypeOptions,
+    // findAllUnQualifiedStockInRecordTypeOptions,
   } from "@/api/basicData/enum.js";
 
   const { proxy } = getCurrentInstance();
@@ -265,12 +265,12 @@
   const fetchStockRecordTypeOptions = () => {
     findAllQualifiedStockInRecordTypeOptions().then(res => {
       stockRecordTypeOptions.value = res.data;
-      findAllUnQualifiedStockInRecordTypeOptions().then(res => {
-        stockRecordTypeOptions.value = [
-          ...stockRecordTypeOptions.value,
-          ...res.data,
-        ];
-      });
+      // findAllUnQualifiedStockInRecordTypeOptions().then(res => {
+      //   stockRecordTypeOptions.value = [
+      //     ...stockRecordTypeOptions.value,
+      //     ...res.data,
+      //   ];
+      // });
     });
   };
 
diff --git a/src/views/procurementManagement/purchaseReturnOrder/New.vue b/src/views/procurementManagement/purchaseReturnOrder/New.vue
index dffdeea..2c6801d 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/New.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/New.vue
@@ -227,10 +227,11 @@
               <span class="title-text">浜у搧鍒楄〃</span>
             </div>
             <el-button type="primary" size="small" style="margin-bottom: 20px" @click="isShowProductsModal = true" :disabled="!formState.purchaseLedgerId">娣诲姞浜у搧</el-button>
-            <el-table :data="formState.purchaseReturnOrderProductsDtos"
+            <div class="product-table-scroll">
+            <el-table class="product-table-inner"
+                      :data="formState.purchaseReturnOrderProductsDtos"
                       border
                       max-height="400"
-                      :scroll-y="true"
                       show-summary
                       :summary-method="summarizeChildrenTable">
               <el-table-column align="center"
@@ -240,6 +241,12 @@
                                label="搴忓彿"
                                type="index"
                                width="60" />
+              <el-table-column label="鍏ュ簱鍗曞彿"
+                               prop="inboundBatches"
+                               width="150" />
+              <el-table-column label="鎵规鍙�"
+                               prop="batchNo"
+                               width="150" />
               <el-table-column label="浜у搧澶х被"
                                prop="productCategory" />
               <el-table-column label="瑙勬牸鍨嬪彿"
@@ -248,11 +255,17 @@
                                prop="unit"
                                width="70" />
               <el-table-column label="鏁伴噺"
-                               prop="quantity"
+                               prop="stockInNum"
                                width="100" />
                                <el-table-column label="鍙��璐ф暟閲�"
-                               prop="availableQuality"
+                               prop="unQuantity"
                                width="130" />
+              <el-table-column label="宸查��璐ф暟閲�"
+                               width="130">
+                <template #default="scope">
+                  {{ calcAlreadyReturned(scope.row) }}
+                </template>
+              </el-table-column>
               <el-table-column label="閫�璐ф暟閲�"
                                prop="returnQuantity"
                                width="180">
@@ -268,27 +281,27 @@
                             placeholder="璇疯緭鍏ラ��璐ф暟閲�" />
                 </template>
               </el-table-column>
-              <el-table-column label="搴撳瓨棰勮鏁伴噺"
+              <!-- <el-table-column label="搴撳瓨棰勮鏁伴噺"
                                prop="warnNum"
                                width="120"
                                show-overflow-tooltip />
               <el-table-column label="绋庣巼(%)"
                                prop="taxRate"
-                               width="80" />
+                               width="80" /> -->
               <el-table-column label="鍚◣鍗曚环(鍏�)"
                                prop="taxInclusiveUnitPrice"
                                :formatter="formattedNumber"
-                               width="150" />
+                               width="120" />
               <el-table-column label="閫�璐ф�讳环(鍏�)"
                                prop="taxInclusiveTotalPrice"
-                               width="180">
+                               width="120">
                 <template #default="scope">
                   {{ formatAmount(getReturnTotal(scope.row)) || '--' }}
                 </template>
               </el-table-column>
               <el-table-column label="鏄惁璐ㄦ"
                                prop="isChecked"
-                               width="150">
+                               width="100">
                 <template #default="scope">
                   <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
                     {{ scope.row.isChecked ? '鏄�' : '鍚�' }}
@@ -311,6 +324,7 @@
                 </template>
               </el-table-column>
             </el-table>
+            </div>
           </div>
 
         <div class="section-title">
@@ -408,9 +422,6 @@
 import {getOptions, purchaseList} from "@/api/procurementManagement/procurementLedger.js";
 import {userListNoPageByTenantId} from "@/api/system/user.js";
 const ProductList = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/ProductList.vue"));
-  import {
-    productList,
-  } from "@/api/procurementManagement/procurementLedger.js";
 const props = defineProps({
   visible: {
     type: Boolean,
@@ -518,6 +529,14 @@
   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) => {
   const qty = toNumber(row?.returnQuantity)
   const unitPrice = toNumber(row?.taxInclusiveUnitPrice)
@@ -553,7 +572,7 @@
 }
 
 const getReturnQtyMax = (row) => {
-  const max = Number(row?.availableQuality)
+  const max = Number(row?.unQuantity)
   if (Number.isNaN(max) || max < 0) {
     return 0
   }
@@ -568,17 +587,17 @@
   return proxy.summarizeTable(
       param,
       [
-        "quantity",
-        "availableQuality",
+        "stockInNum",
+        "unQuantity",
         "returnQuantity",
         "taxInclusiveUnitPrice",
         "taxInclusiveTotalPrice",
         "taxExclusiveTotalPrice",
       ],
       {
-        quantity: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+        stockInNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
         returnQuantity: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-        availableQuality: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+        unQuantity: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
       }
   );
 };
@@ -660,20 +679,10 @@
   }
 }
 
-// 澶勭悊鏀瑰彉閲囪喘鍙拌处鏁版嵁
-const handleChangePurchaseLedgerId = async () => {
+// 澶勭悊鏀瑰彉閲囪喘鍙拌处鏁版嵁锛堜笉璇锋眰鎺ュ彛鍥炴樉浜у搧锛屼骇鍝佷粎鍦ㄣ�屾坊鍔犱骇鍝併�嶅脊绐楀嬀閫夊悗鍐欏叆锛�
+const handleChangePurchaseLedgerId = () => {
   resetFeeInfo()
-  if (!formState.value.purchaseLedgerId) {
-    formState.value.purchaseReturnOrderProductsDtos = []
-    return
-  }
-  const res = await productList({ salesLedgerId: formState.value.purchaseLedgerId, type: 2 });
-  formState.value.purchaseReturnOrderProductsDtos = res.data.map(item => ({
-    ...item,
-    returnQuantity: undefined,
-    taxInclusiveTotalPrice: 0,
-    salesLedgerProductId: item.id,
-  }))
+  formState.value.purchaseReturnOrderProductsDtos = []
   syncTotalAmount()
 }
 
@@ -691,7 +700,7 @@
     ...item,
     returnQuantity: undefined,
     taxInclusiveTotalPrice: 0,
-    salesLedgerProductId: item.id,
+    // salesLedgerProductId: item.salesLedgerProductId,
   }));
   formState.value.purchaseReturnOrderProductsDtos.push(...newProducts);
   syncTotalAmount()
@@ -717,7 +726,7 @@
   // 閫愯鏍¢獙閫�璐ф暟閲忥細浠绘剰涓�琛屾湭濉�/闈炴硶/瓒呴檺閮戒笉鍏佽鎻愪氦
   const invalidRowIndex = productList.findIndex((item) => {
     const qty = Number(item.returnQuantity)
-    const maxQty = Number(item.availableQuality)
+    const maxQty = Number(item.unQuantity)
 
     if (item.returnQuantity === null || item.returnQuantity === undefined || item.returnQuantity === "") {
       return true
@@ -738,7 +747,15 @@
 
   proxy.$refs["formRef"].validate(valid => {
     if (valid) {
-      createPurchaseReturnOrder(formState.value).then(res => {
+      console.log(productList)
+      const submitPayload = {
+        ...formState.value,
+        purchaseReturnOrderProductsDtos: productList.map((row) => ({
+          ...row,
+          stockInRecordId: row.id,
+        })),
+      }
+      createPurchaseReturnOrder(submitPayload).then(res => {
         // 鍏抽棴妯℃�佹
         isShow.value = false;
         // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
@@ -785,4 +802,13 @@
   border-radius: 50%;
   margin-right: 8px;
 }
+
+.product-table-scroll {
+  width: 100%;
+  overflow-x: auto;
+}
+
+.product-table-inner {
+  min-width: 1280px;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue b/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
index 3eeb167..27fae4a 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
@@ -6,9 +6,10 @@
         width="1200"
         @close="closeModal"
     >
-      <div class="table_list">
+      <div class="table_list" v-loading="tableLoading">
         <el-table :data="tableData"
                   border
+                  row-key="id"
                   @selection-change="handleChangeSelection">
           <el-table-column align="center"
                            type="selection"
@@ -17,6 +18,12 @@
                            label="搴忓彿"
                            type="index"
                            width="60" />
+                           <el-table-column label="鍏ュ簱鍗曞彿"
+                               prop="inboundBatches"
+                               width="150" />
+              <el-table-column label="鎵规鍙�"
+                               prop="batchNo"
+                               width="150" />
           <el-table-column label="浜у搧澶х被"
                            prop="productCategory" />
           <el-table-column label="瑙勬牸鍨嬪彿"
@@ -25,27 +32,36 @@
                            prop="unit"
                            width="70" />
           <el-table-column label="鏁伴噺"
-                           prop="quantity"
+                           prop="stockInNum"
                            width="70" />
-          <el-table-column label="搴撳瓨棰勮鏁伴噺"
+          <el-table-column label="鍙��璐ф暟閲�"
+                           prop="unQuantity"
+                           width="130" />
+          <el-table-column label="宸查��璐ф暟閲�"
+                           width="130">
+            <template #default="scope">
+              {{ calcAlreadyReturned(scope.row) }}
+            </template>
+          </el-table-column>
+          <!-- <el-table-column label="搴撳瓨棰勮鏁伴噺"
                            prop="warnNum"
                            width="120"
                            show-overflow-tooltip />
           <el-table-column label="绋庣巼(%)"
                            prop="taxRate"
-                           width="80" />
+                           width="80" /> -->
           <el-table-column label="鍚◣鍗曚环(鍏�)"
                            prop="taxInclusiveUnitPrice"
                            :formatter="formattedNumber"
                            width="150" />
-          <el-table-column label="鍚◣鎬讳环(鍏�)"
+          <!-- <el-table-column label="鍚◣鎬讳环(鍏�)"
                            prop="taxInclusiveTotalPrice"
                            :formatter="formattedNumber"
                            width="150" />
           <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
                            prop="taxExclusiveTotalPrice"
                            :formatter="formattedNumber"
-                           width="150" />
+                           width="150" /> -->
           <el-table-column label="鏄惁璐ㄦ"
                            prop="isChecked"
                            width="150">
@@ -56,8 +72,6 @@
             </template>
           </el-table-column>
         </el-table>
-        <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
-                    :page="page.current" :limit="page.size" @pagination="paginationChange" />
       </div>
 
       <template #footer>
@@ -71,8 +85,8 @@
 </template>
 
 <script setup>
-import {computed, reactive, ref, onMounted} from "vue";
-import {productList} from "@/api/procurementManagement/procurementLedger.js";
+import {computed, ref, onMounted} from "vue";
+import {getPurchaseReturnOrderByPurchaseLedgerId} from "@/api/procurementManagement/purchase_return_order.js";
 import {ElMessage} from "element-plus";
 
 const props = defineProps({
@@ -82,7 +96,7 @@
   },
 
   purchaseLedgerId: {
-    type: Number,
+    type: [Number, String],
     required: true,
   }
 });
@@ -101,32 +115,59 @@
 const tableData = ref([])
 const selectedRows = ref([])
 const tableLoading = ref(false)
-const page = reactive({
-  current: 1,
-  size: 100,
-})
-const total = ref(0)
 const formattedNumber = (row, column, cellValue) => {
   return parseFloat(cellValue).toFixed(2);
 };
 
-const paginationChange = (obj) => {
-  page.current = obj.page;
-  page.size = obj.limit;
-  getList()
+/** 宸查��璐ф暟閲� = 鍏ュ簱琛屾�绘暟閲� 鈭� 褰撳墠鍙��璐ф暟閲忥紙鍓╀綑锛� */
+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;
 }
 
+/** 涓� New.vue 涓噰璐彴璐﹀彉鏇存椂瑙f瀽 getByPurchaseLedgerId 鐨勮鍒欎竴鑷� */
+const parseProductRowsFromLedgerResponse = (res) => {
+  const payload = res?.data
+  let list = []
+  if (Array.isArray(payload)) {
+    list = payload
+  } else if (payload && typeof payload === 'object') {
+    const nested =
+      payload.purchaseReturnOrderProductsDtos ||
+      payload.purchaseReturnOrderProductsDetailVoList
+    list = Array.isArray(nested) ? nested : []
+    if (list.length && list[0]?.salesLedgerProduct) {
+      list = list.map((item) => ({ ...item, ...item.salesLedgerProduct }))
+    }
+  }
+  return list
+}
+
 const fetchData = () => {
-  tableLoading.value = true;
-  productList({salesLedgerId: props.purchaseLedgerId, type: 2}).then((res) => {
-    tableData.value = res.data;
-  }).finally(() => {
-    tableLoading.value = false;
+  if (props.purchaseLedgerId === undefined || props.purchaseLedgerId === null || props.purchaseLedgerId === '') {
+    tableData.value = []
+    return
+  }
+  tableLoading.value = true
+  getPurchaseReturnOrderByPurchaseLedgerId({
+    purchaseLedgerId: props.purchaseLedgerId,
   })
+    .then((res) => {
+      const list = parseProductRowsFromLedgerResponse(res)
+      tableData.value = list
+    })
+    .catch(() => {
+      tableData.value = []
+    })
+    .finally(() => {
+      tableLoading.value = false
+    })
 }
 
 const handleSubmit = () => {
diff --git a/src/views/procurementManagement/purchaseReturnOrder/index.vue b/src/views/procurementManagement/purchaseReturnOrder/index.vue
index 942b4dc..f8866e1 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/index.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/index.vue
@@ -1,24 +1,26 @@
 <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.no"
-                    placeholder="璇疯緭鍏�"
-                    clearable
-                    prefix-icon="Search"
-                    @change="handleQuery" />
+          <el-input
+            v-model="searchForm.no"
+            placeholder="璇疯緭鍏�"
+            clearable
+            prefix-icon="Search"
+            @change="handleQuery"
+          />
         </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>
-        <el-button type="primary" @click="isShowNewModal = true">鏂板</el-button>
+        <el-button type="primary" @click="isShowNewModal = true"
+          >鏂板</el-button
+        >
       </div>
     </div>
 
@@ -35,14 +37,25 @@
         @pagination="paginationChange"
       >
         <template #operation="{ row }">
-          <el-button link type="primary" size="small" style="color: #67C23A" @click="handleDetail(row)">璇︽儏</el-button>
-          <el-button link size="small" @click="handleDelete(row)">鍒犻櫎</el-button>
+          <el-button
+            link
+            type="primary"
+            size="small"
+            style="color: #67c23a"
+            @click="handleDetail(row)"
+            >璇︽儏</el-button
+          >
+          <el-button link size="small" @click="handleDelete(row)"
+            >鍒犻櫎</el-button
+          >
         </template>
       </PIMTable>
     </div>
-    <new v-if="isShowNewModal"
-         v-model:visible="isShowNewModal"
-         @completed="handleQuery" />
+    <new
+      v-if="isShowNewModal"
+      v-model:visible="isShowNewModal"
+      @completed="handleQuery"
+    />
 
     <el-dialog
       v-model="detailVisible"
@@ -52,21 +65,51 @@
     >
       <div v-loading="detailLoading">
         <el-descriptions :column="3" border>
-          <el-descriptions-item label="閫�鏂欏崟鍙�">{{ detailData.no || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="閫�璐ф柟寮�">{{ getReturnTypeLabel(detailData.returnType) }}</el-descriptions-item>
-          <el-descriptions-item label="渚涘簲鍟嗗悕绉�">{{ detailData.supplierName || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="椤圭洰闃舵">{{ getProjectPhaseLabel(detailData.projectPhase) }}</el-descriptions-item>
-          <el-descriptions-item label="鍏宠仈鍗曞彿">{{ detailData.purchaseContractNumber || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="鍒朵綔鏃ユ湡">{{ detailData.preparedAt || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="鍒跺崟浜�">{{ detailData.preparedUserName || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="閫�鏂欎汉">{{ detailData.returnUserName || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="鏁村崟鎶樻墸棰�">{{ formatAmount(detailData.totalDiscountAmount) }}</el-descriptions-item>
-          <el-descriptions-item label="鏁村崟鎶樻墸鐜�">{{ detailData.totalDiscountRate ?? '--' }}</el-descriptions-item>
-          <el-descriptions-item label="鎴愪氦閲戦">{{ formatAmount(detailData.totalAmount) }}</el-descriptions-item>
-          <el-descriptions-item label="鍒涘缓浜�">{{ detailData.createUserName || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="鍒涘缓鏃堕棿">{{ detailData.createTime || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="鏈�杩戞洿鏂版椂闂�">{{ detailData.updateTime || '--' }}</el-descriptions-item>
-          <el-descriptions-item label="澶囨敞" :span="3">{{ detailData.remark || '--' }}</el-descriptions-item>
+          <el-descriptions-item label="閫�鏂欏崟鍙�">{{
+            detailData.no || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="閫�璐ф柟寮�">{{
+            getReturnTypeLabel(detailData.returnType)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="渚涘簲鍟嗗悕绉�">{{
+            detailData.supplierName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="椤圭洰闃舵">{{
+            getProjectPhaseLabel(detailData.projectPhase)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍏宠仈鐨勯噰璐鍗曞彿">{{
+            detailData.purchaseContractNumber || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒朵綔鏃ユ湡">{{
+            detailData.preparedAt || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒跺崟浜�">{{
+            detailData.preparedUserName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="閫�鏂欎汉">{{
+            detailData.returnUserName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鏁村崟鎶樻墸棰�">{{
+            formatAmount(detailData.totalDiscountAmount)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鏁村崟鎶樻墸鐜�">{{
+            detailData.totalDiscountRate ?? "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鎴愪氦閲戦">{{
+            formatAmount(detailData.totalAmount)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒涘缓浜�">{{
+            detailData.createUserName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒涘缓鏃堕棿">{{
+            detailData.createTime || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鏈�杩戞洿鏂版椂闂�">{{
+            detailData.updateTime || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="澶囨敞" :span="3">{{
+            detailData.remark || "--"
+          }}</el-descriptions-item>
         </el-descriptions>
 
         <el-divider content-position="left">浜у搧鍒楄〃</el-divider>
@@ -77,27 +120,75 @@
           max-height="420"
           style="width: 100%"
         >
-          <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-          <el-table-column label="浜у搧澶х被" prop="productCategory" min-width="120" show-overflow-tooltip />
-          <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" min-width="140" show-overflow-tooltip />
+          <el-table-column
+            align="center"
+            label="搴忓彿"
+            type="index"
+            width="60"
+          />
+          <el-table-column label="鍏ュ簱鍗曞彿" prop="inboundBatches" width="150" />
+          <el-table-column label="鎵规鍙�" prop="batchNo" width="150" />
+          <el-table-column
+            label="浜у搧澶х被"
+            prop="productCategory"
+            min-width="120"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            label="瑙勬牸鍨嬪彿"
+            prop="specificationModel"
+            min-width="140"
+            show-overflow-tooltip
+          />
           <el-table-column label="鍗曚綅" prop="unit" width="80" />
-          <el-table-column label="鏁伴噺" prop="quantity" width="80" />
-          <el-table-column label="閫�璐ф暟閲�" prop="returnQuantity" width="100" />
-          <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" width="120" />
-          <el-table-column label="绋庣巼(%)" prop="taxRate" width="90" />
-          <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" width="130">
-            <template #default="scope">{{ formatAmount(scope.row.taxInclusiveUnitPrice) }}</template>
+          <el-table-column label="鏁伴噺" prop="stockInNum" width="80" />
+          <el-table-column label="鍙��璐ф暟閲�"
+                           prop="unQuantity"
+                           width="100" />
+          <el-table-column label="宸查��璐ф暟閲�"
+                           width="100">
+            <template #default="scope">
+              {{ calcAlreadyReturned(scope.row) }}
+            </template>
           </el-table-column>
-          <el-table-column label="閫�璐ф�讳环(鍏�)" prop="taxInclusiveTotalPrice" width="130">
-            <template #default="scope">{{ formatAmount(scope.row.taxInclusiveTotalPrice) }}</template>
+          <!-- <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" width="120" /> -->
+          <!-- <el-table-column label="绋庣巼(%)" prop="taxRate" width="90" /> -->
+          <el-table-column
+            label="鍚◣鍗曚环(鍏�)"
+            prop="taxInclusiveUnitPrice"
+            width="130"
+          >
+            <template #default="scope">{{
+              formatAmount(scope.row.taxInclusiveUnitPrice)
+            }}</template>
           </el-table-column>
-          <el-table-column label="涓嶉��璐ф�讳环(鍏�)" prop="taxExclusiveTotalPrice" width="140">
-            <template #default="scope">{{ formatAmount(scope.row.taxExclusiveTotalPrice) }}</template>
+          <!-- <el-table-column
+            label="閫�璐ф�讳环(鍏�)"
+            prop="taxInclusiveTotalPrice"
+            width="130"
+          >
+            <template #default="scope">{{
+              formatAmount(scope.row.taxInclusiveTotalPrice)
+            }}</template>
           </el-table-column>
-          <el-table-column label="鏄惁璐ㄦ" prop="isChecked" width="100" align="center">
+          <el-table-column
+            label="涓嶉��璐ф�讳环(鍏�)"
+            prop="taxExclusiveTotalPrice"
+            width="140"
+          >
+            <template #default="scope">{{
+              formatAmount(scope.row.taxExclusiveTotalPrice)
+            }}</template>
+          </el-table-column> -->
+          <el-table-column
+            label="鏄惁璐ㄦ"
+            prop="isChecked"
+            width="100"
+            align="center"
+          >
             <template #default="scope">
               <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
-                {{ scope.row.isChecked ? '鏄�' : '鍚�' }}
+                {{ scope.row.isChecked ? "鏄�" : "鍚�" }}
               </el-tag>
             </template>
           </el-table-column>
@@ -111,238 +202,280 @@
 </template>
 
 <script setup>
-import PIMTable from '@/components/PIMTable/PIMTable.vue'
-import { ref, reactive, toRefs, onMounted, defineAsyncComponent, getCurrentInstance } from 'vue'
-const { proxy } = getCurrentInstance()
-import {findPurchaseReturnOrderListPage, getPurchaseReturnOrderDetail, deletePurchaseReturnOrder} from "@/api/procurementManagement/purchase_return_order.js";
-const New = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/New.vue"));
-const tableData = ref([])
-const selectedRows = ref([])
-const tableLoading = ref(false)
+import PIMTable from "@/components/PIMTable/PIMTable.vue";
+import {
+  ref,
+  reactive,
+  toRefs,
+  onMounted,
+  defineAsyncComponent,
+  getCurrentInstance,
+} from "vue";
+const { proxy } = getCurrentInstance();
+import {
+  findPurchaseReturnOrderListPage,
+  getPurchaseReturnOrderDetail,
+  deletePurchaseReturnOrder,
+} from "@/api/procurementManagement/purchase_return_order.js";
+const New = defineAsyncComponent(() =>
+  import("@/views/procurementManagement/purchaseReturnOrder/New.vue")
+);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
 const page = reactive({
   current: 1,
   size: 100,
   total: 0,
-})
-const detailVisible = ref(false)
-const detailLoading = ref(false)
-const detailData = ref({})
-const detailProducts = ref([])
+});
+const detailVisible = ref(false);
+const detailLoading = ref(false);
+const detailData = ref({});
+const detailProducts = ref([]);
 // 鏄惁鏄剧ず鏂板寮规
-const isShowNewModal = ref(false)
+const isShowNewModal = ref(false);
 const returnTypeOptions = [
-  { label: '閫�璐ч��娆�', value: 0 },
-  { label: '鎷掓敹', value: 1 },
-]
+  { label: "閫�璐ч��娆�", value: 0 },
+  { label: "鎷掓敹", value: 1 },
+];
 const projectPhaseOptions = [
-  { label: '绔嬮」', value: 0 },
-  { label: '璁捐', value: 1 },
-  { label: '閲囪喘', value: 2 },
-  { label: '鐢熶骇', value: 3 },
-  { label: '鍑鸿揣', value: 4 },
-]
+  { label: "绔嬮」", value: 0 },
+  { label: "璁捐", value: 1 },
+  { label: "閲囪喘", value: 2 },
+  { label: "鐢熶骇", value: 3 },
+  { label: "鍑鸿揣", value: 4 },
+];
 const tableColumn = ref([
   {
-    label: '閫�鏂欏崟鍙�',
-    prop: 'no',
+    label: "閫�鏂欏崟鍙�",
+    prop: "no",
   },
   {
-    label: '閫�璐ф柟寮�',
-    prop: 'returnType',
-    formatData: (val) => returnTypeOptions.find(item => item.value === val)?.label || '--',
+    label: "閫�璐ф柟寮�",
+    prop: "returnType",
+    formatData: (val) =>
+      returnTypeOptions.find((item) => item.value === val)?.label || "--",
   },
   {
-    label: '渚涘簲鍟嗗悕绉�',
-    prop: 'supplierName',
+    label: "渚涘簲鍟嗗悕绉�",
+    prop: "supplierName",
     width: 180,
   },
   {
-    label: '椤圭洰闃舵',
-    prop: 'projectPhase',
+    label: "椤圭洰闃舵",
+    prop: "projectPhase",
     width: 100,
-    formatData: (val) => projectPhaseOptions.find(item => String(item.value) === String(val))?.label || '--',
+    formatData: (val) =>
+      projectPhaseOptions.find((item) => String(item.value) === String(val))
+        ?.label || "--",
   },
   {
-    label: '鍏宠仈鍗曞彿',
-    prop: 'purchaseContractNumber',
+    label: "鍏宠仈鐨勯噰璐鍗曞彿",
+    prop: "purchaseContractNumber",
     width: 160,
   },
   {
-    label: '鍒朵綔鏃ユ湡',
-    prop: 'preparedAt',
+    label: "鍒朵綔鏃ユ湡",
+    prop: "preparedAt",
     width: 130,
   },
   {
-    label: '鍒跺崟浜�',
-    prop: 'preparedUserName',
+    label: "鍒跺崟浜�",
+    prop: "preparedUserName",
     width: 110,
   },
   {
-    label: '閫�鏂欎汉',
-    prop: 'returnUserName',
+    label: "閫�鏂欎汉",
+    prop: "returnUserName",
     width: 110,
   },
 
   {
-    label: '鏁村崟鎶樻墸棰�',
-    prop: 'totalDiscountAmount',
+    label: "鏁村崟鎶樻墸棰�",
+    prop: "totalDiscountAmount",
     width: 120,
   },
   {
-    label: '鏁村崟鎶樻墸鐜�',
-    prop: 'totalDiscountRate',
+    label: "鏁村崟鎶樻墸鐜�",
+    prop: "totalDiscountRate",
     width: 120,
   },
   {
-    label: '鎴愪氦閲戦',
-    prop: 'totalAmount',
+    label: "鎴愪氦閲戦",
+    prop: "totalAmount",
     width: 120,
   },
   {
-    label: '鍒涘缓浜�',
-    prop: 'createUserName',
+    label: "鍒涘缓浜�",
+    prop: "createUserName",
     width: 110,
   },
   {
-    label: '鍒涘缓鏃堕棿',
-    prop: 'createTime',
+    label: "鍒涘缓鏃堕棿",
+    prop: "createTime",
     width: 170,
   },
   {
-    label: '鏈�杩戞洿鏂版椂闂�',
-    prop: 'updateTime',
+    label: "鏈�杩戞洿鏂版椂闂�",
+    prop: "updateTime",
     width: 170,
   },
   {
-    label: '澶囨敞',
-    prop: 'remark',
+    label: "澶囨敞",
+    prop: "remark",
     width: 180,
   },
   {
     dataType: "action",
     width: 120,
-      label: "鎿嶄綔",
-      align: "center",
-      fixed: "right",
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: "right",
     operation: [
       {
-				name: "璇︽儏",
-				type: "text",
-				clickFun: row => {handleDetail(row);},
-			},
+        name: "璇︽儏",
+        type: "text",
+        clickFun: (row) => {
+          handleDetail(row);
+        },
+      },
       {
         name: "鍒犻櫎",
-        clickFun: row => {handleDelete(row)},
+        clickFun: (row) => {
+          handleDelete(row);
+        },
       },
-  ],
+    ],
   },
-
-])
+]);
 const data = reactive({
   searchForm: {
-    no: '',
-  }
-})
-const { searchForm } = toRefs(data)
+    no: "",
+  },
+});
+const { searchForm } = toRefs(data);
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1
-  getList()
-}
+  page.current = 1;
+  getList();
+};
 
 // 鍒犻櫎鎿嶄綔
 const handleDelete = (row) => {
-  console.log('鍒犻櫎琛屾暟鎹細', row)
-  proxy?.$modal?.confirm('纭畾瑕佸垹闄ゅ悧锛熷垹闄ゅ皢鏃犳硶鎭㈠').then(() => {
-    // 杩欓噷璋冪敤鍒犻櫎鎺ュ彛锛屼紶鍏� row.id
-    deletePurchaseReturnOrder(row.id).then(() => {
-      proxy?.$modal?.msgSuccess?.("鍒犻櫎鎴愬姛");
-      getList()
-    }).catch(() => {
-      proxy?.$modal?.msgError?.('鍒犻櫎澶辫触')
+  console.log("鍒犻櫎琛屾暟鎹細", row);
+  proxy?.$modal
+    ?.confirm("纭畾瑕佸垹闄ゅ悧锛熷垹闄ゅ皢鏃犳硶鎭㈠")
+    .then(() => {
+      // 杩欓噷璋冪敤鍒犻櫎鎺ュ彛锛屼紶鍏� row.id
+      deletePurchaseReturnOrder(row.id)
+        .then(() => {
+          proxy?.$modal?.msgSuccess?.("鍒犻櫎鎴愬姛");
+          getList();
+        })
+        .catch(() => {
+          proxy?.$modal?.msgError?.("鍒犻櫎澶辫触");
+        });
     })
-  }).catch(() => {
-    // 鍙栨秷鍒犻櫎
-    proxy?.$modal?.msgInfo?.('宸插彇娑堝垹闄�')
-
-  })
-}
+    .catch(() => {
+      // 鍙栨秷鍒犻櫎
+      proxy?.$modal?.msgInfo?.("宸插彇娑堝垹闄�");
+    });
+};
 // 鏌ョ湅璇︽儏
 const handleDetail = (row) => {
   if (!row?.id) {
-    proxy?.$modal?.msgWarning?.('鏈幏鍙栧埌鍗曟嵁ID')
-    return
+    proxy?.$modal?.msgWarning?.("鏈幏鍙栧埌鍗曟嵁ID");
+    return;
   }
-  detailVisible.value = true
-  detailLoading.value = true
-  getPurchaseReturnOrderDetail(row.id).then(res => {
-    const payload = res?.data || {}
-    detailData.value = payload
-    // 鎷兼帴杩炰釜瀵硅薄鎴愪竴涓璞★紝鏂逛究灞曠ず item 鍜� item.salesLedgerProduct 閲岀殑瀛楁
+  detailVisible.value = true;
+  detailLoading.value = true;
+  getPurchaseReturnOrderDetail(row.id)
+    .then((res) => {
+      const payload = res?.data || {};
+      detailData.value = payload;
+      // 鎷兼帴杩炰釜瀵硅薄鎴愪竴涓璞★紝鏂逛究灞曠ず item 鍜� item.salesLedgerProduct 閲岀殑瀛楁
 
-
-    detailProducts.value =
-      payload.purchaseReturnOrderProductsDetailVoList.map(item => ({ ...item, ...item.salesLedgerProduct })) ||
-      []
-  }).catch(() => {
-    proxy?.$modal?.msgError?.('鑾峰彇璇︽儏澶辫触')
-  }).finally(() => {
-    detailLoading.value = false
-  })
-}
-
+      detailProducts.value =
+        payload.purchaseReturnOrderProductsDetailVoList.map((item) => ({
+          ...item,
+          ...item.salesLedgerProduct,
+        })) || [];
+    })
+    .catch(() => {
+      proxy?.$modal?.msgError?.("鑾峰彇璇︽儏澶辫触");
+    })
+    .finally(() => {
+      detailLoading.value = false;
+    });
+};
 
 const paginationChange = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
-  getList()
-}
+  getList();
+};
 
 const getList = () => {
-  tableLoading.value = true
-  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page }).then(res => {
-    tableLoading.value = false
-    tableData.value = res.data.records
-    page.total = res.data.total
-  }).catch(() => {
-    tableLoading.value = false
-  })
-}
+  tableLoading.value = true;
+  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      tableData.value = res.data.records;
+      page.total = res.data.total;
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   // 杩囨护鎺夊瓙鏁版嵁
-  selectedRows.value = selection.filter(item => item.id);
-}
+  selectedRows.value = selection.filter((item) => item.id);
+};
 
 const getReturnTypeLabel = (value) => {
-  return returnTypeOptions.find(item => String(item.value) === String(value))?.label || '--'
-}
+  return (
+    returnTypeOptions.find((item) => String(item.value) === String(value))
+      ?.label || "--"
+  );
+};
 
 const getProjectPhaseLabel = (value) => {
-  return projectPhaseOptions.find(item => String(item.value) === String(value))?.label || '--'
-}
+  return (
+    projectPhaseOptions.find((item) => String(item.value) === String(value))
+      ?.label || "--"
+  );
+};
 
 const formatAmount = (value) => {
-  if (value === null || value === undefined || value === '') {
-    return '--'
+  if (value === null || value === undefined || value === "") {
+    return "--";
   }
-  const num = Number(value)
+  const num = Number(value);
   if (Number.isNaN(num)) {
-    return value
+    return value;
   }
-  return num.toFixed(2)
-}
+  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()
-})
+  getList();
+});
 </script>
 <style scoped>
 .table_list {
-	margin-top: unset;
+  margin-top: unset;
 }
 </style>
 
diff --git a/src/views/qualityManagement/processInspection/components/formDia.vue b/src/views/qualityManagement/processInspection/components/formDia.vue
index c1185d2..88c1e20 100644
--- a/src/views/qualityManagement/processInspection/components/formDia.vue
+++ b/src/views/qualityManagement/processInspection/components/formDia.vue
@@ -1,129 +1,165 @@
 <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="process">
-              <el-select v-model="form.process" placeholder="璇烽�夋嫨宸ュ簭" clearable :disabled="processQuantityDisabled" style="width: 100%">
-                <el-option v-for="item in processList" :key="item.name" :label="item.name" :value="item.name"/>
+            <el-form-item label="宸ュ簭锛�"
+                          prop="process">
+              <el-select v-model="form.process"
+                         placeholder="璇烽�夋嫨宸ュ簭"
+                         clearable
+                         :disabled="processQuantityDisabled"
+                         style="width: 100%">
+                <el-option v-for="item in processList"
+                           :key="item.name"
+                           :label="item.name"
+                           :value="item.name" />
               </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="璇烽�夋嫨"
-                  clearable
-                  check-strictly
-                  @change="getModels"
-                  :data="productOptions"
-                  :render-after-expand="false"
-                  :disabled="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="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="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="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%"
-              >
-                <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%">
+                <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="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="processQuantityDisabled" />
             </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/>
+            <el-form-item label="妫�娴嬪崟浣嶏細"
+                          prop="checkCompany">
+              <el-input v-model="form.checkCompany"
+                        placeholder="璇疯緭鍏�"
+                        clearable />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="妫�娴嬬粨鏋滐細" prop="checkResult">
+            <el-form-item label="妫�娴嬬粨鏋滐細"
+                          prop="checkResult">
               <el-select v-model="form.checkResult">
-                <el-option label="鍚堟牸" value="鍚堟牸" />
-                <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>
-								<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
-													 :value="item.nickName"/>
-							</el-select>
+            <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-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-form>
-			<PIMTable
-				rowKey="id"
-				:column="tableColumn"
-				:tableData="tableData"
-				:tableLoading="tableLoading"
-				height="400"
-			>
-				<template #slot="{ row }">
-					<el-input v-model="row.testValue" clearable/>
-				</template>
-			</PIMTable>
+      <PIMTable rowKey="id"
+                :column="tableColumn"
+                :tableData="tableData"
+                :tableLoading="tableLoading"
+                height="400">
+        <template #slot="{ row }">
+          <el-input v-model="row.testValue"
+                    clearable />
+        </template>
+      </PIMTable>
       <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>
@@ -132,332 +168,356 @@
 </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 {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
-import {userListNoPage} from "@/api/system/user.js";
-import {qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js";
-import { list } from "@/api/productionManagement/productionProcess";
-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 {
+    qualityInspectDetailByProductId,
+    getQualityTestStandardParamByTestStandardId,
+  } from "@/api/qualityManagement/metricMaintenance.js";
+  import { userListNoPage } from "@/api/system/user.js";
+  import { qualityInspectParamInfo } from "@/api/qualityManagement/qualityInspectParam.js";
+  import { list } from "@/api/productionManagement/productionProcess";
+  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: "",
-    checkCompany: "",
-    checkResult: "",
-  },
-  rules: {
-    checkTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" },],
-    process: [{ required: true, message: "璇烽�夋嫨宸ュ簭", trigger: "change" }],
-    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" }],
-    checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-    checkResult: [{ required: true, message: "璇疯緭鍏�", trigger: "change" }],
-  },
-});
-const userList = ref([]);
-const { form, rules } = toRefs(data);
-// 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯宸ュ簭銆佹暟閲忕疆鐏�
-const processQuantityDisabled = computed(() => {
-  const v = form.value || {};
-  return !!(v.productMainId != null || v.purchaseLedgerId != null);
-});
-const processList = ref([]); // 宸ュ簭涓嬫媺鍒楄〃锛堝伐搴忓悕绉� name锛�
-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 currentProductId = ref(0);
-const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
-const modelOptions = ref([]);
-
-// 鎵撳紑寮规
-const openDialog = async (type, row) => {
-	operationType.value = type;
-	getOptions().then((res) => {
-		supplierList.value = res.data;
-	});
-	// 鍔犺浇宸ュ簭涓嬫媺鍒楄〃
-	try {
-		const res = await list();
-		processList.value = res.data || [];
-	} catch (e) {
-		console.error("鍔犺浇宸ュ簭鍒楄〃澶辫触", e);
-		processList.value = [];
-	}
-	let userLists = await userListNoPage();
-	userList.value = userLists.data;
-	// 鍏堥噸缃〃鍗曟暟鎹紙淇濇寔瀛楁瀹屾暣锛岄伩鍏嶅脊绐楅娆℃覆鏌撴椂瑙﹀彂蹇呭~绾㈡鈥滈棯涓�涓嬧�濓級
-	form.value = {
-		checkTime: "",
-		process: "",
-		checkName: "",
-		productName: "",
-		productId: "",
-		productModelId: "",
-		model: "",
-		testStandardId: "",
-		unit: "",
-		quantity: "",
-		checkCompany: "",
-		checkResult: "",
-	}
-	testStandardOptions.value = [];
-	tableData.value = [];
-	// 鍏堢‘淇濅骇鍝佹爲宸插姞杞斤紝鍚﹀垯缂栬緫鏃朵骇鍝�/瑙勬牸鍨嬪彿鏃犳硶鍙嶆樉
-	await getProductOptions();
-	if (operationType.value === 'edit') {
-		// 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
-		const savedTestStandardId = row.testStandardId;
-		// 鍏堣缃〃鍗曟暟鎹紝浣嗘殏鏃舵竻绌� testStandardId锛岀瓑閫夐」鍔犺浇瀹屾垚鍚庡啀璁剧疆
-		form.value = {...row, 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: 1,
-				process: form.value.process || ''
-			}
-			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);
-							}
-						} 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 dialogFormVisible = ref(false);
+  const operationType = ref("");
+  const data = reactive({
+    form: {
+      checkTime: "",
+      process: "",
+      checkName: "",
+      productName: "",
+      productId: "",
+      productModelId: "",
+      model: "",
+      testStandardId: "",
+      unit: "",
+      quantity: "",
+      checkCompany: "",
+      checkResult: "",
+    },
+    rules: {
+      checkTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+      process: [{ required: true, message: "璇烽�夋嫨宸ュ簭", trigger: "change" }],
+      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" }],
+      checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+      checkResult: [{ required: true, message: "璇疯緭鍏�", trigger: "change" }],
+    },
   });
-};
-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 userList = ref([]);
+  const { form, rules } = toRefs(data);
+  // 缂栬緫鏃讹細productMainId 鎴� purchaseLedgerId 浠讳竴鏈夊�煎垯宸ュ簭銆佹暟閲忕疆鐏�
+  const processQuantityDisabled = computed(() => {
+    const v = form.value || {};
+    return !!(v.productMainId != null || v.purchaseLedgerId != null);
+  });
+  const processList = ref([]); // 宸ュ簭涓嬫媺鍒楄〃锛堝伐搴忓悕绉� name锛�
+  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 currentProductId = ref(0);
+  const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
+  const modelOptions = ref([]);
 
-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; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+  // 鎵撳紑寮规
+  const openDialog = async (type, row) => {
+    operationType.value = type;
+    getOptions().then(res => {
+      supplierList.value = res.data;
+    });
+    // 鍔犺浇宸ュ簭涓嬫媺鍒楄〃
+    try {
+      const res = await list({ size: -1, current: -1 });
+      processList.value = res.data.records || [];
+    } catch (e) {
+      console.error("鍔犺浇宸ュ簭鍒楄〃澶辫触", e);
+      processList.value = [];
     }
-    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
+    let userLists = await userListNoPage();
+    userList.value = userLists.data;
+    // 鍏堥噸缃〃鍗曟暟鎹紙淇濇寔瀛楁瀹屾暣锛岄伩鍏嶅脊绐楅娆℃覆鏌撴椂瑙﹀彂蹇呭~绾㈡鈥滈棯涓�涓嬧�濓級
+    form.value = {
+      checkTime: "",
+      process: "",
+      checkName: "",
+      productName: "",
+      productId: "",
+      productModelId: "",
+      model: "",
+      testStandardId: "",
+      unit: "",
+      quantity: "",
+      checkCompany: "",
+      checkResult: "",
     };
-    if (children && children.length > 0) {
-      newItem.children = convertIdToValue(children);
-    }
-    
-    return newItem;
-  });
-}
-// 宸ュ簭鍙樺寲澶勭悊
-// 鎻愪氦浜у搧琛ㄥ崟
-const submitForm = () => {
-  proxy.$refs.formRef.validate(valid => {
-    if (valid) {
-      form.value.inspectType = 1
-			const processName = form.value.process || '';
-			if (operationType.value === "add") {
-				tableData.value.forEach((item) => {
-					delete item.id
-				})
-			}
-			const data = {
-				...form.value, 
-				process: processName, // 淇濈暀 process 瀛楁浠ュ吋瀹瑰悗绔�
-				qualityInspectParams: tableData.value
-			}
-      if (operationType.value === "add") {
-        qualityInspectAdd(data).then(res => {
-          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-          closeDia();
-        })
+    testStandardOptions.value = [];
+    tableData.value = [];
+    // 鍏堢‘淇濅骇鍝佹爲宸插姞杞斤紝鍚﹀垯缂栬緫鏃朵骇鍝�/瑙勬牸鍨嬪彿鏃犳硶鍙嶆樉
+    await getProductOptions();
+    if (operationType.value === "edit") {
+      // 鍏堜繚瀛� testStandardId锛岄伩鍏嶈娓呯┖
+      const savedTestStandardId = row.testStandardId;
+      // 鍏堣缃〃鍗曟暟鎹紝浣嗘殏鏃舵竻绌� testStandardId锛岀瓑閫夐」鍔犺浇瀹屾垚鍚庡啀璁剧疆
+      form.value = { ...row, 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: 1,
+          process: form.value.process || "",
+        };
+        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);
+                }
+              } else {
+                // 鍚﹀垯浣跨敤鏃х殑閫昏緫
+                getQualityInspectParamList(row.id);
+              }
+            }, 100);
+          });
+        });
       } else {
-        qualityInspectUpdate(data).then(res => {
-          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-          closeDia();
-        })
+        getQualityInspectParamList(row.id);
       }
     }
-  })
-}
-const getList = () => {
-	if (!currentProductId.value) {
-		testStandardOptions.value = [];
-		tableData.value = [];
-		return;
-	}
-	const processName = form.value.process || '';
-	let params = {
-		productId: currentProductId.value,
-		inspectType: 1,
-		process: processName
-	}
-	qualityInspectDetailByProductId(params).then(res => {
-		// 淇濆瓨涓嬫媺妗嗛�夐」鏁版嵁
-		testStandardOptions.value = res.data || [];
-		// 娓呯┖琛ㄦ牸鏁版嵁锛岀瓑寰呯敤鎴烽�夋嫨鎸囨爣
-		tableData.value = [];
-		// 娓呯┖鎸囨爣閫夋嫨
-		form.value.testStandardId = '';
-	})
-}
+    // 鏈�鍚庡啀鎵撳紑寮圭獥锛屽苟娓呯悊鏍¢獙鎬侊紝閬垮厤蹇呭~鎻愮ず闂儊
+    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 handleTestStandardChange = (testStandardId) => {
-	if (!testStandardId) {
-		tableData.value = [];
-		return;
-	}
-	tableLoading.value = true;
-	getQualityTestStandardParamByTestStandardId(testStandardId).then(res => {
-		tableData.value = res.data || [];
-	}).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 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 = 1;
+        const processName = form.value.process || "";
+        if (operationType.value === "add") {
+          tableData.value.forEach(item => {
+            delete item.id;
+          });
+        }
+        const data = {
+          ...form.value,
+          process: processName, // 淇濈暀 process 瀛楁浠ュ吋瀹瑰悗绔�
+          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;
+    }
+    const processName = form.value.process || "";
+    let params = {
+      productId: currentProductId.value,
+      inspectType: 1,
+      process: processName,
+    };
+    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 || [];
+      })
+      .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,
+  });
 </script>
 
 <style scoped>
-
 </style>
\ No newline at end of file
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index d65727d..c8890cc 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -87,6 +87,11 @@
           show-overflow-tooltip
         />
         <el-table-column
+          label="鍙戣揣鏁伴噺"
+          prop="totalQuantity"
+          show-overflow-tooltip
+        />
+        <el-table-column
           label="鍙戣揣杞︾墝鍙�"
           prop="shippingCarNumber"
           show-overflow-tooltip
@@ -105,7 +110,7 @@
           label="瀹℃牳鐘舵��"
           prop="status"
           align="center"
-          width="120"
+          width="100"
         >
           <template #default="scope">
             <el-tag :type="getApprovalStatusType(scope.row.status)">
@@ -113,6 +118,12 @@
             </el-tag>
           </template>
         </el-table-column>
+        <el-table-column
+          label="鍑哄簱鍗曞彿"
+          prop="outboundBatches"
+          show-overflow-tooltip
+          width="130"
+        />
         <el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
           <template #default="scope">
             <!--            <el-button-->
@@ -279,6 +290,9 @@
           <el-descriptions-item label="蹇�掑崟鍙�" :span="2">{{
             detailRow.expressNumber || "--"
           }}</el-descriptions-item>
+          <el-descriptions-item label="鍑哄簱鍗曞彿" :span="2">{{
+            detailRow.outboundBatches || "--"
+          }}</el-descriptions-item>
         </el-descriptions>
         <el-table
           :data="getDeliveryProductInfoList()"
diff --git a/src/views/salesManagement/returnOrder/components/detailDia.vue b/src/views/salesManagement/returnOrder/components/detailDia.vue
index 9ff4e89..ecc663f 100644
--- a/src/views/salesManagement/returnOrder/components/detailDia.vue
+++ b/src/views/salesManagement/returnOrder/components/detailDia.vue
@@ -10,8 +10,8 @@
         <el-descriptions-item label="瀹㈡埛鍚嶇О">{{ detail.customerName }}</el-descriptions-item>
         <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="椤圭洰鍚嶇О">{{ detail.projectName }}</el-descriptions-item>
+        <el-descriptions-item label="鍏宠仈鍙戣揣鍗曞彿">{{ detail.shippingNo }}</el-descriptions-item>
+        <!-- <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>
         <el-descriptions-item label="閫�璐у師鍥�">{{ detail.returnReason }}</el-descriptions-item>
@@ -20,7 +20,11 @@
 
       <div style="padding-top: 20px">
         <span class="descriptions">浜у搧鍒楄〃</span>
-        <PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData" />
+        <PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData">
+          <template #totalReturnNum="{ row }">
+            {{ calcAlreadyReturned(row) }}
+          </template>
+        </PIMTable>
       </div>
     </div>
     <template #footer>
@@ -41,12 +45,214 @@
 const tableData = ref([]);
 const availableProducts = ref([]);
 
+const sameKey = (a, b) => a != null && b != null && String(a) === String(b);
+
+/** 涓� formDia 涓�鑷达細涓や唤鍒楄〃鎸� id 鍚堝苟锛岄伩鍏嶅彧鍙� productDtoData 鏃剁己鍑哄簱鍗曞彿/鎵规/鏁伴噺 */
+const mergeShippingProductLists = (data) => {
+  const lists = [data?.shippingProductVoList, data?.productDtoData].filter(Array.isArray);
+  if (!lists.length) return [];
+  const map = new Map();
+  for (const list of lists) {
+    for (const p of list) {
+      if (p == null) continue;
+      const key = p.id != null ? String(p.id) : null;
+      if (!key) continue;
+      const prev = map.get(key);
+      map.set(key, prev ? { ...prev, ...p } : { ...p });
+    }
+  }
+  return Array.from(map.values());
+};
+
+const pickShippingLine = (normalized) => {
+  const pid = normalized?.returnSaleLedgerProductId ?? normalized?.id;
+  const sid = normalized?.stockOutRecordId ?? normalized?.shippingProductId;
+  const direct = availableProducts.value.find(
+    (p) =>
+      sameKey(p?.id, pid) ||
+      sameKey(p?.stockOutRecordId, pid) ||
+      sameKey(p?.id, sid) ||
+      sameKey(p?.stockOutRecordId, sid)
+  );
+  if (direct) return direct;
+  const pmid = normalized?.productModelId;
+  if (pmid == null || pmid === "") return undefined;
+  const candidates = availableProducts.value.filter((p) => sameKey(p?.productModelId, pmid));
+  if (!candidates.length) return undefined;
+  if (candidates.length === 1) return candidates[0];
+  const spec = String(normalized?.specificationModel ?? normalized?.model ?? "");
+  if (spec) {
+    const hit = candidates.find((p) => {
+      const ps = String(p?.specificationModel ?? p?.model ?? "");
+      return ps && ps === spec;
+    });
+    if (hit) return hit;
+  }
+  return candidates[0];
+};
+
+const isEmptyText = (v) => v === "" || v == null || v === undefined;
+
+const firstFiniteNumber = (...vals) => {
+  for (const v of vals) {
+    if (v === "" || v == null || v === undefined) continue;
+    const n = Number(v);
+    if (Number.isFinite(n)) return n;
+  }
+  return undefined;
+};
+
+const firstNonEmptyText = (...vals) => {
+  const hit = vals.find((v) => !isEmptyText(v));
+  return hit === undefined ? "" : hit;
+};
+
+const calcAlreadyReturned = (row) => {
+  const total = Number(row?.stockOutNum ?? row?.totalQuantity ?? row?.totalReturnNum ?? 0);
+  const un = Number(row?.unQuantity ?? 0);
+  if (!Number.isFinite(total) || !Number.isFinite(un)) return 0;
+  return Math.max(total - un, 0);
+};
+
+/** 璇︽儏琛ㄧ敤 productName / model锛涘悎骞舵椂鍕胯绌轰覆鐩栨帀鍑哄簱琛屽瓧娈� */
+const mergeDetailProductRow = (product, normalized) => {
+  const row = { ...product, ...normalized };
+  row.outboundBatches = firstNonEmptyText(
+    row.outboundBatches,
+    product?.outboundBatches,
+    product?.shippingNo,
+    product?.outboundNo,
+    normalized?.outboundBatches,
+    normalized?.outboundNo,
+    normalized?.shippingNo
+  );
+  row.batchNo = firstNonEmptyText(
+    row.batchNo,
+    product?.batchNo,
+    product?.batchNumber,
+    product?.lotNo,
+    product?.batchCode,
+    product?.shippingBatchNo,
+    normalized?.batchNo,
+    normalized?.batchNumber,
+    normalized?.lotNo,
+    normalized?.shippingBatchNo
+  );
+  const stock = firstFiniteNumber(
+    row.stockOutNum,
+    product?.stockOutNum,
+    product?.totalQuantity,
+    product?.shippingQuantity,
+    product?.deliveryQuantity,
+    product?.quantity,
+    product?.outQuantity,
+    normalized?.stockOutNum,
+    normalized?.totalQuantity,
+    normalized?.shippingQuantity,
+    normalized?.deliveryQuantity
+  );
+  if (stock !== undefined) row.stockOutNum = stock;
+  const un = firstFiniteNumber(
+    row.unQuantity,
+    product?.unQuantity,
+    product?.remainingQuantity,
+    product?.noReturnQuantity,
+    product?.canReturnQuantity,
+    product?.availableReturnNum,
+    normalized?.unQuantity,
+    normalized?.remainingQuantity,
+    normalized?.noReturnQuantity,
+    normalized?.canReturnQuantity
+  );
+  if (un !== undefined) row.unQuantity = un;
+  else {
+    const s = Number(row.stockOutNum);
+    const ret = Number(row.totalReturnNum ?? 0);
+    if (Number.isFinite(s) && s >= 0 && Number.isFinite(ret) && ret >= 0) {
+      row.unQuantity = Math.max(0, s - ret);
+    }
+  }
+  const returned = firstFiniteNumber(
+    row.totalReturnNum,
+    product?.totalReturnNum,
+    product?.totalReturnedNum,
+    normalized?.totalReturnNum,
+    normalized?.totalReturnedNum
+  );
+  if (returned !== undefined) row.totalReturnNum = returned;
+  else if (isEmptyText(row.totalReturnNum)) row.totalReturnNum = 0;
+  if (isEmptyText(row.unit)) {
+    row.unit = firstNonEmptyText(product?.unit, normalized?.unit);
+  }
+  row.productName = firstNonEmptyText(
+    row.productName,
+    normalized?.productName,
+    normalized?.productCategory,
+    product?.productName,
+    product?.productCategory
+  );
+  row.model = firstNonEmptyText(
+    row.model,
+    normalized?.model,
+    normalized?.specificationModel,
+    product?.model,
+    product?.specificationModel
+  );
+  return row;
+};
+
+const normalizeDetailRow = (raw) => {
+  const ledgerId =
+    raw?.returnSaleLedgerProductId ??
+    raw?.saleLedgerProductId ??
+    raw?.stockOutRecordId ??
+    raw?.shippingProductId;
+  const productId = ledgerId ?? raw?.id;
+  const num = Number(raw?.num ?? raw?.returnQuantity ?? 0);
+  return {
+    ...raw,
+    id: productId,
+    returnSaleLedgerProductId: productId,
+    productModelId: raw?.productModelId,
+    stockOutRecordId: raw?.stockOutRecordId,
+    shippingProductId: raw?.shippingProductId,
+    productName: raw?.productName ?? raw?.productCategory ?? raw?.productTypeName ?? "",
+    model: raw?.model ?? raw?.specificationModel ?? raw?.specModel ?? "",
+    outboundBatches: raw?.outboundBatches ?? raw?.outboundNo ?? raw?.shippingNo,
+    batchNo:
+      raw?.batchNo ??
+      raw?.batchNumber ??
+      raw?.lotNo ??
+      raw?.batchCode ??
+      raw?.shippingBatchNo,
+    stockOutNum:
+      raw?.stockOutNum ??
+      raw?.totalQuantity ??
+      raw?.shippingQuantity ??
+      raw?.deliveryQuantity ??
+      raw?.quantity,
+    totalReturnNum: raw?.totalReturnNum ?? raw?.totalReturnedNum,
+    unQuantity:
+      raw?.unQuantity ??
+      raw?.remainingQuantity ??
+      raw?.noReturnQuantity ??
+      raw?.canReturnQuantity,
+    returnQuantity: Number.isFinite(num) ? num : 0,
+    price: Number(raw?.taxInclusiveUnitPrice ?? raw?.price ?? 0),
+    amount: Number(raw?.amount ?? 0).toFixed(2),
+    isQuality: raw?.isQuality ?? 2,
+    remark: raw?.remark ?? "",
+  };
+};
+
 const tableColumn = [
-  {align: "center", label: "浜у搧澶х被", prop: "productCategory"},
-  {align: "center", label: "瑙勬牸鍨嬪彿", prop: "specificationModel"},
+  {align: "center", label: "鍑哄簱鍗曞彿", prop: "outboundBatches"},
+  {align: "center", label: "鎵规鍙�", prop: "batchNo"},
+  {align: "center", label: "浜у搧澶х被", prop: "productName"},
+  {align: "center", label: "瑙勬牸鍨嬪彿", prop: "model"},
   {align: "center", label: "鍗曚綅", prop: "unit", width: 80},
-  {align: "center", label: "鎬绘暟閲�", prop: "quantity", width: 120},
-  {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120},
+  {align: "center", label: "鎬绘暟閲�", prop: "stockOutNum", 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", width: 120},
   {align: "center", label: "閫�璐т骇鍝佸崟浠�", prop: "price", width: 120},
@@ -82,30 +288,30 @@
     if (detail.value.shippingId) {
       const productRes = await returnManagementGetByShippingId({ shippingId: detail.value.shippingId });
       if (productRes.code === 200) {
-        availableProducts.value = productRes.data.productDtoData || [];
+        availableProducts.value = mergeShippingProductLists(productRes.data);
       }
     }
-    
+
     const list =
       detail.value?.returnSaleProducts ||
-        detail.value?.returnSaleProductList ||
-        detail.value?.returnSaleProductDtoData ||
-        [];
-    
-    tableData.value = Array.isArray(list) ? list.map(raw => {
-      const productId = raw?.returnSaleLedgerProductId ?? raw?.saleLedgerProductId ?? raw?.id;
-      const product = availableProducts.value.find((p) => p.id === productId);
-      const normalized = {
-        ...raw,
-        id: productId,
-        returnQuantity: Number(raw?.num ?? raw?.returnQuantity ?? 0),
-        price: Number(raw?.taxInclusiveUnitPrice ?? raw?.price ?? 0),
-        amount: Number(raw?.amount ?? 0).toFixed(2),
-        isQuality: raw?.isQuality ?? 2,
-        remark: raw?.remark ?? "",
-      };
-      return product ? { ...product, ...normalized } : normalized;
-    }) : [];
+      detail.value?.returnSaleProductList ||
+      detail.value?.returnSaleProductDtoData ||
+      [];
+
+    tableData.value = Array.isArray(list)
+      ? list.map((raw) => {
+          const normalized = normalizeDetailRow(raw);
+          const product = pickShippingLine(normalized);
+          return product ? mergeDetailProductRow(product, normalized) : normalized;
+        })
+      : [];
+
+    const headerShipNo = detail.value?.shippingNo;
+    if (headerShipNo && Array.isArray(tableData.value) && tableData.value.length) {
+      tableData.value = tableData.value.map((r) =>
+        isEmptyText(r.outboundBatches) ? { ...r, outboundBatches: headerShipNo } : r
+      );
+    }
   } catch (e) {
     console.error("Failed to load detail", e);
   } finally {
diff --git a/src/views/salesManagement/returnOrder/components/formDia.vue b/src/views/salesManagement/returnOrder/components/formDia.vue
index 0f27e98..6a6d756 100644
--- a/src/views/salesManagement/returnOrder/components/formDia.vue
+++ b/src/views/salesManagement/returnOrder/components/formDia.vue
@@ -32,7 +32,7 @@
               </el-form-item>
             </el-col>
             <el-col :span="4">
-              <el-form-item label="鍏宠仈鍑哄簱鍗曞彿锛�" prop="shippingId">
+              <el-form-item label="鍏宠仈鍙戣揣鍗曞彿锛�" prop="shippingId">
                 <el-select v-model="form.shippingId" filterable placeholder="璇烽�夋嫨鍑哄簱鍗曞彿" @change="outboundNoChange">
                   <el-option
                     v-for="item in outboundOptions"
@@ -82,6 +82,9 @@
             <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" 
@@ -122,7 +125,7 @@
                 placeholder="璇疯緭鍏�" 
               />
             </template>
-            <template #action="{ row, index }">
+            <template #action="{ index }">
               <el-button type="danger" link @click="deleteRow(index)">鍒犻櫎</el-button>
             </template>
           </PIMTable>
@@ -145,10 +148,12 @@
         row-key="id"
       >
         <el-table-column align="center" type="selection" width="55" />
+        <el-table-column align="center" prop="outboundBatches" label="鍑哄簱鍗曞彿" />
+        <el-table-column align="center" prop="batchNo" label="鎵规鍙�" />
         <el-table-column align="center" prop="productCategory" label="浜у搧澶х被" />
         <el-table-column align="center" prop="specificationModel" label="瑙勬牸鍨嬪彿" />
         <el-table-column align="center" prop="unit" label="鍗曚綅" />
-        <el-table-column align="center" prop="quantity" label="鎬绘暟閲�" />
+        <el-table-column align="center" prop="stockOutNum" label="鎬绘暟閲�" />
         <el-table-column align="center" prop="unQuantity" label="鏈��璐ф暟閲�" />
         <el-table-column align="center" label="宸查��璐ф暟閲�">
           <template #default="{ row }">{{ calcAlreadyReturned(row) }}</template>
@@ -208,18 +213,20 @@
 const { form, rules } = toRefs(data);
 
 const calcAlreadyReturned = (row) => {
-  const total = Number(row?.quantity ?? row?.totalQuantity ?? row?.totalReturnNum ?? 0);
+  const total = Number(row?.stockOutNum ?? row?.totalQuantity ?? row?.totalReturnNum ?? 0);
   const un = Number(row?.unQuantity ?? 0);
   if (!Number.isFinite(total) || !Number.isFinite(un)) return 0;
   return Math.max(total - un, 0);
 };
 
 const tableColumn = ref([
+  {align: "center", label: "鍑哄簱鍗曞彿", prop: "outboundBatches" },
+  {align: "center", label: "鎵规鍙�", prop: "batchNo" },
   {align: "center", label: "浜у搧澶х被", prop: "productCategory" },
   {align: "center", label: "瑙勬牸鍨嬪彿", prop: "specificationModel" },
   {align: "center", label: "鍗曚綅", prop: "unit", width: 80 },
-  {align: "center", label: "鎬绘暟閲�", prop: "quantity", width: 120 },
-  {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120 },
+  {align: "center", label: "鎬绘暟閲�", prop: "stockOutNum", 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 },
@@ -238,8 +245,164 @@
   tableData.value.splice(index, 1);
 };
 
+const sameKey = (a, b) => a != null && b != null && String(a) === String(b);
+
+/** 鎺ュ彛鍙兘鎷嗘垚 shippingProductVoList / productDtoData 涓や唤锛屽彧鍙栧叾涓�浼氱己鎵规銆佹暟閲忕瓑瀛楁 */
+const mergeShippingProductLists = (data) => {
+  const lists = [data?.shippingProductVoList, data?.productDtoData].filter(Array.isArray);
+  if (!lists.length) return [];
+  const map = new Map();
+  for (const list of lists) {
+    for (const p of list) {
+      if (p == null) continue;
+      const key = p.id != null ? String(p.id) : null;
+      if (!key) continue;
+      const prev = map.get(key);
+      map.set(key, prev ? { ...prev, ...p } : { ...p });
+    }
+  }
+  return Array.from(map.values());
+};
+
+const pickShippingLine = (normalized) => {
+  const pid = normalized?.returnSaleLedgerProductId ?? normalized?.id;
+  const sid = normalized?.stockOutRecordId ?? normalized?.shippingProductId;
+  const direct = availableProducts.value.find(
+    (p) =>
+      sameKey(p?.id, pid) ||
+      sameKey(p?.stockOutRecordId, pid) ||
+      sameKey(p?.id, sid) ||
+      sameKey(p?.stockOutRecordId, sid)
+  );
+  if (direct) return direct;
+  const pmid = normalized?.productModelId;
+  if (pmid == null || pmid === "") return undefined;
+  const candidates = availableProducts.value.filter((p) => sameKey(p?.productModelId, pmid));
+  if (!candidates.length) return undefined;
+  if (candidates.length === 1) return candidates[0];
+  const spec = String(normalized?.specificationModel ?? normalized?.model ?? "");
+  if (spec) {
+    const hit = candidates.find((p) => {
+      const ps = String(p?.specificationModel ?? p?.model ?? "");
+      return ps && ps === spec;
+    });
+    if (hit) return hit;
+  }
+  return candidates[0];
+};
+
+const isEmptyText = (v) => v === "" || v == null || v === undefined;
+
+const firstFiniteNumber = (...vals) => {
+  for (const v of vals) {
+    if (v === "" || v == null || v === undefined) continue;
+    const n = Number(v);
+    if (Number.isFinite(n)) return n;
+  }
+  return undefined;
+};
+
+const firstNonEmptyText = (...vals) => {
+  const hit = vals.find((v) => !isEmptyText(v));
+  return hit === undefined ? "" : hit;
+};
+
+/** 璇︽儏鎺ュ彛瀛楁甯镐笉鍏紱{...product,...normalized} 浼氳 normalized 閲岀殑绌轰覆鐩栨帀鍑哄簱琛屼笂鐨勫睍绀哄瓧娈� */
+const mergeShippingLineWithDetail = (product, normalized) => {
+  const row = { ...product, ...normalized };
+  row.outboundBatches = firstNonEmptyText(
+    row.outboundBatches,
+    product?.outboundBatches,
+    product?.shippingNo,
+    product?.outboundNo,
+    normalized?.outboundBatches,
+    normalized?.outboundNo,
+    normalized?.shippingNo
+  );
+  row.batchNo = firstNonEmptyText(
+    row.batchNo,
+    product?.batchNo,
+    product?.batchNumber,
+    product?.lotNo,
+    product?.batchCode,
+    product?.shippingBatchNo,
+    normalized?.batchNo,
+    normalized?.batchNumber,
+    normalized?.lotNo,
+    normalized?.shippingBatchNo
+  );
+  const stock = firstFiniteNumber(
+    row.stockOutNum,
+    product?.stockOutNum,
+    product?.totalQuantity,
+    product?.shippingQuantity,
+    product?.deliveryQuantity,
+    product?.quantity,
+    product?.outQuantity,
+    normalized?.stockOutNum,
+    normalized?.totalQuantity,
+    normalized?.shippingQuantity,
+    normalized?.deliveryQuantity
+  );
+  if (stock !== undefined) row.stockOutNum = stock;
+  const un = firstFiniteNumber(
+    row.unQuantity,
+    product?.unQuantity,
+    product?.remainingQuantity,
+    product?.noReturnQuantity,
+    product?.canReturnQuantity,
+    product?.availableReturnNum,
+    normalized?.unQuantity,
+    normalized?.remainingQuantity,
+    normalized?.noReturnQuantity,
+    normalized?.canReturnQuantity
+  );
+  if (un !== undefined) row.unQuantity = un;
+  else {
+    const s = Number(row.stockOutNum);
+    const ret = Number(row.totalReturnNum ?? 0);
+    if (Number.isFinite(s) && s >= 0 && Number.isFinite(ret) && ret >= 0) {
+      row.unQuantity = Math.max(0, s - ret);
+    }
+  }
+  const returned = firstFiniteNumber(
+    row.totalReturnNum,
+    product?.totalReturnNum,
+    product?.totalReturnedNum,
+    normalized?.totalReturnNum,
+    normalized?.totalReturnedNum
+  );
+  if (returned !== undefined) row.totalReturnNum = returned;
+  else if (isEmptyText(row.totalReturnNum)) row.totalReturnNum = 0;
+  if (isEmptyText(row.unit)) {
+    row.unit = firstNonEmptyText(product?.unit, normalized?.unit);
+  }
+  if (isEmptyText(row.productCategory)) {
+    row.productCategory = firstNonEmptyText(
+      normalized?.productCategory,
+      normalized?.productName,
+      product?.productCategory,
+      product?.productName
+    );
+  }
+  if (isEmptyText(row.specificationModel)) {
+    row.specificationModel = firstNonEmptyText(
+      normalized?.specificationModel,
+      normalized?.model,
+      product?.specificationModel,
+      product?.model
+    );
+  }
+  return row;
+};
+
 const normalizeDetailRow = (raw) => {
-  const productId = raw?.returnSaleLedgerProductId ?? raw?.saleLedgerProductId ?? raw?.id;
+  const ledgerId =
+    raw?.returnSaleLedgerProductId ??
+    raw?.saleLedgerProductId ??
+    raw?.stockOutRecordId ??
+    raw?.shippingProductId;
+  const productId = ledgerId ?? raw?.id;
   const returnSaleProductId = raw?.returnSaleProductId ?? raw?.id;
   const num = Number(raw?.num ?? raw?.returnQuantity ?? 0);
   return {
@@ -248,6 +411,29 @@
     returnSaleProductId,
     returnSaleLedgerProductId: productId,
     productModelId: raw?.productModelId,
+    stockOutRecordId: raw?.stockOutRecordId,
+    shippingProductId: raw?.shippingProductId,
+    productCategory: raw?.productCategory ?? raw?.productName ?? raw?.productTypeName ?? "",
+    specificationModel: raw?.specificationModel ?? raw?.model ?? raw?.specModel ?? "",
+    outboundBatches: raw?.outboundBatches ?? raw?.outboundNo ?? raw?.shippingNo,
+    batchNo:
+      raw?.batchNo ??
+      raw?.batchNumber ??
+      raw?.lotNo ??
+      raw?.batchCode ??
+      raw?.shippingBatchNo,
+    stockOutNum:
+      raw?.stockOutNum ??
+      raw?.totalQuantity ??
+      raw?.shippingQuantity ??
+      raw?.deliveryQuantity ??
+      raw?.quantity,
+    totalReturnNum: raw?.totalReturnNum ?? raw?.totalReturnedNum,
+    unQuantity:
+      raw?.unQuantity ??
+      raw?.remainingQuantity ??
+      raw?.noReturnQuantity ??
+      raw?.canReturnQuantity,
     num,
     returnQuantity: Number.isFinite(num) ? num : 0,
     price: Number(raw?.taxInclusiveUnitPrice ?? raw?.price ?? 0),
@@ -259,7 +445,6 @@
 
 const setFormForEdit = async (row) => {
   const res = await returnManagementGetById({ returnManagementId: row?.id });
-  console.log("res", res);
   const detail = res?.data ?? res ?? {};
 
   Object.assign(form.value, detail);
@@ -281,11 +466,18 @@
   tableData.value = Array.isArray(list)
     ? list.map((raw) => {
         const normalized = normalizeDetailRow(raw);
-        const product = availableProducts.value.find((p) => p.id === normalized.id);
-        return product ? { ...product, ...normalized } : normalized;
+        const product = pickShippingLine(normalized);
+        return product ? mergeShippingLineWithDetail(product, normalized) : normalized;
       })
     : [];
-  
+
+  const headerShipNo = detail?.shippingNo ?? form.value?.shippingNo;
+  if (headerShipNo && Array.isArray(tableData.value) && tableData.value.length) {
+    tableData.value = tableData.value.map((r) =>
+      isEmptyText(r.outboundBatches) ? { ...r, outboundBatches: headerShipNo } : r
+    );
+  }
+
   calculateTotalRefund();
 };
 
@@ -320,7 +512,7 @@
   proxy.$refs["formRef"].validate(valid => {
     if (!valid) return;
     const returnSaleProducts = (tableData.value || []).map(el => ({
-      returnSaleLedgerProductId: el.returnSaleLedgerProductId ?? el.id,
+      stockOutRecordId: el.returnSaleLedgerProductId ?? el.id,
       productModelId: el.productModelId,
       unit: el.unit,
       num: Number(el.num ?? el.returnQuantity ?? 0),
@@ -419,8 +611,7 @@
     // If backend returns project info, set it
     if (res.data.projectId) form.value.projectId = res.data.projectId;
     
-    // Store available products for selection
-    availableProducts.value = res.data.productDtoData || [];
+    availableProducts.value = mergeShippingProductLists(res.data);
     if (clearTable) tableData.value = [];
   }
 };
@@ -457,9 +648,9 @@
 };
 
 const calculateRowAmount = (row) => {
-  const quantity = Number(row.returnQuantity || 0);
+  const stockOutNum = Number(row.returnQuantity || 0);
   const price = Number(row.price || 0);
-  row.amount = (quantity * price).toFixed(2);
+  row.amount = (stockOutNum * price).toFixed(2);
 };
 
 const calculateTotalRefund = () => {
@@ -511,10 +702,11 @@
         amount: "0.00",
         isQuality: 2,
         remark: "",
+        productCategory: product.productCategory ?? product.productName ?? "",
         productName: product.productName,
-        specificationModel: product.specificationModel,
+        specificationModel: product.specificationModel ?? product.model ?? "",
         unit: product.unit,
-        quantity: product.quantity,
+        stockOutNum: product.stockOutNum,
         totalReturnNum: product.totalReturnNum,
         unQuantity: product.unQuantity
       });
diff --git a/src/views/salesManagement/returnOrder/index.vue b/src/views/salesManagement/returnOrder/index.vue
index d41d4bf..0a8257b 100644
--- a/src/views/salesManagement/returnOrder/index.vue
+++ b/src/views/salesManagement/returnOrder/index.vue
@@ -11,8 +11,8 @@
 				<el-form-item label="閿�鍞崟鍙�">
 					<el-input v-model="searchForm.salesContractNo" placeholder="閿�鍞崟鍙�" clearable />
 				</el-form-item>
-				<el-form-item label="鍏宠仈鍑哄簱鍗曞彿">
-					<el-input v-model="searchForm.shippingNo" placeholder="鍏宠仈鍑哄簱鍗曞彿" clearable />
+				<el-form-item label="鍏宠仈鍙戣揣鍗曞彿">
+					<el-input v-model="searchForm.shippingNo" placeholder="鍏宠仈鍙戣揣鍗曞彿" clearable />
 				</el-form-item>
 				<el-form-item>
 					<el-button type="primary" @click="handleQuery">鎼滅储</el-button>
@@ -112,22 +112,22 @@
 ]);
 
 const defaultColumns = [
-  { label: "閫�璐у崟鍙�", prop: "returnNo", width: 160 },
-  { label: "鍗曟嵁鐘舵��", prop: "status", width: 90, dataType: "slot", slot: "status" },
-  { label: "鍒跺崟鏃堕棿", prop: "makeTime", width: 170 },
-  { label: "瀹㈡埛鍚嶇О", prop: "customerName", width: 220 },
-  { label: "閿�鍞崟鍙�", prop: "salesContractNo", width: 160 },
-  { label: "涓氬姟鍛�", prop: "salesman", width: 120 },
-  { label: "鍏宠仈鍑哄簱鍗曞彿", prop: "shippingNo", width: 170 },
-  { label: "椤圭洰鍚嶇О", prop: "projectName", width: 180 },
-  { label: "鍒跺崟浜�", prop: "maker", width: 120 },
+  { label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: 160 },
+  { label: "鍗曟嵁鐘舵��", prop: "status", minWidth: 90, dataType: "slot", slot: "status" },
+  { 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: "projectName", minWidth: 180 },
+  { label: "鍒跺崟浜�", prop: "maker", minWidth: 120 },
   {
     label: "鎿嶄綔",
     prop: "operation",
     dataType: "action",
     align: "center",
     fixed: "right",
-    width: 240,
+    minWidth: 240,
     operation: [
       { name: "缂栬緫", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => openForm("edit", row) },
       { name: "閫�娆惧鐞�", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => handleRowHandle(row) },
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 4e2d84e..fc2851f 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -2594,6 +2594,7 @@
       瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
       瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
       宸插彂璐�: "宸插彂璐�",
+      閮ㄥ垎鍙戣揣: "閮ㄥ垎鍙戣揣",
     };
     return statusTextMap[statusStr] || "寰呭彂璐�";
   };
@@ -2625,6 +2626,7 @@
       瀹℃牳鎷掔粷: "danger",
       瀹℃牳閫氳繃: "success",
       宸插彂璐�: "success",
+      閮ㄥ垎鍙戣揣: "warning",
     };
     return typeTextMap[statusStr] || "info";
   };

--
Gitblit v1.9.3