Jelajahi Sumber

perf(departmentCostCalc): 优化抽屉内报表数据表格渲染性能

- 新增 VirtualRow 基于 IntersectionObserver 实现长列表不可见节点的 DOM 懒渲染
- 抽屉表格改用 defaultExpandedRowKeys 非受控展开,解决外层重新渲染引起的卡顿
- 补充树形节点兜底唯一 ID 逻辑,修复展开一列所有无 ID 列联动展开的 bug
- 缓存表格 onCell / onRow 配置与 scroll 对象避免每次重新生成引发的全量比对
- 执行全局代码格式化
code4eat 2 minggu lalu
induk
melakukan
923af92a15
100 mengubah file dengan 11597 tambahan dan 10066 penghapusan
  1. 4 3
      .VSCodeCounter/2024-08-30_09-54-22/details.md
  2. 4 3
      .VSCodeCounter/2024-08-30_09-54-22/diff-details.md
  3. 6 4
      .VSCodeCounter/2024-08-30_09-54-22/diff.md
  4. 0 0
      .VSCodeCounter/2024-08-30_09-54-22/results.json
  5. 17 15
      .VSCodeCounter/2024-08-30_09-54-22/results.md
  6. 4 3
      .VSCodeCounter/2024-11-05_10-42-46/details.md
  7. 4 3
      .VSCodeCounter/2024-11-05_10-42-46/diff-details.md
  8. 10 8
      .VSCodeCounter/2024-11-05_10-42-46/diff.md
  9. 0 0
      .VSCodeCounter/2024-11-05_10-42-46/results.json
  10. 17 15
      .VSCodeCounter/2024-11-05_10-42-46/results.md
  11. 2 7
      .lintstagedrc
  12. 74 54
      .umirc.ts
  13. 3 3
      .vscode/settings.json
  14. 0 3
      config/proxy.ts
  15. 45 50
      mock/home.ts
  16. 158 170
      mock/monthlyData.ts
  17. 164 181
      mock/monthlyInfo.ts
  18. 41 44
      mock/monthlySet.ts
  19. 1 1
      package.json
  20. 25 37
      src/access.ts
  21. 220 135
      src/app.tsx
  22. 4 1
      src/authWrapper.tsx
  23. 3 6
      src/components/KCIMDrawerForm/index.tsx
  24. 15 18
      src/components/KCIMDrawerForm/style.less
  25. 293 246
      src/components/KCIMLeftList/index.tsx
  26. 128 127
      src/components/KCIMLeftList/style.less
  27. 24 29
      src/components/KCIMModalForm/index.tsx
  28. 51 37
      src/components/KCIMPageContainer/index.tsx
  29. 109 110
      src/components/KCIMPageContainer/style.less
  30. 71 0
      src/components/KCIMTable/VirtualRow.tsx
  31. 48 51
      src/components/KCIMTable/index.tsx
  32. 204 197
      src/components/KCIMTable/style.less
  33. 194 182
      src/components/KCIMTableSelector/index.tsx
  34. 28 30
      src/components/KCIMTableSelector/style.less
  35. 59 53
      src/components/KCIMUpload/index.tsx
  36. 5 6
      src/components/KCIMUpload/style.less
  37. 39 15
      src/components/ProgressModal/index.tsx
  38. 19 25
      src/components/ProgressModal/service.ts
  39. 55 47
      src/components/ResizableContainer/index.tsx
  40. 17 22
      src/components/ResizableContainer/style.less
  41. 144 126
      src/components/SQLEditor/index.tsx
  42. 53 52
      src/components/SQLEditor/style.less
  43. 64 25
      src/components/VirtualTableBody.tsx
  44. 8 8
      src/constant.ts
  45. 521 531
      src/global.less
  46. 25 25
      src/menuIcons.js
  47. 6 5
      src/pages/Home/index.tsx
  48. 28 41
      src/pages/Home/service.ts
  49. 11 11
      src/pages/Home/style.less
  50. 252 220
      src/pages/baseInfoMana/checkGroupMana/index.tsx
  51. 36 49
      src/pages/baseInfoMana/checkGroupMana/service.ts
  52. 3 5
      src/pages/baseInfoMana/checkGroupMana/style.less
  53. 124 110
      src/pages/baseInfoMana/checkGroupMana/tableSelector.tsx
  54. 336 272
      src/pages/baseInfoMana/empMana/index.tsx
  55. 47 54
      src/pages/baseInfoMana/empMana/service.ts
  56. 26 33
      src/pages/baseInfoMana/empMana/style.less
  57. 263 230
      src/pages/baseInfoMana/empMana/tableSelector.tsx
  58. 119 108
      src/pages/baseInfoMana/empMana/transform.tsx
  59. 255 227
      src/pages/baseInfoMana/unitMana/index.tsx
  60. 13 25
      src/pages/baseInfoMana/unitMana/service.ts
  61. 26 31
      src/pages/baseInfoMana/unitMana/style.less
  62. 199 183
      src/pages/baseInfoMana/unitMana/tableSelector.tsx
  63. 490 425
      src/pages/baseSetting/accountingAccountSet/accountingSubMana/index.tsx
  64. 18 39
      src/pages/baseSetting/accountingAccountSet/accountingSubMana/service.ts
  65. 12 13
      src/pages/baseSetting/accountingAccountSet/accountingSubMana/style.less
  66. 311 264
      src/pages/baseSetting/accountingAccountSet/accountingSubMap/index.tsx
  67. 9 29
      src/pages/baseSetting/accountingAccountSet/accountingSubMap/service.ts
  68. 12 13
      src/pages/baseSetting/accountingAccountSet/accountingSubMap/style.less
  69. 489 397
      src/pages/baseSetting/accountingAccountSet/chargeItemMap/index.tsx
  70. 23 32
      src/pages/baseSetting/accountingAccountSet/chargeItemMap/service.ts
  71. 29 32
      src/pages/baseSetting/accountingAccountSet/chargeItemMap/style.less
  72. 217 187
      src/pages/baseSetting/accountingAccountSet/chargeItemMap/tableSelector.tsx
  73. 284 250
      src/pages/baseSetting/accountingAccountSet/costIncomeProjectMana/index.tsx
  74. 16 37
      src/pages/baseSetting/accountingAccountSet/costIncomeProjectMana/service.ts
  75. 9 10
      src/pages/baseSetting/accountingAccountSet/costIncomeProjectMana/style.less
  76. 327 270
      src/pages/baseSetting/costAllocationSet/allocationLevelSet/index.tsx
  77. 16 36
      src/pages/baseSetting/costAllocationSet/allocationLevelSet/service.ts
  78. 12 13
      src/pages/baseSetting/costAllocationSet/allocationLevelSet/style.less
  79. 211 188
      src/pages/baseSetting/costAllocationSet/allocationParamsMap/editTableModal.tsx
  80. 477 417
      src/pages/baseSetting/costAllocationSet/allocationParamsMap/index.tsx
  81. 31 63
      src/pages/baseSetting/costAllocationSet/allocationParamsMap/service.ts
  82. 45 49
      src/pages/baseSetting/costAllocationSet/allocationParamsMap/style.less
  83. 202 172
      src/pages/baseSetting/costAllocationSet/allocationParamsMap/tableSelector.tsx
  84. 503 392
      src/pages/baseSetting/costAllocationSet/costAllocationParamsDeal/index.tsx
  85. 26 43
      src/pages/baseSetting/costAllocationSet/costAllocationParamsDeal/service.ts
  86. 9 11
      src/pages/baseSetting/costAllocationSet/costAllocationParamsDeal/style.less
  87. 341 282
      src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/index.tsx
  88. 27 45
      src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/service.ts
  89. 12 13
      src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/style.less
  90. 265 220
      src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/transform.tsx
  91. 360 326
      src/pages/baseSetting/costAllocationSet/idleCostSetting/index.tsx
  92. 29 50
      src/pages/baseSetting/costAllocationSet/idleCostSetting/service.ts
  93. 12 13
      src/pages/baseSetting/costAllocationSet/idleCostSetting/style.less
  94. 376 327
      src/pages/baseSetting/costAllocationSet/revenueImputationSet/index.tsx
  95. 21 42
      src/pages/baseSetting/costAllocationSet/revenueImputationSet/service.ts
  96. 5 6
      src/pages/baseSetting/costAllocationSet/revenueImputationSet/style.less
  97. 150 123
      src/pages/baseSetting/costAllocationSet/revenueImputationSet/transform.tsx
  98. 1399 813
      src/pages/baseSetting/otherItemSet/departmentCostCalc/index.tsx
  99. 49 63
      src/pages/baseSetting/otherItemSet/departmentCostCalc/service.ts
  100. 49 49
      src/pages/baseSetting/otherItemSet/departmentCostCalc/style.less

+ 4 - 3
.VSCodeCounter/2024-08-30_09-54-22/details.md

@@ -4,13 +4,14 @@ Date : 2024-08-30 09:54:22
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 244 files,  42131 codes, 2729 comments, 8303 blanks, all 53163 lines
+Total : 244 files, 42131 codes, 2729 comments, 8303 blanks, all 53163 lines
 
 [Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
 
 ## Files
+
 | filename | language | code | comment | blank | total |
-| :--- | :--- | ---: | ---: | ---: | ---: |
+| :-- | :-- | --: | --: | --: | --: |
 | [.eslintrc.js](/.eslintrc.js) | JavaScript | 3 | 0 | 1 | 4 |
 | [.prettierignore](/.prettierignore) | Ignore | 3 | 0 | 1 | 4 |
 | [.prettierrc](/.prettierrc) | JSON | 8 | 0 | 1 | 9 |
@@ -256,4 +257,4 @@ Total : 244 files,  42131 codes, 2729 comments, 8303 blanks, all 53163 lines
 | [typings.d.ts](/typings.d.ts) | TypeScript | 8 | 8 | 2 | 18 |
 | [yarn-error.log](/yarn-error.log) | Log | 8,469 | 0 | 1,293 | 9,762 |
 
-[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
+[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)

+ 4 - 3
.VSCodeCounter/2024-08-30_09-54-22/diff-details.md

@@ -4,12 +4,13 @@ Date : 2024-08-30 09:54:22
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 0 files,  0 codes, 0 comments, 0 blanks, all 0 lines
+Total : 0 files, 0 codes, 0 comments, 0 blanks, all 0 lines
 
 [Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
 
 ## Files
+
 | filename | language | code | comment | blank | total |
-| :--- | :--- | ---: | ---: | ---: | ---: |
+| :------- | :------- | ---: | ------: | ----: | ----: |
 
-[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
+[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details

+ 6 - 4
.VSCodeCounter/2024-08-30_09-54-22/diff.md

@@ -4,16 +4,18 @@ Date : 2024-08-30 09:54:22
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 0 files,  0 codes, 0 comments, 0 blanks, all 0 lines
+Total : 0 files, 0 codes, 0 comments, 0 blanks, all 0 lines
 
 [Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
 
 ## Languages
+
 | language | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
+| :------- | ----: | ---: | ------: | ----: | ----: |
 
 ## Directories
+
 | path | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
+| :--- | ----: | ---: | ------: | ----: | ----: |
 
-[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
+[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)

File diff ditekan karena terlalu besar
+ 0 - 0
.VSCodeCounter/2024-08-30_09-54-22/results.json


+ 17 - 15
.VSCodeCounter/2024-08-30_09-54-22/results.md

@@ -4,27 +4,29 @@ Date : 2024-08-30 09:54:22
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 244 files,  42131 codes, 2729 comments, 8303 blanks, all 53163 lines
+Total : 244 files, 42131 codes, 2729 comments, 8303 blanks, all 53163 lines
 
 Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
 
 ## Languages
-| language | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
-| TypeScript JSX | 92 | 22,780 | 1,576 | 3,993 | 28,349 |
-| Log | 1 | 8,469 | 0 | 1,293 | 9,762 |
-| Less | 63 | 5,743 | 103 | 1,001 | 6,847 |
-| TypeScript | 69 | 4,716 | 892 | 1,833 | 7,441 |
-| JavaScript | 13 | 340 | 158 | 176 | 674 |
-| JSON | 2 | 55 | 0 | 2 | 57 |
-| HTML | 1 | 20 | 0 | 1 | 21 |
-| JSON with Comments | 1 | 3 | 0 | 1 | 4 |
-| Ignore | 1 | 3 | 0 | 1 | 4 |
-| Markdown | 1 | 2 | 0 | 2 | 4 |
+
+| language           | files |   code | comment | blank |  total |
+| :----------------- | ----: | -----: | ------: | ----: | -----: |
+| TypeScript JSX     |    92 | 22,780 |   1,576 | 3,993 | 28,349 |
+| Log                |     1 |  8,469 |       0 | 1,293 |  9,762 |
+| Less               |    63 |  5,743 |     103 | 1,001 |  6,847 |
+| TypeScript         |    69 |  4,716 |     892 | 1,833 |  7,441 |
+| JavaScript         |    13 |    340 |     158 |   176 |    674 |
+| JSON               |     2 |     55 |       0 |     2 |     57 |
+| HTML               |     1 |     20 |       0 |     1 |     21 |
+| JSON with Comments |     1 |      3 |       0 |     1 |      4 |
+| Ignore             |     1 |      3 |       0 |     1 |      4 |
+| Markdown           |     1 |      2 |       0 |     2 |      4 |
 
 ## Directories
+
 | path | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
+| :-- | --: | --: | --: | --: | --: |
 | . | 244 | 42,131 | 2,729 | 8,303 | 53,163 |
 | . (Files) | 10 | 8,925 | 22 | 1,318 | 10,265 |
 | config | 1 | 0 | 8 | 4 | 12 |
@@ -123,4 +125,4 @@ Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-
 | src/services/demo | 3 | 126 | 29 | 19 | 174 |
 | src/utils | 8 | 533 | 131 | 175 | 839 |
 
-Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
+Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)

+ 4 - 3
.VSCodeCounter/2024-11-05_10-42-46/details.md

@@ -4,13 +4,14 @@ Date : 2024-11-05 10:42:46
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 250 files,  44380 codes, 2971 comments, 8813 blanks, all 56164 lines
+Total : 250 files, 44380 codes, 2971 comments, 8813 blanks, all 56164 lines
 
 [Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
 
 ## Files
+
 | filename | language | code | comment | blank | total |
-| :--- | :--- | ---: | ---: | ---: | ---: |
+| :-- | :-- | --: | --: | --: | --: |
 | [.eslintrc.js](/.eslintrc.js) | JavaScript | 3 | 0 | 1 | 4 |
 | [.prettierignore](/.prettierignore) | Ignore | 3 | 0 | 1 | 4 |
 | [.prettierrc](/.prettierrc) | JSON | 8 | 0 | 1 | 9 |
@@ -262,4 +263,4 @@ Total : 250 files,  44380 codes, 2971 comments, 8813 blanks, all 56164 lines
 | [typings.d.ts](/typings.d.ts) | TypeScript | 8 | 8 | 2 | 18 |
 | [yarn-error.log](/yarn-error.log) | Log | 8,469 | 0 | 1,293 | 9,762 |
 
-[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
+[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)

+ 4 - 3
.VSCodeCounter/2024-11-05_10-42-46/diff-details.md

@@ -4,13 +4,14 @@ Date : 2024-11-05 10:42:46
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 46 files,  2249 codes, 242 comments, 510 blanks, all 3001 lines
+Total : 46 files, 2249 codes, 242 comments, 510 blanks, all 3001 lines
 
 [Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
 
 ## Files
+
 | filename | language | code | comment | blank | total |
-| :--- | :--- | ---: | ---: | ---: | ---: |
+| :-- | :-- | --: | --: | --: | --: |
 | [.umirc.ts](/.umirc.ts) | TypeScript | 10 | 0 | 0 | 10 |
 | [src/app.tsx](/src/app.tsx) | TypeScript JSX | 24 | -7 | 2 | 19 |
 | [src/components/KCIMLeftList/index.tsx](/src/components/KCIMLeftList/index.tsx) | TypeScript JSX | -1 | 0 | 0 | -1 |
@@ -58,4 +59,4 @@ Total : 46 files,  2249 codes, 242 comments, 510 blanks, all 3001 lines
 | [src/utils/format.ts](/src/utils/format.ts) | TypeScript | 13 | 0 | 3 | 16 |
 | [src/utils/tableToExcel.ts](/src/utils/tableToExcel.ts) | TypeScript | 14 | 1 | 2 | 17 |
 
-[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
+[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details

+ 10 - 8
.VSCodeCounter/2024-11-05_10-42-46/diff.md

@@ -4,20 +4,22 @@ Date : 2024-11-05 10:42:46
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 46 files,  2249 codes, 242 comments, 510 blanks, all 3001 lines
+Total : 46 files, 2249 codes, 242 comments, 510 blanks, all 3001 lines
 
 [Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
 
 ## Languages
-| language | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
-| TypeScript JSX | 34 | 1,666 | 209 | 375 | 2,250 |
-| Less | 6 | 441 | 1 | 61 | 503 |
-| TypeScript | 6 | 142 | 32 | 74 | 248 |
+
+| language       | files |  code | comment | blank | total |
+| :------------- | ----: | ----: | ------: | ----: | ----: |
+| TypeScript JSX |    34 | 1,666 |     209 |   375 | 2,250 |
+| Less           |     6 |   441 |       1 |    61 |   503 |
+| TypeScript     |     6 |   142 |      32 |    74 |   248 |
 
 ## Directories
+
 | path | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
+| :-- | --: | --: | --: | --: | --: |
 | . | 46 | 2,249 | 242 | 510 | 3,001 |
 | . (Files) | 1 | 10 | 0 | 0 | 10 |
 | src | 45 | 2,239 | 242 | 510 | 2,991 |
@@ -68,4 +70,4 @@ Total : 46 files,  2249 codes, 242 comments, 510 blanks, all 3001 lines
 | src/services | 1 | 5 | 1 | 1 | 7 |
 | src/utils | 2 | 27 | 1 | 5 | 33 |
 
-[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
+[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)

File diff ditekan karena terlalu besar
+ 0 - 0
.VSCodeCounter/2024-11-05_10-42-46/results.json


+ 17 - 15
.VSCodeCounter/2024-11-05_10-42-46/results.md

@@ -4,27 +4,29 @@ Date : 2024-11-05 10:42:46
 
 Directory /Users/dema/work/CostAccountingSys
 
-Total : 250 files,  44380 codes, 2971 comments, 8813 blanks, all 56164 lines
+Total : 250 files, 44380 codes, 2971 comments, 8813 blanks, all 56164 lines
 
 Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
 
 ## Languages
-| language | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
-| TypeScript JSX | 94 | 24,446 | 1,785 | 4,368 | 30,599 |
-| Log | 1 | 8,469 | 0 | 1,293 | 9,762 |
-| Less | 65 | 6,184 | 104 | 1,062 | 7,350 |
-| TypeScript | 71 | 4,858 | 924 | 1,907 | 7,689 |
-| JavaScript | 13 | 340 | 158 | 176 | 674 |
-| JSON | 2 | 55 | 0 | 2 | 57 |
-| HTML | 1 | 20 | 0 | 1 | 21 |
-| JSON with Comments | 1 | 3 | 0 | 1 | 4 |
-| Ignore | 1 | 3 | 0 | 1 | 4 |
-| Markdown | 1 | 2 | 0 | 2 | 4 |
+
+| language           | files |   code | comment | blank |  total |
+| :----------------- | ----: | -----: | ------: | ----: | -----: |
+| TypeScript JSX     |    94 | 24,446 |   1,785 | 4,368 | 30,599 |
+| Log                |     1 |  8,469 |       0 | 1,293 |  9,762 |
+| Less               |    65 |  6,184 |     104 | 1,062 |  7,350 |
+| TypeScript         |    71 |  4,858 |     924 | 1,907 |  7,689 |
+| JavaScript         |    13 |    340 |     158 |   176 |    674 |
+| JSON               |     2 |     55 |       0 |     2 |     57 |
+| HTML               |     1 |     20 |       0 |     1 |     21 |
+| JSON with Comments |     1 |      3 |       0 |     1 |      4 |
+| Ignore             |     1 |      3 |       0 |     1 |      4 |
+| Markdown           |     1 |      2 |       0 |     2 |      4 |
 
 ## Directories
+
 | path | files | code | comment | blank | total |
-| :--- | ---: | ---: | ---: | ---: | ---: |
+| :-- | --: | --: | --: | --: | --: |
 | . | 250 | 44,380 | 2,971 | 8,813 | 56,164 |
 | . (Files) | 10 | 8,935 | 22 | 1,318 | 10,275 |
 | config | 1 | 0 | 8 | 4 | 12 |
@@ -125,4 +127,4 @@ Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-
 | src/services/demo | 3 | 126 | 29 | 19 | 174 |
 | src/utils | 8 | 560 | 132 | 180 | 872 |
 
-Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
+Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)

+ 2 - 7
.lintstagedrc

@@ -1,11 +1,6 @@
 {
-  "*.{md,json}": [
-    "prettier --cache --write"
-  ],
-  "*.{js,jsx}": [
-    "max lint --fix --eslint-only",
-    "prettier --cache --write"
-  ],
+  "*.{md,json}": ["prettier --cache --write"],
+  "*.{js,jsx}": ["max lint --fix --eslint-only", "prettier --cache --write"],
   "*.{css,less}": [
     "max lint --fix --stylelint-only",
     "prettier --cache --write"

+ 74 - 54
.umirc.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-14 14:14:32
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2024-12-05 17:33:15
+ * @LastEditTime: 2026-03-24 11:37:52
  * @FilePath: /BudgetManaSystem/.umirc.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -10,16 +10,15 @@ import { defineConfig } from '@umijs/max';
 
 import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
 
-
 const { REACT_APP_ENV } = process.env;
 const path = require('path');
 
 // 从 package.json 读取版本号,如果没有则使用默认值
 const pkg = require('./package.json');
 const APP_VERSION = pkg.version || '1.0.0';
-const BUILD_TIME = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
-
-
+const BUILD_TIME = new Date().toLocaleString('zh-CN', {
+  timeZone: 'Asia/Shanghai',
+});
 
 export default defineConfig({
   // 注入版本信息到全局变量
@@ -44,7 +43,7 @@ export default defineConfig({
     modifyVars: {
       '@ant-prefix': 'cost-ant',
       '@primary-color': '#3377FF',
-      '@border-color-base': '#dae2f2'
+      '@border-color-base': '#dae2f2',
     },
     javascriptEnabled: true,
   }, //对应修改生成的 antd 样式类名
@@ -53,8 +52,8 @@ export default defineConfig({
     config.plugin('monaco-editor').use(MonacoWebpackPlugin, [
       {
         // 指定需要加载的语言和特性
-        languages: ['sql', 'javascript', 'typescript']
-      }
+        languages: ['sql', 'javascript', 'typescript'],
+      },
     ]);
   },
 
@@ -68,7 +67,7 @@ export default defineConfig({
     layout: 'side',
     menuProps: {
       theme: 'light',
-    }
+    },
   },
   manifest: {
     basePath: '/',
@@ -76,12 +75,11 @@ export default defineConfig({
   publicPath: REACT_APP_ENV == 'dev' ? '/' : '/costAccount/',
   proxy: {
     '/gateway': {
-      target: 'http://120.27.235.181:5000/gateway',//开发
-      //target:'http://47.96.149.190:5000/gateway', //演示
+      //target: 'http://120.27.235.181:5000/gateway',//开发
+      target: 'http://47.96.149.190:5000/gateway', //演示
       changeOrigin: true,
       // pathRewrite: { '^/gateway': '' },
-
-    }
+    },
   },
   routes: [
     {
@@ -108,12 +106,14 @@ export default defineConfig({
             {
               path: '/baseSetting/responsibilityCenterSet/responsibilityCenter',
               name: '责任中心管理',
-              component: './baseSetting/responsibilityCenterSet/responsibilityCenter/index',
+              component:
+                './baseSetting/responsibilityCenterSet/responsibilityCenter/index',
             },
             {
               path: '/baseSetting/responsibilityCenterSet/responsibilityCenterConnect',
               name: '责任中心对应',
-              component: './baseSetting/responsibilityCenterSet/responsibilityCenterConnect/index',
+              component:
+                './baseSetting/responsibilityCenterSet/responsibilityCenterConnect/index',
             },
           ],
         },
@@ -124,22 +124,26 @@ export default defineConfig({
             {
               path: '/baseSetting/accountingAccountSet/costIncomeProjectMana',
               name: '会计收入项目管理',
-              component: './baseSetting/accountingAccountSet/costIncomeProjectMana/index',
+              component:
+                './baseSetting/accountingAccountSet/costIncomeProjectMana/index',
             },
             {
               path: '/baseSetting/accountingAccountSet/accountingSubMana',
               name: '会计科目管理',
-              component: './baseSetting/accountingAccountSet/accountingSubMana/index',
+              component:
+                './baseSetting/accountingAccountSet/accountingSubMana/index',
             },
             {
               path: '/baseSetting/accountingAccountSet/accountingSubMap',
               name: '会计科目对应',
-              component: './baseSetting/accountingAccountSet/accountingSubMap/index',
+              component:
+                './baseSetting/accountingAccountSet/accountingSubMap/index',
             },
             {
               path: '/baseSetting/accountingAccountSet/chargeItemMap',
               name: '收费项目对应',
-              component: './baseSetting/accountingAccountSet/chargeItemMap/index',
+              component:
+                './baseSetting/accountingAccountSet/chargeItemMap/index',
             },
           ],
         },
@@ -151,32 +155,38 @@ export default defineConfig({
             {
               path: '/baseSetting/costAllocationSet/allocationLevelSet',
               name: '分摊层级设置',
-              component: './baseSetting/costAllocationSet/allocationLevelSet/index',
+              component:
+                './baseSetting/costAllocationSet/allocationLevelSet/index',
             },
             {
               path: '/baseSetting/costAllocationSet/idleCostSetting',
               name: '闲置成本设置',
-              component: './baseSetting/costAllocationSet/idleCostSetting/index',
+              component:
+                './baseSetting/costAllocationSet/idleCostSetting/index',
             },
             {
               path: '/baseSetting/costAllocationSet/costAllocationParamsSet',
               name: '成本分摊参数设置',
-              component: './baseSetting/costAllocationSet/costAllocationParamsSet/index',
+              component:
+                './baseSetting/costAllocationSet/costAllocationParamsSet/index',
             },
             {
               path: '/baseSetting/costAllocationSet/costAllocationParamsDeal',
               name: '成本分摊参数处理',
-              component: './baseSetting/costAllocationSet/costAllocationParamsDeal/index',
+              component:
+                './baseSetting/costAllocationSet/costAllocationParamsDeal/index',
             },
             {
               path: '/baseSetting/costAllocationSet/allocationParamsMap',
               name: '分摊参数对应',
-              component: './baseSetting/costAllocationSet/allocationParamsMap/index',
+              component:
+                './baseSetting/costAllocationSet/allocationParamsMap/index',
             },
             {
               path: '/baseSetting/costAllocationSet/revenueImputationSet',
               name: '收入归集设置',
-              component: './baseSetting/costAllocationSet/revenueImputationSet/index',
+              component:
+                './baseSetting/costAllocationSet/revenueImputationSet/index',
             },
           ],
         },
@@ -203,12 +213,14 @@ export default defineConfig({
             {
               path: '/baseSetting/otherItemSet/visitsAndBedDayCostSetting',
               name: '诊次/床日成本设置',
-              component: './baseSetting/otherItemSet/visitsAndBedDayCostSetting/index',
+              component:
+                './baseSetting/otherItemSet/visitsAndBedDayCostSetting/index',
             },
             {
               path: '/baseSetting/otherItemSet/wholeHospCostAndIncomeSet',
               name: '全院其他收支设置',
-              component: './baseSetting/otherItemSet/wholeHospCostAndIncomeSet/index',
+              component:
+                './baseSetting/otherItemSet/wholeHospCostAndIncomeSet/index',
             },
           ],
         },
@@ -304,7 +316,7 @@ export default defineConfig({
         {
           path: '/costAccounting/:calcPageKey',
           component: './costAccounting/calcPageTemplate/index',
-        }
+        },
       ],
     },
     {
@@ -318,17 +330,14 @@ export default defineConfig({
               path: '/reportExport/:reportType/:reportCode',
               component: './reportExport/report',
             },
-          ]
-        }
-
+          ],
+        },
       ],
     },
     {
       path: '/operationalAnalysis',
       name: '运营分析',
-      routes: [
-        {}
-      ],
+      routes: [{}],
     },
     {
       path: '/costLibraryManagement',
@@ -341,27 +350,32 @@ export default defineConfig({
             {
               path: '/costLibraryManagement/basicCostManagement/personnelClassificationMana',
               name: '人事分类管理',
-              component: './costLibraryManagement/basicCostManagement/personnelClassificationMana/index',
+              component:
+                './costLibraryManagement/basicCostManagement/personnelClassificationMana/index',
             },
             {
               path: '/costLibraryManagement/basicCostManagement/drugCostManagement',
               name: '药品成本管理',
-              component: './costLibraryManagement/basicCostManagement/drugCostManagement/index',
+              component:
+                './costLibraryManagement/basicCostManagement/drugCostManagement/index',
             },
             {
               path: '/costLibraryManagement/basicCostManagement/materialCostManagement',
               name: '材料成本管理',
-              component: './costLibraryManagement/basicCostManagement/materialCostManagement/index',
+              component:
+                './costLibraryManagement/basicCostManagement/materialCostManagement/index',
             },
             {
               path: '/costLibraryManagement/basicCostManagement/equipmentCostManagement',
               name: '设备成本管理',
-              component: './costLibraryManagement/basicCostManagement/equipmentCostManagement/index',
+              component:
+                './costLibraryManagement/basicCostManagement/equipmentCostManagement/index',
             },
             {
               path: '/costLibraryManagement/basicCostManagement/spaceCostManagement',
               name: '空间成本管理',
-              component: './costLibraryManagement/basicCostManagement/spaceCostManagement/index',
+              component:
+                './costLibraryManagement/basicCostManagement/spaceCostManagement/index',
             },
           ],
         },
@@ -372,22 +386,26 @@ export default defineConfig({
             {
               path: '/costLibraryManagement/projectCostManagement/chargeItemsMana',
               name: '收费项目管理',
-              component: './costLibraryManagement/projectCostManagement/chargeItemsMana/index',
+              component:
+                './costLibraryManagement/projectCostManagement/chargeItemsMana/index',
             },
             {
               path: '/costLibraryManagement/projectCostManagement/standardProjectMana',
               name: '标准项目管理',
-              component: './costLibraryManagement/projectCostManagement/standardProjectMana/index',
+              component:
+                './costLibraryManagement/projectCostManagement/standardProjectMana/index',
             },
             {
               path: '/costLibraryManagement/projectCostManagement/projectShareParamsSet',
               name: '项目分摊参数设置',
-              component: './costLibraryManagement/projectCostManagement/projectShareParamsSet/index',
+              component:
+                './costLibraryManagement/projectCostManagement/projectShareParamsSet/index',
             },
             {
               path: '/costLibraryManagement/projectCostManagement/projectCostShareSet',
               name: '项目成本分摊设置',
-              component: './costLibraryManagement/projectCostManagement/projectCostShareSet/index',
+              component:
+                './costLibraryManagement/projectCostManagement/projectCostShareSet/index',
             },
           ],
         },
@@ -398,7 +416,8 @@ export default defineConfig({
             {
               path: '/costLibraryManagement/medicalOrderProject/medicalOrderProjectMana',
               name: '收费项目管理',
-              component: './costLibraryManagement/medicalOrderProject/medicalOrderProjectMana/index',
+              component:
+                './costLibraryManagement/medicalOrderProject/medicalOrderProjectMana/index',
             },
           ],
         },
@@ -409,21 +428,21 @@ export default defineConfig({
             {
               path: '/costLibraryManagement/diseaseCostManagement/diseaseMana',
               name: '病种管理',
-              component: './costLibraryManagement/diseaseCostManagement/diseaseMana/index',
+              component:
+                './costLibraryManagement/diseaseCostManagement/diseaseMana/index',
             },
             {
               path: '/costLibraryManagement/diseaseCostManagement/diseaseDiagnosisComparison',
               name: '病种诊断对照',
-              component: './costLibraryManagement/diseaseCostManagement/diseaseDiagnosisComparison/index',
+              component:
+                './costLibraryManagement/diseaseCostManagement/diseaseDiagnosisComparison/index',
             },
           ],
         },
         {
           path: '/costLibraryManagement/clinicalPathwayCostManagement',
           name: '临床路径成本管理',
-          routes: [
-            {}
-          ],
+          routes: [{}],
         },
         {
           path: '/costLibraryManagement/reportMana',
@@ -432,24 +451,25 @@ export default defineConfig({
             {
               path: '/costLibraryManagement/reportMana/reportColumnMana',
               name: '报表列管理',
-              component: './costLibraryManagement/reportMana/reportColumnMana/index',
+              component:
+                './costLibraryManagement/reportMana/reportColumnMana/index',
             },
             {
               path: '/costLibraryManagement/reportMana/reportListMana',
               name: '报表管理',
-              component: './costLibraryManagement/reportMana/reportListMana/index',
+              component:
+                './costLibraryManagement/reportMana/reportListMana/index',
             },
             {
               path: '/costLibraryManagement/reportMana/reportNavSet',
               name: '报表跳转',
-              component: './costLibraryManagement/reportMana/reportNavSet/index',
+              component:
+                './costLibraryManagement/reportMana/reportNavSet/index',
             },
           ],
         },
       ],
     },
-
   ],
   npmClient: 'yarn',
 });
-

+ 3 - 3
.vscode/settings.json

@@ -1,4 +1,4 @@
 {
-    "vue.features.codeActions.enable": false,
-    "typescript.tsdk": "node_modules/typescript/lib"
-}
+  "vue.features.codeActions.enable": false,
+  "typescript.tsdk": "node_modules/typescript/lib"
+}

+ 0 - 3
config/proxy.ts

@@ -6,6 +6,3 @@
  * @FilePath: /BudgetManaSystem/config/proxy.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
-
-
-

+ 45 - 50
mock/home.ts

@@ -7,54 +7,49 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
 export default {
-    'GET /performance/index': (req: any, res: any) => {        
-        res.json(
-            {
-                success: true,
-                data: [
-                    {
-                        id: 1,
-                        computeDate: "2022-09",
-                        code: 1,
-                        name: "月度结转",
-                        preCode: 0,
-                        sort: 1,
-                        status: 2,
-                        audit: "0"
-                    },
-                    {
-                        id: 1,
-                        computeDate: "2022-09",
-                        code: 1,
-                        name: "设置信息",
-                        preCode: 0,
-                        sort: 1,
-                        status: 2,
-                        audit: "0"
-                    },
-                    {
-                        id: 1,
-                        computeDate: "2022-09",
-                        code: 1,
-                        name: "绩效数据",
-                        preCode: 0,
-                        sort: 1,
-                        status: 1,
-                        audit: "0"
-                    }
-                ],
-                errorCode: 0,
-            });
-    },
-    'GET /performance/index/getCurrentComputeDate':(req: any, res: any)=>{
-        res.json({
-              success:true,
-              data:`${Math.random()}`
-        })
-    }
-
-};
+  'GET /performance/index': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: [
+        {
+          id: 1,
+          computeDate: '2022-09',
+          code: 1,
+          name: '月度结转',
+          preCode: 0,
+          sort: 1,
+          status: 2,
+          audit: '0',
+        },
+        {
+          id: 1,
+          computeDate: '2022-09',
+          code: 1,
+          name: '设置信息',
+          preCode: 0,
+          sort: 1,
+          status: 2,
+          audit: '0',
+        },
+        {
+          id: 1,
+          computeDate: '2022-09',
+          code: 1,
+          name: '绩效数据',
+          preCode: 0,
+          sort: 1,
+          status: 1,
+          audit: '0',
+        },
+      ],
+      errorCode: 0,
+    });
+  },
+  'GET /performance/index/getCurrentComputeDate': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: `${Math.random()}`,
+    });
+  },
+};

+ 158 - 170
mock/monthlyData.ts

@@ -7,236 +7,224 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
 export default {
-    'GET /performance/kpi/getSalary': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: [
-                    {
-                        "unitType": 1,
-
-                        "unitCode": 1,
-
-                        "unitName": "四病区护理组",
-
-                        "deptCode": "1",
-
-                        "deptName": "内科1",
-
-                        "empNo": "90083",
-
-                        "empName": "程静静",
-
-                        "salaryType": "1",
-
-                        "salaryTypeName": "学历工资",
-
-                        "salary": 10250
-                    },
-                    {
-                        "unitType": 1,
-
-                        "unitCode": 2,
-
-                        "unitName": "四病区护理组",
-
-                        "deptCode": "2",
+  'GET /performance/kpi/getSalary': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: [
+          {
+            unitType: 1,
 
-                        "deptName": "内科1",
+            unitCode: 1,
 
-                        "empNo": "90084",
+            unitName: '四病区护理组',
 
-                        "empName": "程静静",
+            deptCode: '1',
 
-                        "salaryType": "1",
+            deptName: '内科1',
 
-                        "salaryTypeName": "学历工资",
+            empNo: '90083',
 
-                        "salary": 20250
-                    }
-                ],
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
+            empName: '程静静',
 
-        })
-    },
-    'GET /performance/kpi/getNonAssessmentList': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: [
-                    {
-                        "unitType": "1",
+            salaryType: '1',
 
-                        "unitTypeName": "护理",
+            salaryTypeName: '学历工资',
 
-                        "unitCode": "1",
+            salary: 10250,
+          },
+          {
+            unitType: 1,
 
-                        "unitName": "四病区护理组",
+            unitCode: 2,
 
-                        "deptCode": 1,
+            unitName: '四病区护理组',
 
-                        "deptName": "内科1",
+            deptCode: '2',
 
-                        "assessmentCode": "1",
+            deptName: '内科1',
 
-                        "assessmentName": "最看红按头还",
+            empNo: '90084',
 
-                        "distributionType": 1,
+            empName: '程静静',
 
-                        "targetValue": "02032",
+            salaryType: '1',
 
-                        "targetValueName": "程静静",
+            salaryTypeName: '学历工资',
 
-                        "describe": "测试说明"
-                    },
-                    {
-                        "unitType": "1",
+            salary: 20250,
+          },
+        ],
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+  'GET /performance/kpi/getNonAssessmentList': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: [
+          {
+            unitType: '1',
 
-                        "unitTypeName": "护理",
+            unitTypeName: '护理',
 
-                        "unitCode": "1",
+            unitCode: '1',
 
-                        "unitName": "四病区护理组",
+            unitName: '四病区护理组',
 
-                        "deptCode": 1,
+            deptCode: 1,
 
-                        "deptName": "内科1",
+            deptName: '内科1',
 
-                        "assessmentCode": "2",
+            assessmentCode: '1',
 
-                        "assessmentName": "最看红按头还",
+            assessmentName: '最看红按头还',
 
-                        "distributionType": 1,
+            distributionType: 1,
 
-                        "targetValue": "02032",
+            targetValue: '02032',
 
-                        "targetValueName": "程静静",
+            targetValueName: '程静静',
 
-                        "describe": "测试说明"
-                    }
-                ],
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
+            describe: '测试说明',
+          },
+          {
+            unitType: '1',
 
-        })
-    },
-    'GET /performance/kpi/getAssessmentList': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: [
-                {
-                    "code": "听现音红当",
+            unitTypeName: '护理',
 
-                    "name": "物军动前压",
+            unitCode: '1',
 
-                    "child": [
-                        {
-                            "code": "太必世八目花电速点这动务史主不车每他象身民作或物员做",
+            unitName: '四病区护理组',
 
-                            "name": "文时较清斗最程后作给水",
+            deptCode: 1,
 
-                            "child": []
+            deptName: '内科1',
 
-                        }
-                    ]
+            assessmentCode: '2',
 
-                }
-            ],
+            assessmentName: '最看红按头还',
 
-        })
-    },
-    'GET /performance/getAssessmentData': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: [
-                    {
-                        "itemCode": "1",
+            distributionType: 1,
 
-                        "itemName": "腹腔引流袋",
+            targetValue: '02032',
 
-                        "itemType": "1",
+            targetValueName: '程静静',
 
-                        "itemTypeName": "收费项目",
+            describe: '测试说明',
+          },
+        ],
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+  'GET /performance/kpi/getAssessmentList': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: [
+        {
+          code: '听现音红当',
 
-                        "pointValue": 50,
+          name: '物军动前压',
 
-                        "value": 10000,
+          child: [
+            {
+              code: '太必世八目花电速点这动务史主不车每他象身民作或物员做',
 
-                        "createUser": "低基林算几安",
+              name: '文时较清斗最程后作给水',
 
-                        "createTime": "位派济查却精义"
-                    },
-                    {
-                        "itemCode": "1",
+              child: [],
+            },
+          ],
+        },
+      ],
+    });
+  },
+  'GET /performance/getAssessmentData': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: [
+          {
+            itemCode: '1',
 
-                        "itemName": "腹腔引流袋",
+            itemName: '腹腔引流袋',
 
-                        "itemType": "1",
+            itemType: '1',
 
-                        "itemTypeName": "收费项目",
+            itemTypeName: '收费项目',
 
-                        "pointValue": 50,
+            pointValue: 50,
 
-                        "value": 10000,
+            value: 10000,
 
-                        "createUser": "低基林算几安",
+            createUser: '低基林算几安',
 
-                        "createTime": "位派济查却精义"
-                    }
-                ],
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
+            createTime: '位派济查却精义',
+          },
+          {
+            itemCode: '1',
 
-        })
-    },
-    'GET /performance/manager/list': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: [
-                    {
-                        "unitCode": "1",
+            itemName: '腹腔引流袋',
 
-                        "unitName": "护理组",
+            itemType: '1',
 
-                        "deptCode": "1",
+            itemTypeName: '收费项目',
 
-                        "deptName": "内科",
+            pointValue: 50,
 
-                        "CMIData": {
-                            "targetValue": 1.1,
+            value: 10000,
 
-                            "value": 1.2,
+            createUser: '低基林算几安',
 
-                            "score": 27.7
+            createTime: '位派济查却精义',
+          },
+        ],
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+  'GET /performance/manager/list': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: [
+          {
+            unitCode: '1',
 
-                        },
+            unitName: '护理组',
 
-                        "totalScore": 100
+            deptCode: '1',
 
-                    }
-                ],
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
+            deptName: '内科',
 
-        })
-    },
-}
+            CMIData: {
+              targetValue: 1.1,
+
+              value: 1.2,
+
+              score: 27.7,
+            },
+
+            totalScore: 100,
+          },
+        ],
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+};

+ 164 - 181
mock/monthlyInfo.ts

@@ -9,197 +9,180 @@
 
 import mockjs from 'mockjs';
 
-
-
-
 const list = [...new Array(100).keys()].map((item, index) => {
-    return {
-        account: "admin",
-        avatarUrl: "",
-        departmentId: "A00002",
-        departmentName: "",
-        doctorLevel: "2",
-        entryTime: "2022-06-28 12:00:00",
-        gender: 2,
-        hospId: "30",
-        hospName: "武汉市儿童医院",
-        id: `30614${index}`,
-        idCardNum: "",
-        isOnService: 0,
-        jobTitle: "2",
-        major: "2",
-        name: `管理员${index}`,
-        password: "e10adc3949ba59abbe56e057f20f883e",
-        phoneNumber: "",
-        practiceCate: "1",
-        practiceCertificateNo: "",
-        practiceStatus: "1",
-        practiceSubject: "2",
-        qualificationCertificateNo: "",
-        remark: "",
-        title: "2",
-        userCate: "1",
-        userId: "30614",
-    }
+  return {
+    account: 'admin',
+    avatarUrl: '',
+    departmentId: 'A00002',
+    departmentName: '',
+    doctorLevel: '2',
+    entryTime: '2022-06-28 12:00:00',
+    gender: 2,
+    hospId: '30',
+    hospName: '武汉市儿童医院',
+    id: `30614${index}`,
+    idCardNum: '',
+    isOnService: 0,
+    jobTitle: '2',
+    major: '2',
+    name: `管理员${index}`,
+    password: 'e10adc3949ba59abbe56e057f20f883e',
+    phoneNumber: '',
+    practiceCate: '1',
+    practiceCertificateNo: '',
+    practiceStatus: '1',
+    practiceSubject: '2',
+    qualificationCertificateNo: '',
+    remark: '',
+    title: '2',
+    userCate: '1',
+    userId: '30614',
+  };
 });
 
-
 const users = [
-    { id: 0, name: 'Umi', nickName: 'U', gender: 'MALE' },
-    { id: 1, name: 'Fish', nickName: 'B', gender: 'FEMALE' },
+  { id: 0, name: 'Umi', nickName: 'U', gender: 'MALE' },
+  { id: 1, name: 'Fish', nickName: 'B', gender: 'FEMALE' },
 ];
 
-
 export default {
-    'GET /performance/check/getUnitList': (req: any, res: any) => {
-
-        console.log({ req, res });
-
-        res.json(
-            {
-                success: true,
-                data: [
-                    {
-                        code: 8662827685293679,
-
-                        name: "病区护理",
-
-                        child: [
-                            {
-                                code: 3994166660344023,
-
-                                name: "心内科病区",
+  'GET /performance/check/getUnitList': (req: any, res: any) => {
+    console.log({ req, res });
 
-                                child: [
-                                    {
-                                        code: 8338644021754079,
+    res.json({
+      success: true,
+      data: [
+        {
+          code: 8662827685293679,
 
-                                        name: "心内科一病区"
+          name: '病区护理',
 
-                                    }
-                                ]
+          child: [
+            {
+              code: 3994166660344023,
 
-                            }
-                        ]
+              name: '心内科病区',
 
-                    }
-                ],
-                errorCode: 0,
-            });
-    },
-    'GET /performance/check/empList': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: [
+              child: [
                 {
-                    "unitCode": 1,
-
-                    "empNo": "1",
-
-                    "empName": "程静静",
-
-                    "jobLevel": "N3",
-
-                    "jobTitle": "护士长",
-
-                    "jobRate": "1.6",
-
-                    "seniority": "17"
-
-                }
-            ],
-
-        })
-    },
-    'GET /centerSys/user/list': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: list,
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
-
-        })
-    },
-    'GET /performance/check/deptList': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: [
-                    {
-                        "unitCode": 1,
-
-                        "deptCode": "1",
-
-                        "deptName": "内一科",
-
-                        "deptType": 2,
-
-                        "describe": "临床科室",
-
-                        "deptTypeName": "临床"
-                    },
-                    {
-                        "unitCode": 2,
-
-                        "deptCode": "2",
-
-                        "deptName": "内一科",
-
-                        "deptType": 2,
-
-                        "describe": "临床科室",
-
-                        "deptTypeName": "临床"
-                    }
-                ],
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
-
-        })
-    },
-    'GET /performance/check/itemList': (req: any, res: any) => {
-        res.json({
-            success: true,
-            data: {
-                current: 1,
-                list: [
-                    {
-                        "itemCode": "000000040",
-
-                        "itemName": "I级护理",
-
-                        "itemType": "护理费",
-
-                        "itemPoint": 50,
-
-                        "coreFlag": "1"
-                    },
-                    {
-                        "itemCode": "000000041",
-
-                        "itemName": "I级护理",
-
-                        "itemType": "护理费",
-
-                        "itemPoint": 50,
-
-                        "coreFlag": "1"
-                    }
-                ],
-                pageSize: 10,
-                totalCount: 0,
-                totalPage: 0
-            }
-
-        })
-    },
-
-
-};
+                  code: 8338644021754079,
+
+                  name: '心内科一病区',
+                },
+              ],
+            },
+          ],
+        },
+      ],
+      errorCode: 0,
+    });
+  },
+  'GET /performance/check/empList': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: [
+        {
+          unitCode: 1,
+
+          empNo: '1',
+
+          empName: '程静静',
+
+          jobLevel: 'N3',
+
+          jobTitle: '护士长',
+
+          jobRate: '1.6',
+
+          seniority: '17',
+        },
+      ],
+    });
+  },
+  'GET /centerSys/user/list': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: list,
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+  'GET /performance/check/deptList': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: [
+          {
+            unitCode: 1,
+
+            deptCode: '1',
+
+            deptName: '内一科',
+
+            deptType: 2,
+
+            describe: '临床科室',
+
+            deptTypeName: '临床',
+          },
+          {
+            unitCode: 2,
+
+            deptCode: '2',
+
+            deptName: '内一科',
+
+            deptType: 2,
+
+            describe: '临床科室',
+
+            deptTypeName: '临床',
+          },
+        ],
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+  'GET /performance/check/itemList': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        current: 1,
+        list: [
+          {
+            itemCode: '000000040',
+
+            itemName: 'I级护理',
+
+            itemType: '护理费',
+
+            itemPoint: 50,
+
+            coreFlag: '1',
+          },
+          {
+            itemCode: '000000041',
+
+            itemName: 'I级护理',
+
+            itemType: '护理费',
+
+            itemPoint: 50,
+
+            coreFlag: '1',
+          },
+        ],
+        pageSize: 10,
+        totalCount: 0,
+        totalPage: 0,
+      },
+    });
+  },
+};

+ 41 - 44
mock/monthlySet.ts

@@ -7,48 +7,45 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 export default {
-    'GET /performance/carry/list': (req: any, res: any) => {
-        res.json(
-            {
-                success: true,
-                data: {
-                    preCarry: {
-                        "computeDate":`${Math.random()}`, //核算年月
-                        "dateRange": "2022/10/01-2022/10/31", //日期区间
-                        "personalRate": "10%", //人事成本比例
-                        "seniority": 30 //年资
-                    }, //上月度结转数据
-                    currentCarry: {
-                        "computeDate":`${Math.random()}`, //核算年月
-                        "dateRange": "2022/11/01-2022/11/31", //日期区间
-                        "personalRate": "10%", //人事成本比例
-                        "seniority": "30.00" //年资
-                    }, //本月度结转数据
-                    lastCarry: {
-                        "computeDate":`${Math.random()}`, //核算年月
-                        "dateRange": "2022/12/01-2022/12/31", //日期区间
-                        "personalRate": "10%", //人事成本比例
-                        "seniority": "30.00" //年资
-                    } //下月度结转数据
-                },
-                errorCode: 0,
-            });
-    },
-    'POST /performance/carry/over': (req: any, res: any) => {
-        res.json({
-            code: "200",
-            message: "返回成功",
-            data: null
-        })
-    },
-    'POST /performance/carry/back': (req: any, res: any) => {
-        res.json({
-            code: "200",
-            message: "返回成功",
-            data: null
-        })
-    }
-};
+  'GET /performance/carry/list': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: {
+        preCarry: {
+          computeDate: `${Math.random()}`, //核算年月
+          dateRange: '2022/10/01-2022/10/31', //日期区间
+          personalRate: '10%', //人事成本比例
+          seniority: 30, //年资
+        }, //上月度结转数据
+        currentCarry: {
+          computeDate: `${Math.random()}`, //核算年月
+          dateRange: '2022/11/01-2022/11/31', //日期区间
+          personalRate: '10%', //人事成本比例
+          seniority: '30.00', //年资
+        }, //本月度结转数据
+        lastCarry: {
+          computeDate: `${Math.random()}`, //核算年月
+          dateRange: '2022/12/01-2022/12/31', //日期区间
+          personalRate: '10%', //人事成本比例
+          seniority: '30.00', //年资
+        }, //下月度结转数据
+      },
+      errorCode: 0,
+    });
+  },
+  'POST /performance/carry/over': (req: any, res: any) => {
+    res.json({
+      code: '200',
+      message: '返回成功',
+      data: null,
+    });
+  },
+  'POST /performance/carry/back': (req: any, res: any) => {
+    res.json({
+      code: '200',
+      message: '返回成功',
+      data: null,
+    });
+  },
+};

+ 1 - 1
package.json

@@ -47,4 +47,4 @@
     "prettier-plugin-packagejson": "^2",
     "typescript": "^4.1.2"
   }
-}
+}

+ 25 - 37
src/access.ts

@@ -7,11 +7,6 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
-
 interface MenuItem {
   function: any;
   path: string;
@@ -21,58 +16,51 @@ interface MenuItem {
 
 function findMenuItem(menu: MenuItem[], path: string): MenuItem | undefined {
   for (let i = 0; i < menu.length; i++) {
-      if (menu[i].path === path) {
-          return menu[i];
-      } else if (menu[i].children) {
-          let found = findMenuItem(menu[i].children as MenuItem[], path);
-          if (found) return found;
-      }
+    if (menu[i].path === path) {
+      return menu[i];
+    } else if (menu[i].children) {
+      let found = findMenuItem(menu[i].children as MenuItem[], path);
+      if (found) return found;
+    }
   }
 }
 
-
-
-
-
-export default (initialState: { name: string;memuData:any[] }) => {
+export default (initialState: { name: string; memuData: any[] }) => {
   // 在这里按照初始化数据定义项目中的权限,统一管理
   // 参考文档 https://next.umijs.org/docs/max/access
-  
+
   //console.log({initialState});
 
-  const {memuData} = initialState;
-  
+  const { memuData } = initialState;
+
   const canSeeAdmin = !!(
     initialState && initialState.name !== 'dontHaveAccess'
   );
 
-  const whatCanIDoInThisPage = (pagePath:string)=>{
-       
-        if(memuData){
-          const thisPageData = findMenuItem(memuData,pagePath);
-          if(thisPageData){
-            return thisPageData.function?thisPageData.function:[];
-          }
-          return [];
-        }
-
-  }
+  const whatCanIDoInThisPage = (pagePath: string) => {
+    if (memuData) {
+      const thisPageData = findMenuItem(memuData, pagePath);
+      if (thisPageData) {
+        return thisPageData.function ? thisPageData.function : [];
+      }
+      return [];
+    }
+  };
 
-  const canIReadThisPage = (pagePath:string)=>{
-    if(memuData){
-      const thisPageData = findMenuItem(memuData,pagePath);
+  const canIReadThisPage = (pagePath: string) => {
+    if (memuData) {
+      const thisPageData = findMenuItem(memuData, pagePath);
       // console.log({pagePath,thisPageData});
-      if(thisPageData){
+      if (thisPageData) {
         return true;
       }
       return false;
     }
-  }
- 
+  };
 
   return {
     canSeeAdmin,
     whatCanIDoInThisPage,
-    canIReadThisPage
+    canIReadThisPage,
   };
 };

+ 220 - 135
src/app.tsx

@@ -11,10 +11,14 @@
 // 打印版本信息(在模块加载时立即执行)
 (function printVersion() {
   console.log(
-    '%c 成本核算系统 %c v' + process.env.APP_VERSION + ' %c 构建时间:' + process.env.BUILD_TIME + ' ',
+    '%c 成本核算系统 %c v' +
+      process.env.APP_VERSION +
+      ' %c 构建时间:' +
+      process.env.BUILD_TIME +
+      ' ',
     'background: #3377FF; color: #fff; padding: 2px 6px; border-radius: 3px 0 0 3px;',
     'background: #35495e; color: #fff; padding: 2px 6px;',
-    'background: #41b883; color: #fff; padding: 2px 6px; border-radius: 0 3px 3px 0;'
+    'background: #41b883; color: #fff; padding: 2px 6px; border-radius: 0 3px 3px 0;',
   );
 })();
 
@@ -30,21 +34,27 @@ import iconEnum from './menuIcons.js';
 // import Report from './pages/reports/index';
 import Static from './pages/static/index';
 
-
 import DevicePixelRatio from './utils/devicePixelRatio.js';
 
 import Icon, { createFromIconfontCN, FolderOutlined } from '@ant-design/icons';
 import { getLastComputeDate, getPlatformMenu } from '@/services/auth';
-import { JSXElementConstructor, Key, ReactElement, ReactFragment, ReactPortal, useEffect, useRef, useState } from 'react';
-
-
-import './utils/zhongtaiC'
+import {
+  JSXElementConstructor,
+  Key,
+  ReactElement,
+  ReactFragment,
+  ReactPortal,
+  useEffect,
+  useRef,
+  useState,
+} from 'react';
+
+import './utils/zhongtaiC';
 import { RuntimeAntdConfig } from '@umijs/max';
 import { useLocation } from '@umijs/max';
 import ResizableContainer from './components/ResizableContainer/index';
 import { IRoute } from '@umijs/max';
 
-
 // 权限检查函数
 function checkAccess(menu: IRoute[], pathname: string): boolean {
   for (const item of menu) {
@@ -68,12 +78,10 @@ function removePrefix(input: string, prefix: string): string {
   return input;
 }
 
-
 const IconFont = createFromIconfontCN({
   scriptUrl: '',
 });
 
-
 // 错误处理方案: 错误类型
 enum ErrorShowType {
   SILENT = 0,
@@ -93,11 +101,11 @@ interface ResponseStructure {
 }
 
 interface UserData {
-  name?: string,
-  ruleVersion?: string,
-  token?: string,
-  userId?: number,
-  youshuToken?: string
+  name?: string;
+  ruleVersion?: string;
+  token?: string;
+  userId?: number;
+  youshuToken?: string;
 }
 
 interface TransformResult {
@@ -106,7 +114,6 @@ interface TransformResult {
   firstLeafNodePath: any[];
 }
 
-
 function transformTree(tree: any[]): TransformResult {
   let firstLeafNode: any | null = null;
   let firstLeafNodePath: any[] = [];
@@ -120,7 +127,9 @@ function transformTree(tree: any[]): TransformResult {
     const newPath = [...path, newNode];
 
     if (node.children && node.children.length > 0) {
-      newNode.children = node.children.map((child: any) => traverse(child, newPath));
+      newNode.children = node.children.map((child: any) =>
+        traverse(child, newPath),
+      );
     } else {
       if (!firstLeafNode) {
         firstLeafNode = newNode;
@@ -136,7 +145,7 @@ function transformTree(tree: any[]): TransformResult {
     return newNode;
   }
 
-  const newTree = tree.map(node => traverse(node, []));
+  const newTree = tree.map((node) => traverse(node, []));
 
   return { newTree, firstLeafNode, firstLeafNodePath };
 }
@@ -154,17 +163,21 @@ const findItemByKey: any = (tree: any[], key: string, keyName: string) => {
     }
   }
   return null;
-}
-
-
+};
 
 export async function getInitialState(): Promise<{
-  isCollapsed: boolean, spacicalPageParamsType?: any[], userData: UserData, memuData: any[], computeDate: string
+  isCollapsed: boolean;
+  spacicalPageParamsType?: any[];
+  userData: UserData;
+  memuData: any[];
+  computeDate: string;
 }> {
   new DevicePixelRatio().init();
 
   // 默认的计算日期
-  let computeDate = `${new Date().getFullYear()}-${(new Date().getMonth() + 1).toString().padStart(2, '0')}`;
+  let computeDate = `${new Date().getFullYear()}-${(new Date().getMonth() + 1)
+    .toString()
+    .padStart(2, '0')}`;
 
   try {
     // 获取最新计算日期的请求
@@ -186,8 +199,6 @@ export async function getInitialState(): Promise<{
   };
 }
 
-
-
 export const request: RequestConfig = {
   // 统一的请求设定
   timeout: 100000000,
@@ -217,9 +228,7 @@ export const request: RequestConfig = {
     // 错误接收及处理
     errorHandler: (error: any, opts: any) => {
       if (opts?.skipErrorHandler) throw error;
-
     },
-
   },
 
   // 请求拦截器
@@ -228,19 +237,22 @@ export const request: RequestConfig = {
       // 拦截请求配置,进行个性化处理。
       const userData = localStorage.getItem('userData');
       const { token = '' } = JSON.parse(userData as any);
-      return { ...config, url: `/gateway${config.url}`, headers: { token } }
+      return { ...config, url: `/gateway${config.url}`, headers: { token } };
       // return { ...config }
-    }
+    },
   ],
 
   // 响应拦截器
   responseInterceptors: [
     (response: AxiosResponse) => {
       // 拦截响应数据,进行个性化处理
-      const { status, data: { status: code, errorMessage, msg }, config: { method } } = response;
+      const {
+        status,
+        data: { status: code, errorMessage, msg },
+        config: { method },
+      } = response;
 
       try {
-
         if (status == 200) {
           // 网络请求成功
           if (errorMessage && errorMessage.indexOf('Token') != -1) {
@@ -250,16 +262,14 @@ export const request: RequestConfig = {
             return false;
           }
 
-
           if (method == 'post') {
-
             if (code == 200) {
-
-              return response.data.data == null ? {
-                success: true,
-                data: true
-              } : response.data
-
+              return response.data.data == null
+                ? {
+                    success: true,
+                    data: true,
+                  }
+                : response.data;
             } else {
               notification.error({
                 top: 72,
@@ -267,55 +277,49 @@ export const request: RequestConfig = {
                 description: errorMessage || msg,
                 placement: 'topRight',
                 icon: <IconFont type="icon-jinggaotishi" />,
-                style: { padding: 16, borderRadius: 8 }
-              })
-              return false
+                style: { padding: 16, borderRadius: 8 },
+              });
+              return false;
             }
           } else {
             if (status != 200) {
               message.error('请求失败!');
-              return false
+              return false;
             } else {
               if (code == 200) {
                 //console.log({code,'response.data':response.data});
-                return response.data
+                return response.data;
               } else {
-
                 notification.error({
                   top: 72,
                   message: '提示',
                   description: errorMessage || msg,
                   placement: 'topRight',
                   icon: <IconFont type="icon-jinggaotishi" />,
-                  style: { padding: 16, borderRadius: 8 }
-                })
-                return false
+                  style: { padding: 16, borderRadius: 8 },
+                });
+                return false;
               }
             }
-
           }
-
         } else {
-          return false
+          return false;
         }
-
       } catch (error) {
         console.log({ error });
       }
-    }
-  ]
+    },
+  ],
 };
 
-
-
 export type menuDataItemType = {
-  path: string,
-  name: string,
-  icon: any,
-  component?: string,
-  softUrl?: string, // 帆软url
-  children?: menuDataItemType[]
-}
+  path: string;
+  name: string;
+  icon: any;
+  component?: string;
+  softUrl?: string; // 帆软url
+  children?: menuDataItemType[];
+};
 
 // 将服务端获取的菜单 icon 字符串映射为对应的 icon Dom
 const mappingIcon = (menuData: menuDataItemType[]) => {
@@ -326,10 +330,10 @@ const mappingIcon = (menuData: menuDataItemType[]) => {
         name: '',
         icon: '',
         component: './404',
-      }
-    ]
+      },
+    ];
   }
-  const mappingMenu: menuDataItemType[] = menuData.map(item => ({
+  const mappingMenu: menuDataItemType[] = menuData.map((item) => ({
     ...item,
     icon: item.icon && iconEnum[item.icon],
     children: item.children ? mappingIcon(item.children) : [],
@@ -337,34 +341,27 @@ const mappingIcon = (menuData: menuDataItemType[]) => {
   return mappingMenu;
 };
 
-
-
 const imgNode = (props: any) => {
-  return <IconFont type='icon-shouye' {...props} />
+  return <IconFont type="icon-shouye" {...props} />;
 };
 const fileIcon = () => {
-  return <IconFont type='icon-jixiaoguanli' />
+  return <IconFont type="icon-jixiaoguanli" />;
 };
 
 const setting = () => {
-  return <IconFont type='icon-xitongshezhi' />
+  return <IconFont type="icon-xitongshezhi" />;
 };
 
 const secondaryDistribute = () => {
-  return <IconFont type='icon-ercifenpei' />
+  return <IconFont type="icon-ercifenpei" />;
 };
 
 const reportCheck = () => {
-  return <IconFont type='icon-baobiaochaxun' />
+  return <IconFont type="icon-baobiaochaxun" />;
 };
 
-
-
-
 export function patchClientRoutes({ routes }: { routes: any }) {
-
   const treeLoop = (treeData: any) => {
-
     if (treeData.routes) {
       const paths = [...new Array(10).keys()].map((a, index) => ({
         path: `${treeData.path == '/' ? '' : treeData.path}/reports/${index}`,
@@ -385,28 +382,28 @@ export function patchClientRoutes({ routes }: { routes: any }) {
       lanhuPagePaths.forEach((a: any) => {
         treeData.routes.push(a);
       });
-
     }
     if (treeData.routes && treeData.routes.length > 0) {
       treeData.routes.forEach((a: any) => {
         treeLoop(a);
-      })
+      });
     }
-
-
-  }
+  };
 
   treeLoop(routes[0]);
 
   console.log({ routes });
 }
 
-
 //布局配置
 
-
-export const layout = ({ initialState, setInitialState }: { initialState: any, setInitialState: any }) => {
-
+export const layout = ({
+  initialState,
+  setInitialState,
+}: {
+  initialState: any;
+  setInitialState: any;
+}) => {
   const { isCollapsed } = initialState;
 
   const location = useLocation();
@@ -430,9 +427,6 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
     return hasAccess;
   };
 
-
-
-
   // useEffect(() => {
   //   return history.listen((location: any) => {
   //     if (!isMenuClickRef.current) {
@@ -449,30 +443,50 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
   //   });
   // }, [initialState]);
 
-
-
-
   return {
-
     menuHeaderRender: false,
     disableMobile: true,
-    onPageChange: () => { },
+    onPageChange: () => {},
     collapsedButtonRender: () => {
       return (
-        <div style={{
-          position: 'absolute', zIndex: 10, right: 17, bottom: 12,
-          display: 'flex', justifyContent: 'center', alignItems: 'center',
-          cursor: 'pointer', width: 24, height: 24
-        }} onClick={
-          () => {
+        <div
+          style={{
+            position: 'absolute',
+            zIndex: 10,
+            right: 17,
+            bottom: 12,
+            display: 'flex',
+            justifyContent: 'center',
+            alignItems: 'center',
+            cursor: 'pointer',
+            width: 24,
+            height: 24,
+          }}
+          onClick={() => {
             onCollapse(isCollapsed ? false : true);
-          }
-        }><IconFont className='menuCollapseIcon' type={isCollapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'} /></div>
-      )
+          }}
+        >
+          <IconFont
+            className="menuCollapseIcon"
+            type={isCollapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'}
+          />
+        </div>
+      );
     },
     collapsed: isCollapsed,
     // fixSiderbar:false,
-    menuItemRender: (item: { path: any; }, dom: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal | null | undefined) => {
+    menuItemRender: (
+      item: { path: any },
+      dom:
+        | string
+        | number
+        | boolean
+        | ReactElement<any, string | JSXElementConstructor<any>>
+        | ReactFragment
+        | ReactPortal
+        | null
+        | undefined,
+    ) => {
       return (
         <a
           onClick={() => {
@@ -496,7 +510,7 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
             function processMenuItem(item: any) {
               if (!item) return null;
 
-              let newItem = { ...item };  // 深拷贝当前节点
+              let newItem = { ...item }; // 深拷贝当前节点
 
               // 如果是叶子节点
               if (!item.children || item.children.length === 0) {
@@ -529,8 +543,12 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
 
             const _menu = processMenu(data);
 
-            setInitialState((t: any) => ({ ...t, spacicalPageParamsType: _menu, memuData: data, userData: JSON.parse(userData as string) }));
-
+            setInitialState((t: any) => ({
+              ...t,
+              spacicalPageParamsType: _menu,
+              memuData: data,
+              userData: JSON.parse(userData as string),
+            }));
 
             function addIconToPath(node: any, paths: string[]) {
               if (paths.includes(node.path)) {
@@ -538,70 +556,137 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
                   node.icon = <Icon component={imgNode} />;
                 }
                 if (node.path == '/baseSetting') {
-
                   node.icon = <Icon component={setting} />;
                 }
                 if (node.path == '/monthlyInfoSearch') {
-                  node.icon = <Icon component={() => <IconFont type='icon-yueduxinxicaiji' />} />;
+                  node.icon = (
+                    <Icon
+                      component={() => <IconFont type="icon-yueduxinxicaiji" />}
+                    />
+                  );
                 }
                 if (node.path == '/costAccounting') {
-                  node.icon = <Icon component={() => <IconFont type='icon-jixiaoguanli' />} />;
+                  node.icon = (
+                    <Icon
+                      component={() => <IconFont type="icon-jixiaoguanli" />}
+                    />
+                  );
                 }
                 // 新增:standardCostReport 使用与 /costAccounting 相同的 icon
                 if (node.path == '/standardCostReport') {
-                  node.icon = <Icon component={() => <IconFont type='icon-jixiaoguanli' />} />;
+                  node.icon = (
+                    <Icon
+                      component={() => <IconFont type="icon-jixiaoguanli" />}
+                    />
+                  );
                 }
                 if (node.path == '/reportExport') {
-                  node.icon = <Icon component={() => <IconFont type='icon-jixiaoguanli' />} />;
+                  node.icon = (
+                    <Icon
+                      component={() => <IconFont type="icon-jixiaoguanli" />}
+                    />
+                  );
                 }
                 if (node.path == '/costLibraryManagement') {
-                  node.icon = <Icon component={() => <IconFont type='icon-chengbenkuguanli' />} />;
+                  node.icon = (
+                    <Icon
+                      component={() => (
+                        <IconFont type="icon-chengbenkuguanli" />
+                      )}
+                    />
+                  );
                 }
                 if (node.path == '/static') {
-                  node.icon = <Icon component={() => <IconFont type='icon-baobiaochaxun' />} />;
+                  node.icon = (
+                    <Icon
+                      component={() => <IconFont type="icon-baobiaochaxun" />}
+                    />
+                  );
                 }
               }
               // 目录默认 icon:无 icon 且有子节点时使用文件夹图标
-              if (!node.icon && Array.isArray(node.children) && node.children.length > 0) {
+              if (
+                !node.icon &&
+                Array.isArray(node.children) &&
+                node.children.length > 0
+              ) {
                 node.icon = <FolderOutlined />;
               }
               if (node.children) {
-                node.children.forEach((child: any) => addIconToPath(child, paths));
+                node.children.forEach((child: any) =>
+                  addIconToPath(child, paths),
+                );
               }
             }
 
             _menu.forEach((item: any) => {
-              addIconToPath(item, ['/home', '/baseInfoMana', '/costAccounting', '/standardCostReport', '/monthlyInfoSearch', '/static', '/reportExport', '/costLibraryManagement', '/baseSetting']);
+              addIconToPath(item, [
+                '/home',
+                '/baseInfoMana',
+                '/costAccounting',
+                '/standardCostReport',
+                '/monthlyInfoSearch',
+                '/static',
+                '/reportExport',
+                '/costLibraryManagement',
+                '/baseSetting',
+              ]);
             });
 
-            const { newTree, firstLeafNode, firstLeafNodePath } = transformTree(_menu);
+            const { newTree, firstLeafNode, firstLeafNodePath } =
+              transformTree(_menu);
 
             // console.log({newTree});
 
-            return newTree
-
+            return newTree;
           }
         }
-      }
+      },
     },
     menuRender: (props: any, defaultDom: any) => {
-
       return (
-        <ResizableContainer width={isCollapsed ? 64 : 200} minWidth={0} maxWidth={600} height={'calc(100vh - 47px)'}>
-          <div style={{ height: '100%', background: '#fff', position: 'relative' }}>
-            <div className='menuWrapper' style={{ height: 'calc(100% - 40px)', overflowY: 'scroll', overflowX: 'hidden' }}>
+        <ResizableContainer
+          width={isCollapsed ? 64 : 200}
+          minWidth={0}
+          maxWidth={600}
+          height={'calc(100vh - 47px)'}
+        >
+          <div
+            style={{ height: '100%', background: '#fff', position: 'relative' }}
+          >
+            <div
+              className="menuWrapper"
+              style={{
+                height: 'calc(100% - 40px)',
+                overflowY: 'scroll',
+                overflowX: 'hidden',
+              }}
+            >
               {defaultDom}
             </div>
 
-            <div style={{
-              position: 'absolute', zIndex: 10, right: 17, bottom: 9,
-              display: 'flex', justifyContent: 'center', alignItems: 'center',
-              cursor: 'pointer', width: 24, height: 24
-            }} onClick={
-              () => {
+            <div
+              style={{
+                position: 'absolute',
+                zIndex: 10,
+                right: 17,
+                bottom: 9,
+                display: 'flex',
+                justifyContent: 'center',
+                alignItems: 'center',
+                cursor: 'pointer',
+                width: 24,
+                height: 24,
+              }}
+              onClick={() => {
                 onCollapse(isCollapsed ? false : true);
-              }
-            }><IconFont className='menuCollapseIcon' type={isCollapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'} /></div>
+              }}
+            >
+              <IconFont
+                className="menuCollapseIcon"
+                type={isCollapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'}
+              />
+            </div>
           </div>
         </ResizableContainer>
       );
@@ -611,7 +696,7 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
       //height: '94.5vh',  //以去除顶部导航高度
       borderRadius: '22px',
       background: '#F7F9FC',
-      height: 'calc(100vh - 48px)'
+      height: 'calc(100vh - 48px)',
       // overflow:'scroll',
       // margin:'20px 20px'
     },

+ 4 - 1
src/authWrapper.tsx

@@ -47,7 +47,10 @@ const AuthWrapper: React.FC = (props) => {
       if (menu.length > 0) {
         setDataLoaded(true);
         const { pathname } = history.location;
-        const hasAccess = checkAccess(menu, removePrefix(pathname, '/CostAccountingSys'));
+        const hasAccess = checkAccess(
+          menu,
+          removePrefix(pathname, '/CostAccountingSys'),
+        );
         // console.log({ hasAccess, menu, pathname });
         if (!hasAccess) {
           history.push('/noAccess');

+ 3 - 6
src/components/KCIMDrawerForm/index.tsx

@@ -6,17 +6,14 @@
  * @FilePath: /pfmBackMana/src/components/KCIMDrawerForm/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
-import { DrawerForm, DrawerFormProps } from "@ant-design/pro-components";
+import { DrawerForm, DrawerFormProps } from '@ant-design/pro-components';
 
 import './style.less';
 
-
 const KCIMDrawerForm: React.FC<DrawerFormProps> = (props) => {
-    // 在这里可以添加任何自定义逻辑或样式
+  // 在这里可以添加任何自定义逻辑或样式
 
-    return <DrawerForm {...props} />;
+  return <DrawerForm {...props} />;
 };
 
-
 export default KCIMDrawerForm;
-

+ 15 - 18
src/components/KCIMDrawerForm/style.less

@@ -1,20 +1,17 @@
-
-
-
 .cost-ant-drawer {
-      .cost-ant-drawer-content-wrapper {
-           .cost-ant-drawer-content {
-                .cost-ant-drawer-wrapper-body {
-                       .cost-ant-drawer-footer {
-                             .cost-ant-space-item {
-                                  .cost-ant-btn {
-                                       height: 24px !important;
-                                       padding: 0 11px;
-                                       border-radius: 4px !important;
-                                  }
-                             }
-                       }
-                }
-           }
+  .cost-ant-drawer-content-wrapper {
+    .cost-ant-drawer-content {
+      .cost-ant-drawer-wrapper-body {
+        .cost-ant-drawer-footer {
+          .cost-ant-space-item {
+            .cost-ant-btn {
+              height: 24px !important;
+              padding: 0 11px;
+              border-radius: 4px !important;
+            }
+          }
+        }
       }
-}
+    }
+  }
+}

+ 293 - 246
src/components/KCIMLeftList/index.tsx

@@ -9,289 +9,336 @@
 
 import { createFromIconfontCN } from '@ant-design/icons';
 import Dropdown from '@ant-design/pro-table/es/components/Dropdown';
-import { Input, Tooltip, TreeProps, Empty } from 'antd'
+import { Input, Tooltip, TreeProps, Empty } from 'antd';
 import { Key, useEffect, useState } from 'react';
 import DirectoryTree from 'antd/es/tree/DirectoryTree';
 import { DataNode } from 'antd/es/tree';
 
 import './style.less';
 
-
 import expandedIcon from '../../../static/treenode_open.png';
 import closeIcon from '../../../static/treenode_collapse.png';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
 interface ListItem {
-    name: string,
-    subText: string,
-    [key: string]: any
+  name: string;
+  subText: string;
+  [key: string]: any;
 }
 
 interface TreeNodeItem {
-    [key: string]: any
+  [key: string]: any;
 }
 
 export interface KCIMLeftListProps {
-    dataSource?: any[],
-    searchKey: string,
-    placeholder?: string,
-    listType?: 'list' | 'tree',
-    icon?: string,
-    contentH?: number|string,
-    rowKey?: string,
-    fieldNames?: { title?: string, key?: string, children?: string },
-    onChange?: (selectedItem: ListItem) => void,
-    onReachBottom?: () => void,
-    loading?: boolean,
-    useRemoteSearch?: boolean,
-    onSearchChange?: (keyword: string) => void
+  dataSource?: any[];
+  searchKey: string;
+  placeholder?: string;
+  listType?: 'list' | 'tree';
+  icon?: string;
+  contentH?: number | string;
+  rowKey?: string;
+  fieldNames?: { title?: string; key?: string; children?: string };
+  onChange?: (selectedItem: ListItem) => void;
+  onReachBottom?: () => void;
+  loading?: boolean;
+  useRemoteSearch?: boolean;
+  onSearchChange?: (keyword: string) => void;
 }
 
-
-function searchTreeAndKeepHierarchy(tree: any[], keyword: string, searchKey: string, children: string) {
-    function search(node: any) {
-        // 深度复制节点,避免修改原始树
-        let newNode = { ...node };
-        if (node[`${searchKey}`].includes(keyword)) {
-            // 如果节点名称包含关键字,返回整个节点及其子节点
-            return newNode;
-        } else if (node[`${children}`] && node[`${children}`].length > 0) {
-            // 如果当前节点不匹配但有子节点,递归搜索子节点
-            let filteredChildren = node[`${children}`].map(search).filter((child: any) => child !== null); // 递归并过滤掉null
-            if (filteredChildren.length > 0) {
-                // 如果有子节点匹配,只返回匹配的子节点
-                newNode[`${children}`] = filteredChildren;
-                return newNode;
-            }
-        }
-        // 如果节点和其子节点都不匹配,返回null
-        return null;
+function searchTreeAndKeepHierarchy(
+  tree: any[],
+  keyword: string,
+  searchKey: string,
+  children: string,
+) {
+  function search(node: any) {
+    // 深度复制节点,避免修改原始树
+    let newNode = { ...node };
+    if (node[`${searchKey}`].includes(keyword)) {
+      // 如果节点名称包含关键字,返回整个节点及其子节点
+      return newNode;
+    } else if (node[`${children}`] && node[`${children}`].length > 0) {
+      // 如果当前节点不匹配但有子节点,递归搜索子节点
+      let filteredChildren = node[`${children}`]
+        .map(search)
+        .filter((child: any) => child !== null); // 递归并过滤掉null
+      if (filteredChildren.length > 0) {
+        // 如果有子节点匹配,只返回匹配的子节点
+        newNode[`${children}`] = filteredChildren;
+        return newNode;
+      }
     }
+    // 如果节点和其子节点都不匹配,返回null
+    return null;
+  }
 
-    // 对树的每个根节点进行搜索,并过滤掉不匹配的节点
-    return tree.map(search).filter(node => node !== null);
+  // 对树的每个根节点进行搜索,并过滤掉不匹配的节点
+  return tree.map(search).filter((node) => node !== null);
 }
 
-
-
 const findFirstLeafNodeWithParents: any = (node: any, children: string) => {
-    // 定义一个内部递归函数来处理节点和跟踪父节点
-    const findNode: any = (currentNode: any, parents: any[]) => {
-        // 打印当前节点信息,用于调试
-        // console.log({ currentNode });
-
-        // 检查当前节点是否为叶子节点(无子节点或子节点为空数组)
-        if (!currentNode[children] || currentNode[children].length === 0) {
-            return { leafNode: currentNode, parents };
-        }
-
-        // 添加当前节点到父节点列表
-        parents.push(currentNode);
-
-        // 递归查找第一个子节点的第一个叶子节点
-        return findNode(currentNode[children][0], parents);
-    };
-
-    // 调用内部函数,初始父节点列表为空
-    return findNode(node, []);
-}
-
+  // 定义一个内部递归函数来处理节点和跟踪父节点
+  const findNode: any = (currentNode: any, parents: any[]) => {
+    // 打印当前节点信息,用于调试
+    // console.log({ currentNode });
+
+    // 检查当前节点是否为叶子节点(无子节点或子节点为空数组)
+    if (!currentNode[children] || currentNode[children].length === 0) {
+      return { leafNode: currentNode, parents };
+    }
 
+    // 添加当前节点到父节点列表
+    parents.push(currentNode);
 
+    // 递归查找第一个子节点的第一个叶子节点
+    return findNode(currentNode[children][0], parents);
+  };
 
+  // 调用内部函数,初始父节点列表为空
+  return findNode(node, []);
+};
 
 export const KCIMLeftList = (props: KCIMLeftListProps) => {
-
-    const { searchKey, placeholder = '请输入', onChange, listType = 'list', dataSource: data = [], icon, contentH = 500, rowKey = 'id', fieldNames = { title: 'title', key: 'key', children: 'children' }, onReachBottom, loading = false, useRemoteSearch = false, onSearchChange } = props;
-    
-    const [dataSource, set_dataSource] = useState<ListItem[] | TreeNodeItem[]>([]);
-    const [showList, set_showList] = useState<ListItem[] | TreeNodeItem[]>([]);
-    const [currentSelected, set_currentSelected] = useState<undefined | any>(undefined);
-    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
-    const [autoExpandParent, setAutoExpandParent] = useState(true);
-    const [defaultSelectedKeys, set_defaultSelectedKeys] = useState<Key[]>([]);
-
-
-
-
-    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
-        // console.log('selected', selectedKeys, info);
-        const { node } = info;
-        if (!node[fieldNames.children as keyof typeof node] || (node[fieldNames.children as keyof typeof node] as any[]).length === 0) {
-            set_currentSelected(node);
-        }
-        
-    };
-
-    const onExpand = (newExpandedKeys: React.Key[]) => {
-        setExpandedKeys(newExpandedKeys);
-        setAutoExpandParent(false);
-    };
-
-
-    useEffect(() => {
-        onChange && onChange(currentSelected);
-    }, [currentSelected])
-
-    useEffect(() => {
-        if (showList.length > 0) {
+  const {
+    searchKey,
+    placeholder = '请输入',
+    onChange,
+    listType = 'list',
+    dataSource: data = [],
+    icon,
+    contentH = 500,
+    rowKey = 'id',
+    fieldNames = { title: 'title', key: 'key', children: 'children' },
+    onReachBottom,
+    loading = false,
+    useRemoteSearch = false,
+    onSearchChange,
+  } = props;
+
+  const [dataSource, set_dataSource] = useState<ListItem[] | TreeNodeItem[]>(
+    [],
+  );
+  const [showList, set_showList] = useState<ListItem[] | TreeNodeItem[]>([]);
+  const [currentSelected, set_currentSelected] = useState<undefined | any>(
+    undefined,
+  );
+  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+  const [autoExpandParent, setAutoExpandParent] = useState(true);
+  const [defaultSelectedKeys, set_defaultSelectedKeys] = useState<Key[]>([]);
+
+  const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+    // console.log('selected', selectedKeys, info);
+    const { node } = info;
+    if (
+      !node[fieldNames.children as keyof typeof node] ||
+      (node[fieldNames.children as keyof typeof node] as any[]).length === 0
+    ) {
+      set_currentSelected(node);
+    }
+  };
+
+  const onExpand = (newExpandedKeys: React.Key[]) => {
+    setExpandedKeys(newExpandedKeys);
+    setAutoExpandParent(false);
+  };
+
+  useEffect(() => {
+    onChange && onChange(currentSelected);
+  }, [currentSelected]);
+
+  useEffect(() => {
+    if (showList.length > 0) {
+      if (listType == 'list') {
+        set_currentSelected(showList[0]);
+      }
+      if (listType == 'tree') {
+        const result = findFirstLeafNodeWithParents(
+          showList[0],
+          fieldNames.children ? fieldNames.children : 'children',
+        );
+        // console.log({ result });
+
+        setExpandedKeys([
+          ...result.parents.map(
+            (parent: any) => parent[fieldNames.key as string],
+          ),
+        ]);
+        set_currentSelected(result.leafNode);
+        set_defaultSelectedKeys([result.leafNode[`${fieldNames.key}`]]);
+      }
+    } else {
+      set_currentSelected(undefined);
+    }
+  }, [showList]);
+
+  useEffect(() => {
+    set_dataSource([...data]);
+    set_showList([...data]);
+  }, [data]);
+
+  const handleScroll = (e: any) => {
+    const target = e.currentTarget;
+    if (!target) return;
+    const { scrollTop, scrollHeight, clientHeight } = target;
+    const nearBottom = scrollHeight - (scrollTop + clientHeight) <= 20;
+    if (nearBottom && onReachBottom && !loading) {
+      onReachBottom();
+    }
+  };
+
+  return (
+    <div className="KCIMLeftList">
+      <div className="toolbar">
+        <Input
+          placeholder={placeholder}
+          allowClear
+          autoComplete="off"
+          suffix={<IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />}
+          // style={{ width: 156 }}
+          onChange={(e) => {
+            if (useRemoteSearch) {
+              onSearchChange && onSearchChange(e.target.value);
+              return;
+            }
             if (listType == 'list') {
-                set_currentSelected(showList[0]);
+              const result = dataSource.filter(
+                (item) => item[`${searchKey}`].indexOf(e.target.value) != -1,
+              );
+              set_showList(result);
             }
             if (listType == 'tree') {
-                const result = findFirstLeafNodeWithParents(showList[0], fieldNames.children ? fieldNames.children : 'children');
-                // console.log({ result });
-        
-                setExpandedKeys([...(result.parents.map((parent:any) => parent[fieldNames.key as string]))]);
-                set_currentSelected(result.leafNode);
-                set_defaultSelectedKeys([result.leafNode[`${fieldNames.key}`]]);
+              const result = searchTreeAndKeepHierarchy(
+                dataSource,
+                e.target.value,
+                searchKey,
+                fieldNames.children as string,
+              );
+              set_showList(result);
             }
-
-        } else {
-            set_currentSelected(undefined);
-        }
-    }, [showList]);
-
-
-    useEffect(() => {
-        set_dataSource([...data]);
-        set_showList([...data]);
-    }, [data]);
-
-
-    const handleScroll = (e: any) => {
-        const target = e.currentTarget;
-        if (!target) return;
-        const { scrollTop, scrollHeight, clientHeight } = target;
-        const nearBottom = scrollHeight - (scrollTop + clientHeight) <= 20;
-        if (nearBottom && onReachBottom && !loading) {
-            onReachBottom();
-        }
-    }
-
-    return (
-        <div className="KCIMLeftList">
-            <div className='toolbar'>
-                <Input placeholder={placeholder} allowClear autoComplete='off'
-                    suffix={
-                        <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
-                    }
-                    // style={{ width: 156 }}
-                    onChange={(e) => {
-                        if (useRemoteSearch) {
-                            onSearchChange && onSearchChange(e.target.value);
-                            return;
-                        }
-                        if (listType == 'list') {
-                            const result = dataSource.filter(item => item[`${searchKey}`].indexOf(e.target.value) != -1);
-                            set_showList(result);
-                        }
-                        if (listType == 'tree') {
-                            const result = searchTreeAndKeepHierarchy(dataSource, e.target.value, searchKey, fieldNames.children as string);
-                            set_showList(result);
-                        }
-
-                    }}
-
+          }}
+        />
+        {/* <UpDataActBtn key={'act'} record={undefined} type='ADD_LEFTDATA' /> */}
+      </div>
+      <div
+        className="wrap_cost"
+        style={{ height: contentH, overflowY: 'scroll' }}
+        onScroll={handleScroll}
+      >
+        {listType == 'list' &&
+          showList.map((item, index) => {
+            return (
+              <div
+                className={
+                  currentSelected
+                    ? currentSelected[`${rowKey}`] == item[`${rowKey}`]
+                      ? 'list on'
+                      : 'list'
+                    : 'list'
+                }
+                key={index}
+                onClick={() => {
+                  set_currentSelected(item);
+
+                  // _currentSelectedType = item;
+                }}
+              >
+                <img
+                  className="icon"
+                  src={
+                    icon ? icon : require('../../../static/departmentIcon.png')
+                  }
+                  alt=""
                 />
-                {/* <UpDataActBtn key={'act'} record={undefined} type='ADD_LEFTDATA' /> */}
-
-            </div>
-            <div className='wrap_cost' style={{ height: contentH, overflowY: 'scroll' }} onScroll={handleScroll}>
-                {
-                    listType == 'list' && showList.map((item, index) => {
-                        return (
-                            <div className={currentSelected ? currentSelected[`${rowKey}`] == item[`${rowKey}`] ? 'list on' : 'list' : 'list'}
-                                key={index}
-                                onClick={() => {
-                                    set_currentSelected(item);
-
-                                    // _currentSelectedType = item;
-                                }}
-                            >
-                                <img className='icon' src={icon ? icon : require('../../../static/departmentIcon.png')} alt="" />
-                                <div className='content'>
-                                    <Tooltip title={item.subText} >
-                                        <div className='name'>{item.name}</div>
-                                        <div className='sub'>{item.subText}</div>
-                                    </Tooltip>
-                                </div>
-
-                                {/* <Dropdown menu={{ items: moreItems }} placement="bottom" onOpenChange={(bool) => { bool && set_currentEditLeftData(item) }}>
+                <div className="content">
+                  <Tooltip title={item.subText}>
+                    <div className="name">{item.name}</div>
+                    <div className="sub">{item.subText}</div>
+                  </Tooltip>
+                </div>
+
+                {/* <Dropdown menu={{ items: moreItems }} placement="bottom" onOpenChange={(bool) => { bool && set_currentEditLeftData(item) }}>
                                         <div className='more'>
                                             <img src={require('../../../../../static/more_point_gray.png')} alt="" />
                                         </div>
                                     </Dropdown> */}
-                            </div>
-                        )
-                    })
-                }
-
-                {
-                    (!showList || showList.length == 0) && (
-                        <div><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /></div>
-                    )
-                }
-
-                {
-                    listType == 'tree' && dataSource.length > 0 && currentSelected && defaultSelectedKeys.length > 0 && (
-                        <DirectoryTree
-                            className='KC-DirectoryTree'
-                            fieldNames={fieldNames}
-                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
-                            onSelect={onSelect}
-                            onExpand={onExpand}
-                            expandedKeys={expandedKeys}
-                            autoExpandParent={autoExpandParent}
-                            selectedKeys={[currentSelected[`${fieldNames.key}`]]}
-                            blockNode={true}
-                            icon={() => null}
-                            // titleRender={
-                            //     (nodeData: any) => {
-                            //         const strTitle = nodeData.name as string;
-                            //         const index = strTitle.indexOf(searchValue);
-                            //         const beforeStr = strTitle.substring(0, index);
-                            //         const afterStr = strTitle.slice(index + searchValue.length);
-                            //         const title =
-                            //             index > -1 ? (
-                            //                 <span>
-                            //                     {beforeStr}
-                            //                     <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
-                            //                     {afterStr}
-                            //                 </span>
-                            //             ) : (
-                            //                 <span className='strTitle'>{strTitle}</span>
-                            //             );
-                            //         return <div style={{
-                            //             display: 'flex', flexDirection: 'row',
-                            //             width: '100%',
-                            //             justifyContent: 'flex-start', alignItems: 'center', height: 32,
-                            //             borderRadius: '4px',
-                            //             overflow: 'hidden',
-                            //             color: '#17181A',
-                            //             textOverflow: 'ellipsis',
-                            //             whiteSpace: 'nowrap'
-
-                            //         }}>{title}</div>
-                            //     }
-                            // }
-                            // defaultSelectedKeys={['B0100']}
-                            treeData={showList as unknown as DataNode[]}
-                            // treeData={treeDataNew}
-                            switcherIcon={(props: any) => {
-                                const { expanded } = props;
-                                return <IconFont style={{fontSize:16,position:'relative',top:2}} type={expanded?'icon-shouqi1':'icon-zhankai1'} />
-                            }}
-                        />
-                    )
-                }
-            </div>
-
-        </div>
-    )
-}
+              </div>
+            );
+          })}
+
+        {(!showList || showList.length == 0) && (
+          <div>
+            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+          </div>
+        )}
+
+        {listType == 'tree' &&
+          dataSource.length > 0 &&
+          currentSelected &&
+          defaultSelectedKeys.length > 0 && (
+            <DirectoryTree
+              className="KC-DirectoryTree"
+              fieldNames={fieldNames}
+              rootStyle={{
+                height: '100%',
+                paddingBottom: 50,
+                overflowY: 'scroll',
+                overflowX: 'hidden',
+              }}
+              onSelect={onSelect}
+              onExpand={onExpand}
+              expandedKeys={expandedKeys}
+              autoExpandParent={autoExpandParent}
+              selectedKeys={[currentSelected[`${fieldNames.key}`]]}
+              blockNode={true}
+              icon={() => null}
+              // titleRender={
+              //     (nodeData: any) => {
+              //         const strTitle = nodeData.name as string;
+              //         const index = strTitle.indexOf(searchValue);
+              //         const beforeStr = strTitle.substring(0, index);
+              //         const afterStr = strTitle.slice(index + searchValue.length);
+              //         const title =
+              //             index > -1 ? (
+              //                 <span>
+              //                     {beforeStr}
+              //                     <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
+              //                     {afterStr}
+              //                 </span>
+              //             ) : (
+              //                 <span className='strTitle'>{strTitle}</span>
+              //             );
+              //         return <div style={{
+              //             display: 'flex', flexDirection: 'row',
+              //             width: '100%',
+              //             justifyContent: 'flex-start', alignItems: 'center', height: 32,
+              //             borderRadius: '4px',
+              //             overflow: 'hidden',
+              //             color: '#17181A',
+              //             textOverflow: 'ellipsis',
+              //             whiteSpace: 'nowrap'
+
+              //         }}>{title}</div>
+              //     }
+              // }
+              // defaultSelectedKeys={['B0100']}
+              treeData={showList as unknown as DataNode[]}
+              // treeData={treeDataNew}
+              switcherIcon={(props: any) => {
+                const { expanded } = props;
+                return (
+                  <IconFont
+                    style={{ fontSize: 16, position: 'relative', top: 2 }}
+                    type={expanded ? 'icon-shouqi1' : 'icon-zhankai1'}
+                  />
+                );
+              }}
+            />
+          )}
+      </div>
+    </div>
+  );
+};

+ 128 - 127
src/components/KCIMLeftList/style.less

@@ -1,139 +1,140 @@
+.KCIMLeftList {
+  border-radius: 4px;
+  padding: 8px 0;
+  padding-top: 0;
+  width: 100%;
+  height: 100%;
+  overflow-y: hidden;
+  // padding-top: 16px;
+  // border: 1px solid #DAE2F2;
+  .toolbar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 16px;
 
+    .add {
+      cursor: pointer;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 24px;
+      height: 24px;
+      background: #fafcff;
+      border-radius: 4px;
+      border: 1px solid #dae2f2;
 
+      & > img {
+        width: 16px;
+        height: 16px;
+      }
+    }
+  }
 
-.KCIMLeftList {
-    border-radius: 4px;
-    padding:8px 0;
-    padding-top: 0;
-    width: 100%;
-    height:100%;
-    overflow-y: hidden;
-    // padding-top: 16px;
-    // border: 1px solid #DAE2F2;
-    .toolbar {
-        display: flex;
-        flex-direction: row;
-        justify-content: space-between;
-        align-items: center;
-        padding: 0 16px;
-  
-        .add {
-          cursor: pointer;
-          display: flex;
-          justify-content: center;
-          align-items: center;
-          width: 24px;
-          height: 24px;
-          background: #FAFCFF;
-          border-radius: 4px;
-          border: 1px solid #DAE2F2;
-  
-          &>img {
-            width: 16px;
-            height: 16px;
-          }
-        }
+  .wrap_cost {
+    margin-top: 12px;
+    .cost-ant-tree.cost-ant-tree-directory
+      .cost-ant-tree-treenode-selected:hover::before,
+    .cost-ant-tree.cost-ant-tree-directory
+      .cost-ant-tree-treenode-selected::before {
+      border-radius: 4px;
+      background: rgb(240 242 245 / 100%);
+    }
+
+    .bms-ant-tree.bms-ant-tree-directory
+      .bms-ant-tree-treenode
+      .bms-ant-tree-node-content-wrapper.bms-ant-tree-node-selected {
+      font-weight: bold;
+    }
+
+    .KC-DirectoryTree {
+      padding: 0 16px;
+      // .cost-ant-tree-treenode-selected {
+      //      .cost-ant-tree-title {
+      //         color:#17181A !important;
+      //         font-weight: 500 !important;
+      //      }
+      // }
+    }
+
+    .cost-ant-tree.cost-ant-tree-directory
+      .cost-ant-tree-treenode
+      .cost-ant-tree-node-content-wrapper.cost-ant-tree-node-selected {
+      color: #17181a !important;
+      font-weight: 500 !important;
+    }
+
+    .list {
+      cursor: pointer;
+      height: 48px;
+      border-radius: 4px;
+      background: #ffffff;
+      display: flex;
+      padding-left: 8px;
+      padding-right: 8px;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 4px;
+
+      .icon {
+        width: 25px;
+        height: 25px;
       }
-  
-      .wrap_cost {
-        margin-top: 12px;
-        .cost-ant-tree.cost-ant-tree-directory .cost-ant-tree-treenode-selected:hover::before,
-        .cost-ant-tree.cost-ant-tree-directory .cost-ant-tree-treenode-selected::before {
-            border-radius: 4px;
-            background: rgb(240 242 245 / 100%);
+
+      .content {
+        width: 87%;
+        padding-left: 7px;
+
+        .name {
+          height: 15px;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+          font-weight: 500;
+          color: #17181a;
+          line-height: 15px;
+          margin-bottom: 4px;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
         }
 
-        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode .bms-ant-tree-node-content-wrapper.bms-ant-tree-node-selected {
-            font-weight: bold;
+        .sub {
+          height: 13px;
+          font-size: 12px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #7a8599;
+          line-height: 13px;
         }
+      }
 
-        .KC-DirectoryTree {
-          padding: 0 16px;
-          // .cost-ant-tree-treenode-selected {
-          //      .cost-ant-tree-title {
-          //         color:#17181A !important;
-          //         font-weight: 500 !important;
-          //      }
-          // }
+      .more {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        cursor: pointer;
+        width: 16px;
+        height: 16px;
+        border-radius: 4px;
+        background: #ffffff;
 
-          
+        & > img {
+          width: 100%;
+          height: 100%;
         }
+      }
 
-        .cost-ant-tree.cost-ant-tree-directory .cost-ant-tree-treenode .cost-ant-tree-node-content-wrapper.cost-ant-tree-node-selected {
-          color:#17181A !important;
-          font-weight: 500 !important;
-        }
-  
-        .list {
-          cursor: pointer;
-          height: 48px;
-          border-radius: 4px;
-          background: #FFFFFF;
-          display: flex;
-          padding-left: 8px;
-          padding-right: 8px;
-          flex-direction: row;
-          justify-content: space-between;
-          align-items: center;
-          margin-bottom: 4px;
-  
-          .icon {
-            width: 25px;
-            height: 25px;
-          }
-  
-          .content {
-            width: 87%;
-            padding-left: 7px;
-  
-            .name {
-              height: 15px;
-              font-size: 14px;
-              font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-              font-weight: 500;
-              color: #17181A;
-              line-height: 15px;
-              margin-bottom: 4px;
-              overflow: hidden;
-              white-space: nowrap;
-              text-overflow: ellipsis;
-            }
-  
-            .sub {
-              height: 13px;
-              font-size: 12px;
-              font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-              font-weight: 400;
-              color: #7A8599;
-              line-height: 13px;
-            }
-          }
-  
-          .more {
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            cursor: pointer;
-            width: 16px;
-            height: 16px;
-            border-radius: 4px;
-            background: #FFFFFF;
-  
-            &>img {
-              width: 100%;
-              height: 100%;
-            }
-          }
-  
-          &.on {
-            font-weight: 500;
-            color: #17181A;
-            background: #F0F2F5;
-          }
-  
-          &:last-child {
-            margin-bottom: 0;
-          }
-        }
+      &.on {
+        font-weight: 500;
+        color: #17181a;
+        background: #f0f2f5;
+      }
+
+      &:last-child {
+        margin-bottom: 0;
       }
-}
+    }
+  }
+}

+ 24 - 29
src/components/KCIMModalForm/index.tsx

@@ -6,37 +6,32 @@
  * @FilePath: /BudgetManaSystem/src/components/BMSModalForm/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
-import { ModalForm, ModalFormProps } from "@ant-design/pro-components";
-import { FormLayout } from "antd/es/form/Form";
-import { useState } from "react";
-
-
-export type KCIMModalFormProps = ModalFormProps & {
-
-}
+import { ModalForm, ModalFormProps } from '@ant-design/pro-components';
+import { FormLayout } from 'antd/es/form/Form';
+import { useState } from 'react';
 
+export type KCIMModalFormProps = ModalFormProps & {};
 
 const LAYOUT_TYPE_HORIZONTAL = 'horizontal';
 
 const KCIMModalForm = (props: KCIMModalFormProps) => {
-
-    const { children, ...rest } = props;
-    const [formLayoutType, setFormLayoutType] = useState<FormLayout>('vertical');
-
-    const [grid, setGrid] = useState(true);
-
-    return (
-        <ModalForm {...rest}
-            layout={formLayoutType}
-            grid={grid}
-            rowProps={{
-                gutter: [16, formLayoutType === 'inline' ? 16 : 0],
-            }}
-        >
-            {children}
-        </ModalForm>
-    )
-}
-
-
-export default KCIMModalForm
+  const { children, ...rest } = props;
+  const [formLayoutType, setFormLayoutType] = useState<FormLayout>('vertical');
+
+  const [grid, setGrid] = useState(true);
+
+  return (
+    <ModalForm
+      {...rest}
+      layout={formLayoutType}
+      grid={grid}
+      rowProps={{
+        gutter: [16, formLayoutType === 'inline' ? 16 : 0],
+      }}
+    >
+      {children}
+    </ModalForm>
+  );
+};
+
+export default KCIMModalForm;

+ 51 - 37
src/components/KCIMPageContainer/index.tsx

@@ -12,16 +12,13 @@ import { PageContainer, PageContainerProps } from '@ant-design/pro-components';
 import { useModel } from '@umijs/max';
 import { useState } from 'react';
 import './style.less';
-import '../../utils/zhongtaiA'
+import '../../utils/zhongtaiA';
 
 const IconFont = createFromIconfontCN({
   scriptUrl: '',
 });
 
-
-export type KCIMPagecontainerPropType = PageContainerProps & {
-
-}
+export type KCIMPagecontainerPropType = PageContainerProps & {};
 
 interface MenuItem {
   function: any;
@@ -43,59 +40,76 @@ function findMenuItem(menu: MenuItem[], path: string): MenuItem | undefined {
 }
 
 const KCIMPagecontainer = (props: KCIMPagecontainerPropType) => {
-
   const { children, header, ...rest } = props;
-  
+
   const { initialState } = useModel('@@initialState');
 
-  const [open,set_open] = useState(false);
+  const [open, set_open] = useState(false);
 
   let description: undefined | string = undefined;
 
   if (initialState) {
     const thisPageData = findMenuItem(initialState.memuData, location.pathname);
-    description = thisPageData?.description
+    description = thisPageData?.description;
   }
 
-
   return (
-    <PageContainer {...rest}
+    <PageContainer
+      {...rest}
       header={{
         ...header,
         breadcrumb: {},
-        style: { padding: 0, },
-        childrenContentStyle: { padding: 0 }
+        style: { padding: 0 },
+        childrenContentStyle: { padding: 0 },
       }}
     >
       {children}
-      {
-        description && (
-          <div className={open?'pageHelp active':'pageHelp'} style={{ position: 'fixed', bottom: 24, right: 24, zIndex: 999, width: 40, height: 40 }}
-             onClick={(e)=>{ 
-              e.stopPropagation();             
-               set_open(!open)
-            }}
+      {description && (
+        <div
+          className={open ? 'pageHelp active' : 'pageHelp'}
+          style={{
+            position: 'fixed',
+            bottom: 24,
+            right: 24,
+            zIndex: 999,
+            width: 40,
+            height: 40,
+          }}
+          onClick={(e) => {
+            e.stopPropagation();
+            set_open(!open);
+          }}
+        >
+          <div
+            className={open ? 'helpContent open' : 'helpContent'}
+            onClick={(e) => e.stopPropagation()}
           >
-            <div className={open?'helpContent open':'helpContent'} onClick={(e)=>e.stopPropagation()}>
-              <div className='contentHeader'>
-                帮助中心
-                <div className='closeBtn' onClick={()=>set_open(false)}><IconFont type="iconquxiao" /></div>
+            <div className="contentHeader">
+              帮助中心
+              <div className="closeBtn" onClick={() => set_open(false)}>
+                <IconFont type="iconquxiao" />
               </div>
-              <div className='content'>
-                <img src={require('../../../static/mingcijieshi.png')} alt="" />
-                <div className='container'>
-                  <div className='inner' dangerouslySetInnerHTML={{ __html: description ? description : '' }}></div>
-                </div>
+            </div>
+            <div className="content">
+              <img src={require('../../../static/mingcijieshi.png')} alt="" />
+              <div className="container">
+                <div
+                  className="inner"
+                  dangerouslySetInnerHTML={{
+                    __html: description ? description : '',
+                  }}
+                ></div>
               </div>
             </div>
-            <IconFont className='boolIcon' type="icon-bangzhuzhongxin-weixuanzhong" />
           </div>
-        )
-      }
-
+          <IconFont
+            className="boolIcon"
+            type="icon-bangzhuzhongxin-weixuanzhong"
+          />
+        </div>
+      )}
     </PageContainer>
-  )
-}
-
+  );
+};
 
-export default KCIMPagecontainer
+export default KCIMPagecontainer;

+ 109 - 110
src/components/KCIMPageContainer/style.less

@@ -1,138 +1,137 @@
-
 .cost-ant-pro-page-container {
-    
-    border: 16px solid #F7F9FC;
+  border: 16px solid #f7f9fc;
 }
-.cost-ant-pro-page-container .cost-ant-pro-page-container-warp-page-header~.cost-ant-pro-grid-content .cost-ant-pro-page-container-children-content {
-    padding-block: 0 !important;
-    
+.cost-ant-pro-page-container
+  .cost-ant-pro-page-container-warp-page-header
+  ~ .cost-ant-pro-grid-content
+  .cost-ant-pro-page-container-children-content {
+  padding-block: 0 !important;
 }
 
 .cost-ant-pro-page-container-children-content {
-    padding-inline: 0 !important;
-    padding-block: 0 !important;
-    padding: 0;
+  padding-inline: 0 !important;
+  padding-block: 0 !important;
+  padding: 0;
 }
 
-
-.cost-ant-pro-page-container-warp-page-header~.cost-ant-pro-grid-content .cost-ant-pro-page-container-children-content {
-    padding-top: 16px !important;
+.cost-ant-pro-page-container-warp-page-header
+  ~ .cost-ant-pro-grid-content
+  .cost-ant-pro-page-container-children-content {
+  padding-top: 16px !important;
 }
 
-
-
 .cost-ant-page-header .cost-ant-page-header-heading-left {
-    margin-block: 0;
+  margin-block: 0;
 }
 
 .cost-ant-page-header .cost-ant-page-header-heading-title {
-    font-size: 16px;
-    height: 21px;
-    font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-    font-weight: 500;
-    color: #17181A;
-    line-height: 21px !important;
+  font-size: 16px;
+  height: 21px;
+  font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+  font-weight: 500;
+  color: #17181a;
+  line-height: 21px !important;
 }
 
 .pageHelp {
-    position: relative;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    background: #FFFFFF;
-    box-shadow: 0px 4px 6px 0px rgba(64, 85, 128, 0.1);
+  position: relative;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: #ffffff;
+  box-shadow: 0px 4px 6px 0px rgba(64, 85, 128, 0.1);
+  border-radius: 8px;
+  border: 1px solid #e6eaf2;
+  cursor: pointer;
+
+  .helpContent {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 0;
+    height: 0;
+    background: #ffffff;
+    box-shadow: 0px 8px 16px 0px rgba(64, 85, 128, 0.1);
     border-radius: 8px;
-    border: 1px solid #E6EAF2;
-    cursor: pointer;
-
-    .helpContent {
+    border: 1px solid #e6eaf2;
+    overflow: hidden;
+    transition: all 0.2s ease-in;
+
+    .contentHeader {
+      position: relative;
+      height: 40px;
+      background: #f7f9fc;
+      font-size: 16px;
+      font-weight: 500;
+      color: #17181a;
+      line-height: 40px;
+      padding-left: 16px;
+      border-bottom: 1px solid #e6eaf2;
+
+      .closeBtn {
+        display: flex;
+        justify-content: center;
+        align-items: center;
         position: absolute;
-        top:0;
-        right: 0;
-        width: 0;
-        height: 0;
-        background: #FFFFFF;
-        box-shadow: 0px 8px 16px 0px rgba(64, 85, 128, 0.1);
-        border-radius: 8px;
-        border: 1px solid #E6EAF2;
-        overflow: hidden;
-        transition: all 0.2s ease-in;
+        width: 20px;
+        height: 20px;
+        right: 12px;
+        top: 12px;
 
-        .contentHeader {
-            position: relative;
-            height: 40px;
-            background: #F7F9FC;
-            font-size: 16px;
-            font-weight: 500;
-            color: #17181A;
-            line-height: 40px;
-            padding-left: 16px;
-            border-bottom: 1px solid #E6EAF2;
-
-            .closeBtn {
-                display: flex;
-                justify-content: center;
-                align-items: center;
-                position: absolute;
-                width: 20px;
-                height: 20px;
-                right: 12px;
-                top:12px;
-
-                .anticon {
-                    font-size: 16px;
-                    color:#17181A
-                }
-            }
-        }
-        .content {
-            padding:16px;
-            img {
-                 width: 288px;
-                 height: 80px;
-                 margin-bottom: 16px;
-            }
-            .container {
-                 height: 430px;
-                 overflow-y: scroll;
-                 .inner {
-                    font-size: 12px;
-                    font-weight: 400;
-                    color: #525966;
-                    line-height: 16px;
-                    h1 {
-                        margin-bottom: 4px;
-                    }
-                    p {
-                        line-height: 16px;
-                    }
-                 }
-            }
+        .anticon {
+          font-size: 16px;
+          color: #17181a;
         }
-
-        &.open {
-         width: 320px;
-         height: 600px;
-         top: -616px;
+      }
+    }
+    .content {
+      padding: 16px;
+      img {
+        width: 288px;
+        height: 80px;
+        margin-bottom: 16px;
+      }
+      .container {
+        height: 430px;
+        overflow-y: scroll;
+        .inner {
+          font-size: 12px;
+          font-weight: 400;
+          color: #525966;
+          line-height: 16px;
+          h1 {
+            margin-bottom: 4px;
+          }
+          p {
+            line-height: 16px;
+          }
         }
+      }
     }
 
-    .anticon {
-        font-size: 27px;
-        color: #6B7A99;
+    &.open {
+      width: 320px;
+      height: 600px;
+      top: -616px;
     }
+  }
 
-    &.active {
-        .anticon {
-            font-size: 27px;
-            color: #17181A;
-        }
+  .anticon {
+    font-size: 27px;
+    color: #6b7a99;
+  }
+
+  &.active {
+    .anticon {
+      font-size: 27px;
+      color: #17181a;
     }
+  }
 
-    &:hover {
-        .anticon {
-            font-size: 27px;
-            color: #17181A;
-        }
+  &:hover {
+    .anticon {
+      font-size: 27px;
+      color: #17181a;
     }
-}
+  }
+}

+ 71 - 0
src/components/KCIMTable/VirtualRow.tsx

@@ -0,0 +1,71 @@
+import React, { useEffect, useRef, useState } from 'react';
+
+const observerOptions = {
+  rootMargin: '200px 0px',
+  threshold: 0,
+};
+
+// Global observer to reduce memory usage
+let globalObserver: IntersectionObserver | null = null;
+const observerCallbacks = new WeakMap<Element, (inView: boolean) => void>();
+
+const getObserver = () => {
+  if (typeof window === 'undefined') return null;
+  if (!globalObserver) {
+    globalObserver = new IntersectionObserver((entries) => {
+      entries.forEach((entry) => {
+        const callback = observerCallbacks.get(entry.target);
+        if (callback) {
+          callback(entry.isIntersecting);
+        }
+      });
+    }, observerOptions);
+  }
+  return globalObserver;
+};
+
+export const VirtualRow = React.forwardRef<any, any>((props, ref) => {
+  const { className, style, children, ...restProps } = props;
+  const [inView, setInView] = useState(true); // Default to true to render initially and let observer hide it if out of view
+  const rowRef = useRef<HTMLTableRowElement>(null);
+
+  useEffect(() => {
+    if (typeof ref === 'function') ref(rowRef.current);
+    else if (ref) (ref as any).current = rowRef.current;
+  }, [ref, rowRef.current]);
+
+  useEffect(() => {
+    const target = rowRef.current;
+    if (!target) return;
+
+    const observer = getObserver();
+    if (observer) {
+      observerCallbacks.set(target, setInView);
+      observer.observe(target);
+    }
+
+    return () => {
+      if (observer && target) {
+        observer.unobserve(target);
+        observerCallbacks.delete(target);
+      }
+    };
+  }, []);
+
+  if (!inView) {
+    return (
+      <tr
+        ref={rowRef}
+        className={className}
+        style={{ ...style, height: 38 }}
+        {...restProps}
+      />
+    );
+  }
+
+  return (
+    <tr ref={rowRef} className={className} style={style} {...restProps}>
+      {children}
+    </tr>
+  );
+});

+ 48 - 51
src/components/KCIMTable/index.tsx

@@ -6,60 +6,57 @@
  * @FilePath: /BudgetManaSystem/src/components/BMSTable/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
-import { deepEqual } from "@/utils/tooljs"
-import { ProTable, ProTableProps } from "@ant-design/pro-components"
-import { useEffect, useState } from "react"
+import { ProTable, ProTableProps } from '@ant-design/pro-components';
+import { useMemo } from 'react';
 
-import './style.less'
+import './style.less';
 
-export type KCIMTablePropsType<T, U, ValueType> = ProTableProps<T, U, ValueType> & {
-    
-}
+export type KCIMTablePropsType<T, U, ValueType> = ProTableProps<
+  T,
+  U,
+  ValueType
+> & {};
 
 export const KCIMTablePageDefaultConfig = {
-    defaultPageSize:10
-}
+  defaultPageSize: 10,
+};
 
 export const KCIMTable = (props: KCIMTablePropsType<any, any, any>) => {
-
-    const { params,options = false,request,columns,...rest } = props;
-    const [prevParams,set_prevParams] = useState<any>(undefined);
-
-    useEffect(()=>{
-        // console.log({'deepEqual(prevParams,params)':deepEqual(prevParams,params)});
-        // console.log({prevParams,params});
-
-        if(deepEqual(prevParams,params)){
-            
-        }else{
-              
-        }
-        set_prevParams(params);
-    
-    },[params])
-
-    
-    
-    return (
-        <ProTable
-            tableClassName="KCIMTable"
-            toolBarRender={false}
-            options={options}
-            columns={columns?.map(a=>({...a,ellipsis:true}))}
-            pagination={{
-                   showSizeChanger:true,
-                   ...KCIMTablePageDefaultConfig
-            }}
-            //locale={{emptyText:'暂无数据'}}
-            params={{...params}}
-            bordered={false}
-            search={false}
-            tableStyle={{
-                border:'1px solid #DAE2F2',
-                borderRadius:'8px'
-            }}
-            request={request?(params,sort,filter)=>request({...params},sort,filter):undefined}
-            {...rest} 
-        />
-    )
-}
+  const { params, options = false, request, columns, ...rest } = props;
+  const mergedColumns = useMemo(
+    () => columns?.map((column) => ({ ...column, ellipsis: true })),
+    [columns],
+  );
+  const mergedParams = useMemo(
+    () => (params ? { ...params } : params),
+    [params],
+  );
+  const wrappedRequest = useMemo(() => {
+    if (!request) return undefined;
+    return (requestParams: any, sort: any, filter: any) =>
+      request({ ...requestParams }, sort, filter);
+  }, [request]);
+
+  return (
+    <ProTable
+      tableClassName="KCIMTable"
+      toolBarRender={false}
+      options={options}
+      columns={mergedColumns}
+      pagination={{
+        showSizeChanger: true,
+        ...KCIMTablePageDefaultConfig,
+      }}
+      //locale={{emptyText:'暂无数据'}}
+      params={mergedParams}
+      bordered={false}
+      search={false}
+      tableStyle={{
+        border: '1px solid #DAE2F2',
+        borderRadius: '8px',
+      }}
+      request={wrappedRequest}
+      {...rest}
+    />
+  );
+};

+ 204 - 197
src/components/KCIMTable/style.less

@@ -1,260 +1,267 @@
 .cost-ant-table-wrapper {
-    border-radius: 4px !important;
+  border-radius: 4px !important;
 
-    table {
-        border-radius: 4px !important;
-    }
+  table {
+    border-radius: 4px !important;
+  }
 
-    .cost-ant-table-container {
-        border-start-start-radius: 4px !important;
-        border-start-end-radius: 4px !important;
-    }
+  .cost-ant-table-container {
+    border-start-start-radius: 4px !important;
+    border-start-end-radius: 4px !important;
+  }
 
-    // 移除空规则,避免linter警告
+  // 移除空规则,避免linter警告
 }
 
 .cost-ant-table .cost-ant-table-header {
-    border-radius: 4px !important;
+  border-radius: 4px !important;
 }
 
 .cost-ant-pro-table .cost-ant-pro-card .cost-ant-pro-card-body {
-     padding-inline: 0 !important;
+  padding-inline: 0 !important;
 }
 
 .cost-ant-table-thead > tr > th {
-    padding: 8px 8px !important;
-    background: #eef3fa !important;
+  padding: 8px 8px !important;
+  background: #eef3fa !important;
 
-    &::before {
-        display: none !important;
-    }
+  &::before {
+    display: none !important;
+  }
 }
 
-
 .cost-ant-table-wrapper .cost-ant-table-pagination.cost-ant-pagination {
-    padding-right: 16px;
+  padding-right: 16px;
 }
 
-.cost-ant-table-wrapper .cost-ant-table.cost-ant-table-bordered>.cost-ant-table-container>.cost-ant-table-body>table>tbody>tr>td {
-    //#dae2f2
-    border-inline-end: 1px solid #dae2f2 !important;
+.cost-ant-table-wrapper
+  .cost-ant-table.cost-ant-table-bordered
+  > .cost-ant-table-container
+  > .cost-ant-table-body
+  > table
+  > tbody
+  > tr
+  > td {
+  //#dae2f2
+  border-inline-end: 1px solid #dae2f2 !important;
 }
 
-
-
 .KCIMTable {
-    .cost-ant-table {
-        .cost-ant-space-align-center {
-            gap: 0 !important;
+  .cost-ant-table {
+    .cost-ant-space-align-center {
+      gap: 0 !important;
+    }
+
+    .cost-ant-table-thead {
+      .cost-ant-table-cell {
+        padding: 8px 8px !important;
+        background: rgb(238 243 250 / 100%) !important;
+        // 表头允许换行
+        white-space: normal !important;
+        word-break: break-word !important;
+        overflow-wrap: anywhere;
+        // 多层级表头边框
+        border-bottom: 1px solid #dae2f2 !important;
+        border-right: 1px solid #dae2f2 !important;
+      }
+      // 首列左边框
+      > tr > th:first-child {
+        border-left: 1px solid #dae2f2 !important;
+      }
+
+      a {
+        color: #3376fe;
+      }
+
+      .cost-ant-table-selection {
+        .cost-ant-table-selection-extra {
+          top: 5px;
         }
+      }
 
-        .cost-ant-table-thead {
-            .cost-ant-table-cell {
-                padding: 8px 8px !important;
-                background: rgb(238 243 250 / 100%) !important;
-                // 表头允许换行
-                white-space: normal !important;
-                word-break: break-word !important;
-                overflow-wrap: anywhere;
-                // 多层级表头边框
-                border-bottom: 1px solid #dae2f2 !important;
-                border-right: 1px solid #dae2f2 !important;
-            }
-            // 首列左边框
-            > tr > th:first-child { border-left: 1px solid #dae2f2 !important; }
+      &::before {
+        display: none;
+      }
 
-            a {
-                color: #3376FE;
-            }
+      &:hover {
+        background: rgb(238 243 250 / 100%) !important;
+      }
 
+      // 不再去掉最后一个表头格子的右边框,保持分隔
+    }
 
-            .cost-ant-table-selection {
-                .cost-ant-table-selection-extra {
-                    top: 5px;
-                }
-            }
+    .cost-ant-table-tbody {
+      & > tr {
+        &.cost-ant-table-measure-row {
+          border: none !important;
+          & > td {
+            border-inline-end: none !important;
+          }
+        }
 
-            &::before {
-                display: none;
+        &.cost-ant-table-row {
+          .cost-ant-table-cell {
+            font-size: 14px;
+            font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+            justify-content: flex-start !important;
+            color: #17181a;
+            padding: 8px 8px !important;
+            border-bottom: none !important;
+            border-top: 1px solid rgb(218 226 242) !important;
+
+            &.cost-ant-table-cell-with-append {
+              .cost-ant-table-row-expand-icon {
+                border-radius: 4px !important;
+                border: 1px solid #dae2f2 !important;
+
+                &:hover {
+                  color: #3377ff;
+                  border: 1px solid #3377ff !important;
+                }
+              }
             }
 
-            &:hover {
-                background: rgb(238 243 250 / 100%) !important;
+            & > .cost-ant-typography {
+              line-height: unset;
             }
 
-            // 不再去掉最后一个表头格子的右边框,保持分隔
-        }
+            // 移除空规则,避免linter警告
 
-        .cost-ant-table-tbody {
-            &>tr {
-                &.cost-ant-table-measure-row {
-                    border: none !important;
-                    &>td {
-                        border-inline-end:none !important;
-                    }
-                }
+            // &:hover {
+            //     border-radius: 0 !important;
+            //     background: #FAFBFC !important;
 
-                &.cost-ant-table-row {
-                    .cost-ant-table-cell {
-                    
-                        font-size: 14px;
-                        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-                        justify-content: flex-start !important;
-                        color: #17181A;
-                        padding: 8px 8px !important; 
-                        border-bottom: none !important;
-                        border-top: 1px solid rgb(218 226 242) !important;
-
-                        &.cost-ant-table-cell-with-append {
-                            .cost-ant-table-row-expand-icon {
-                                  border-radius: 4px !important;
-                                  border: 1px solid #DAE2F2 !important;
-
-                                  &:hover {
-                                    color: #3377ff;
-                                    border: 1px solid #3377ff !important;
-                                  }
-                            }
-                        }
-    
-                        &>.cost-ant-typography {
-                            line-height:unset;
-                        }
-    
-                        // 移除空规则,避免linter警告
-    
-                        // &:hover {
-                        //     border-radius: 0 !important;
-                        //     background: #FAFBFC !important;
-    
-                        // }
-                    }
-                }
+            // }
+          }
+        }
 
+        &.cost-ant-table-row-selected {
+          .cost-ant-table-cell {
+            border-radius: 0 !important;
+          }
+          &:hover {
+            background: #bae0ff !important;
+          }
+        }
 
+        &:last-child > td {
+          border-bottom: none !important;
+        }
+      }
+    }
 
-                &.cost-ant-table-row-selected {
-                    .cost-ant-table-cell {
-                        border-radius: 0 !important;
-                    }
-                    &:hover {
-                        background: #bae0ff !important;
-                    }
-                }
+    .cost-ant-table-summary {
+      & > tr > td {
+        // 不强制对齐,让各列按照 Summary.Cell 的 align 与列配置对齐
+        padding: 8px 8px !important; // 与tbody行保持一致高度
+        border-top: 1px solid #dae2f2 !important;
+      }
+    }
 
-                &:last-child>td {
-                    border-bottom: none !important;
-                }
+    &.cost-ant-table-bordered {
+      .cost-ant-table-container {
+        border-left: none !important;
+        .cost-ant-table-thead {
+          & > tr {
+            & > th {
+              border-right: 1px solid #dae2f2 !important;
+              border-bottom: 1px solid #dae2f2 !important;
+              border-top: none !important;
+
+              &.cost-ant-table-cell-scrollbar {
+                border: none !important;
+              }
+
+              &::after {
+                border: none !important;
+              }
             }
-        }
 
-        .cost-ant-table-summary {
-            &>tr>td {
-                // 不强制对齐,让各列按照 Summary.Cell 的 align 与列配置对齐
-                padding: 8px 8px !important; // 与tbody行保持一致高度
-                border-top: 1px solid #dae2f2 !important;
+            &:last-child {
+              & > th {
+                border-top: none !important;
+              }
             }
+          }
         }
-
-       
-
-        &.cost-ant-table-bordered {
-            .cost-ant-table-container {
-                border-left: none !important;
-                .cost-ant-table-thead {
-                    &>tr {
-                        &>th {
-                            border-right: 1px solid #dae2f2 !important;
-                            border-bottom: 1px solid #dae2f2 !important;
-                            border-top: none !important;
-
-                            &.cost-ant-table-cell-scrollbar {
-                                border: none !important;
-                            }
-
-                            &::after {
-                                border: none !important;
-                            }
-                        }
-
-                        &:last-child {
-                            &>th {
-                                border-top:none !important;
-                            }
-                        }
-                    }
-                }
-                .cost-ant-table-tbody{
-                    tr > td {
-                        border-right: 1px solid #dae2f2 !important;
-                        &::after {
-                            border: none !important;
-                        }
-                    }
-                }
-                
+        .cost-ant-table-tbody {
+          tr > td {
+            border-right: 1px solid #dae2f2 !important;
+            &::after {
+              border: none !important;
             }
+          }
         }
+      }
     }
-    .cost-ant-pagination {
-        padding: 7px 0;
-        margin: 0 !important;
-        border-top: 1px solid #dae2f2 !important;
-
-        .cost-ant-pagination-item-active {
-            font-weight: 600;
-            background-color: #37F !important;
-            border-color: #37F !important;
-        }
+  }
+  .cost-ant-pagination {
+    padding: 7px 0;
+    margin: 0 !important;
+    border-top: 1px solid #dae2f2 !important;
+
+    .cost-ant-pagination-item-active {
+      font-weight: 600;
+      background-color: #37f !important;
+      border-color: #37f !important;
     }
+  }
 
-    .cost-ant-pagination .cost-ant-pagination-item-active a {
-        color: #fff !important;
-    }
-
-
+  .cost-ant-pagination .cost-ant-pagination-item-active a {
+    color: #fff !important;
+  }
 }
 
-.cost-ant-table-wrapper .cost-ant-table-container table>thead>tr:first-child th:first-child {
-    border-start-start-radius: 4px !important;
+.cost-ant-table-wrapper
+  .cost-ant-table-container
+  table
+  > thead
+  > tr:first-child
+  th:first-child {
+  border-start-start-radius: 4px !important;
 }
 
-.cost-ant-table-wrapper .cost-ant-table-container table>thead>tr:first-child th:last-child {
-    border-start-end-radius: 4px !important;
+.cost-ant-table-wrapper
+  .cost-ant-table-container
+  table
+  > thead
+  > tr:first-child
+  th:last-child {
+  border-start-end-radius: 4px !important;
 }
 
 .cost-ant-empty-normal {
-    margin-block: 80px !important;
-    color: rgb(0 0 0 / 25%);
+  margin-block: 80px !important;
+  color: rgb(0 0 0 / 25%);
 }
 
 // 小计行高亮背景样式
 .subtotal-row {
-    background: #F2F8FF !important;
-    font-weight: 600; // 小计行加粗
+  background: #f2f8ff !important;
+  font-weight: 600; // 小计行加粗
 }
 
 // 兼容固定列:为固定列的单元格也着色
 .KCIMTable {
-    .cost-ant-table {
-        .cost-ant-table-tbody {
-            tr.subtotal-row > td,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-left,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-right,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-left-last,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-right-first {
-                background: #F2F8FF !important;
-                position: relative;
-                font-weight: 600; // 与整行一致加粗
-            }
-            // 去掉固定列的阴影遮罩,避免覆盖行背景
-            tr.subtotal-row > td.cost-ant-table-cell-fix-left::after,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-left-last::after,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-right::after,
-            tr.subtotal-row > td.cost-ant-table-cell-fix-right-first::after {
-                box-shadow: none !important;
-                background: transparent !important;
-            }
-        }
+  .cost-ant-table {
+    .cost-ant-table-tbody {
+      tr.subtotal-row > td,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-left,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-right,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-left-last,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-right-first {
+        background: #f2f8ff !important;
+        position: relative;
+        font-weight: 600; // 与整行一致加粗
+      }
+      // 去掉固定列的阴影遮罩,避免覆盖行背景
+      tr.subtotal-row > td.cost-ant-table-cell-fix-left::after,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-left-last::after,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-right::after,
+      tr.subtotal-row > td.cost-ant-table-cell-fix-right-first::after {
+        box-shadow: none !important;
+        background: transparent !important;
+      }
     }
-}
+  }
+}

+ 194 - 182
src/components/KCIMTableSelector/index.tsx

@@ -1,194 +1,206 @@
-import React, { Key, useEffect, useState } from "react";
+import React, { Key, useEffect, useState } from 'react';
 
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
 
+import {
+  ModalForm,
+  ProColumns,
+  ProFormSelect,
+  ProFormText,
+} from '@ant-design/pro-components';
 
-import { ModalForm, ProColumns, ProFormSelect, ProFormText } from "@ant-design/pro-components";
-
-import { set } from "lodash";
-import './style.less'
+import { set } from 'lodash';
+import './style.less';
 
 interface TableSelecterProps {
-    record: any
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
-
-const TableSelecter = (
-    { 
-        record, 
-        open, 
-        title, 
-        columns,
-        onVisibleChange,
-        rowKey = 'id',
-        request, 
-        tableData,
-        onFinish,
-        defaultSelectedKeys,
-    }: 
-    {
-        record: any,
-        columns:ProColumns[],
-        open: boolean,
-        title: string,
-        tableData?:any[],
-        onVisibleChange: (bool: boolean) => void,
-        defaultSelectedKeys: Key[],
-        rowKey?: string,
-        request?: () => Promise<any>,
-        onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void
-    }
-) => {
-
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-        const [selectedRows, set_selectedRows] = useState<any[]>([]);
-        const [showList, set_showList] = useState<any[]>([]);
-        const [filter, set_filter] = useState<undefined | any>(undefined);
-        const [code, set_code] = useState<undefined | any>(undefined);
-        const [keyword, set_keyword] = useState<string | undefined>(undefined);
-
-
-        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-            set_selectedRows([...selectedRows]);
-
-        };
-
-        const saveHandle = async () => {
-            const selectedRowkeys = selectedRows.map((a) => a[`${rowKey}`]);
-            const rows = datasource.filter((a) => selectedRowkeys.includes(a[`${rowKey}`]));
-            onFinish && onFinish(selectedKeys, rows);
-        }
-
-        const getTableData = async () => {
-
-            const resp = !tableData&&request?await request():tableData;
-
-            let selectedCodes: string[] = [];
-            let selectedRows: any[] = [];
-            if (resp) {
-                console.log({defaultSelectedKeys});
-                const data = resp.map((a: any) => {
-                    if (defaultSelectedKeys.includes(a[`${rowKey}`])) {
-                        selectedCodes.push(a[`${rowKey}`]);
-                        selectedRows.push(a);
-                        //const needItem = record.departList.filter((b: any) => a[`${rowKey}`] == b[`${rowKey}`]);
-
-                        return {
-                            ...a,
-                            //flag: needItem[0].isManager ? true : false
-                        }
-                    } else {
-                        return a
-                    }
-                });
-
-                set_showList(data);
-                set_selectedRows([...selectedRows]);
-                setSelectedKeys([...selectedCodes]);
-                set_datasource([...datasource, ...data]);
-            }
-
-
-            return Promise.resolve([]);
-        }
-
-        useEffect(() => {
-            // console.log({code, keyword});
-            const result = datasource.filter((a) => {
-                return a.name ? a.name.indexOf(keyword) != -1 : false
-            });
-
-            set_showList([...result]);
-        }, [keyword]);
-
-        // useEffect(()=>{
-        //     (record)&&getTableData(record)
-        // },[record])
-
-        useEffect(()=>{
-           getTableData()
-        },[])
-
-        return (
-            <div >
-                <div className="filter" style={{ display: 'flex', flexDirection: 'row', marginBottom: 8 }}>
-                    <ProFormText noStyle placeholder={'请输入'}
-                        fieldProps={{
-                            suffix: <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />,
-                            onChange: (e) => {
-                                if (e.target.value.length != 0) {
-                                    set_keyword(e.target.value);
-                                } else {
-                                    set_keyword('');
-                                }
-                            }
-                        }}
-                    />
-                </div>
-
-                <KCIMTable columns={columns}
-                    options={{
-                        density: true,
-                        setting: {
-                            listsHeight: 100,
-                        },
-                    }}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    rowSelection={{
-                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
-                        // 注释该行则默认不显示下拉选项
-                        // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
-                        selectedRowKeys: selectedKeys,
-                        onChange: onSelectChange,
-                    }}
-                    pagination={{ showTitle: false, showSizeChanger: false, simple: true }}
-                    dataSource={showList}
-
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
-                </div>
-            </div>
-
-        )
-    });
-
-    const close = () => {
-        onVisibleChange && onVisibleChange(false);
-    }
-
+const TableSelecter = ({
+  record,
+  open,
+  title,
+  columns,
+  onVisibleChange,
+  rowKey = 'id',
+  request,
+  tableData,
+  onFinish,
+  defaultSelectedKeys,
+}: {
+  record: any;
+  columns: ProColumns[];
+  open: boolean;
+  title: string;
+  tableData?: any[];
+  onVisibleChange: (bool: boolean) => void;
+  defaultSelectedKeys: Key[];
+  rowKey?: string;
+  request?: () => Promise<any>;
+  onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void;
+}) => {
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+    const [selectedRows, set_selectedRows] = useState<any[]>([]);
+    const [showList, set_showList] = useState<any[]>([]);
+    const [filter, set_filter] = useState<undefined | any>(undefined);
+    const [code, set_code] = useState<undefined | any>(undefined);
+    const [keyword, set_keyword] = useState<string | undefined>(undefined);
+
+    const onSelectChange = (
+      newSelectedRowKeys: React.Key[],
+      selectedRows: any,
+    ) => {
+      setSelectedKeys([...newSelectedRowKeys]);
+      set_selectedRows([...selectedRows]);
+    };
+
+    const saveHandle = async () => {
+      const selectedRowkeys = selectedRows.map((a) => a[`${rowKey}`]);
+      const rows = datasource.filter((a) =>
+        selectedRowkeys.includes(a[`${rowKey}`]),
+      );
+      onFinish && onFinish(selectedKeys, rows);
+    };
+
+    const getTableData = async () => {
+      const resp = !tableData && request ? await request() : tableData;
+
+      let selectedCodes: string[] = [];
+      let selectedRows: any[] = [];
+      if (resp) {
+        console.log({ defaultSelectedKeys });
+        const data = resp.map((a: any) => {
+          if (defaultSelectedKeys.includes(a[`${rowKey}`])) {
+            selectedCodes.push(a[`${rowKey}`]);
+            selectedRows.push(a);
+            //const needItem = record.departList.filter((b: any) => a[`${rowKey}`] == b[`${rowKey}`]);
+
+            return {
+              ...a,
+              //flag: needItem[0].isManager ? true : false
+            };
+          } else {
+            return a;
+          }
+        });
+
+        set_showList(data);
+        set_selectedRows([...selectedRows]);
+        setSelectedKeys([...selectedCodes]);
+        set_datasource([...datasource, ...data]);
+      }
+
+      return Promise.resolve([]);
+    };
+
+    useEffect(() => {
+      // console.log({code, keyword});
+      const result = datasource.filter((a) => {
+        return a.name ? a.name.indexOf(keyword) != -1 : false;
+      });
+
+      set_showList([...result]);
+    }, [keyword]);
+
+    // useEffect(()=>{
+    //     (record)&&getTableData(record)
+    // },[record])
+
+    useEffect(() => {
+      getTableData();
+    }, []);
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={400} submitter={{
-            render: false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-
-
-export default TableSelecter
+      <div>
+        <div
+          className="filter"
+          style={{ display: 'flex', flexDirection: 'row', marginBottom: 8 }}
+        >
+          <ProFormText
+            noStyle
+            placeholder={'请输入'}
+            fieldProps={{
+              suffix: (
+                <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
+              ),
+              onChange: (e) => {
+                if (e.target.value.length != 0) {
+                  set_keyword(e.target.value);
+                } else {
+                  set_keyword('');
+                }
+              },
+            }}
+          />
+        </div>
+
+        <KCIMTable
+          columns={columns}
+          options={{
+            density: true,
+            setting: {
+              listsHeight: 100,
+            },
+          }}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          rowSelection={{
+            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+            // 注释该行则默认不显示下拉选项
+            // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+            selectedRowKeys: selectedKeys,
+            onChange: onSelectChange,
+          }}
+          pagination={{
+            showTitle: false,
+            showSizeChanger: false,
+            simple: true,
+          }}
+          dataSource={showList}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认(${
+            selectedKeys.length > 0 && selectedKeys.length
+          })`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={400}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default TableSelecter;

+ 28 - 30
src/components/KCIMTableSelector/style.less

@@ -1,33 +1,31 @@
 .TableSelecter {
+  .pfm-ant-modal-footer {
+    display: none !important;
+  }
 
-    .pfm-ant-modal-footer {
-      display: none !important;
-    }
-    
-    .footer {
-         display: flex;
-         flex-direction:row;
-         justify-content: flex-end;
-         margin-top: 15px;
-         span {
-             display: inline-block;
-             width: 56px;
-             height: 24px;  
-             font-size: 14px;
-             line-height: 23px;
-             text-align: center;
-             border-radius: 4px;
-             cursor: pointer;
-  
-             &.ok {
-                 color: #FFFFFF;
-                 background:#3377FF;
-                 margin-left: 8px;
-             }
-             &.cancel {
-                 border: 1px solid #DAE2F2;
-             }
-         }
-  
+  .footer {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+    margin-top: 15px;
+    span {
+      display: inline-block;
+      width: 56px;
+      height: 24px;
+      font-size: 14px;
+      line-height: 23px;
+      text-align: center;
+      border-radius: 4px;
+      cursor: pointer;
+
+      &.ok {
+        color: #ffffff;
+        background: #3377ff;
+        margin-left: 8px;
+      }
+      &.cancel {
+        border: 1px solid #dae2f2;
+      }
     }
-  }
+  }
+}

+ 59 - 53
src/components/KCIMUpload/index.tsx

@@ -7,8 +7,6 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import React, { useState } from 'react';
 import { InboxOutlined } from '@ant-design/icons';
 import { Alert, UploadFile, UploadProps } from 'antd';
@@ -19,61 +17,69 @@ import './style.less';
 const { Dragger } = Upload;
 
 type KCIMUploadPropsType = {
-    onChange?: () => void;
-    ifShowTip?: boolean;  //是否展示黄底提示
-    ifShowTemplateDownload?: boolean;//是否展示模板下载
-    downloadTemplateFile?: () => void; //模板下载回调
-} & UploadProps
+  onChange?: () => void;
+  ifShowTip?: boolean; //是否展示黄底提示
+  ifShowTemplateDownload?: boolean; //是否展示模板下载
+  downloadTemplateFile?: () => void; //模板下载回调
+} & UploadProps;
 
 const KCIMUpload = (props: KCIMUploadPropsType) => {
-    const [fileList, setFileList] = useState<UploadFile[]>([]);
-    const { onChange, downloadTemplateFile, ifShowTip = true, ifShowTemplateDownload = true } = props;
+  const [fileList, setFileList] = useState<UploadFile[]>([]);
+  const {
+    onChange,
+    downloadTemplateFile,
+    ifShowTip = true,
+    ifShowTemplateDownload = true,
+  } = props;
 
-    const config: UploadProps = {
-        action: () => Promise.resolve(''),
-        name: 'file',
-        multiple: false,
-        beforeUpload: (file) => {
-            setFileList([...fileList, file]);
-            return false;
-        },
-        //onChange:onChange?onChange:()=>{},
-        onChange: (fileInfo) => {
-            onChange && onChange(fileInfo);
-            
-        },
-        onDrop(e) {
-            console.log('Dropped files', e.dataTransfer.files);
-        },
-    };
+  const config: UploadProps = {
+    action: () => Promise.resolve(''),
+    name: 'file',
+    multiple: false,
+    beforeUpload: (file) => {
+      setFileList([...fileList, file]);
+      return false;
+    },
+    //onChange:onChange?onChange:()=>{},
+    onChange: (fileInfo) => {
+      onChange && onChange(fileInfo);
+    },
+    onDrop(e) {
+      console.log('Dropped files', e.dataTransfer.files);
+    },
+  };
 
-    const download = () => {
-        downloadTemplateFile && downloadTemplateFile()
-    }
+  const download = () => {
+    downloadTemplateFile && downloadTemplateFile();
+  };
 
-    return (
-        <div className='KCIMUpload' style={{ paddingBottom: 16 }}>
-            {
-                ifShowTemplateDownload && (
-                    <div className='toolBar'>
-                        <span>文件下载</span>
-                        <span onClick={() => download()}>模板下载</span>
-                    </div>
-                )
-            }
-            {
-               ifShowTip&&(<Alert message="注意,导入的数据将会覆盖当前数据" type="warning" style={{ height: 24, fontSize: 12, marginBottom: 16, marginTop: 16 }} showIcon closable banner />) 
-            }
-            
-            <Dragger {...config} height={140}>
-                <p className="ant-upload-drag-icon" style={{ marginBottom: 5 }}>
-                    <InboxOutlined style={{ fontSize: 50, color: '#3376FE' }} />
-                </p>
-                <p className="ant-upload-text">点击或将文件拖拽到这里上传</p>
-
-            </Dragger>
+  return (
+    <div className="KCIMUpload" style={{ paddingBottom: 16 }}>
+      {ifShowTemplateDownload && (
+        <div className="toolBar">
+          <span>文件下载</span>
+          <span onClick={() => download()}>模板下载</span>
         </div>
-    )
-}
+      )}
+      {ifShowTip && (
+        <Alert
+          message="注意,导入的数据将会覆盖当前数据"
+          type="warning"
+          style={{ height: 24, fontSize: 12, marginBottom: 16, marginTop: 16 }}
+          showIcon
+          closable
+          banner
+        />
+      )}
+
+      <Dragger {...config} height={140}>
+        <p className="ant-upload-drag-icon" style={{ marginBottom: 5 }}>
+          <InboxOutlined style={{ fontSize: 50, color: '#3376FE' }} />
+        </p>
+        <p className="ant-upload-text">点击或将文件拖拽到这里上传</p>
+      </Dragger>
+    </div>
+  );
+};
 
-export default KCIMUpload;
+export default KCIMUpload;

+ 5 - 6
src/components/KCIMUpload/style.less

@@ -11,20 +11,19 @@
     margin-bottom: 16px;
     margin-top: 16px;
 
-    &>span {
+    & > span {
       display: inline-block;
       height: 15px;
       font-size: 14px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #17181A;
-      line-height:15px;
+      color: #17181a;
+      line-height: 15px;
 
       &:last-child {
-           cursor: pointer;
-           color: #3376FE;
+        cursor: pointer;
+        color: #3376fe;
       }
     }
   }
-  
 }

+ 39 - 15
src/components/ProgressModal/index.tsx

@@ -14,10 +14,15 @@ interface ProgressModalProps {
   type: string;
   onComplete: () => void;
   visible: boolean;
-  title: string
+  title: string;
 }
 
-const ProgressModal: React.FC<ProgressModalProps> = ({ type, onComplete, visible, title }) => {
+const ProgressModal: React.FC<ProgressModalProps> = ({
+  type,
+  onComplete,
+  visible,
+  title,
+}) => {
   const [progressPercent, setProgressPercent] = useState(0);
   const [processStr, set_processStr] = useState('');
 
@@ -37,7 +42,6 @@ const ProgressModal: React.FC<ProgressModalProps> = ({ type, onComplete, visible
           onComplete(); // 当进度达到100%时,触发完成回调
         }
       }
-
     } catch (error) {
       console.error('Error fetching progress data:', error);
     }
@@ -48,7 +52,7 @@ const ProgressModal: React.FC<ProgressModalProps> = ({ type, onComplete, visible
     if (resp) {
       onComplete();
     }
-  }
+  };
 
   useEffect(() => {
     let pollingInterval: NodeJS.Timeout | null = null;
@@ -74,17 +78,37 @@ const ProgressModal: React.FC<ProgressModalProps> = ({ type, onComplete, visible
       closable={false} // 如果不需要模态框的关闭按钮,可以设置为 false
     >
       <Progress percent={progressPercent} />
-      {
-        type == 'ITEM_BATCH_MATCH' && (
-          <>
-            <div style={{ fontSize: 14, color: '#525866', marginTop: 3, marginBottom: 24 }}>已完成{processStr}</div>
-            <div onClick={() => stopHandle()} style={{
-              width: 56, height: 24, textAlign: 'center', fontSize: 14, marginLeft: 430,
-              color: '#17181A', cursor: 'pointer', background: '#FAFCFF', borderRadius: 4, border: '1px solid #DAE2F2'
-            }}>取消</div>
-          </>
-        )
-      }
+      {type == 'ITEM_BATCH_MATCH' && (
+        <>
+          <div
+            style={{
+              fontSize: 14,
+              color: '#525866',
+              marginTop: 3,
+              marginBottom: 24,
+            }}
+          >
+            已完成{processStr}
+          </div>
+          <div
+            onClick={() => stopHandle()}
+            style={{
+              width: 56,
+              height: 24,
+              textAlign: 'center',
+              fontSize: 14,
+              marginLeft: 430,
+              color: '#17181A',
+              cursor: 'pointer',
+              background: '#FAFCFF',
+              borderRadius: 4,
+              border: '1px solid #DAE2F2',
+            }}
+          >
+            取消
+          </div>
+        </>
+      )}
     </Modal>
   );
 };

+ 19 - 25
src/components/ProgressModal/service.ts

@@ -7,28 +7,22 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
-import { request } from '@@/plugin-request'
-
-
-
-export const getPercentData = (type:string)=>{
-    return request('/costAccount/public/getPercent', {
-         method:'GET',
-         params:{
-            type 
-        }
-    })
-}
-
-export const stopGetPercentData = (type:string)=>{
-    return request('/costAccount/public/endProgress', {
-         method:'POST',
-         params:{
-            type 
-        }
-    })
-}
+import { request } from '@@/plugin-request';
+
+export const getPercentData = (type: string) => {
+  return request('/costAccount/public/getPercent', {
+    method: 'GET',
+    params: {
+      type,
+    },
+  });
+};
+
+export const stopGetPercentData = (type: string) => {
+  return request('/costAccount/public/endProgress', {
+    method: 'POST',
+    params: {
+      type,
+    },
+  });
+};

+ 55 - 47
src/components/ResizableContainer/index.tsx

@@ -10,62 +10,70 @@ import React, { useState, useCallback, useEffect, useRef } from 'react';
 import './style.less';
 
 interface ResizableContainerProps {
-    width?: number;
-    minWidth?: number;
-    maxWidth?: number;
-    height?:string;
+  width?: number;
+  minWidth?: number;
+  maxWidth?: number;
+  height?: string;
 }
 
-const ResizableContainer: React.FC<React.PropsWithChildren<ResizableContainerProps>> = ({
-    width = 250,
-    minWidth = 100,
-    maxWidth = 800,
-    height = '800px',
-    children,
+const ResizableContainer: React.FC<
+  React.PropsWithChildren<ResizableContainerProps>
+> = ({
+  width = 250,
+  minWidth = 100,
+  maxWidth = 800,
+  height = '800px',
+  children,
 }) => {
-    const [containerWidth, setContainerWidth] = useState(width);
-    const isResizing = useRef(false);
+  const [containerWidth, setContainerWidth] = useState(width);
+  const isResizing = useRef(false);
 
-    const handleMouseMove = useCallback((e: MouseEvent) => {
-        if (isResizing.current) {
-            const newWidth = Math.min(Math.max(e.clientX, minWidth), maxWidth);
-            setContainerWidth(newWidth);
-        }
-    }, [minWidth, maxWidth]);
+  const handleMouseMove = useCallback(
+    (e: MouseEvent) => {
+      if (isResizing.current) {
+        const newWidth = Math.min(Math.max(e.clientX, minWidth), maxWidth);
+        setContainerWidth(newWidth);
+      }
+    },
+    [minWidth, maxWidth],
+  );
 
-    const handleMouseUp = useCallback(() => {
-        isResizing.current = false;
-        document.removeEventListener('mousemove', handleMouseMove);
-        document.removeEventListener('mouseup', handleMouseUp);
-        document.body.style.userSelect = 'auto'; // 恢复文本选择
-    }, [handleMouseMove]);
+  const handleMouseUp = useCallback(() => {
+    isResizing.current = false;
+    document.removeEventListener('mousemove', handleMouseMove);
+    document.removeEventListener('mouseup', handleMouseUp);
+    document.body.style.userSelect = 'auto'; // 恢复文本选择
+  }, [handleMouseMove]);
 
-    const handleMouseDown = useCallback(() => {
-        isResizing.current = true;
-        document.addEventListener('mousemove', handleMouseMove);
-        document.addEventListener('mouseup', handleMouseUp);
-        document.body.style.userSelect = 'none'; // 禁用文本选择
-    }, [handleMouseMove, handleMouseUp]);
+  const handleMouseDown = useCallback(() => {
+    isResizing.current = true;
+    document.addEventListener('mousemove', handleMouseMove);
+    document.addEventListener('mouseup', handleMouseUp);
+    document.body.style.userSelect = 'none'; // 禁用文本选择
+  }, [handleMouseMove, handleMouseUp]);
 
-    useEffect(() => {
-        return () => {
-            document.removeEventListener('mousemove', handleMouseMove);
-            document.removeEventListener('mouseup', handleMouseUp);
-        };
-    }, [handleMouseMove, handleMouseUp]);
+  useEffect(() => {
+    return () => {
+      document.removeEventListener('mousemove', handleMouseMove);
+      document.removeEventListener('mouseup', handleMouseUp);
+    };
+  }, [handleMouseMove, handleMouseUp]);
 
-    useEffect(() => {
-        setContainerWidth(width);
-    }, [width]);
+  useEffect(() => {
+    setContainerWidth(width);
+  }, [width]);
 
-    return (
-        <div className="ResizableContainer">
-            <div className="resizable" style={{ width: `${containerWidth}px`, height: `${height}` }}>
-                {children}
-            </div>
-            <div className="resizer" onMouseDown={handleMouseDown} />
-        </div>
-    );
+  return (
+    <div className="ResizableContainer">
+      <div
+        className="resizable"
+        style={{ width: `${containerWidth}px`, height: `${height}` }}
+      >
+        {children}
+      </div>
+      <div className="resizer" onMouseDown={handleMouseDown} />
+    </div>
+  );
 };
 
 export default ResizableContainer;

+ 17 - 22
src/components/ResizableContainer/style.less

@@ -1,24 +1,19 @@
-
-
 .ResizableContainer {
-    position: relative;
-    height:100%;
-    .resizable {
-        height: 100%;
-        overflow: hidden;
-    }
-    
-    .resizer {
-        position: absolute;
-        z-index: 999;
-        right: 0;
-        top:0;
-        width: 1px;
-        height:90vh;
-        cursor: ew-resize;
-        background-color:transparent;
-    }
-   
-}
-
+  position: relative;
+  height: 100%;
+  .resizable {
+    height: 100%;
+    overflow: hidden;
+  }
 
+  .resizer {
+    position: absolute;
+    z-index: 999;
+    right: 0;
+    top: 0;
+    width: 1px;
+    height: 90vh;
+    cursor: ew-resize;
+    background-color: transparent;
+  }
+}

+ 144 - 126
src/components/SQLEditor/index.tsx

@@ -13,143 +13,161 @@ import './style.less';
 import { copyToClipboard } from '@/utils/tooljs';
 
 interface SQLEditorProps {
-    name: string;
-    label: string;
-    rules: { required: boolean; message: string }[];
-    form: any; // 你可以根据你的表单库提供更具体的类型
-    width?: string; // 可选的宽度属性
-    height?: string;
-    value?: string;
+  name: string;
+  label: string;
+  rules: { required: boolean; message: string }[];
+  form: any; // 你可以根据你的表单库提供更具体的类型
+  width?: string; // 可选的宽度属性
+  height?: string;
+  value?: string;
 }
 
-function extractSqlParameters(sqlQuery:string) {
-    // 正则表达式匹配冒号开头的参数名,如 :param
-    const paramRegex = /#(\w+)/g;
-    const params = [];
-  
-    let match;
-    while (match = paramRegex.exec(sqlQuery)) {
-      params.push(match[1]); // 将匹配的参数名添加到数组中
-    }
-  
-    return params;
+function extractSqlParameters(sqlQuery: string) {
+  // 正则表达式匹配冒号开头的参数名,如 :param
+  const paramRegex = /#(\w+)/g;
+  const params = [];
+
+  let match;
+  while ((match = paramRegex.exec(sqlQuery))) {
+    params.push(match[1]); // 将匹配的参数名添加到数组中
   }
 
-const SQLEditor: React.FC<SQLEditorProps> = ({ name, label, rules, form, width = '100%', value = '', height = '100%' }) => {
-    const [editorValue, setEditorValue] = useState(value);
-    const [modalForm] = Form.useForm();
-    const handleSQLEditorChange = (newValue: string) => {
-        setEditorValue(newValue); 
-        form.current.setFieldValue(name, newValue);
-    };
+  return params;
+}
 
-    const copyHandle = ()=>{
-        copyToClipboard(editorValue as string);
-        message.success('复制成功!');
-    }
+const SQLEditor: React.FC<SQLEditorProps> = ({
+  name,
+  label,
+  rules,
+  form,
+  width = '100%',
+  value = '',
+  height = '100%',
+}) => {
+  const [editorValue, setEditorValue] = useState(value);
+  const [modalForm] = Form.useForm();
+  const handleSQLEditorChange = (newValue: string) => {
+    setEditorValue(newValue);
+    form.current.setFieldValue(name, newValue);
+  };
 
-    const verifyHandle = ()=>{
-        const params = extractSqlParameters(editorValue as string);
-        
+  const copyHandle = () => {
+    copyToClipboard(editorValue as string);
+    message.success('复制成功!');
+  };
 
-        Modal.confirm({
-            title:'验证参数',
-            icon:null,
-            content:(
-                <Form form={modalForm} layout="vertical">
-                    {[...new Set(params)].map(param => (
-                        <Form.Item
-                            key={param}
-                            label={`${param}`}
-                            name={param}
-                            rules={[{ required: true, message: `请输入${param}` }]}
-                        >
-                            <Input />
-                        </Form.Item>
-                    ))}
-                </Form>
-            ),
-            onOk: () => {
-                return new Promise((resolve, reject) => {
-                    modalForm.validateFields()
-                        .then(values => {
-                            let finalSql = editorValue as string;
-                            params.forEach(param => {
-                                finalSql = finalSql.replace(new RegExp(`#${param}`, 'g'), values[param]);
-                            });
-                            copyToClipboard(finalSql);
-                            message.success('替换参数值并复制成功!');
-                            resolve(true);
-                        }).catch(errorInfo => {
-                            reject(errorInfo);
-                        });
-                });
-            }
-        })
-    }
+  const verifyHandle = () => {
+    const params = extractSqlParameters(editorValue as string);
 
-    const editorDidMount = (editor:any, monaco:any) => {
-        editor.focus();
-    };
-    
-    // const handleEditorWillMount = (monaco: any) => {
-    //     // 绑定事件确保粘贴未被拦截
-    //     monaco.editor.onDidPaste(() => {
-    //         console.log('Pasted content');
-    //     });
-    // };
-    const handleEditorWillMount = (monacoInstance: typeof monaco) => {
-        // 监听编辑器的粘贴事件
-        monacoInstance.editor.onDidCreateEditor((editor) => {
-          editor.onDidChangeModelContent((event) => {
-            if (event.isFlush) {
-              console.log('Pasted content detected!');
-            }
-          });
+    Modal.confirm({
+      title: '验证参数',
+      icon: null,
+      content: (
+        <Form form={modalForm} layout="vertical">
+          {[...new Set(params)].map((param) => (
+            <Form.Item
+              key={param}
+              label={`${param}`}
+              name={param}
+              rules={[{ required: true, message: `请输入${param}` }]}
+            >
+              <Input />
+            </Form.Item>
+          ))}
+        </Form>
+      ),
+      onOk: () => {
+        return new Promise((resolve, reject) => {
+          modalForm
+            .validateFields()
+            .then((values) => {
+              let finalSql = editorValue as string;
+              params.forEach((param) => {
+                finalSql = finalSql.replace(
+                  new RegExp(`#${param}`, 'g'),
+                  values[param],
+                );
+              });
+              copyToClipboard(finalSql);
+              message.success('替换参数值并复制成功!');
+              resolve(true);
+            })
+            .catch((errorInfo) => {
+              reject(errorInfo);
+            });
         });
-    };
+      },
+    });
+  };
+
+  const editorDidMount = (editor: any, monaco: any) => {
+    editor.focus();
+  };
+
+  // const handleEditorWillMount = (monaco: any) => {
+  //     // 绑定事件确保粘贴未被拦截
+  //     monaco.editor.onDidPaste(() => {
+  //         console.log('Pasted content');
+  //     });
+  // };
+  const handleEditorWillMount = (monacoInstance: typeof monaco) => {
+    // 监听编辑器的粘贴事件
+    monacoInstance.editor.onDidCreateEditor((editor) => {
+      editor.onDidChangeModelContent((event) => {
+        if (event.isFlush) {
+          console.log('Pasted content detected!');
+        }
+      });
+    });
+  };
+
+  useEffect(() => {
+    setEditorValue(form.current.getFieldValue(name));
+  }, [form, name]);
 
-    useEffect(() => {
-        setEditorValue(form.current.getFieldValue(name));
-    }, [form, name]);
+  return (
+    <Form.Item
+      name={name}
+      label={label}
+      rules={rules}
+      getValueProps={() => ({ value: editorValue })}
+    >
+      <div
+        className="sql_editor"
+        style={{ border: '1px solid #CFD7E6', borderRadius: 4 }}
+      >
+        <MonacoEditor
+          language="sql"
+          theme="vs-light"
+          value={editorValue}
+          options={{
+            selectOnLineNumbers: true,
+            // autoIndent: true,
 
-    return (
-        <Form.Item
-            name={name}
-            label={label}
-            rules={rules}
-            getValueProps={() => ({ value: editorValue })}
-        >
-            <div className='sql_editor' style={{ border: '1px solid #CFD7E6', borderRadius: 4 }}>
-                <MonacoEditor
-                    language="sql"
-                    theme="vs-light"
-                    value={editorValue}
-                    options={{
-                        selectOnLineNumbers: true,
-                        // autoIndent: true,
-                        
-                        automaticLayout: true,
-                        fontSize: 14,
-                        pasteAs:{
-                            enabled:true,
-                            showPasteSelector:'afterPaste'
-                        }
-                    }}
-                
-                    width={width}
-                    height={height}
-                    onChange={handleSQLEditorChange}
-                    editorDidMount={editorDidMount}
-                    editorWillMount={handleEditorWillMount}
-                />
-                <div className='editerFooter'>
-                       <div className='a' onClick={()=>copyHandle()}>原文复制</div>
-                       <div className='b' onClick={()=>verifyHandle()}>替换参数值并复制</div>
-                </div>
-            </div>
-        </Form.Item>
-    );
+            automaticLayout: true,
+            fontSize: 14,
+            pasteAs: {
+              enabled: true,
+              showPasteSelector: 'afterPaste',
+            },
+          }}
+          width={width}
+          height={height}
+          onChange={handleSQLEditorChange}
+          editorDidMount={editorDidMount}
+          editorWillMount={handleEditorWillMount}
+        />
+        <div className="editerFooter">
+          <div className="a" onClick={() => copyHandle()}>
+            原文复制
+          </div>
+          <div className="b" onClick={() => verifyHandle()}>
+            替换参数值并复制
+          </div>
+        </div>
+      </div>
+    </Form.Item>
+  );
 };
 
 export default SQLEditor;

+ 53 - 52
src/components/SQLEditor/style.less

@@ -1,55 +1,56 @@
-.sql_editor {    
-    // .ace_editor_custom {
-    //     font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace !important;
-    // } 
-    // @media screen and (-webkit-min-device-pixel-ratio:0) {
-    //     .ace_editor_custom {
-    //         font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace !important;
-    //     }
-       
-    // }
-    .editerFooter {
-        display: flex;
-        flex-direction: row;
-        justify-content:flex-start;
-        align-items:center;
-        height: 32px;
-        padding: 0 10px;
-        border-top: 1px solid #DAE2F2;
-        background-color: #EEF3FA;
+.sql_editor {
+  // .ace_editor_custom {
+  //     font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace !important;
+  // }
+  // @media screen and (-webkit-min-device-pixel-ratio:0) {
+  //     .ace_editor_custom {
+  //         font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace !important;
+  //     }
 
-        .a,.b {
-            cursor: pointer;
-            font-size: 12px;
-            font-weight: 400;
-            color: #17181A;
-        }
-        .a {
-             margin-right: 16px;
-              &::before {
-                  position: relative;
-                  top:3px;
-                  display: inline-block;
-                  content: '';
-                  margin-right: 5px;
-                  width: 16px;
-                  height: 16px;
-                  background: url('./images/copy.png');
-                  background-size: cover;
-              }
-        }
-        .b {
-            &::before {
-                position: relative;
-                top:3px;
-                display: inline-block;
-                content: '';
-                margin-right: 5px;
-                width: 16px;
-                height: 16px;
-                background: url('./images/confirm.png');
-                background-size: cover;
-            }
+  // }
+  .editerFooter {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    align-items: center;
+    height: 32px;
+    padding: 0 10px;
+    border-top: 1px solid #dae2f2;
+    background-color: #eef3fa;
+
+    .a,
+    .b {
+      cursor: pointer;
+      font-size: 12px;
+      font-weight: 400;
+      color: #17181a;
+    }
+    .a {
+      margin-right: 16px;
+      &::before {
+        position: relative;
+        top: 3px;
+        display: inline-block;
+        content: '';
+        margin-right: 5px;
+        width: 16px;
+        height: 16px;
+        background: url('./images/copy.png');
+        background-size: cover;
+      }
+    }
+    .b {
+      &::before {
+        position: relative;
+        top: 3px;
+        display: inline-block;
+        content: '';
+        margin-right: 5px;
+        width: 16px;
+        height: 16px;
+        background: url('./images/confirm.png');
+        background-size: cover;
       }
     }
-}
+  }
+}

+ 64 - 25
src/components/VirtualTableBody.tsx

@@ -1,4 +1,11 @@
-import React, { CSSProperties, UIEvent, useEffect, useMemo, useRef, useState } from 'react';
+import React, {
+  CSSProperties,
+  UIEvent,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from 'react';
 import VirtualList from 'rc-virtual-list';
 import { formatMoneyNumber, formatToPercentage } from '@/utils/format';
 
@@ -41,9 +48,14 @@ export function buildVirtualBody(options: {
   const { columns, rowHeight = 44, height, width } = options;
 
   const leafColumns = flattenLeafColumns(columns);
-  const columnWidths = leafColumns.map((c) => (typeof c.width === 'number' ? c.width : 120));
-
-  const VirtualBody: React.FC<{ rawData: any[]; info: BodyInfo }> = ({ rawData, info }) => {
+  const columnWidths = leafColumns.map((c) =>
+    typeof c.width === 'number' ? c.width : 120,
+  );
+
+  const VirtualBody: React.FC<{ rawData: any[]; info: BodyInfo }> = ({
+    rawData,
+    info,
+  }) => {
     // 外层滚动容器(承担横向滚动同步)
     const outerRef = useRef<HTMLDivElement | null>(null);
     const listRef = useRef<any>(null);
@@ -70,14 +82,17 @@ export function buildVirtualBody(options: {
 
     const getColumnWidth = (index: number) => columnWidths[index] || 120;
 
-    const cellStyleBase: CSSProperties = useMemo(() => ({
-      boxSizing: 'border-box',
-      padding: '8px 8px',
-      borderTop: '1px solid rgb(218 226 242)',
-      overflow: 'hidden',
-      whiteSpace: 'nowrap',
-      textOverflow: 'ellipsis',
-    }), []);
+    const cellStyleBase: CSSProperties = useMemo(
+      () => ({
+        boxSizing: 'border-box',
+        padding: '8px 8px',
+        borderTop: '1px solid rgb(218 226 242)',
+        overflow: 'hidden',
+        whiteSpace: 'nowrap',
+        textOverflow: 'ellipsis',
+      }),
+      [],
+    );
 
     const Row = ({ index }: { index: number; style?: CSSProperties }) => {
       const record = rawData[index] || {};
@@ -92,20 +107,31 @@ export function buildVirtualBody(options: {
             let text: any = raw;
             try {
               const titleStr = typeof col?.title === 'string' ? col.title : '';
-              const isRatio = String(dataIndex || '').toLowerCase().endsWith('ratio') || String(titleStr).includes('占比');
+              const isRatio =
+                String(dataIndex || '')
+                  .toLowerCase()
+                  .endsWith('ratio') || String(titleStr).includes('占比');
               if (typeof (col as any).renderText === 'function') {
                 text = (col as any).renderText(raw, record);
               } else if (isRatio) {
                 text = formatToPercentage(raw);
               } else if (typeof raw === 'number') {
-                text = formatMoneyNumber(raw, { decimalPlaces: 2, useThousandSeparator: true });
+                text = formatMoneyNumber(raw, {
+                  decimalPlaces: 2,
+                  useThousandSeparator: true,
+                });
               }
             } catch {}
             return (
               <div
                 key={String(col.key || dataIndex || columnIndex)}
                 className="virtual-table-cell"
-                style={{ ...cellStyleBase, textAlign: align as any, width: w, flex: '0 0 auto' }}
+                style={{
+                  ...cellStyleBase,
+                  textAlign: align as any,
+                  width: w,
+                  flex: '0 0 auto',
+                }}
               >
                 {text as any}
               </div>
@@ -128,31 +154,46 @@ export function buildVirtualBody(options: {
       const container = outerRef.current;
       const max = (container.scrollWidth || 0) - (container.clientWidth || 0);
       if (max <= 0) return;
-      const next = Math.max(0, Math.min(max, container.scrollLeft + (e.deltaX || (e.deltaY > 0 ? 40 : -40))));
+      const next = Math.max(
+        0,
+        Math.min(
+          max,
+          container.scrollLeft + (e.deltaX || (e.deltaY > 0 ? 40 : -40)),
+        ),
+      );
       if (next !== container.scrollLeft) {
         container.scrollLeft = next;
-        try { info?.onScroll?.({ scrollLeft: next }); } catch {}
+        try {
+          info?.onScroll?.({ scrollLeft: next });
+        } catch {}
         e.preventDefault();
       }
     };
 
     return (
-      <div style={{ width: '100%', overflowX: 'auto' }} ref={outerRef} onScroll={handleScroll} onWheelCapture={handleWheelCapture}>
+      <div
+        style={{ width: '100%', overflowX: 'auto' }}
+        ref={outerRef}
+        onScroll={handleScroll}
+        onWheelCapture={handleWheelCapture}
+      >
         <div style={{ width }}>
           <VirtualList
             ref={listRef}
             data={rawData}
             height={height}
             itemHeight={rowHeight}
-            itemKey={(item: any, idx: number) => String(item?.id ?? item?.key ?? idx)}
+            itemKey={(item: any, idx: number) =>
+              String(item?.id ?? item?.key ?? idx)
+            }
             style={{ overflowX: 'hidden' }}
             onScroll={(e: any) => {
-              try { info?.onScroll?.({ scrollTop: e.scrollTop }); } catch {}
+              try {
+                info?.onScroll?.({ scrollTop: e.scrollTop });
+              } catch {}
             }}
           >
-            {(item: any, index: number) => (
-              <Row index={index} />
-            )}
+            {(item: any, index: number) => <Row index={index} />}
           </VirtualList>
         </div>
       </div>
@@ -166,5 +207,3 @@ export function buildVirtualBody(options: {
 }
 
 export default buildVirtualBody;
-
-

+ 8 - 8
src/constant.ts

@@ -10,11 +10,11 @@ export const KcimCenterSysId = '1547394914533380096';
 
 export const CostAccountingSysId = '1714195886747291648';
 
-export const  tableColumnsWidObj = {
-       departmentName:'10%',
-       responsibilityCenter:'10%',
-       responsibilityCenterCode:'10%',
-       year:'5%',
-       month:'5%',
-       shareLevel:'5%'
-}
+export const tableColumnsWidObj = {
+  departmentName: '10%',
+  responsibilityCenter: '10%',
+  responsibilityCenterCode: '10%',
+  year: '5%',
+  month: '5%',
+  shareLevel: '5%',
+};

+ 521 - 531
src/global.less

@@ -1,30 +1,32 @@
 * {
-    font-family: 'SourceHanSansCN, SourceHanSansCN';
+  font-family: 'SourceHanSansCN, SourceHanSansCN';
 }
 
 /* Safari */
-@media screen and (min-device-pixel-ratio:0)
-{
+@media screen and (min-device-pixel-ratio: 0) {
   * {
     margin: 0;
     padding: 0;
-    font-family:system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+    font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
+      Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue',
+      sans-serif;
   }
 
   #password {
     &::placeholder {
-      font-family:system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+      font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
+        Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue',
+        sans-serif;
     }
   }
 }
 
 body {
-    margin: 0;
-    height: 100%;
-    zoom: unset !important;
+  margin: 0;
+  height: 100%;
+  zoom: unset !important;
 }
 
-
 /* 禁用所有输入框的自动填充背景 */
 input:-webkit-autofill,
 textarea:-webkit-autofill,
@@ -34,306 +36,287 @@ select:-webkit-autofill {
   -webkit-text-fill-color: #000 !important;
 }
 
-
-
-
 .cost-ant-space-item {
-    &>a {
-        color: #37F !important;
-    }
+  & > a {
+    color: #37f !important;
+  }
 }
 
-
-
 textarea {
-    border-radius: 4px !important;
-    border: 1px solid #CFD7E6 !important;
+  border-radius: 4px !important;
+  border: 1px solid #cfd7e6 !important;
 }
 
 .cost-ant-btn-primary {
-    background: #37F;
+  background: #37f;
 }
 
-.cost-ant-btn-primary[disabled]{
-    background:#f5f5f5 ;
+.cost-ant-btn-primary[disabled] {
+  background: #f5f5f5;
 }
 
 .cost-ant-checkbox {
-    &.cost-ant-checkbox-checked {
-          .cost-ant-checkbox-inner {
-            background-color:#37F;
-            background: #37F;
-          }
+  &.cost-ant-checkbox-checked {
+    .cost-ant-checkbox-inner {
+      background-color: #37f;
+      background: #37f;
     }
-    // &.cost-ant-checkbox-indeterminate {
-    //     &.cost-ant-checkbox-inner {
-    //         &::after {
-    //             background-color:#3377FF !important;
-    //         }
-    //     }
-    // }
+  }
+  // &.cost-ant-checkbox-indeterminate {
+  //     &.cost-ant-checkbox-inner {
+  //         &::after {
+  //             background-color:#3377FF !important;
+  //         }
+  //     }
+  // }
 }
 
 .cost-ant-checkbox-indeterminate .cost-ant-checkbox-inner::after {
-    background-color:#37F;
+  background-color: #37f;
 }
 
 .cost-ant-input-affix-wrapper {
-    border-radius: 4px !important;
+  border-radius: 4px !important;
 }
 
 .cost-ant-input {
-    border-radius: 4px;
-    // border: 1px solid #CFD7E6 !important;
-    &::placeholder {
-        color: #99A6BF !important;
-    }
+  border-radius: 4px;
+  // border: 1px solid #CFD7E6 !important;
+  &::placeholder {
+    color: #99a6bf !important;
+  }
 }
 
 .cost-ant-table-cell {
-    a {
-        color: #3376FE !important;
-    }
+  a {
+    color: #3376fe !important;
+  }
 }
 
 .cost-ant-input-number {
-    border-radius: 4px !important;
+  border-radius: 4px !important;
 }
 
+//Modal
 
+.cost-ant-modal {
+  .cost-ant-modal-content {
+    padding: 16px !important;
+    border-radius: 4px !important;
 
+    .cost-ant-modal-header {
+      padding: 0;
+      margin-bottom: 16px;
+      border-bottom: none;
+    }
 
+    .cost-ant-modal-body {
+      max-height: 570px;
+      overflow-y: scroll;
+      overflow-x: hidden;
+      padding: 0;
+      padding-left: 4px;
 
+      .cost-ant-modal-confirm-body-wrapper {
+        .cost-ant-modal-confirm-body {
+          .cost-ant-modal-confirm-title {
+            font-size: 16px;
+            height: 18px;
+          }
 
-//Modal
+          .cost-ant-modal-confirm-content {
+            max-width: 100% !important;
+            max-height: 498px;
+            overflow-y: scroll;
+            overflow-x: hidden;
+            margin-block-start: 16px;
+
+            .TableTransfer {
+              .cost-ant-transfer-operation {
+                //   align-self: self-end;
+                //   margin-bottom: 30px;
+
+                button {
+                  //color: #17181A;
+                  width: 24px;
+                  height: 40px !important;
+                  // background: #FAFCFF;
+                  border-radius: 4px;
+                  border: 1px solid #dae2f2;
+                }
+              }
 
-.cost-ant-modal {
-    .cost-ant-modal-content {
-        padding: 16px !important;
-        border-radius: 4px !important;
+              .cost-ant-transfer-list {
+                overflow: hidden;
+                border: 1px solid #dae2f2;
 
-        .cost-ant-modal-header {
-             padding: 0 ;
-             margin-bottom: 16px;
-             border-bottom: none;
-        }
+                .cost-ant-transfer-list-header {
+                  height: 32px;
+                  font-size: 12px;
+                  border-bottom: 1px solid #dae2f2;
 
-        .cost-ant-modal-body {
-            max-height: 570px;
-            overflow-y: scroll;
-            overflow-x: hidden;
-            padding: 0;
-            padding-left: 4px;
-
-            .cost-ant-modal-confirm-body-wrapper {
-                .cost-ant-modal-confirm-body {
-                    .cost-ant-modal-confirm-title {
-                        font-size: 16px;
-                        height:18px;
-                      
+                  .anticon {
+                    color: #99a6bf;
+                  }
+
+                  .cost-ant-transfer-list-header-selected {
+                    color: #515866;
+                  }
+                }
+
+                .cost-ant-transfer-list-body {
+                  .cost-ant-transfer-list-body-search-wrapper {
+                    padding: 8px;
+
+                    .cost-ant-input-prefix {
+                      .anticon-search {
+                        color: #99a6bf;
+                      }
                     }
+                  }
 
-                    .cost-ant-modal-confirm-content {
-                        max-width: 100% !important;
-                        max-height: 498px;
-                        overflow-y: scroll;
-                        overflow-x: hidden;
-                        margin-block-start:16px;
-
-                        .TableTransfer {
-                            .cost-ant-transfer-operation {
-                                //   align-self: self-end;
-                                //   margin-bottom: 30px;
-
-                                button {
-                                    //color: #17181A;
-                                    width: 24px;
-                                    height: 40px !important;
-                                    // background: #FAFCFF;
-                                    border-radius: 4px;
-                                    border: 1px solid #DAE2F2;
-                                }
-                            }
-
-                            .cost-ant-transfer-list {
-                                overflow: hidden;
-                                border: 1px solid #DAE2F2;
-
-                                .cost-ant-transfer-list-header {
-                                    height: 32px;
-                                    font-size: 12px;
-                                    border-bottom: 1px solid #DAE2F2;
-
-                                    .anticon {
-                                        color: #99A6BF;
-                                    }
-
-                                    .cost-ant-transfer-list-header-selected {
-                                        color: #515866;
-                                    }
-                                }
-
-                                .cost-ant-transfer-list-body {
-                                    .cost-ant-transfer-list-body-search-wrapper {
-                                        padding: 8px;
-
-                                        .cost-ant-input-prefix {
-                                            .anticon-search {
-                                                color: #99A6BF;
-                                            }
-                                        }
-                                    }
-
-                                    .cost-ant-transfer-list-body-customize-wrapper {
-                                        .costTable {
-                                            border: none !important;
-                                            border-radius: 0 !important;
-                                        }
-                                    }
-                                }
-                            }
-
-
-
-                            .cost-ant-table {
-                                .cost-ant-table-container {
-                                    .cost-ant-table-content {
-                                        .cost-ant-table-thead {
-                                            &>tr>th {
-                                                font-size: 14px;
-                                                font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-                                                font-weight: 500;
-                                                color: #17181A;
-                                                background: #EEF3FA;
-                                                border-radius: 0 !important;
-                                                padding: 4px 8px !important;
-                                                border-bottom: none;
-                                            }
-
-                                        }
-
-                                        .cost-ant-table-tbody {
-                                            &>tr>td {
-                                                padding-left: 8px !important;
-                                                padding-right: 8px !important;
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
+                  .cost-ant-transfer-list-body-customize-wrapper {
+                    .costTable {
+                      border: none !important;
+                      border-radius: 0 !important;
                     }
+                  }
                 }
+              }
+
+              .cost-ant-table {
+                .cost-ant-table-container {
+                  .cost-ant-table-content {
+                    .cost-ant-table-thead {
+                      & > tr > th {
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                        font-weight: 500;
+                        color: #17181a;
+                        background: #eef3fa;
+                        border-radius: 0 !important;
+                        padding: 4px 8px !important;
+                        border-bottom: none;
+                      }
+                    }
 
-                .cost-ant-modal-confirm-btns {
-                    display: flex;
-                    flex-direction: row;
-                    align-items: center;
-                    justify-content: flex-end;
-                    margin-top: 16px;
-
-                    &>button {
-                        display: flex;
-                        justify-content: center;
-                        align-items: center;
-                        padding: 0 14px;
-                        height: 24px;
-                        border-radius: 4px;
-
-                        &.cost-ant-btn-default {
-                            border: 1px solid #DAE2F2;
-                            background-color: #FAFCFF;
-                        }
-
-                        &.cost-ant-btn-primary {
-                            background-color: #3376FE;
-                        }
+                    .cost-ant-table-tbody {
+                      & > tr > td {
+                        padding-left: 8px !important;
+                        padding-right: 8px !important;
+                      }
                     }
+                  }
                 }
+              }
             }
+          }
         }
 
-        .cost-ant-modal-footer {
-            border-top: none;
-            padding: 0;
-            margin-top: 16px;
+        .cost-ant-modal-confirm-btns {
+          display: flex;
+          flex-direction: row;
+          align-items: center;
+          justify-content: flex-end;
+          margin-top: 16px;
+
+          & > button {
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            padding: 0 14px;
+            height: 24px;
+            border-radius: 4px;
+
+            &.cost-ant-btn-default {
+              border: 1px solid #dae2f2;
+              background-color: #fafcff;
+            }
 
-            .cost-ant-btn {
-                 border-radius: 4px !important;
-                 height: 24px !important;
-                 padding: 0 14px !important;
+            &.cost-ant-btn-primary {
+              background-color: #3376fe;
             }
+          }
         }
+      }
     }
 
     .cost-ant-modal-footer {
-        margin-top: 0;
-
-        .cost-ant-space-item {
-            &>button {
-                display: flex;
-                justify-content: center;
-                align-items: center;
-                padding: 0 14px;
-                height: 24px;
-                ;
-                border-radius: 4px;
-
-                &>span {}
-
-                &.cost-ant-btn-default {
-                    border: 1px solid #DAE2F2;
-                    background-color: #FAFCFF;
-                }
+      border-top: none;
+      padding: 0;
+      margin-top: 16px;
 
-                &.cost-ant-btn-primary {
-                    background-color: #3376FE;
-                }
-            }
-        }
+      .cost-ant-btn {
+        border-radius: 4px !important;
+        height: 24px !important;
+        padding: 0 14px !important;
+      }
     }
-}
+  }
+
+  .cost-ant-modal-footer {
+    margin-top: 0;
 
+    .cost-ant-space-item {
+      & > button {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding: 0 14px;
+        height: 24px;
+        border-radius: 4px;
+
+        & > span {
+        }
 
+        &.cost-ant-btn-default {
+          border: 1px solid #dae2f2;
+          background-color: #fafcff;
+        }
+
+        &.cost-ant-btn-primary {
+          background-color: #3376fe;
+        }
+      }
+    }
+  }
+}
 
 //message
 
 .cost-ant-message {
-    .ant-message-notice-success {
-        .cost-ant-message-notice-content {
-            .anticon-check-circle {
-                &>svg {
-                    color: #52c41a;
-                }
-            }
+  .ant-message-notice-success {
+    .cost-ant-message-notice-content {
+      .anticon-check-circle {
+        & > svg {
+          color: #52c41a;
         }
+      }
     }
+  }
 }
 
 //Form
 
 .cost-ant-form {
-    &.cost-ant-form-vertical {
-        .cost-ant-form-item {
-            margin-bottom: 16px;
-
-            .cost-ant-form-item-label {
-                padding: 0 !important;
-                height: 15px;
-                margin-bottom: 8px;
-                line-height: 15px;
-            }
+  &.cost-ant-form-vertical {
+    .cost-ant-form-item {
+      margin-bottom: 16px;
 
-            .cost-ant-form-item-control-input {
-                min-height: 24px;
-            }
-        }
+      .cost-ant-form-item-label {
+        padding: 0 !important;
+        height: 15px;
+        margin-bottom: 8px;
+        line-height: 15px;
+      }
+
+      .cost-ant-form-item-control-input {
+        min-height: 24px;
+      }
     }
+  }
 }
 
-
-
-
 // .cost-ant-form-item-label {
 //     padding: 0;
 //     //height: 15px;
@@ -348,31 +331,30 @@ textarea {
 // }
 
 .cost-ant-input-affix-wrapper {
-    padding: 0 8px !important;
-    border-radius: 4px;
-    border: 1px solid #CFD7E6 !important;
+  padding: 0 8px !important;
+  border-radius: 4px;
+  border: 1px solid #cfd7e6 !important;
 
-    &>input {
-        &::placeholder {
-            font-size: 14px;
-            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-            font-weight: 400;
-            color: #99A6BF;
-        }
+  & > input {
+    &::placeholder {
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #99a6bf;
     }
+  }
 }
 
 .cost-ant-input-disabled {
-    &::placeholder {
-        color: #7A8599 !important;
-    }
+  &::placeholder {
+    color: #7a8599 !important;
+  }
 }
 
 .cost-ant-input-affix-wrapper-disabled {
-    background: #F0F2F5 !important;
+  background: #f0f2f5 !important;
 }
 
-
 // //proContsiner 标题样式覆盖
 // .cost-ant-page-header .cost-ant-page-header-heading-title {
 //      height: 17px !important;
@@ -381,458 +363,466 @@ textarea {
 // }
 
 .cost-ant-page-header {
-    .cost-ant-page-header-heading-title {
-         font-size: 16px !important;
-    }
+  .cost-ant-page-header-heading-title {
+    font-size: 16px !important;
+  }
 }
 
 .cost-ant-page-header .cost-ant-page-header-heading-left {
-    margin-block: 0 !important;
+  margin-block: 0 !important;
 }
 
-
 .cost-ant-pro .cost-ant-pro-layout .cost-ant-pro-sider-fixed {
-    position: absolute !important;
-    // min-width:230px !important;
-    // width: 230px !important;
+  position: absolute !important;
+  // min-width:230px !important;
+  // width: 230px !important;
 }
 
 //避免logo区域的层级过高,影响父容器
 .cost-ant-pro .cost-ant-pro-layout .cost-ant-pro-sider-fixed {
-    height: calc(100vh - 48px) !important;
-    z-index: 0 !important;
+  height: calc(100vh - 48px) !important;
+  z-index: 0 !important;
 }
 
 .cost-ant-pro .cost-ant-pro-layout .cost-ant-pro-sider-menu {
-    height: calc(100vh - 200px) !important;
-    overflow-y: scroll !important;
-    overflow-x: hidden;
+  height: calc(100vh - 200px) !important;
+  overflow-y: scroll !important;
+  overflow-x: hidden;
 }
 
-
-
-.cost-ant-menu .cost-ant-menu-root .cost-ant-menu-inline .cost-ant-menu-light .cost-ant-pro-sider-menu  .cost-ant-pro-base-menu{
-     height: calc(100vh - 90px) !important;
+.cost-ant-menu
+  .cost-ant-menu-root
+  .cost-ant-menu-inline
+  .cost-ant-menu-light
+  .cost-ant-pro-sider-menu
+  .cost-ant-pro-base-menu {
+  height: calc(100vh - 90px) !important;
 }
 
-.cost-ant-pro-base-menu .cost-ant-pro-base-menu-submenu-has-icon >.cost-ant-menu-sub {
-    padding-inline-start:0 !important;
+.cost-ant-pro-base-menu
+  .cost-ant-pro-base-menu-submenu-has-icon
+  > .cost-ant-menu-sub {
+  padding-inline-start: 0 !important;
 }
 
-
 .cost-ant-menu-submenu {
-    &.cost-ant-menu-submenu-selected {
-        color: #3376FE !important; 
-    }
+  &.cost-ant-menu-submenu-selected {
+    color: #3376fe !important;
+  }
 }
 
 .cost-ant-menu-item-selected {
-    color: #3376FE !important; 
-    background-color:#F2F6FF !important;
-    // margin:8px !important;
-    &:hover {
-         color: #3376FE !important; 
-    }
+  color: #3376fe !important;
+  background-color: #f2f6ff !important;
+  // margin:8px !important;
+  &:hover {
+    color: #3376fe !important;
+  }
 }
 
-.cost-ant-menu-light:not(.cost-ant-menu-horizontal) .cost-ant-menu-item:not(.cost-ant-menu-item-selected):hover {
-    background-color: #f0f2f5 !important;
-    // margin:8px !important;
+.cost-ant-menu-light:not(.cost-ant-menu-horizontal)
+  .cost-ant-menu-item:not(.cost-ant-menu-item-selected):hover {
+  background-color: #f0f2f5 !important;
+  // margin:8px !important;
 }
 
-.cost-ant-menu-light:not(.cost-ant-menu-horizontal) .cost-ant-menu-submenu-title:hover {
-    background-color: #f0f2f5 !important;
+.cost-ant-menu-light:not(.cost-ant-menu-horizontal)
+  .cost-ant-menu-submenu-title:hover {
+  background-color: #f0f2f5 !important;
 }
 
 .cost-ant-tree.cost-ant-tree-directory .cost-ant-tree-treenode:hover::before {
-    background: #f0f2f5 !important;
-    border-radius: 4px;
+  background: #f0f2f5 !important;
+  border-radius: 4px;
 }
 
 .cost-EditableProTable {
-    .cost-ant-pro-card-body {
-        padding-inline: 0 !important;
-        padding-block: 0 !important;
-
-        .cost-ant-table {
-            border: 1px solid #CFD7E6 !important;
-            overflow: hidden;
-
-            .cost-ant-table-content {
-                .cost-ant-table-thead {
-                    &>tr>th {
-                        height: 15px;
-                        line-height: 15px;
-                        font-size: 14px;
-                        padding: 12px 16px !important;
-                        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-                        // font-weight: 500;
+  .cost-ant-pro-card-body {
+    padding-inline: 0 !important;
+    padding-block: 0 !important;
 
-                        color: #17181A;
-                        border-bottom: 1px solid #CFD7E6 !important;
-                        background: rgb(238 243 250 / 100%) !important;
+    .cost-ant-table {
+      border: 1px solid #cfd7e6 !important;
+      overflow: hidden;
 
-                        &::before {
-                            display: none !important;
-                        }
-                    }
-                }
+      .cost-ant-table-content {
+        .cost-ant-table-thead {
+          & > tr > th {
+            height: 15px;
+            line-height: 15px;
+            font-size: 14px;
+            padding: 12px 16px !important;
+            font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+            // font-weight: 500;
 
-                .cost-ant-table-tbody {
-                    .cost-ant-table-row {
-                        .cost-ant-table-cell {
-                            height: 15px;
-                            line-height: 15px;
-                            font-size: 14px;
-                            padding: 8px !important;
-                            font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-                            color: #17181A;
-
-                            &>div {
-                                justify-content: flex-start !important;
-                            }
-                        }
-
-                        &:last-child {
-                            &>td {
-                                border-bottom-color: none !important;
-                            }
-                        }
-                    }
-                }
+            color: #17181a;
+            border-bottom: 1px solid #cfd7e6 !important;
+            background: rgb(238 243 250 / 100%) !important;
+
+            &::before {
+              display: none !important;
+            }
+          }
+        }
+
+        .cost-ant-table-tbody {
+          .cost-ant-table-row {
+            .cost-ant-table-cell {
+              height: 15px;
+              line-height: 15px;
+              font-size: 14px;
+              padding: 8px !important;
+              font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+              color: #17181a;
+
+              & > div {
+                justify-content: flex-start !important;
+              }
+            }
+
+            &:last-child {
+              & > td {
+                border-bottom-color: none !important;
+              }
             }
+          }
         }
+      }
     }
+  }
 }
 
 .cost-ant-table-wrapper {
-    .cost-ant-table:not(.cost-ant-table-bordered) .cost-ant-table-tbody>tr.cost-ant-table-row.cost-ant-table-row-selected>td:first-child {
-        border-radius: 0 !important;
-    }
+  .cost-ant-table:not(.cost-ant-table-bordered)
+    .cost-ant-table-tbody
+    > tr.cost-ant-table-row.cost-ant-table-row-selected
+    > td:first-child {
+    border-radius: 0 !important;
+  }
 
-    .cost-ant-table-content {
-        .cost-ant-table-thead {
-            tr {
-                &:last-child {
-                    .cost-ant-table-cell {
-                        // border-top: 1px solid #dae2f2;
-                    }
-                }
-            }
+  .cost-ant-table-content {
+    .cost-ant-table-thead {
+      tr {
+        &:last-child {
+          .cost-ant-table-cell {
+            // border-top: 1px solid #dae2f2;
+          }
         }
+      }
     }
+  }
 }
 
-.cost-ant-table-wrapper .cost-ant-table:not(.cost-ant-table-bordered) .cost-ant-table-tbody>tr.cost-ant-table-row:hover>td:first-child {
-    border-start-start-radius: 0 !important;
-    border-end-start-radius: 0 !important;
+.cost-ant-table-wrapper
+  .cost-ant-table:not(.cost-ant-table-bordered)
+  .cost-ant-table-tbody
+  > tr.cost-ant-table-row:hover
+  > td:first-child {
+  border-start-start-radius: 0 !important;
+  border-end-start-radius: 0 !important;
 }
 
-.cost-ant-table-wrapper .cost-ant-table:not(.cost-ant-table-bordered) .cost-ant-table-tbody>tr.cost-ant-table-row:last-child:hover>td {
-    border-bottom-color: #dae2f2 !important;
+.cost-ant-table-wrapper
+  .cost-ant-table:not(.cost-ant-table-bordered)
+  .cost-ant-table-tbody
+  > tr.cost-ant-table-row:last-child:hover
+  > td {
+  border-bottom-color: #dae2f2 !important;
 }
 
-.cost-ant-table-wrapper .cost-ant-table:not(.cost-ant-table-bordered) .cost-ant-table-tbody>tr.cost-ant-table-row:last-child>td {
-    border-bottom-color: #dae2f2 !important;
+.cost-ant-table-wrapper
+  .cost-ant-table:not(.cost-ant-table-bordered)
+  .cost-ant-table-tbody
+  > tr.cost-ant-table-row:last-child
+  > td {
+  border-bottom-color: #dae2f2 !important;
 }
 
-
-.cost-ant-table-wrapper .cost-ant-table:not(.cost-ant-table-bordered) .cost-ant-table-tbody>tr.cost-ant-table-row:hover>td:last-child {
-    border-end-end-radius: 0 !important;
-    border-start-end-radius: 0 !important;
+.cost-ant-table-wrapper
+  .cost-ant-table:not(.cost-ant-table-bordered)
+  .cost-ant-table-tbody
+  > tr.cost-ant-table-row:hover
+  > td:last-child {
+  border-end-end-radius: 0 !important;
+  border-start-end-radius: 0 !important;
 }
 
-
 .cost-ant-pro .cost-ant-pro-layout .cost-ant-pro-layout-bg-list {
-    background: #F7F9FC !important;
+  background: #f7f9fc !important;
 }
 
 // .cost-ant-message-notice .cost-ant-message-success .anticon {
 //     color: #52c41a !important;
 // }
 .ant-message-success {
-    .anticon .anticon-check-circle {
-        color: #52c41a !important;
-    }
+  .anticon .anticon-check-circle {
+    color: #52c41a !important;
+  }
 }
 
-
 /**
     Select
 **/
 .cost-ant-select {
-    .cost-ant-select-selector {
-        height: 24px !important;
-        padding: 0 8px !important;
-        border-radius: 4px !important;
-        border: 1px solid #CFD7E6 !important;
-
-        .cost-ant-select-selection-item {
-            line-height: 24px !important;
-        }
-
-        .cost-ant-select-selection-search-input {
-            height: 24px !important;
-        }
-
-        .cost-ant-select-selection-placeholder {
-            line-height: 22px !important;
-            font-size: 14px;
-            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-            font-weight: 400;
-            color: #99A6BF;
-        }
+  .cost-ant-select-selector {
+    height: 24px !important;
+    padding: 0 8px !important;
+    border-radius: 4px !important;
+    border: 1px solid #cfd7e6 !important;
 
-        .cost-ant-select-selection-overflow {
-            .cost-ant-select-selection-overflow-item {
-                .cost-ant-select-selection-item {
-                    height: 22px !important;
-                    line-height: 22px !important;
-                    margin-top: 0 !important;
-                    margin-bottom: 7px !important;
-                }
-            }
-        }
+    .cost-ant-select-selection-item {
+      line-height: 24px !important;
     }
 
-    .cost-ant-select-arrow {
-        color: #CFD7E6;
+    .cost-ant-select-selection-search-input {
+      height: 24px !important;
     }
 
-    &.cost-ant-select-disabled {
-        .cost-ant-select-selector {
-            border: 1px solid #DADEE6 !important;
-
-            .cost-ant-select-selection-placeholder {
-                color: #7A8599;
-            }
-        }
+    .cost-ant-select-selection-placeholder {
+      line-height: 22px !important;
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #99a6bf;
+    }
 
-        .cost-ant-select-arrow {
-            color: #7A8599;
+    .cost-ant-select-selection-overflow {
+      .cost-ant-select-selection-overflow-item {
+        .cost-ant-select-selection-item {
+          height: 22px !important;
+          line-height: 22px !important;
+          margin-top: 0 !important;
+          margin-bottom: 7px !important;
         }
+      }
     }
-}
-
-
+  }
 
+  .cost-ant-select-arrow {
+    color: #cfd7e6;
+  }
 
+  &.cost-ant-select-disabled {
+    .cost-ant-select-selector {
+      border: 1px solid #dadee6 !important;
 
-.cost-ant-tabs {
-    .cost-ant-tabs-tab {
-        padding: 5px 0 !important;
-        padding-top: 12px !important;
+      .cost-ant-select-selection-placeholder {
+        color: #7a8599;
+      }
     }
 
-    .cost-ant-tabs-nav {
-        &::before {
-            border-bottom: none !important;
-        }
+    .cost-ant-select-arrow {
+      color: #7a8599;
     }
-   
+  }
 }
 
+.cost-ant-tabs {
+  .cost-ant-tabs-tab {
+    padding: 5px 0 !important;
+    padding-top: 12px !important;
+  }
 
+  .cost-ant-tabs-nav {
+    &::before {
+      border-bottom: none !important;
+    }
+  }
+}
 
 .cost-ant-table-wrapper {
-    overflow: hidden;
+  overflow: hidden;
 }
 
-
-
 .cost-ant-pro-layout .cost-ant-pro-layout-container {
-    flex: 1;
-    overflow-y: scroll;
-    background: #F7F9FC !important;
+  flex: 1;
+  overflow-y: scroll;
+  background: #f7f9fc !important;
 }
 
 //页面全局底色
 .cost-ant-pro .cost-ant-pro-layout .cost-ant-pro-layout-bg-list {
-    background: rgb(247 249 252 / 100%);
+  background: rgb(247 249 252 / 100%);
 }
 
 .cost-ant-pro-page-container-children-content {
-    padding-inline: 0 !important;
+  padding-inline: 0 !important;
 }
 
 .cost-ant-pro-sider-actions {
-    display: none !important;
+  display: none !important;
 }
 
-
 .cost-ant-pro-sider-collapsed-button {
-    top: 95% !important;
-    right: 17px !important;
+  top: 95% !important;
+  right: 17px !important;
 }
 
-
 .cost-ant-menu .cost-ant-menu-submenu-title .anticon {
-    transition: none !important;
+  transition: none !important;
 }
 
-.cost-ant-menu .cost-ant-menu-item .anticon+span {
-    transition: none !important;
+.cost-ant-menu .cost-ant-menu-item .anticon + span {
+  transition: none !important;
 }
 
 .cost-ant-menu .cost-ant-menu-item .anticon {
-    transition: none !important;
+  transition: none !important;
 }
 
 .cost-ant-menu .cost-ant-menu-item {
-    transition: none !important;
+  transition: none !important;
 }
 
-.cost-ant-menu .cost-ant-menu-submenu-title .anticon+span {
-    transition: none !important;
+.cost-ant-menu .cost-ant-menu-submenu-title .anticon + span {
+  transition: none !important;
 }
 
-.cost-ant-tabs .cost-ant-tabs-tab+.cost-ant-tabs-tab {
-    margin: 0 0 0 24px !important;
+.cost-ant-tabs .cost-ant-tabs-tab + .cost-ant-tabs-tab {
+  margin: 0 0 0 24px !important;
 }
 
-
 .menuCollapseIcon {
-    &>svg {
-        width: 24px;
-        height: 24px;
-    }
+  & > svg {
+    width: 24px;
+    height: 24px;
+  }
 }
 
 .cost-ant-layout-sider {
-    max-width: 100% !important;
-    min-width: unset !important;
-    width: 100% !important; 
+  max-width: 100% !important;
+  min-width: unset !important;
+  width: 100% !important;
 }
 
-.cost-ant-pro .cost-ant-pro-layout .cost-ant-pro-sider .cost-ant-layout-sider-children {
-    padding-inline: 0 !important;
+.cost-ant-pro
+  .cost-ant-pro-layout
+  .cost-ant-pro-sider
+  .cost-ant-layout-sider-children {
+  padding-inline: 0 !important;
 
-    &>div {
-       &>ul {
-          padding-inline: 8px !important;
-       }
+  & > div {
+    & > ul {
+      padding-inline: 8px !important;
     }
+  }
 }
 
-
-.cost-ant-pro-form>div:not(.cost-ant-pro-form-light-filter) .pro-field-lg {
-    width: 100% !important;
+.cost-ant-pro-form > div:not(.cost-ant-pro-form-light-filter) .pro-field-lg {
+  width: 100% !important;
 }
 
 .cost-ant-select {
-    .cost-ant-select-selector {
-        border: 1px solid #CFD7E6 !important;
-        // color: #99A6BF !important;
+  .cost-ant-select-selector {
+    border: 1px solid #cfd7e6 !important;
+    // color: #99A6BF !important;
 
-        .cost-ant-select-selection-placeholder {
-            color: #99A6BF !important;
-        }
+    .cost-ant-select-selection-placeholder {
+      color: #99a6bf !important;
     }
+  }
 
-    .cost-ant-select-arrow {
-        color: #99A6BF !important;
-    }
+  .cost-ant-select-arrow {
+    color: #99a6bf !important;
+  }
 }
 
-
 .cost-ant-input-number-input {
-    border-radius: 4px;
+  border-radius: 4px;
 
-    &::placeholder {
-        color: #99A6BF !important;
-    }
+  &::placeholder {
+    color: #99a6bf !important;
+  }
 }
 
 .cost-ant-select-disabled {
-    .cost-ant-select-selector {
-        border: 1px solid #DADEE6 !important;
-        background: #F0F2F5 !important;
+  .cost-ant-select-selector {
+    border: 1px solid #dadee6 !important;
+    background: #f0f2f5 !important;
 
-        .cost-ant-select-selection-placeholder {
-            color: #7A8599 !important;
-        }
+    .cost-ant-select-selection-placeholder {
+      color: #7a8599 !important;
     }
+  }
 
-    .cost-ant-select-arrow {
-        color: #7A8599 !important;
-    }
+  .cost-ant-select-arrow {
+    color: #7a8599 !important;
+  }
 }
 
-
-
 .cost-ant-input-number {
-    border: 1px solid #CFD7E6 !important;
-    // color: #99A6BF !important;
-    border-radius: 4px;
-    box-shadow: none !important;
-
-    .cost-ant-input-number-input {
-        height: 22px !important;
-        line-height: 22px !important;
-    }
+  border: 1px solid #cfd7e6 !important;
+  // color: #99A6BF !important;
+  border-radius: 4px;
+  box-shadow: none !important;
+
+  .cost-ant-input-number-input {
+    height: 22px !important;
+    line-height: 22px !important;
+  }
 }
 
 .cost-ant-input-number-disabled {
-    border: 1px solid #DADEE6 !important;
-    background: #F0F2F5 !important;
+  border: 1px solid #dadee6 !important;
+  background: #f0f2f5 !important;
 
-    .cost-ant-input-number-input {
-        color: #7A8599 !important;
-    }
+  .cost-ant-input-number-input {
+    color: #7a8599 !important;
+  }
 }
 
 .cost-ant-input-affix-wrapper-disabled {
-    border: 1px solid #DADEE6 !important;
+  border: 1px solid #dadee6 !important;
 }
 
 .cost-ant-picker {
-    border-radius: 4px !important;
-    border: 1px solid #CFD7E6 !important;
-    height: 24px;
+  border-radius: 4px !important;
+  border: 1px solid #cfd7e6 !important;
+  height: 24px;
 
-    .cost-ant-picker-input {
-        &>input {
-             &::placeholder {
-                color:#99A6BF !important;
-             }
-        }
+  .cost-ant-picker-input {
+    & > input {
+      &::placeholder {
+        color: #99a6bf !important;
+      }
+    }
 
-        .cost-ant-picker-suffix {
-            color:#99A6BF !important;
-        }
+    .cost-ant-picker-suffix {
+      color: #99a6bf !important;
     }
+  }
 }
 
 .cost-ant-picker-panel-container {
-    .cost-ant-picker-panel {
-        .cost-ant-picker-month-panel {
-            .cost-ant-picker-body {
-                .cost-ant-picker-content {
-                    tr {
-                        td {
-                            &.cost-ant-picker-cell-selected {
-                                .cost-ant-picker-cell-inner {
-                                    background:#37F;
-                                }
-                            }
-                        }
-                    }
+  .cost-ant-picker-panel {
+    .cost-ant-picker-month-panel {
+      .cost-ant-picker-body {
+        .cost-ant-picker-content {
+          tr {
+            td {
+              &.cost-ant-picker-cell-selected {
+                .cost-ant-picker-cell-inner {
+                  background: #37f;
                 }
+              }
             }
+          }
         }
+      }
     }
+  }
 }
 
-.cost-ant-picker-input>input[disabled] {
-    color: #7A8599 !important;
+.cost-ant-picker-input > input[disabled] {
+  color: #7a8599 !important;
 }
 
 .cost-ant-picker-disabled {
-    background: #F0F2F5 !important;
-    border: 1px solid #DADEE6 !important;
+  background: #f0f2f5 !important;
+  border: 1px solid #dadee6 !important;
 
-    .anticon-swap-right,
-    .anticon-calendar {
-        color: #7A8599 !important;
-    }
-}
+  .anticon-swap-right,
+  .anticon-calendar {
+    color: #7a8599 !important;
+  }
+}

+ 25 - 25
src/menuIcons.js

@@ -7,22 +7,22 @@
  * @FilePath: /CostAccountManaSys/src/menuIcons.js
  */
 
-
 import React from 'react';
-import { SmileOutlined,
-     HomeOutlined, 
-     PicLeftOutlined, 
-     SettingOutlined,
-     NodeExpandOutlined,
-     BorderOuterOutlined,
-     CopyrightOutlined,
-     ProfileOutlined,
-     AccountBookOutlined,
-     ControlOutlined,
-     CrownOutlined,
-     ToolOutlined,
-     TableOutlined,
-     FileDoneOutlined
+import {
+  SmileOutlined,
+  HomeOutlined,
+  PicLeftOutlined,
+  SettingOutlined,
+  NodeExpandOutlined,
+  BorderOuterOutlined,
+  CopyrightOutlined,
+  ProfileOutlined,
+  AccountBookOutlined,
+  ControlOutlined,
+  CrownOutlined,
+  ToolOutlined,
+  TableOutlined,
+  FileDoneOutlined,
 } from '@ant-design/icons';
 
 const iconEnum = {
@@ -30,16 +30,16 @@ const iconEnum = {
   home: <HomeOutlined />,
   picLeft: <PicLeftOutlined />,
   setting: <SettingOutlined />,
-  crown:<CrownOutlined />,
-  tool:<ToolOutlined />,
-  TableOutlined:<TableOutlined />,
-  NodeExpandOutlined:<NodeExpandOutlined />,
-  BorderOuterOutlined:<BorderOuterOutlined />,
-  CopyrightOutlined:<CopyrightOutlined />,
-  ProfileOutlined:<ProfileOutlined />,
-  AccountBookOutlined:<AccountBookOutlined />,
-  ControlOutlined:<ControlOutlined />,
-  FileDoneOutlined:<FileDoneOutlined />
+  crown: <CrownOutlined />,
+  tool: <ToolOutlined />,
+  TableOutlined: <TableOutlined />,
+  NodeExpandOutlined: <NodeExpandOutlined />,
+  BorderOuterOutlined: <BorderOuterOutlined />,
+  CopyrightOutlined: <CopyrightOutlined />,
+  ProfileOutlined: <ProfileOutlined />,
+  AccountBookOutlined: <AccountBookOutlined />,
+  ControlOutlined: <ControlOutlined />,
+  FileDoneOutlined: <FileDoneOutlined />,
 };
 
 // const iconEnum = {

+ 6 - 5
src/pages/Home/index.tsx

@@ -15,13 +15,14 @@ import './style.less';
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 
 const HomePage: React.FC = () => {
-  
   return (
     <KCIMPagecontainer title={false} ghost>
-      <div className='HomePage'>
-        <div className='title'>全成本核算系统</div>
-        <div className='titleSub'>以促进医院内部经济、经营管理向正规化的轨道转变,建立规范以及完整的成本管理决策体系,将管理重点转移到经济管理上来,并透过完善的信息化建设,实现对成本管理的支撑。纠正医院的成本管控理念及应用错误,改变现行的“四类三级”成本核算方法。实现医院科室成本核算,支持医院床位动态管理,支持科室实施主诊医师负责制;实现科室真实盈亏计算及盈亏平衡分析,指导科室经营;实现利润敏感性分析,使用国际先进的管理会计理论用以医院经营管理决策。</div>
-        <div className='banner'>
+      <div className="HomePage">
+        <div className="title">全成本核算系统</div>
+        <div className="titleSub">
+          以促进医院内部经济、经营管理向正规化的轨道转变,建立规范以及完整的成本管理决策体系,将管理重点转移到经济管理上来,并透过完善的信息化建设,实现对成本管理的支撑。纠正医院的成本管控理念及应用错误,改变现行的“四类三级”成本核算方法。实现医院科室成本核算,支持医院床位动态管理,支持科室实施主诊医师负责制;实现科室真实盈亏计算及盈亏平衡分析,指导科室经营;实现利润敏感性分析,使用国际先进的管理会计理论用以医院经营管理决策。
+        </div>
+        <div className="banner">
           <img src={require('../../../static/indexBgCenter.png')} alt="" />
         </div>
       </div>

+ 28 - 41
src/pages/Home/service.ts

@@ -7,54 +7,41 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-import { request } from '@@/plugin-request'
-
-
-
-
+import { request } from '@@/plugin-request';
 
 //获取首页信息
 
 export type getIndexDataRespType = {
-    id:number,
-    computeDate:string,
-    code:number,
-    name:string,
-    preCode:number,
-    sort:number,
-    status:number,
-    audit:string
-}
-
-export const getIndexData = (computeDate:string)=>{
-       
-       return request<getIndexDataRespType[]>('/performance/index', {
-            method: 'GET',
-            params:{computeDate},
-       })
-}
-
+  id: number;
+  computeDate: string;
+  code: number;
+  name: string;
+  preCode: number;
+  sort: number;
+  status: number;
+  audit: string;
+};
+
+export const getIndexData = (computeDate: string) => {
+  return request<getIndexDataRespType[]>('/performance/index', {
+    method: 'GET',
+    params: { computeDate },
+  });
+};
 
 //获取当前计算年月
 
-export const getComputeDate = ()=>{
-       
-    return request<string>('/performance/index/getCurrentComputeDate', {
-         method: 'GET',
-    })
-}
-
+export const getComputeDate = () => {
+  return request<string>('/performance/index/getCurrentComputeDate', {
+    method: 'GET',
+  });
+};
 
 //获取动态报表的path
 
-export const getReportPath = (params:any)=>{
-       
-   return request('/performance/parameter/getList', {
-         method: 'GET',
-         params:{...params}
-    });
-}
-
-
-
-
+export const getReportPath = (params: any) => {
+  return request('/performance/parameter/getList', {
+    method: 'GET',
+    params: { ...params },
+  });
+};

+ 11 - 11
src/pages/Home/style.less

@@ -3,13 +3,13 @@
   flex-direction: column;
   height: calc(100vh - 80px);
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
   .title {
     height: 24px;
     font-weight: bold;
     font-size: 24px;
-    color: #17181A;
+    color: #17181a;
     line-height: 24px;
     margin-bottom: 12px;
     padding-left: 8px;
@@ -37,7 +37,7 @@
     overflow: hidden;
     background-repeat: no-repeat !important;
 
-    &>img {
+    & > img {
       width: 810px;
       transition: all 0.3s linear;
     }
@@ -45,50 +45,50 @@
 
   /* 当屏幕宽度小于或等于 600px */
   @media screen and (max-width: 1250px) {
-    .banner>img {
+    .banner > img {
       width: 600px;
     }
   }
 
   /* 当屏幕宽度小于或等于 600px */
   @media screen and (min-width: 1250px) and (max-width: 1360px) {
-    .banner>img {
+    .banner > img {
       width: 700px;
     }
   }
 
   /* 当屏幕宽度在 601px 到 900px */
   @media screen and (min-width: 1360px) and (max-width: 1500px) {
-    .banner>img {
+    .banner > img {
       width: 800px;
     }
   }
 
   /* 当屏幕宽度大于 900px */
   @media screen and (min-width: 1500px) and (max-width: 1760px) {
-    .banner>img {
+    .banner > img {
       width: 900px;
     }
   }
 
   /* 当屏幕宽度大于 900px */
   @media screen and (min-width: 1760px) and (max-width: 1920px) {
-    .banner>img {
+    .banner > img {
       width: 1000px;
     }
   }
 
   /* 当屏幕宽度大于 900px */
   @media screen and (min-width: 1960px) and (max-width: 2000px) {
-    .banner>img {
+    .banner > img {
       width: 1200px;
     }
   }
 
   /* 当屏幕宽度大于 900px */
   @media screen and (min-width: 2000px) {
-    .banner>img {
+    .banner > img {
       width: 1400px;
     }
   }
-}
+}

+ 252 - 220
src/pages/baseInfoMana/checkGroupMana/index.tsx

@@ -7,18 +7,25 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
-
 import { createFromIconfontCN } from '@ant-design/icons';
 
-import { ActionType, DrawerForm, EditableFormInstance, EditableProTable, ProFormInstance, ProFormSelect } from '@ant-design/pro-components';
-import { ModalForm, ProFormDigit, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import {
+  ActionType,
+  DrawerForm,
+  EditableFormInstance,
+  EditableProTable,
+  ProFormInstance,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import {
+  ModalForm,
+  ProFormDigit,
+  ProFormText,
+  ProFormTextArea,
+} from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm } from 'antd';
-import { useEffect, useRef, useState } from 'react'
+import { useEffect, useRef, useState } from 'react';
 
 import { addData, delData, editData, getChackGroupData } from './service';
 
@@ -28,234 +35,259 @@ import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 import KCIMDrawerForm from '@/components/KCIMDrawerForm';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 type TableDataResponse = {
-    data: any[]; 
-    success: boolean; 
-    total: number; 
-    pageSize: number; 
-    totalPage: number;
+  data: any[];
+  success: boolean;
+  total: number;
+  pageSize: number;
+  totalPage: number;
 };
 
 export default function FenyeTemplate() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-
-    const columns: ProColumns[] = [
-
-        {
-            title: 'ID',
-            dataIndex: 'id',
-        },
-        {
-            title: '查核组名称',
-            dataIndex: 'name',
-        },
-        {
-            title: '组长',
-            dataIndex: 'groupManagerName',
-        },
-        {
-            title: '备注',
-            dataIndex: 'createUserName',
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width:150,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <a key='emp'>人员</a>,
-                    // <a key=''>查核要点</a>
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any):Promise<TableDataResponse|any[]> => {
-        const resp = await getChackGroupData(params);
-        if (resp) {
-
-            if(resp.totalCount == 0 && resp.currPage != 1){
-                 return getTableData({...params,current:resp.currPage - 1});
-            }else{
-                return {
-                    data: resp.list,
-                    success: true,
-                    total: resp.totalCount,
-                    pageSize: resp.pageSize,
-                    totalPage: resp.totalPage,
-                }
-            }
-            
-        }
-        return []
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+
+  const columns: ProColumns[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+    },
+    {
+      title: '查核组名称',
+      dataIndex: 'name',
+    },
+    {
+      title: '组长',
+      dataIndex: 'groupManagerName',
+    },
+    {
+      title: '备注',
+      dataIndex: 'createUserName',
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 150,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <a key="emp">人员</a>,
+          // <a key=''>查核要点</a>
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (
+    params: any,
+  ): Promise<TableDataResponse | any[]> => {
+    const resp = await getChackGroupData(params);
+    if (resp) {
+      if (resp.totalCount == 0 && resp.currPage != 1) {
+        return getTableData({ ...params, current: resp.currPage - 1 });
+      } else {
+        return {
+          data: resp.list,
+          success: true,
+          total: resp.totalCount,
+          pageSize: resp.pageSize,
+          totalPage: resp.totalPage,
+        };
+      }
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData(record.id);
-        if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
-        }
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData(record.id);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
+    }
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    const content = formVal.table.map((a: any) => ({}));
+
+    if (type == 'ADD') {
+      const result = {
+        name: formVal.name,
+        content: JSON.stringify(formVal.table),
+        remark: formVal.remark,
+      };
+      const resp = await addData({ ...result });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      const result = {
+        id: formVal.id,
+        name: formVal.name,
+        content: JSON.stringify(formVal.table),
+        remark: formVal.remark,
+      };
+      const resp = await editData({ ...result });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
 
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-
-        const content = formVal.table.map((a: any) => ({
-
-        }))
+    return true;
+  };
 
-        if (type == 'ADD') {
-            const result = {
-                name: formVal.name,
-                content: JSON.stringify(formVal.table),
-                remark: formVal.remark
-            }
-            const resp = await addData({ ...result });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    const formRef = useRef<ProFormInstance<any>>();
 
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}查核组`}
+        width={400}
+        initialValues={
+          type == 'EDIT'
+            ? { ...record, filedType: 'Text' }
+            : { filedType: 'Text' }
         }
-        if (type == 'EDIT') {
-            const result = {
-                id: formVal.id,
-                name: formVal.name,
-                content: JSON.stringify(formVal.table),
-                remark: formVal.remark
-            }
-            const resp = await editData({ ...result });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-
-        return true;
-    }
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-        const formRef = useRef<ProFormInstance<any>>();
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}查核组`}
-                width={400}
-                initialValues={type == 'EDIT' ? { ...record, filedType: 'Text' } : { filedType: 'Text' }}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val: any) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                formRef={formRef}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormText
-                    name="name"
-                    label="查核组名称:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '名称不能为空!' }]}
+        onFinish={(val: any) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        formRef={formRef}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText
+          name="name"
+          label="查核组名称:"
+          placeholder="请输入"
+          rules={[{ required: true, message: '名称不能为空!' }]}
+        />
+        <ProFormTextArea name="remark" label="备注:" placeholder="请输入" />
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="checkGroupMana" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem" style={{ marginRight: 16, width: 205 }}>
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'请输入查核组名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-                <ProFormTextArea
-                    name="remark"
-                    label="备注:"
-                    placeholder="请输入"
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    groupName: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  groupName: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+          <div className="filterItem" style={{ marginRight: 16, width: 220 }}>
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              组长名称:
+            </span>
+            <Input
+              placeholder={'请输入'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-            </ModalForm>
-        )
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-    }
-
-
-    useEffect(() => {
-
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='checkGroupMana' title={false}>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem' style={{ marginRight: 16, width: 205 }}>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'请输入查核组名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        groupName: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    groupName: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                    <div className='filterItem' style={{ marginRight: 16, width: 220 }}>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 组长名称:</span>
-                        <Input placeholder={'请输入'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        groupManagerName: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    groupManagerName: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                {/* <div className='btnGroup'>
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    groupManagerName: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  groupManagerName: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        {/* <div className='btnGroup'>
                     <UpDataActBtn record type='ADD' />
                 </div> */}
-            </div>
-            <div style={{ marginTop: 16 }}>
-                <KCIMTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+      </div>
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 36 - 49
src/pages/baseInfoMana/checkGroupMana/service.ts

@@ -7,90 +7,77 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { request } from 'umi';
 
 //获取table列表数据
 
 export type FenyeTemplateItemType = {
-  id:number;
-  hiId:number;
-  name:string;
-  content:string;
-  remark:string;
-  createUserId:number;
-  createUserName:string;
-  date:string
-}
-
+  id: number;
+  hiId: number;
+  name: string;
+  content: string;
+  remark: string;
+  createUserId: number;
+  createUserName: string;
+  date: string;
+};
 
-export const getChackGroupData = (params?:any) => {
+export const getChackGroupData = (params?: any) => {
   return request<{
-       currPage: number;
-       current:number;
-       list:any[];
-       pageSize:number;
-       totalCount:number;
-       totalPage:number;
+    currPage: number;
+    current: number;
+    list: any[];
+    pageSize: number;
+    totalCount: number;
+    totalPage: number;
   }>('/manager/CheckGroup/getCheckGroupList', {
     method: 'GET',
-    params:{...params}
+    params: { ...params },
   });
 };
 
 //获取查核组字典
-export const getCheckData = (params?:any) => {
+export const getCheckData = (params?: any) => {
   return request<{
-       currPage: number;
-       current:number;
-       list:any[];
-       pageSize:number;
-       totalCount:number;
-       totalPage:number;
+    currPage: number;
+    current: number;
+    list: any[];
+    pageSize: number;
+    totalCount: number;
+    totalPage: number;
   }>('/manager/CheckGroup/getCheckGroup', {
     method: 'GET',
-    params:{...params}
+    params: { ...params },
   });
 };
 
-
-//新增表格数据 
+//新增表格数据
 export type AddTableDataType = {
-  name:string;
-  content:string;
-  remark:string;
-}
-export const addData = (data:AddTableDataType) => {
+  name: string;
+  content: string;
+  remark: string;
+};
+export const addData = (data: AddTableDataType) => {
   return request('/manager/setting/addPageTemplate', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
 //编辑表格数据
 
-export const editData = (data:{id:number}&AddTableDataType) => {
+export const editData = (data: { id: number } & AddTableDataType) => {
   return request('/manager/setting/editPageTemplate', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
 
-export const delData = (id:string) => {
+export const delData = (id: string) => {
   return request('/manager/setting/deletePageTemplate', {
     method: 'POST',
-    params:{id}
+    params: { id },
   });
 };
-
-
-
-
-
-
-
-

+ 3 - 5
src/pages/baseInfoMana/checkGroupMana/style.less

@@ -1,9 +1,8 @@
 .checkGroupMana {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -31,13 +30,12 @@
         font-size: 14px;
         font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
-        color: #FFFFFF;
+        color: #ffffff;
         line-height: 24px;
         padding: 0 14px;
-        background: #3377FF;
+        background: #3377ff;
         border-radius: 4px;
       }
     }
-
   }
 }

+ 124 - 110
src/pages/baseInfoMana/checkGroupMana/tableSelector.tsx

@@ -1,120 +1,134 @@
-import React, { useEffect, useState } from "react";
-import {Input} from 'antd'
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
-import { getCheckData } from "../checkGroupMana/service";
-import { getData } from "@/pages/setting/qualitativeOptionsMana/service";
-import { ModalForm } from "@ant-design/pro-components";
+import React, { useEffect, useState } from 'react';
+import { Input } from 'antd';
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { getCheckData } from '../checkGroupMana/service';
+import { getData } from '@/pages/setting/qualitativeOptionsMana/service';
+import { ModalForm } from '@ant-design/pro-components';
 
 // import './style.less';
 
-
-interface TableSelecterProps  {
-    tableSelecterColumn: any[];
-    record: any
+interface TableSelecterProps {
+  tableSelecterColumn: any[];
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
-
-const TableSelecter = ({tableSelecterColumn, record,open,title,onVisibleChange,rowKey='id',request,onFinish }:{
-    tableSelecterColumn:any[],record:any,open:boolean,title:string,onVisibleChange:(bool:boolean)=>void,
-    rowKey?:string,request?:(params:any)=>Promise<any>,onFinish?:(selectedKeys:React.Key[],selectedRows:any[])=>void
-})=>{
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-        const [selectedRows,set_selectedRows] = useState<any[]>([]);
-        const [showList, set_showList] = useState<any[]>([]);
-        
-        
-        const onSelectChange = (newSelectedRowKeys: React.Key[],selectedRows:any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-    
-        };
-    
-        const saveHandle = async () => {
-    
-            onFinish&&onFinish(selectedKeys,selectedRows);
-            
-        }
-    
-    
-        return (
-            <div >
-                <Input placeholder={'请输入项目名称'} allowClear autoComplete='off'
-                    suffix={
-                        <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
-                    }
-                    style={{ marginBottom: 8 }}
-                    onChange={(e) => {
-                        if (e.target.value.length != 0) {
-                            const result = datasource.filter(item => item.indicatorName.indexOf(e.target.value) != -1);
-                            set_showList(result);
-                        } else {
-                            set_showList(datasource);
-                        }
-    
-                    }}
-    
-                />
-                <KCIMTable columns={tableSelecterColumn}
-                    options={{
-                        density: true,
-                        setting: {
-                            listsHeight: 100,
-                        },
-                    }}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    rowSelection={{
-                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
-                        // 注释该行则默认不显示下拉选项
-                        // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
-                        onChange: onSelectChange,
-                    }}
-                    pagination={{ showTitle: false, showSizeChanger: true }}
-                    //dataSource={showList}
-                    request={request?async (params)=>request(params):undefined}
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
-                </div>
-            </div>
-    
-        )
-    });
-
-    const close = ()=>{
-        onVisibleChange&&onVisibleChange(false);
-    }
-
+const TableSelecter = ({
+  tableSelecterColumn,
+  record,
+  open,
+  title,
+  onVisibleChange,
+  rowKey = 'id',
+  request,
+  onFinish,
+}: {
+  tableSelecterColumn: any[];
+  record: any;
+  open: boolean;
+  title: string;
+  onVisibleChange: (bool: boolean) => void;
+  rowKey?: string;
+  request?: (params: any) => Promise<any>;
+  onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void;
+}) => {
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+    const [selectedRows, set_selectedRows] = useState<any[]>([]);
+    const [showList, set_showList] = useState<any[]>([]);
+
+    const onSelectChange = (
+      newSelectedRowKeys: React.Key[],
+      selectedRows: any,
+    ) => {
+      setSelectedKeys([...newSelectedRowKeys]);
+    };
+
+    const saveHandle = async () => {
+      onFinish && onFinish(selectedKeys, selectedRows);
+    };
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={600} submitter={{
-            render:false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-                tableSelecterColumn={tableSelecterColumn}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-
-
-export default TableSelecter
+      <div>
+        <Input
+          placeholder={'请输入项目名称'}
+          allowClear
+          autoComplete="off"
+          suffix={<IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />}
+          style={{ marginBottom: 8 }}
+          onChange={(e) => {
+            if (e.target.value.length != 0) {
+              const result = datasource.filter(
+                (item) => item.indicatorName.indexOf(e.target.value) != -1,
+              );
+              set_showList(result);
+            } else {
+              set_showList(datasource);
+            }
+          }}
+        />
+        <KCIMTable
+          columns={tableSelecterColumn}
+          options={{
+            density: true,
+            setting: {
+              listsHeight: 100,
+            },
+          }}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          rowSelection={{
+            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+            // 注释该行则默认不显示下拉选项
+            // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+            onChange: onSelectChange,
+          }}
+          pagination={{ showTitle: false, showSizeChanger: true }}
+          //dataSource={showList}
+          request={request ? async (params) => request(params) : undefined}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认(${
+            selectedKeys.length > 0 && selectedKeys.length
+          })`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={600}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+        tableSelecterColumn={tableSelecterColumn}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default TableSelecter;

+ 336 - 272
src/pages/baseInfoMana/empMana/index.tsx

@@ -7,20 +7,35 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
-
 import { createFromIconfontCN } from '@ant-design/icons';
 
-import { ActionType, DrawerForm, EditableFormInstance, EditableProTable, ProFormCheckbox, ProFormInstance, ProFormSelect } from '@ant-design/pro-components';
-import { ModalForm, ProFormDigit, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import {
+  ActionType,
+  DrawerForm,
+  EditableFormInstance,
+  EditableProTable,
+  ProFormCheckbox,
+  ProFormInstance,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import {
+  ModalForm,
+  ProFormDigit,
+  ProFormText,
+  ProFormTextArea,
+} from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Switch } from 'antd';
-import { createRef, useEffect, useRef, useState } from 'react'
+import { createRef, useEffect, useRef, useState } from 'react';
 
-import { addData, bindCheckGroupReq, bindUnitReq, delData, editData, getData } from './service';
+import {
+  addData,
+  bindCheckGroupReq,
+  bindUnitReq,
+  delData,
+  editData,
+  getData,
+} from './service';
 
 import './style.less';
 
@@ -32,288 +47,337 @@ import TableSelecter from './tableSelector';
 import { getCheckData } from '../checkGroupMana/service';
 import { debounce } from 'lodash';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 type TableDataResponse = {
-    data: any[];
-    success: boolean;
-    total: number;
-    pageSize: number;
-    totalPage: number;
+  data: any[];
+  success: boolean;
+  total: number;
+  pageSize: number;
+  totalPage: number;
 };
 
-
-
 export default function FenyeTemplate() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
-    const [tableSelecterType, set_tableSelecterType] = useState<'UNIT' | 'CHECKGROUP'>('UNIT'); //穿梭框类型
-
-    const [currentEdit, set_currentEdit] = useState<any | undefined>(undefined);
-
-    const columns: ProColumns[] = [
-
-        {
-            title: 'ID',
-            dataIndex: 'id',
-        },
-        // {
-        //     title: '工号',
-        //     dataIndex: 'employeeId',
-        // },
-        {
-            title: '用户名',
-            dataIndex: 'account',
-        },
-        {
-            title: '姓名',
-            dataIndex: 'name',
-        },
-        {
-            title: '查核组',
-            dataIndex: 'groupList',
-            ellipsis:true,
-            renderText(groupList, record, index, action) {
-                if (groupList) {
-                    return groupList.reduce((prev: string, next: any) => `${prev.length > 0 ? prev + ',' : prev}${next.name}`, '')
-                }
-            },
-        },
-        {
-            title: '单位名',
-            dataIndex: 'departList',
-            ellipsis: true,
-            renderText(departList, record, index, action) {
-                if (departList) {
-                    return departList.reduce((prev: string, next: any) => `${prev.length > 0 ? prev + ',' : prev}${next.name}`, '')
-                }
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 160,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <a key='unit' onClick={() => { openTransformModal(record); set_tableSelecterType('UNIT'); }}>单位</a>,
-                    <a key='checkGroup' onClick={() => { openTransformModal(record); set_tableSelecterType('CHECKGROUP'); }}>查核组</a>
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getData(params);
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount
-            }
-        }
-        return []
-    }
-
-
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-        if (type == 'ADD') {
-            const result = {
-                name: formVal.name,
-                content: JSON.stringify(formVal.table),
-                remark: formVal.remark
-            }
-            const resp = await addData({ ...result });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
+  const [tableSelecterType, set_tableSelecterType] = useState<
+    'UNIT' | 'CHECKGROUP'
+  >('UNIT'); //穿梭框类型
+
+  const [currentEdit, set_currentEdit] = useState<any | undefined>(undefined);
+
+  const columns: ProColumns[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+    },
+    // {
+    //     title: '工号',
+    //     dataIndex: 'employeeId',
+    // },
+    {
+      title: '用户名',
+      dataIndex: 'account',
+    },
+    {
+      title: '姓名',
+      dataIndex: 'name',
+    },
+    {
+      title: '查核组',
+      dataIndex: 'groupList',
+      ellipsis: true,
+      renderText(groupList, record, index, action) {
+        if (groupList) {
+          return groupList.reduce(
+            (prev: string, next: any) =>
+              `${prev.length > 0 ? prev + ',' : prev}${next.name}`,
+            '',
+          );
         }
-        if (type == 'EDIT') {
-            const result = {
-                id: formVal.id,
-                name: formVal.name,
-                employeeId: formVal.employeeId,
-                account: formVal.account,
-                permission: formVal.permission.join(',')
-            }
-            const resp = await editData({ ...result });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
+      },
+    },
+    {
+      title: '单位名',
+      dataIndex: 'departList',
+      ellipsis: true,
+      renderText(departList, record, index, action) {
+        if (departList) {
+          return departList.reduce(
+            (prev: string, next: any) =>
+              `${prev.length > 0 ? prev + ',' : prev}${next.name}`,
+            '',
+          );
         }
-
-        return true;
-    }
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-
-        const formRef = useRef<ProFormInstance<any>>();
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}权限`}
-                width={600}
-                initialValues={type == 'EDIT' ? { ...record, permission: record.roleList ? record.roleList.split(',') : [] } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑权限</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val: any) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                formRef={formRef}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormCheckbox.Group
-                    name="permission"
-                    layout='horizontal'
-                    label="行业分布"
-                    options={[
-                        { label: '管理员', value: '1' },
-                        { label: '查核组长', value: '2' },
-                        { label: '查核组员', value: '3' },
-                        { label: '单位负责人', value: '4' },
-                        { label: '改善人', value: '5' },
-                        { label: '职能科室负责人', value: '6' },
-                        { label: '职能科室普通人员', value: '7' },
-                        { label: '自查人', value: '8' },
-                    ]}
-                />
-            </ModalForm>
-        )
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 160,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <a
+            key="unit"
+            onClick={() => {
+              openTransformModal(record);
+              set_tableSelecterType('UNIT');
+            }}
+          >
+            单位
+          </a>,
+          <a
+            key="checkGroup"
+            onClick={() => {
+              openTransformModal(record);
+              set_tableSelecterType('CHECKGROUP');
+            }}
+          >
+            查核组
+          </a>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getData(params);
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+      };
     }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
+    return [];
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    if (type == 'ADD') {
+      const result = {
+        name: formVal.name,
+        content: JSON.stringify(formVal.table),
+        remark: formVal.remark,
+      };
+      const resp = await addData({ ...result });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
-
-
-    const openTransformModal = (record: any) => {
-        set_currentEdit(record);
-        set_tableSelecterVisible(true);
+    if (type == 'EDIT') {
+      const result = {
+        id: formVal.id,
+        name: formVal.name,
+        employeeId: formVal.employeeId,
+        account: formVal.account,
+        permission: formVal.permission.join(','),
+      };
+      const resp = await editData({ ...result });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
 
+    return true;
+  };
 
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    const formRef = useRef<ProFormInstance<any>>();
 
-    const tableSelecterCommit = async (keys: React.Key[], rows: any[]) => {
-        if (tableSelecterType == 'CHECKGROUP') {
-            const result = {
-                employeeId: currentEdit.employeeId,
-                employeeName: currentEdit.name,
-                groupList: rows.map((a: any) => ({
-                    code: a.code,
-                    name: a.name,
-                    isManager: a.flag ? 1 : 0
-                }))
-            }
-            const resp = await bindCheckGroupReq(result);
-            if (resp) {
-                set_tableSelecterVisible(false);
-                tableRef.current?.reload();
-            }
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}权限`}
+        width={600}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+                permission: record.roleList ? record.roleList.split(',') : [],
+              }
+            : {}
         }
-        if (tableSelecterType == 'UNIT') {
-            const result = {
-                employeeId: currentEdit.employeeId,
-                employeeName: currentEdit.name,
-                departmentList: rows.map((a: any) => ({
-                    code: a.code,
-                    name: a.name,
-                    isManager: a.flag ? 1 : 0,
-                    isFunction: 0
-                }))
-            };
-            const resp = await bindUnitReq(result);
-            if (resp) {
-                set_tableSelecterVisible(false);
-                tableRef.current?.reload();
-            }
-
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑权限</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
+        onFinish={(val: any) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        formRef={formRef}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormCheckbox.Group
+          name="permission"
+          layout="horizontal"
+          label="行业分布"
+          options={[
+            { label: '管理员', value: '1' },
+            { label: '查核组长', value: '2' },
+            { label: '查核组员', value: '3' },
+            { label: '单位负责人', value: '4' },
+            { label: '改善人', value: '5' },
+            { label: '职能科室负责人', value: '6' },
+            { label: '职能科室普通人员', value: '7' },
+            { label: '自查人', value: '8' },
+          ]}
+        />
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const openTransformModal = (record: any) => {
+    set_currentEdit(record);
+    set_tableSelecterVisible(true);
+  };
+
+  const tableSelecterCommit = async (keys: React.Key[], rows: any[]) => {
+    if (tableSelecterType == 'CHECKGROUP') {
+      const result = {
+        employeeId: currentEdit.employeeId,
+        employeeName: currentEdit.name,
+        groupList: rows.map((a: any) => ({
+          code: a.code,
+          name: a.name,
+          isManager: a.flag ? 1 : 0,
+        })),
+      };
+      const resp = await bindCheckGroupReq(result);
+      if (resp) {
+        set_tableSelecterVisible(false);
+        tableRef.current?.reload();
+      }
     }
-
-    const debouncedFetch = debounce(async (keyWords, callback) => {
-        const resp = await getCheckData({ pageSize: 20, current: 1, filter: keyWords });
-        if (resp) {
-            callback(resp.list.map((a: any) => ({
-                label: a.name,
-                value: a.code,
-            })));
-        } else {
-            callback([]);
-        }
-    }, 300);
-
-
-    useEffect(() => {
-
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='empMana' title={false}>
-            <TableSelecter
-                onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
-                title='关联'
-                rowKey={tableSelecterType == 'UNIT' ? 'code' : 'id'}
-                tableSelecterType={tableSelecterType}
-                record={currentEdit}
-                open={tableSelecterVisible}
-                onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+    if (tableSelecterType == 'UNIT') {
+      const result = {
+        employeeId: currentEdit.employeeId,
+        employeeName: currentEdit.name,
+        departmentList: rows.map((a: any) => ({
+          code: a.code,
+          name: a.name,
+          isManager: a.flag ? 1 : 0,
+          isFunction: 0,
+        })),
+      };
+      const resp = await bindUnitReq(result);
+      if (resp) {
+        set_tableSelecterVisible(false);
+        tableRef.current?.reload();
+      }
+    }
+  };
+
+  const debouncedFetch = debounce(async (keyWords, callback) => {
+    const resp = await getCheckData({
+      pageSize: 20,
+      current: 1,
+      filter: keyWords,
+    });
+    if (resp) {
+      callback(
+        resp.list.map((a: any) => ({
+          label: a.name,
+          value: a.code,
+        })),
+      );
+    } else {
+      callback([]);
+    }
+  }, 300);
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="empMana" title={false}>
+      <TableSelecter
+        onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
+        title="关联"
+        rowKey={tableSelecterType == 'UNIT' ? 'code' : 'id'}
+        tableSelecterType={tableSelecterType}
+        record={currentEdit}
+        open={tableSelecterVisible}
+        onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+      />
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem" style={{ marginRight: 16, width: 220 }}>
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'请输入姓名/工号'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
+                />
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    filter: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  filter: (e.target as HTMLInputElement).value,
+                });
+              }}
             />
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem' style={{ marginRight: 16, width: 220 }}>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'请输入姓名/工号'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        filter: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    filter: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                {/* <div className='btnGroup'>
+          </div>
+        </div>
+        {/* <div className='btnGroup'>
                     <UpDataActBtn record type='ADD' />
                 </div> */}
-            </div>
-            <div style={{ marginTop: 16 }}>
-                <KCIMTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+      </div>
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 47 - 54
src/pages/baseInfoMana/empMana/service.ts

@@ -7,100 +7,93 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { request } from 'umi';
 
 //获取table列表数据
 
 export type FenyeTemplateItemType = {
-  id:number;
-  hiId:number;
-  name:string;
-  content:string;
-  remark:string;
-  createUserId:number;
-  createUserName:string;
-  date:string
-}
-
+  id: number;
+  hiId: number;
+  name: string;
+  content: string;
+  remark: string;
+  createUserId: number;
+  createUserName: string;
+  date: string;
+};
 
-export const getData = (params?:any) => {
+export const getData = (params?: any) => {
   return request('/manager/Employee/getEmployee', {
     method: 'GET',
-    params:{...params}
+    params: { ...params },
   });
 };
 
-
-//新增表格数据 
+//新增表格数据
 export type AddTableDataType = {
-  name:string;
-  content:string;
-  remark:string;
-}
-export const addData = (data:AddTableDataType) => {
+  name: string;
+  content: string;
+  remark: string;
+};
+export const addData = (data: AddTableDataType) => {
   return request('/manager/setting/addPageTemplate', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
 //编辑权限
-export const editData = (data:{id:number,account:string,name:string,employeeId:number,permission:string}) => {
+export const editData = (data: {
+  id: number;
+  account: string;
+  name: string;
+  employeeId: number;
+  permission: string;
+}) => {
   return request('/manager/Employee/editEmployeePermission', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //关联单位
-export const bindUnitReq = (data:{
-  employeeId:string,
-  employeeName:string,
-  departmentList:{
-    code:string,
-    name:string,
-    isManager:number,
-    isFunction:number
-  }[]
+export const bindUnitReq = (data: {
+  employeeId: string;
+  employeeName: string;
+  departmentList: {
+    code: string;
+    name: string;
+    isManager: number;
+    isFunction: number;
+  }[];
 }) => {
   return request('/manager/Employee/editDepartment', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //关联查核组
-export const bindCheckGroupReq = (data:{
-  employeeId:string,
-  employeeName:string,
-  groupList:{
-    code:string,
-    name:string,
-    isManager:number,
-  }[]
+export const bindCheckGroupReq = (data: {
+  employeeId: string;
+  employeeName: string;
+  groupList: {
+    code: string;
+    name: string;
+    isManager: number;
+  }[];
 }) => {
   return request('/manager/Employee/editCheckGroup', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
 
-export const delData = (id:string) => {
+export const delData = (id: string) => {
   return request('/manager/setting/deletePageTemplate', {
     method: 'POST',
-    params:{id}
+    params: { id },
   });
 };
-
-
-
-
-
-
-
-

+ 26 - 33
src/pages/baseInfoMana/empMana/style.less

@@ -1,46 +1,40 @@
-
-
-
 .TableSelecter {
-
   .pfm-ant-modal-footer {
     display: none !important;
   }
-  
-  .footer {
-       display: flex;
-       flex-direction:row;
-       justify-content: flex-end;
-       margin-top: 15px;
-       span {
-           display: inline-block;
-           width: 56px;
-           height: 24px;  
-           font-size: 14px;
-           line-height: 23px;
-           text-align: center;
-           border-radius: 4px;
-           cursor: pointer;
 
-           &.ok {
-               color: #FFFFFF;
-               background:#3377FF;
-               margin-left: 8px;
-           }
-           &.cancel {
-               border: 1px solid #DAE2F2;
-           }
-       }
+  .footer {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+    margin-top: 15px;
+    span {
+      display: inline-block;
+      width: 56px;
+      height: 24px;
+      font-size: 14px;
+      line-height: 23px;
+      text-align: center;
+      border-radius: 4px;
+      cursor: pointer;
 
+      &.ok {
+        color: #ffffff;
+        background: #3377ff;
+        margin-left: 8px;
+      }
+      &.cancel {
+        border: 1px solid #dae2f2;
+      }
+    }
   }
 }
 
 .empMana {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -68,13 +62,12 @@
         font-size: 14px;
         font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
-        color: #FFFFFF;
+        color: #ffffff;
         line-height: 24px;
         padding: 0 14px;
-        background: #3377FF;
+        background: #3377ff;
         border-radius: 4px;
       }
     }
-
   }
 }

+ 263 - 230
src/pages/baseInfoMana/empMana/tableSelector.tsx

@@ -1,250 +1,283 @@
-import React, { useEffect, useState } from "react";
-import { Input, Switch } from 'antd'
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
-import { getChackGroupData, getCheckData } from "../checkGroupMana/service";
+import React, { useEffect, useState } from 'react';
+import { Input, Switch } from 'antd';
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { getChackGroupData, getCheckData } from '../checkGroupMana/service';
 
-import { ModalForm, ProColumns } from "@ant-design/pro-components";
-import { getData } from "../unitMana/service";
-import { set } from "lodash";
+import { ModalForm, ProColumns } from '@ant-design/pro-components';
+import { getData } from '../unitMana/service';
+import { set } from 'lodash';
 
 // import './style.less';
 
-
 interface TableSelecterProps {
-    record: any
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
-
-const TableSelecter = ({ tableSelecterType, record, open, title, onVisibleChange, rowKey = 'id', request, onFinish }: {
-    record: any, open: boolean, title: string, onVisibleChange: (bool: boolean) => void,
-    tableSelecterType: 'UNIT' | 'CHECKGROUP',
-    rowKey?: string, request?: (params: any) => Promise<any>, onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void
+const TableSelecter = ({
+  tableSelecterType,
+  record,
+  open,
+  title,
+  onVisibleChange,
+  rowKey = 'id',
+  request,
+  onFinish,
+}: {
+  record: any;
+  open: boolean;
+  title: string;
+  onVisibleChange: (bool: boolean) => void;
+  tableSelecterType: 'UNIT' | 'CHECKGROUP';
+  rowKey?: string;
+  request?: (params: any) => Promise<any>;
+  onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void;
 }) => {
-
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-        const [selectedRows, set_selectedRows] = useState<any[]>([]);
-        const [showList, set_showList] = useState<any[]>([]);
-
-
-        const unitColumns: ProColumns[] = [
-            {
-                title: 'Code',
-                dataIndex: 'code',
-            },
-            {
-                title: '单位名',
-                dataIndex: 'name',
-            },
-            {
-                title: '是否单位管理人',
-                dataIndex: 'flag',
-                renderText(flag, record, index, action) {
-                    return <Switch size='small' checked={flag} onChange={(bool) => onSwitchChange(bool, record)} />
-                },
-            }
-        ];
-        const checkGroupColumns: ProColumns[] = [
-            {
-                title: 'ID',
-                dataIndex: 'id',
-            },
-            {
-                title: '查核组名',
-                dataIndex: 'name',
-            },
-            {
-                title: '是否查核组长',
-                dataIndex: 'flag',
-                renderText(flag, record, index, action) {
-                    return <Switch size='small' checked={flag} onChange={(bool) => onSwitchChange(bool, record)} />
-                },
-            }
-        ];
-
-
-        const onSwitchChange = (bool: boolean, record: any) => {
-            const newData = datasource.map((item) => {
-                if (item.code == record.code) {
-                    return {
-                        ...item,
-                        flag: bool
-                    }
-                } else {
-                    return item
-                }
-            });
-            const newShowList = showList.map((item) => {
-                if (item.code == record.code) {
-                    return {
-                        ...item,
-                        flag: bool
-                    }
-                } else {
-                    return item
-                }
-            });
-
-            
-            set_datasource([...newData]);
-            set_showList([...newShowList]);
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+    const [selectedRows, set_selectedRows] = useState<any[]>([]);
+    const [showList, set_showList] = useState<any[]>([]);
+
+    const unitColumns: ProColumns[] = [
+      {
+        title: 'Code',
+        dataIndex: 'code',
+      },
+      {
+        title: '单位名',
+        dataIndex: 'name',
+      },
+      {
+        title: '是否单位管理人',
+        dataIndex: 'flag',
+        renderText(flag, record, index, action) {
+          return (
+            <Switch
+              size="small"
+              checked={flag}
+              onChange={(bool) => onSwitchChange(bool, record)}
+            />
+          );
+        },
+      },
+    ];
+    const checkGroupColumns: ProColumns[] = [
+      {
+        title: 'ID',
+        dataIndex: 'id',
+      },
+      {
+        title: '查核组名',
+        dataIndex: 'name',
+      },
+      {
+        title: '是否查核组长',
+        dataIndex: 'flag',
+        renderText(flag, record, index, action) {
+          return (
+            <Switch
+              size="small"
+              checked={flag}
+              onChange={(bool) => onSwitchChange(bool, record)}
+            />
+          );
+        },
+      },
+    ];
+
+    const onSwitchChange = (bool: boolean, record: any) => {
+      const newData = datasource.map((item) => {
+        if (item.code == record.code) {
+          return {
+            ...item,
+            flag: bool,
+          };
+        } else {
+          return item;
         }
-
-        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-            set_selectedRows([...selectedRows]);
-
-        };
-
-        const saveHandle = async () => {
-            const selectedRowCodes = selectedRows.map((a)=>a.code);
-            const rows = datasource.filter((a)=>selectedRowCodes.includes(a.code));
-            onFinish && onFinish(selectedKeys, rows);
+      });
+      const newShowList = showList.map((item) => {
+        if (item.code == record.code) {
+          return {
+            ...item,
+            flag: bool,
+          };
+        } else {
+          return item;
         }
-
-        const getTableData = async () => {
-            if(tableSelecterType == 'UNIT'){
-                const resp = await getData();
-                const checkedUnitCodes = record.departList?record.departList.map((a:any)=>a.code):[];
-                let selectedCodes:string[] = [];
-                let selectedRows:any[] = [];
-                if (resp) {
-                    const data = resp.map((a:any)=>{
-                        if(checkedUnitCodes.includes(a.code)){
-                            selectedCodes.push(a.code);
-                            selectedRows.push(a);
-                            const needItem = record.departList.filter((b:any)=>a.code == b.code);
-                            
-                             return {
-                                ...a,
-                                flag:needItem[0].isManager?true:false
-                             }
-                        }else{
-                             return a
-                        }
-                    });
-
-                    set_showList(data);
-                    set_selectedRows([...selectedRows]);
-                    setSelectedKeys([...selectedCodes]);
-                    set_datasource([...datasource, ...data]);
-                }
-            }
-            if(tableSelecterType == 'CHECKGROUP'){
-                const resp = await getCheckData({pageSize:500,current:1});
-                const checkedUnitCodes = record.groupList?record.groupList.map((a:any)=>a.code):[];
-                let selectedCodes:string[] = [];
-                let selectedRows:any[] = [];
-                if (resp) {
-                    const data = resp.list.map((a:any)=>{
-                          if(checkedUnitCodes.includes(a.code)){
-                            selectedCodes.push(a.code);
-                            selectedRows.push(a);
-                            const needItem = record.groupList.filter((b:any)=>a.code == b.code);
-                               return {
-                                  ...a,
-                                  flag:needItem[0].isManager?true:false
-                               }
-                          }else{
-                               return a
-                          }
-                    });
-                    set_showList(data);
-                    set_selectedRows([...selectedRows]);
-                    setSelectedKeys([...selectedCodes]);
-                    set_datasource([...datasource, ...data]);
-                }
+      });
+
+      set_datasource([...newData]);
+      set_showList([...newShowList]);
+    };
+
+    const onSelectChange = (
+      newSelectedRowKeys: React.Key[],
+      selectedRows: any,
+    ) => {
+      setSelectedKeys([...newSelectedRowKeys]);
+      set_selectedRows([...selectedRows]);
+    };
+
+    const saveHandle = async () => {
+      const selectedRowCodes = selectedRows.map((a) => a.code);
+      const rows = datasource.filter((a) => selectedRowCodes.includes(a.code));
+      onFinish && onFinish(selectedKeys, rows);
+    };
+
+    const getTableData = async () => {
+      if (tableSelecterType == 'UNIT') {
+        const resp = await getData();
+        const checkedUnitCodes = record.departList
+          ? record.departList.map((a: any) => a.code)
+          : [];
+        let selectedCodes: string[] = [];
+        let selectedRows: any[] = [];
+        if (resp) {
+          const data = resp.map((a: any) => {
+            if (checkedUnitCodes.includes(a.code)) {
+              selectedCodes.push(a.code);
+              selectedRows.push(a);
+              const needItem = record.departList.filter(
+                (b: any) => a.code == b.code,
+              );
+
+              return {
+                ...a,
+                flag: needItem[0].isManager ? true : false,
+              };
+            } else {
+              return a;
             }
+          });
 
-            return Promise.resolve([]);
+          set_showList(data);
+          set_selectedRows([...selectedRows]);
+          setSelectedKeys([...selectedCodes]);
+          set_datasource([...datasource, ...data]);
+        }
+      }
+      if (tableSelecterType == 'CHECKGROUP') {
+        const resp = await getCheckData({ pageSize: 500, current: 1 });
+        const checkedUnitCodes = record.groupList
+          ? record.groupList.map((a: any) => a.code)
+          : [];
+        let selectedCodes: string[] = [];
+        let selectedRows: any[] = [];
+        if (resp) {
+          const data = resp.list.map((a: any) => {
+            if (checkedUnitCodes.includes(a.code)) {
+              selectedCodes.push(a.code);
+              selectedRows.push(a);
+              const needItem = record.groupList.filter(
+                (b: any) => a.code == b.code,
+              );
+              return {
+                ...a,
+                flag: needItem[0].isManager ? true : false,
+              };
+            } else {
+              return a;
+            }
+          });
+          set_showList(data);
+          set_selectedRows([...selectedRows]);
+          setSelectedKeys([...selectedCodes]);
+          set_datasource([...datasource, ...data]);
         }
+      }
 
- 
-
-        useEffect(() => {
-            getTableData()
-        }, [])
-
-
-        return (
-            <div >
-                <Input placeholder={tableSelecterType == 'UNIT'?'请输入单位名称':'请输入查核组名称'} allowClear autoComplete='off'
-                    suffix={
-                        <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
-                    }
-                    style={{ marginBottom: 8 }}
-                    onChange={(e) => {
-                        if (e.target.value.length != 0) {
-                            const result = datasource.filter(item => item.name.indexOf(e.target.value) != -1);
-                            set_showList(result);
-                        } else {
-                            set_showList(datasource);
-                        }
-
-                    }}
-
-                />
-                <KCIMTable columns={tableSelecterType == 'UNIT' ? unitColumns : checkGroupColumns}
-                    options={{
-                        density: true,
-                        setting: {
-                            listsHeight: 100,
-                        },
-                    }}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    rowSelection={{
-                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
-                        // 注释该行则默认不显示下拉选项
-                        // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
-                        selectedRowKeys:selectedKeys,
-                        onChange: onSelectChange,
-                    }}
-                    pagination={{ showTitle: false, showSizeChanger: true }}
-                    dataSource={showList}
-
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
-                </div>
-            </div>
-
-        )
-    });
-
-    const close = () => {
-        onVisibleChange && onVisibleChange(false);
-    }
+      return Promise.resolve([]);
+    };
 
+    useEffect(() => {
+      getTableData();
+    }, []);
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={500} submitter={{
-            render: false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-
-
-export default TableSelecter
+      <div>
+        <Input
+          placeholder={
+            tableSelecterType == 'UNIT' ? '请输入单位名称' : '请输入查核组名称'
+          }
+          allowClear
+          autoComplete="off"
+          suffix={<IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />}
+          style={{ marginBottom: 8 }}
+          onChange={(e) => {
+            if (e.target.value.length != 0) {
+              const result = datasource.filter(
+                (item) => item.name.indexOf(e.target.value) != -1,
+              );
+              set_showList(result);
+            } else {
+              set_showList(datasource);
+            }
+          }}
+        />
+        <KCIMTable
+          columns={
+            tableSelecterType == 'UNIT' ? unitColumns : checkGroupColumns
+          }
+          options={{
+            density: true,
+            setting: {
+              listsHeight: 100,
+            },
+          }}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          rowSelection={{
+            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+            // 注释该行则默认不显示下拉选项
+            // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+            selectedRowKeys: selectedKeys,
+            onChange: onSelectChange,
+          }}
+          pagination={{ showTitle: false, showSizeChanger: true }}
+          dataSource={showList}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认(${
+            selectedKeys.length > 0 && selectedKeys.length
+          })`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={500}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default TableSelecter;

+ 119 - 108
src/pages/baseInfoMana/empMana/transform.tsx

@@ -1,19 +1,18 @@
-import React, { useEffect, useImperativeHandle, useState } from "react";
-import {Transfer} from 'antd'
+import React, { useEffect, useImperativeHandle, useState } from 'react';
+import { Transfer } from 'antd';
 import { TransferItem, TransferProps } from 'antd/es/transfer';
 import { ColumnsType } from 'antd/es/table';
-import { difference } from "lodash";
+import { difference } from 'lodash';
 import { TableRowSelection } from 'antd/es/table/interface';
-import { KCIMTable } from "@/components/KCIMTable";
-
+import { KCIMTable } from '@/components/KCIMTable';
 
 interface TableTransferProps extends TransferProps<TransferItem> {
-    leftColumns: ColumnsType<any>;
-    rightColumns: ColumnsType<any>;
+  leftColumns: ColumnsType<any>;
+  rightColumns: ColumnsType<any>;
 }
 
-const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, ...restProps }: TableTransferProps, ref) => {
-
+const TableTransfer = React.forwardRef(
+  ({ leftColumns, rightColumns, ...restProps }: TableTransferProps, ref) => {
     const [_data, _set_data] = useState<any>();
     const [targetKeys, setTargetKeys] = useState<string[]>([]);
     const [datasource, set_datasource] = useState<any[]>([]);
@@ -21,114 +20,126 @@ const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, ...restProp
 
     //获取单元
     const getFuncList = async () => {
-
-        // const resp = await getTotalEmps({
-        //     computeDate: currentComputeDate as string,
-        //     unitCode: currentSelectedTreeNode.code
-        // });
-        // if (resp) {
-        //     //_set_data(resp);
-        //     const allData = resp.allEmployees.concat(resp.checkEmployees);
-        //     set_datasource(allData);
-        //     const defaultSelctedkeys = resp.checkEmployees.map((item: any) => item.empNo);
-        //     setTargetKeys(defaultSelctedkeys);
-        // }
-    }
+      // const resp = await getTotalEmps({
+      //     computeDate: currentComputeDate as string,
+      //     unitCode: currentSelectedTreeNode.code
+      // });
+      // if (resp) {
+      //     //_set_data(resp);
+      //     const allData = resp.allEmployees.concat(resp.checkEmployees);
+      //     set_datasource(allData);
+      //     const defaultSelctedkeys = resp.checkEmployees.map((item: any) => item.empNo);
+      //     setTargetKeys(defaultSelctedkeys);
+      // }
+    };
 
     const onChange = (nextTargetKeys: string[]) => {
-        setTargetKeys(nextTargetKeys);
+      setTargetKeys(nextTargetKeys);
     };
 
-    const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
-        //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
-        setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+    const onSelectChange = (
+      sourceSelectedKeys: string[],
+      targetSelectedKeys: string[],
+    ) => {
+      //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+      setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
     };
 
     useImperativeHandle(ref, () => ({
-        save: async () => {
-            // const items = datasource.filter(a => targetKeys.includes(a.empNo));
-            // const resp = await saveEmpsRequest(items);
-            // if (resp) {
-            //     tableRef.current?.reload();
-            // }
-        }
+      save: async () => {
+        // const items = datasource.filter(a => targetKeys.includes(a.empNo));
+        // const resp = await saveEmpsRequest(items);
+        // if (resp) {
+        //     tableRef.current?.reload();
+        // }
+      },
     }));
 
     useEffect(() => {
-        getFuncList();
-    }, [])
+      getFuncList();
+    }, []);
 
     return (
-        <Transfer className='TableTransfer' showSearch
-            titles={['待选项', '已选项']}
-            locale={{
-                itemUnit: '项',
-                itemsUnit: '项',
-                searchPlaceholder: '请输入',
-            }}
-            oneWay={true}
-            onChange={onChange}
-            onSelectChange={onSelectChange}
-            dataSource={datasource}
-            rowKey={record => record.empNo}
-            targetKeys={targetKeys}
-            selectedKeys={selectedKeys}
-            filterOption={(inputValue, item) => {
-                return item.name!.indexOf(inputValue) !== -1
-
-            }}
-        >
-            {({
-                direction,
-                filteredItems,
-                onItemSelectAll,
-                onItemSelect,
-                selectedKeys: listSelectedKeys,
-                disabled: listDisabled,
-            }) => {
-
-                // console.log({ filteredItems, listSelectedKeys,direction });
-                const columns = direction === 'left' ? leftColumns : rightColumns;
-
-                const rowSelection: TableRowSelection<TransferItem> = {
-                    getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
-                    onSelectAll(selected, selectedRows) {
-                        const treeSelectedKeys = selectedRows.map(({ empNo }) => empNo);
-                        const diffKeys = selected
-                            ? difference(treeSelectedKeys, listSelectedKeys)
-                            : difference(listSelectedKeys, treeSelectedKeys);
-                        onItemSelectAll(diffKeys as string[], selected);
-                    },
-                    onSelect({ empNo }, selected) {
-                        onItemSelect(empNo as string, selected);
-                    },
-                    selectedRowKeys: listSelectedKeys,
-                };
-
-                return (
-                    <KCIMTable
-                        rowSelection={rowSelection}
-                        columns={columns as TransferItem[]}
-                        dataSource={filteredItems}
-                        size="small"
-                        bordered={false}
-                        rowKey={'empNo'}
-                        pagination={{ showTitle: false, pageSize: 9, showLessItems: false, simple: true, showTotal: () => false }}
-                        tableAlertRender={false}
-                        style={{ pointerEvents: listDisabled ? 'none' : undefined }}
-                        onRow={({ empNo, disabled: itemDisabled }) => ({
-                            onClick: () => {
-                                if (itemDisabled || listDisabled) return;
-                                onItemSelect(empNo as string, !listSelectedKeys.includes(empNo as string));
-                            },
-                        })}
-                    />
-                );
-            }}
-        </Transfer>
-    )
-});
-
-export default TableTransfer
-
-
+      <Transfer
+        className="TableTransfer"
+        showSearch
+        titles={['待选项', '已选项']}
+        locale={{
+          itemUnit: '项',
+          itemsUnit: '项',
+          searchPlaceholder: '请输入',
+        }}
+        oneWay={true}
+        onChange={onChange}
+        onSelectChange={onSelectChange}
+        dataSource={datasource}
+        rowKey={(record) => record.empNo}
+        targetKeys={targetKeys}
+        selectedKeys={selectedKeys}
+        filterOption={(inputValue, item) => {
+          return item.name!.indexOf(inputValue) !== -1;
+        }}
+      >
+        {({
+          direction,
+          filteredItems,
+          onItemSelectAll,
+          onItemSelect,
+          selectedKeys: listSelectedKeys,
+          disabled: listDisabled,
+        }) => {
+          // console.log({ filteredItems, listSelectedKeys,direction });
+          const columns = direction === 'left' ? leftColumns : rightColumns;
+
+          const rowSelection: TableRowSelection<TransferItem> = {
+            getCheckboxProps: (item) => ({
+              disabled: listDisabled || item.disabled,
+            }),
+            onSelectAll(selected, selectedRows) {
+              const treeSelectedKeys = selectedRows.map(({ empNo }) => empNo);
+              const diffKeys = selected
+                ? difference(treeSelectedKeys, listSelectedKeys)
+                : difference(listSelectedKeys, treeSelectedKeys);
+              onItemSelectAll(diffKeys as string[], selected);
+            },
+            onSelect({ empNo }, selected) {
+              onItemSelect(empNo as string, selected);
+            },
+            selectedRowKeys: listSelectedKeys,
+          };
+
+          return (
+            <KCIMTable
+              rowSelection={rowSelection}
+              columns={columns as TransferItem[]}
+              dataSource={filteredItems}
+              size="small"
+              bordered={false}
+              rowKey={'empNo'}
+              pagination={{
+                showTitle: false,
+                pageSize: 9,
+                showLessItems: false,
+                simple: true,
+                showTotal: () => false,
+              }}
+              tableAlertRender={false}
+              style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+              onRow={({ empNo, disabled: itemDisabled }) => ({
+                onClick: () => {
+                  if (itemDisabled || listDisabled) return;
+                  onItemSelect(
+                    empNo as string,
+                    !listSelectedKeys.includes(empNo as string),
+                  );
+                },
+              })}
+            />
+          );
+        }}
+      </Transfer>
+    );
+  },
+);
+
+export default TableTransfer;

+ 255 - 227
src/pages/baseInfoMana/unitMana/index.tsx

@@ -7,18 +7,25 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
-
 import { createFromIconfontCN } from '@ant-design/icons';
 
-import { ActionType, DrawerForm, EditableFormInstance, EditableProTable, ProFormInstance, ProFormSelect } from '@ant-design/pro-components';
-import { ModalForm, ProFormDigit, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import {
+  ActionType,
+  DrawerForm,
+  EditableFormInstance,
+  EditableProTable,
+  ProFormInstance,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import {
+  ModalForm,
+  ProFormDigit,
+  ProFormText,
+  ProFormTextArea,
+} from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm } from 'antd';
-import React, { useEffect, useRef, useState } from 'react'
+import React, { useEffect, useRef, useState } from 'react';
 
 import { addData, delData, editData, getData } from './service';
 
@@ -29,242 +36,263 @@ import { KCIMTable } from '@/components/KCIMTable';
 import KCIMDrawerForm from '@/components/KCIMDrawerForm';
 import TableSelecter from './tableSelector';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 type TableDataResponse = {
-    data: any[]; 
-    success: boolean; 
-    total: number; 
-    pageSize: number; 
-    totalPage: number;
+  data: any[];
+  success: boolean;
+  total: number;
+  pageSize: number;
+  totalPage: number;
 };
 
 export default function FenyeTemplate() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-
-    const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
-    const [tableSelecterType, set_tableSelecterType] = useState<'EMP' | 'CHECKGROUP'>('EMP'); //穿梭框类型
-
-    const [currentEdit,set_currentEdit] = useState<any|undefined>(undefined);
-
-    const columns: ProColumns[] = [
-
-        {
-            title: 'Code',
-            dataIndex: 'code',
-        },
-        {
-            title: '展示排序',
-            dataIndex: 'sort',
-        },
-        {
-            title: '单位名',
-            dataIndex: 'name',
-        },
-        {
-            title: '职能科室',
-            dataIndex: 'createUserName',
-        },
-        {
-            title: '单位负责人',
-            dataIndex: 'manager',
-            renderText(list, record, index, action) {
-                 if(list){
-                      return list.reduce((prev:string,cur:any)=>`${prev.length>0?prev+',':''}${cur.name}`,'')
-                 }
-            },
-        },
-        {
-            title: '备注',
-            dataIndex: 'remark',
-        },
-        {
-            title: '是否作废',
-            dataIndex: 'remark',
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 140,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <a key={'emp'} onClick={() => { openTransformModal(record);set_tableSelecterType('EMP');}} >人员</a>,
-                    // <a key={'theme'}>主题</a>,
-                    // <a key={'checkPoint'}>查核要点</a>
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getData(params);
-        if (resp) {
-            return {
-                data: resp,
-                success: true,
-            }
-            
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+
+  const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
+  const [tableSelecterType, set_tableSelecterType] = useState<
+    'EMP' | 'CHECKGROUP'
+  >('EMP'); //穿梭框类型
+
+  const [currentEdit, set_currentEdit] = useState<any | undefined>(undefined);
+
+  const columns: ProColumns[] = [
+    {
+      title: 'Code',
+      dataIndex: 'code',
+    },
+    {
+      title: '展示排序',
+      dataIndex: 'sort',
+    },
+    {
+      title: '单位名',
+      dataIndex: 'name',
+    },
+    {
+      title: '职能科室',
+      dataIndex: 'createUserName',
+    },
+    {
+      title: '单位负责人',
+      dataIndex: 'manager',
+      renderText(list, record, index, action) {
+        if (list) {
+          return list.reduce(
+            (prev: string, cur: any) =>
+              `${prev.length > 0 ? prev + ',' : ''}${cur.name}`,
+            '',
+          );
         }
-        return []
+      },
+    },
+    {
+      title: '备注',
+      dataIndex: 'remark',
+    },
+    {
+      title: '是否作废',
+      dataIndex: 'remark',
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 140,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <a
+            key={'emp'}
+            onClick={() => {
+              openTransformModal(record);
+              set_tableSelecterType('EMP');
+            }}
+          >
+            人员
+          </a>,
+          // <a key={'theme'}>主题</a>,
+          // <a key={'checkPoint'}>查核要点</a>
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getData(params);
+    if (resp) {
+      return {
+        data: resp,
+        success: true,
+      };
     }
-
-    const openTransformModal = (record:any) => {
-        set_currentEdit(record);
-        set_tableSelecterVisible(true);
+    return [];
+  };
+
+  const openTransformModal = (record: any) => {
+    set_currentEdit(record);
+    set_tableSelecterVisible(true);
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    const content = formVal.table.map((a: any) => ({}));
+
+    if (type == 'ADD') {
+      const result = {
+        name: formVal.name,
+        content: JSON.stringify(formVal.table),
+        remark: formVal.remark,
+      };
+      const resp = await addData({ ...result });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      const result = {
+        id: formVal.id,
+        name: formVal.name,
+        content: JSON.stringify(formVal.table),
+        remark: formVal.remark,
+      };
+      const resp = await editData({ ...result });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
 
+    return true;
+  };
 
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-
-        const content = formVal.table.map((a: any) => ({
-
-        }))
-
-        if (type == 'ADD') {
-            const result = {
-                name: formVal.name,
-                content: JSON.stringify(formVal.table),
-                remark: formVal.remark
-            }
-            const resp = await addData({ ...result });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    const formRef = useRef<ProFormInstance<any>>();
 
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}单位`}
+        width={400}
+        initialValues={
+          type == 'EDIT'
+            ? { ...record, filedType: 'Text' }
+            : { filedType: 'Text' }
         }
-        if (type == 'EDIT') {
-            const result = {
-                id: formVal.id,
-                name: formVal.name,
-                content: JSON.stringify(formVal.table),
-                remark: formVal.remark
-            }
-            const resp = await editData({ ...result });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-
-        return true;
-    }
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-
-        const formRef = useRef<ProFormInstance<any>>();
-        
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}单位`}
-                width={400}
-                initialValues={type == 'EDIT' ? { ...record, filedType: 'Text' } : { filedType: 'Text' }}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val: any) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                formRef={formRef}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormText
-                    name="name"
-                    label="单位名称:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '名称不能为空!' }]}
-                />
-                <ProFormDigit name="sort" label='展示排序' />
-                <ProFormTextArea
-                    name="remark"
-                    label="备注:"
-                    placeholder="请输入"
+        onFinish={(val: any) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        formRef={formRef}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText
+          name="name"
+          label="单位名称:"
+          placeholder="请输入"
+          rules={[{ required: true, message: '名称不能为空!' }]}
+        />
+        <ProFormDigit name="sort" label="展示排序" />
+        <ProFormTextArea name="remark" label="备注:" placeholder="请输入" />
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const tableSelecterCommit = async (keys: React.Key[], rows: any[]) => {};
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="unitMana" title={false}>
+      <TableSelecter
+        onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
+        title="关联"
+        rowKey="id"
+        tableSelecterType={tableSelecterType}
+        record={currentEdit}
+        open={tableSelecterVisible}
+        onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+      />
+
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem" style={{ marginRight: 16, width: 250 }}>
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'请输入单位/负责人'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-
-                
-            </ModalForm>
-        )
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-    }
-
-    const tableSelecterCommit = async (keys:React.Key[],rows:any[]) => {
-        
-    }
-
-
-    useEffect(() => {
-
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='unitMana' title={false}>
-            
-            <TableSelecter
-                onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
-                title='关联'
-                rowKey='id'
-                tableSelecterType={tableSelecterType}
-                record={currentEdit}
-                open={tableSelecterVisible}
-                onFinish={(keys,rows)=>tableSelecterCommit(keys,rows)}
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    filter: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  filter: (e.target as HTMLInputElement).value,
+                });
+              }}
             />
-
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem' style={{ marginRight: 16, width: 250 }}>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'请输入单位/负责人'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        filter: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    filter: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                {/* <div className='btnGroup'>
+          </div>
+        </div>
+        {/* <div className='btnGroup'>
                     <UpDataActBtn record type='ADD' />
                 </div> */}
-            </div>
-            <div style={{ marginTop: 16 }}>
-                <KCIMTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+      </div>
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 13 - 25
src/pages/baseInfoMana/unitMana/service.ts

@@ -7,56 +7,44 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { request } from 'umi';
 
 //获取table列表数据
 
-export const getData = (params?:any) => {
+export const getData = (params?: any) => {
   return request('/manager/Department/getDepartmentList', {
     method: 'GET',
-    params:{...params}
+    params: { ...params },
   });
 };
 
-
-//新增表格数据 
+//新增表格数据
 export type AddTableDataType = {
-  name:string;
-  content:string;
-  remark:string;
-}
-export const addData = (data:AddTableDataType) => {
+  name: string;
+  content: string;
+  remark: string;
+};
+export const addData = (data: AddTableDataType) => {
   return request('/manager/setting/addPageTemplate', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
 //编辑表格数据
 
-export const editData = (data:{id:number}&AddTableDataType) => {
+export const editData = (data: { id: number } & AddTableDataType) => {
   return request('/manager/setting/editPageTemplate', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
 
-export const delData = (id:string) => {
+export const delData = (id: string) => {
   return request('/manager/setting/deletePageTemplate', {
     method: 'POST',
-    params:{id}
+    params: { id },
   });
 };
-
-
-
-
-
-
-
-

+ 26 - 31
src/pages/baseInfoMana/unitMana/style.less

@@ -1,44 +1,40 @@
-
 .TableSelecter {
-
   .pfm-ant-modal-footer {
     display: none !important;
   }
-  
-  .footer {
-       display: flex;
-       flex-direction:row;
-       justify-content: flex-end;
-       margin-top: 15px;
-       span {
-           display: inline-block;
-           width: 56px;
-           height: 24px;  
-           font-size: 14px;
-           line-height: 23px;
-           text-align: center;
-           border-radius: 4px;
-           cursor: pointer;
 
-           &.ok {
-               color: #FFFFFF;
-               background:#3377FF;
-               margin-left: 8px;
-           }
-           &.cancel {
-               border: 1px solid #DAE2F2;
-           }
-       }
+  .footer {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+    margin-top: 15px;
+    span {
+      display: inline-block;
+      width: 56px;
+      height: 24px;
+      font-size: 14px;
+      line-height: 23px;
+      text-align: center;
+      border-radius: 4px;
+      cursor: pointer;
 
+      &.ok {
+        color: #ffffff;
+        background: #3377ff;
+        margin-left: 8px;
+      }
+      &.cancel {
+        border: 1px solid #dae2f2;
+      }
+    }
   }
 }
 
 .unitMana {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -66,13 +62,12 @@
         font-size: 14px;
         font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
-        color: #FFFFFF;
+        color: #ffffff;
         line-height: 24px;
         padding: 0 14px;
-        background: #3377FF;
+        background: #3377ff;
         border-radius: 4px;
       }
     }
-
   }
 }

+ 199 - 183
src/pages/baseInfoMana/unitMana/tableSelector.tsx

@@ -1,198 +1,214 @@
-import React, { useEffect, useState } from "react";
-import { Input, Switch } from 'antd'
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
-import { getCheckData } from "../checkGroupMana/service";
+import React, { useEffect, useState } from 'react';
+import { Input, Switch } from 'antd';
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { getCheckData } from '../checkGroupMana/service';
 
-import { ModalForm, ProColumns } from "@ant-design/pro-components";
-import { getData } from "../empMana/service";
+import { ModalForm, ProColumns } from '@ant-design/pro-components';
+import { getData } from '../empMana/service';
 
 // import './style.less';
 
-
 interface TableSelecterProps {
-    record: any
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
-
-const TableSelecter = ({ tableSelecterType, record, open, title, onVisibleChange, rowKey = 'id', request, onFinish }: {
-    record: any, open: boolean, title: string, onVisibleChange: (bool: boolean) => void,
-    tableSelecterType:string,
-    rowKey?: string, request?: (params: any) => Promise<any>, onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void
+const TableSelecter = ({
+  tableSelecterType,
+  record,
+  open,
+  title,
+  onVisibleChange,
+  rowKey = 'id',
+  request,
+  onFinish,
+}: {
+  record: any;
+  open: boolean;
+  title: string;
+  onVisibleChange: (bool: boolean) => void;
+  tableSelecterType: string;
+  rowKey?: string;
+  request?: (params: any) => Promise<any>;
+  onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void;
 }) => {
-
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-        const [selectedRows, set_selectedRows] = useState<any[]>([]);
-        const [showList, set_showList] = useState<any[]>([]);
-
-
-        const empColumns: ProColumns[] = [
-            {
-                title: 'ID',
-                dataIndex: 'id',
-            },
-            {
-                title: '姓名',
-                dataIndex: 'name',
-            },
-        ];
-        const checkGroupColumns: ProColumns[] = [
-            {
-                title: 'ID',
-                dataIndex: 'id',
-            },
-            {
-                title: '查核组名',
-                dataIndex: 'id',
-            },
-            {
-                title: '是否查核组长',
-                dataIndex: 'flag',
-                renderText(flag, record, index, action) {
-                    return <Switch size='small' checked={flag == '1'} onChange={(bool) => onSwitchChange(bool, record)} />
-                },
-            }
-        ];
-
-
-        const onSwitchChange = (bool: boolean, record: any) => {
-            const newData = datasource.map((item) => {
-                if (item.id == record.id) {
-                    return {
-                        ...item,
-                        flag: bool
-                    }
-                } else {
-                    return item
-                }
-            });
-            const newShowList = showList.map((item) => {
-                if (item.id == record.id) {
-                    return {
-                        ...item,
-                        flag: bool
-                    }
-                } else {
-                    return item
-                }
-            });
-
-            // console.log({newData,newShowList});
-            set_datasource([...newData]);
-            set_showList([...newShowList]);
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+    const [selectedRows, set_selectedRows] = useState<any[]>([]);
+    const [showList, set_showList] = useState<any[]>([]);
+
+    const empColumns: ProColumns[] = [
+      {
+        title: 'ID',
+        dataIndex: 'id',
+      },
+      {
+        title: '姓名',
+        dataIndex: 'name',
+      },
+    ];
+    const checkGroupColumns: ProColumns[] = [
+      {
+        title: 'ID',
+        dataIndex: 'id',
+      },
+      {
+        title: '查核组名',
+        dataIndex: 'id',
+      },
+      {
+        title: '是否查核组长',
+        dataIndex: 'flag',
+        renderText(flag, record, index, action) {
+          return (
+            <Switch
+              size="small"
+              checked={flag == '1'}
+              onChange={(bool) => onSwitchChange(bool, record)}
+            />
+          );
+        },
+      },
+    ];
+
+    const onSwitchChange = (bool: boolean, record: any) => {
+      const newData = datasource.map((item) => {
+        if (item.id == record.id) {
+          return {
+            ...item,
+            flag: bool,
+          };
+        } else {
+          return item;
         }
-
-        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-
-        };
-
-        const saveHandle = async () => {
-
-            onFinish && onFinish(selectedKeys, selectedRows);
-
-        }
-
-        const getTableData = async () => {
-            const resp = await getData({
-                current: 1,
-                pageSize: 500
-            });
-            if (resp) {
-                set_showList(resp.list);
-                set_datasource([...datasource, ...resp.list]);
-            }
-
-            return Promise.resolve([]);
+      });
+      const newShowList = showList.map((item) => {
+        if (item.id == record.id) {
+          return {
+            ...item,
+            flag: bool,
+          };
+        } else {
+          return item;
         }
-
-        useEffect(()=>{
-            console.log({record});
-        },[record]);
-
-        useEffect(() => {
-            getTableData()
-        }, [])
-
-
-        return (
-            <div >
-                <Input placeholder={'请输入名称'} allowClear autoComplete='off'
-                    suffix={
-                        <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
-                    }
-                    style={{ marginBottom: 8 }}
-                    onChange={(e) => {
-                        if (e.target.value.length != 0) {
-                            const result = datasource.filter(item => item.name.indexOf(e.target.value) != -1);
-                            set_showList(result);
-                        } else {
-                            set_showList(datasource);
-                        }
-
-                    }}
-
-                />
-                <KCIMTable columns={tableSelecterType == 'EMP' ? empColumns : checkGroupColumns}
-                    options={{
-                        density: true,
-                        setting: {
-                            listsHeight: 100,
-                        },
-                    }}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    rowSelection={{
-                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
-                        // 注释该行则默认不显示下拉选项
-                        // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
-                        onChange: onSelectChange,
-                    }}
-                    pagination={{ showTitle: false, showSizeChanger: true }}
-                    dataSource={showList}
-
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
-                </div>
-            </div>
-
-        )
-    });
-
-    const close = () => {
-        onVisibleChange && onVisibleChange(false);
-    }
-
+      });
+
+      // console.log({newData,newShowList});
+      set_datasource([...newData]);
+      set_showList([...newShowList]);
+    };
+
+    const onSelectChange = (
+      newSelectedRowKeys: React.Key[],
+      selectedRows: any,
+    ) => {
+      setSelectedKeys([...newSelectedRowKeys]);
+    };
+
+    const saveHandle = async () => {
+      onFinish && onFinish(selectedKeys, selectedRows);
+    };
+
+    const getTableData = async () => {
+      const resp = await getData({
+        current: 1,
+        pageSize: 500,
+      });
+      if (resp) {
+        set_showList(resp.list);
+        set_datasource([...datasource, ...resp.list]);
+      }
+
+      return Promise.resolve([]);
+    };
+
+    useEffect(() => {
+      console.log({ record });
+    }, [record]);
+
+    useEffect(() => {
+      getTableData();
+    }, []);
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={600} submitter={{
-            render: false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-
-
-export default TableSelecter
+      <div>
+        <Input
+          placeholder={'请输入名称'}
+          allowClear
+          autoComplete="off"
+          suffix={<IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />}
+          style={{ marginBottom: 8 }}
+          onChange={(e) => {
+            if (e.target.value.length != 0) {
+              const result = datasource.filter(
+                (item) => item.name.indexOf(e.target.value) != -1,
+              );
+              set_showList(result);
+            } else {
+              set_showList(datasource);
+            }
+          }}
+        />
+        <KCIMTable
+          columns={tableSelecterType == 'EMP' ? empColumns : checkGroupColumns}
+          options={{
+            density: true,
+            setting: {
+              listsHeight: 100,
+            },
+          }}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          rowSelection={{
+            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+            // 注释该行则默认不显示下拉选项
+            // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+            onChange: onSelectChange,
+          }}
+          pagination={{ showTitle: false, showSizeChanger: true }}
+          dataSource={showList}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认(${
+            selectedKeys.length > 0 && selectedKeys.length
+          })`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={600}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default TableSelecter;

+ 490 - 425
src/pages/baseSetting/accountingAccountSet/accountingSubMana/index.tsx

@@ -7,16 +7,20 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect, ProFormRadio } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+  ProFormRadio,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Tag, Tabs } from 'antd';
 import { Key, useEffect, useRef, useState } from 'react';
@@ -24,458 +28,519 @@ import { Key, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, delData, editData, getAccountingSubjectList, getAccountTypeDictReq } from './service';
+import {
+  addData,
+  delData,
+  editData,
+  getAccountingSubjectList,
+  getAccountTypeDictReq,
+} from './service';
 
 import './style.less';
 import { renameChildListToChildren } from '@/utils/tooljs';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 let currentRow: any = undefined;
 
- export const searchTree = (tree:any[], searchTerm:string) => {
-    const searchTermLower = searchTerm.toLowerCase();
-
-    function searchNode(node:any) {
-        const matchedChildren: any[] = [];
+export const searchTree = (tree: any[], searchTerm: string) => {
+  const searchTermLower = searchTerm.toLowerCase();
 
-        if (node.children && node.children.length > 0) {
-            node.children.forEach((child: any) => {
-                const matchedChild = searchNode(child);
-                if (matchedChild) {
-                    matchedChildren.push(matchedChild);
-                }
-            });
-        }
+  function searchNode(node: any) {
+    const matchedChildren: any[] = [];
 
-        if (node.accountingName.toLowerCase().includes(searchTermLower) || node.accountingCode.toLowerCase().includes(searchTermLower)) {
-            return {
-                ...node,
-                children: matchedChildren.length > 0 ? matchedChildren : node.children
-            };
-        } else if (matchedChildren.length > 0) {
-            return {
-                ...node,
-                children: matchedChildren
-            };
+    if (node.children && node.children.length > 0) {
+      node.children.forEach((child: any) => {
+        const matchedChild = searchNode(child);
+        if (matchedChild) {
+          matchedChildren.push(matchedChild);
         }
-
-        return null;
+      });
     }
 
-    return tree.map(rootNode => searchNode(rootNode)).filter(node => node !== null);
- }
-
-
- function sortTreeByCode(tree:any[], codeKey = 'accountingCode', childrenKey = 'children') {
-    // 首先对当前层级的节点按照 codeKey 进行排序
-    tree.sort((a, b) => {
-        return Number(a[codeKey]) - Number(b[codeKey]); // 按照 code 从小到大排序
-    });
+    if (
+      node.accountingName.toLowerCase().includes(searchTermLower) ||
+      node.accountingCode.toLowerCase().includes(searchTermLower)
+    ) {
+      return {
+        ...node,
+        children: matchedChildren.length > 0 ? matchedChildren : node.children,
+      };
+    } else if (matchedChildren.length > 0) {
+      return {
+        ...node,
+        children: matchedChildren,
+      };
+    }
 
-    // 然后对于每个节点的子节点,不进行排序,只递归下去
-    tree.forEach(node => {
-        if (node[childrenKey] && node[childrenKey].length > 0) {
-            sortTreeByCode(node[childrenKey], codeKey, childrenKey); // 递归处理子节点
-        }
-    });
+    return null;
+  }
+
+  return tree
+    .map((rootNode) => searchNode(rootNode))
+    .filter((node) => node !== null);
+};
+
+function sortTreeByCode(
+  tree: any[],
+  codeKey = 'accountingCode',
+  childrenKey = 'children',
+) {
+  // 首先对当前层级的节点按照 codeKey 进行排序
+  tree.sort((a, b) => {
+    return Number(a[codeKey]) - Number(b[codeKey]); // 按照 code 从小到大排序
+  });
+
+  // 然后对于每个节点的子节点,不进行排序,只递归下去
+  tree.forEach((node) => {
+    if (node[childrenKey] && node[childrenKey].length > 0) {
+      sortTreeByCode(node[childrenKey], codeKey, childrenKey); // 递归处理子节点
+    }
+  });
 
-    return tree; // 返回排序后的树
+  return tree; // 返回排序后的树
 }
 
-
-
 export default function AccountingSubMana() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ accountType: 1 });
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [selectableLevelList, setSelectableLevelList] = useState([]);//可选的分摊层级列表
-    const [tabs, set_tabs] = useState<any[]>([]);
-    const [accountType, set_accountType] = useState<Key>(1);
-    const columns: ProColumns[] = [
-
-        {
-            title: '会计科目名称',
-            width: 400,
-            ellipsis: true,
-            fixed: 'left',
-            dataIndex: 'accountingName',
-        },
-        {
-            title: '会计科目编码',
-            dataIndex: 'accountingCode',
-        },
-        {
-            title: '会计科目类别',
-            dataIndex: 'typeName',
-        },
-        {
-            title: '成本类别',
-            hideInTable: accountType == 1,
-            dataIndex: 'costType',
-            renderText(type) {
-                return type == 1 ? '医疗成本' : type == 2 ? '医疗全成本' : '医院全成本'
-            },
-        },
-        {
-            title: '成本属性',
-            hideInTable: accountType == 1,
-            dataIndex: 'isBaseCost',
-            renderText(type) {
-                return type == 1 ? '固定成本' : '变动成本'
-            },
-        },
-        {
-            title: '可控类型',
-            dataIndex: 'controlType',
-            renderText(type) {
-                return type == 1 ? '不可控' : '可控'
-            },
-        },
-        {
-            title: '诊别',
-            dataIndex: 'medicalType',
-            renderText(type) {
-                return type == 0 ? '全院' : type == 1 ? '门诊' : '住院'
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 120,
-            fixed: 'right',
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn record={record} type='ADDCHILD' />,
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const {filter} = params;
-        const resp = await getAccountingSubjectList({ ...params, accountType,pageSize:500 });
-        if (resp) {
-            let data = [];
-            if(filter){
-                 data = searchTree(renameChildListToChildren(resp.list, 'child'),filter) 
-            }else{
-                data = renameChildListToChildren(resp.list, 'child')
-            }
-            return {
-                data:sortTreeByCode(data),
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        }
-        return []
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({ accountType: 1 });
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [selectableLevelList, setSelectableLevelList] = useState([]); //可选的分摊层级列表
+  const [tabs, set_tabs] = useState<any[]>([]);
+  const [accountType, set_accountType] = useState<Key>(1);
+  const columns: ProColumns[] = [
+    {
+      title: '会计科目名称',
+      width: 400,
+      ellipsis: true,
+      fixed: 'left',
+      dataIndex: 'accountingName',
+    },
+    {
+      title: '会计科目编码',
+      dataIndex: 'accountingCode',
+    },
+    {
+      title: '会计科目类别',
+      dataIndex: 'typeName',
+    },
+    {
+      title: '成本类别',
+      hideInTable: accountType == 1,
+      dataIndex: 'costType',
+      renderText(type) {
+        return type == 1 ? '医疗成本' : type == 2 ? '医疗全成本' : '医院全成本';
+      },
+    },
+    {
+      title: '成本属性',
+      hideInTable: accountType == 1,
+      dataIndex: 'isBaseCost',
+      renderText(type) {
+        return type == 1 ? '固定成本' : '变动成本';
+      },
+    },
+    {
+      title: '可控类型',
+      dataIndex: 'controlType',
+      renderText(type) {
+        return type == 1 ? '不可控' : '可控';
+      },
+    },
+    {
+      title: '诊别',
+      dataIndex: 'medicalType',
+      renderText(type) {
+        return type == 0 ? '全院' : type == 1 ? '门诊' : '住院';
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 120,
+      fixed: 'right',
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn record={record} type="ADDCHILD" />,
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const { filter } = params;
+    const resp = await getAccountingSubjectList({
+      ...params,
+      accountType,
+      pageSize: 500,
+    });
+    if (resp) {
+      let data = [];
+      if (filter) {
+        data = searchTree(
+          renameChildListToChildren(resp.list, 'child'),
+          filter,
+        );
+      } else {
+        data = renameChildListToChildren(resp.list, 'child');
+      }
+      return {
+        data: sortTreeByCode(data),
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData(record.id);
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData(record.id);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
+    }
+  };
+
+  const updateTable = async (
+    formVal: any,
+    type: 'EDIT' | 'ADD' | 'ADDCHILD',
+  ) => {
+    if (type == 'ADD' || type == 'ADDCHILD') {
+      let id = 0;
+      type == 'ADDCHILD' && (id = formVal.id);
+
+      const result =
+        accountType == 1
+          ? { ...formVal, accountingType: accountType, id: id }
+          : { ...formVal, accountingType: accountType, id: id };
+
+      const resp = await addData(result);
+      if (resp) {
+        currentRow = undefined;
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      try {
+        const resp = await editData({
+          ...formVal,
+          isIncomeGroutSetSelect: false,
+          isShareParamSelect: false,
+          accountType,
+        });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      } catch (error) {
+        console.log({ error });
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | "ADDCHILD") => {
-
-        if (type == 'ADD' || type == 'ADDCHILD') {
-
-            let id = 0;
-            (type == 'ADDCHILD') && (id = formVal.id);
-
-            const result = accountType == 1 ? { ...formVal, accountingType: accountType, id: id } : { ...formVal, accountingType: accountType, id: id, };
-
-            const resp = await addData(result);
-            if (resp) {
-                currentRow = undefined;
-                tableRef.current?.reload();
-                message.success('操作成功!');
-
-            }
-
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD' | 'ADDCHILD';
+  }) => {
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}会计科目`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+              }
+            : { controlType: 1, medicalType: 0 }
         }
-        if (type == 'EDIT') {
-            try {
-                const resp = await editData({ ...formVal, isIncomeGroutSetSelect: false, isShareParamSelect: false, accountType });
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
-                }
-            } catch (error) {
-                console.log({ error });
-            }
-
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : type == 'ADDCHILD' ? (
+            <a className="add">添加</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-        return true;
-
-    }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'ADDCHILD' }) => {
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}会计科目`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record
-                } : { controlType: 1, medicalType: 0 }}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : type == 'ADDCHILD' ? <a className='add'>添加</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : type == 'ADDCHILD' ? { ...val, id: record.id } : { ...val }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormText name='typeName' hidden />
-                <ProFormText
-                    label="会计科目编码"
-                    disabled={type == 'EDIT'}
-                    rules={[
-                        {
-                            required: true,
-                            message: '会计科目编码是必填项',
-                        },
-                    ]}
-                    name="accountingCode"
-                />
-                <ProFormText
-                    label="会计科目名"
-                    rules={[
-                        {
-                            required: true,
-                            message: '会计科目名是必填项',
-                        },
-                    ]}
-                    name="accountingName"
-                />
-                <ProFormDependency name={['accountingCode']}>
-                    {
-                        ({ accountingCode }) => {
-                            return accountType == 2 ? (
-                                <>
-                                    <ProFormSelect
-                                        rules={[
-                                            {
-                                                required: true,
-                                                message: '',
-                                            },
-                                        ]}
-                                        options={[
-                                            {
-                                                value: 0,
-                                                label: '不是',
-                                            },
-                                            {
-                                                value: 1,
-                                                label: '是',
-                                            },
-                                        ]}
-                                        name="isBaseCost"
-                                        label="是否固定成本"
-                                    />
-                                    <ProFormRadio.Group
-                                        name="costType"
-                                        label="成本类别"
-                                        rules={[
-                                            {
-                                                required: true,
-                                                message: '成本类别是必填项',
-                                            },
-                                        ]}
-                                        options={[
-                                            {
-                                                label: '医疗成本',
-                                                value: 1,
-                                            },
-                                            {
-                                                label: '医疗全成本',
-                                                value: 2,
-                                            },
-                                            {
-                                                label: '医院全成本',
-                                                value: 3,
-                                            },
-                                        ]}
-                                    />
-                                </>
-                            ) : <></>
-                        }
-                    }
-                </ProFormDependency>
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT'
+              ? { ...record, ...val }
+              : type == 'ADDCHILD'
+              ? { ...val, id: record.id }
+              : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText name="typeName" hidden />
+        <ProFormText
+          label="会计科目编码"
+          disabled={type == 'EDIT'}
+          rules={[
+            {
+              required: true,
+              message: '会计科目编码是必填项',
+            },
+          ]}
+          name="accountingCode"
+        />
+        <ProFormText
+          label="会计科目名"
+          rules={[
+            {
+              required: true,
+              message: '会计科目名是必填项',
+            },
+          ]}
+          name="accountingName"
+        />
+        <ProFormDependency name={['accountingCode']}>
+          {({ accountingCode }) => {
+            return accountType == 2 ? (
+              <>
                 <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择会计科目类别',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getAccountTypeDictReq(accountType as number);
-                        if (resp) {
-                            return resp.map((a: any) => ({ label: a.name, value: a.code }))
-                        }
-                        return []
-
-                    }}
-                    fieldProps={{
-                        onChange(value, option: any) {
-                            const { label } = option;
-                            formRef.current?.setFieldValue('typeName', label);
-                        },
-                    }}
-                    name="type"
-                    label="会计科目类别"
-                />
-                <ProFormRadio.Group
-                    name="controlType"
-                    label="可控类型"
-                    rules={[
-                        {
-                            required: true,
-                            message: '可控类型是必填项',
-                        },
-                    ]}
-                    options={[
-                        {
-                            label: '不可控',
-                            value: 1,
-                        },
-                        {
-                            label: '可控',
-                            value: 2,
-                        },
-                    ]}
+                  rules={[
+                    {
+                      required: true,
+                      message: '',
+                    },
+                  ]}
+                  options={[
+                    {
+                      value: 0,
+                      label: '不是',
+                    },
+                    {
+                      value: 1,
+                      label: '是',
+                    },
+                  ]}
+                  name="isBaseCost"
+                  label="是否固定成本"
                 />
                 <ProFormRadio.Group
-                    name="medicalType"
-                    label="就诊类别"
-                    rules={[
-                        {
-                            required: true,
-                            message: '就诊类别是必填项',
-                        },
-                    ]}
-                    options={[
-                        {
-                            label: '全院',
-                            value: 0,
-                        },
-                        {
-                            label: '门诊',
-                            value: 1,
-                        },
-                        {
-                            label: '住院',
-                            value: 3,
-                        },
-                    ]}
+                  name="costType"
+                  label="成本类别"
+                  rules={[
+                    {
+                      required: true,
+                      message: '成本类别是必填项',
+                    },
+                  ]}
+                  options={[
+                    {
+                      label: '医疗成本',
+                      value: 1,
+                    },
+                    {
+                      label: '医疗全成本',
+                      value: 2,
+                    },
+                    {
+                      label: '医院全成本',
+                      value: 3,
+                    },
+                  ]}
                 />
-
-            </ModalForm>
-        )
-    }
-
-    const onTabChanged = (key: Key) => {
-        set_accountType(key);
-        tableRef.current?.reload();
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
-    }
-
-    useEffect(() => {
-        set_tabs([
+              </>
+            ) : (
+              <></>
+            );
+          }}
+        </ProFormDependency>
+        <ProFormSelect
+          rules={[
             {
-                label: '收入',
-                key: 1,
+              required: true,
+              message: '请选择会计科目类别',
             },
+          ]}
+          request={async () => {
+            const resp = await getAccountTypeDictReq(accountType as number);
+            if (resp) {
+              return resp.map((a: any) => ({ label: a.name, value: a.code }));
+            }
+            return [];
+          }}
+          fieldProps={{
+            onChange(value, option: any) {
+              const { label } = option;
+              formRef.current?.setFieldValue('typeName', label);
+            },
+          }}
+          name="type"
+          label="会计科目类别"
+        />
+        <ProFormRadio.Group
+          name="controlType"
+          label="可控类型"
+          rules={[
             {
-                label: '支出',
-                key: 2,
+              required: true,
+              message: '可控类型是必填项',
             },
-        ])
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='AccountingSubMana' title={false}>
-            <div className='toolBar' >
-                <Tabs
-                    defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
-                    items={tabs}
-                    key={'key'}
-                    onChange={(key) => onTabChanged(key)}
+          ]}
+          options={[
+            {
+              label: '不可控',
+              value: 1,
+            },
+            {
+              label: '可控',
+              value: 2,
+            },
+          ]}
+        />
+        <ProFormRadio.Group
+          name="medicalType"
+          label="就诊类别"
+          rules={[
+            {
+              required: true,
+              message: '就诊类别是必填项',
+            },
+          ]}
+          options={[
+            {
+              label: '全院',
+              value: 0,
+            },
+            {
+              label: '门诊',
+              value: 1,
+            },
+            {
+              label: '住院',
+              value: 3,
+            },
+          ]}
+        />
+      </ModalForm>
+    );
+  };
+
+  const onTabChanged = (key: Key) => {
+    set_accountType(key);
+    tableRef.current?.reload();
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  useEffect(() => {
+    set_tabs([
+      {
+        label: '收入',
+        key: 1,
+      },
+      {
+        label: '支出',
+        key: 2,
+      },
+    ]);
+  }, []);
+
+  return (
+    <KCIMPagecontainer className="AccountingSubMana" title={false}>
+      <div className="toolBar">
+        <Tabs
+          defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
+          items={tabs}
+          key={'key'}
+          onChange={(key) => onTabChanged(key)}
+        />
+        <div
+          className="filter"
+          style={{
+            display: 'flex',
+            flexDirection: 'row',
+            justifyContent: 'space-between',
+            alignItems: 'center',
+            marginBottom: 16,
+          }}
+        >
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'会计科目编码/名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-                <div className='filter' style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center',marginBottom:16 }}>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'会计科目编码/名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        filter: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    filter: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                    <div className='btnGroup'>
-                        <UpDataActBtn record type='ADD' />
-                    </div>
-                </div>
-
-            </div>
-
-            <div>
-                <KCIMTable pagination={false} columns={columns as ProColumns[]} scroll={{ y: 'calc(100vh - 270px)' }} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    filter: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  filter: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+          <div className="btnGroup">
+            <UpDataActBtn record type="ADD" />
+          </div>
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          pagination={false}
+          columns={columns as ProColumns[]}
+          scroll={{ y: 'calc(100vh - 270px)' }}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 18 - 39
src/pages/baseSetting/accountingAccountSet/accountingSubMana/service.ts

@@ -7,76 +7,55 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { request } from 'umi';
 
 //获取table列表数据
-export const getAccountingSubjectList = (params:any) => {
+export const getAccountingSubjectList = (params: any) => {
   return request('/costAccount/accounting/list', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  code:string,
-  name:string,
-  description:string
-}
+  code: string;
+  name: string;
+  description: string;
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/accounting/save', {
-    
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/accounting/edit', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (id:string) => {
+export const delData = (id: string) => {
   return request('/costAccount/accounting/delete', {
     method: 'POST',
-    params:{id}
+    params: { id },
   });
 };
 
-//获取会计科目类别字典 
-export const getAccountTypeDictReq = (type:number) => {
+//获取会计科目类别字典
+export const getAccountTypeDictReq = (type: number) => {
   return request('/costAccount/accounting/getAccountTypeDict', {
     method: 'GET',
-    params:{type}
+    params: { type },
   });
 };
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+ 12 - 13
src/pages/baseSetting/accountingAccountSet/accountingSubMana/style.less

@@ -1,10 +1,9 @@
 .AccountingSubMana {
   padding: 16px;
   padding-top: 0;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     // display: flex;
     // flex-direction: row;
@@ -26,17 +25,17 @@
     }
 
     .btnGroup {
-        .add {
-          cursor: pointer;
-          display: inline-block;
-          font-size: 14px;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 24px;
-          padding: 0 14px;
-          background: #3377FF;
-          border-radius: 4px;
-        }
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377ff;
+        border-radius: 4px;
+      }
     }
   }
 }

+ 311 - 264
src/pages/baseSetting/accountingAccountSet/accountingSubMap/index.tsx

@@ -7,16 +7,19 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Tag, Tabs } from 'antd';
 import { Key, useEffect, useRef, useState } from 'react';
@@ -24,287 +27,331 @@ import { Key, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { getAccountProductConnectableList, getAccountProductConnectList, saveAccountProductConnected } from './service';
+import {
+  getAccountProductConnectableList,
+  getAccountProductConnectList,
+  saveAccountProductConnected,
+} from './service';
 
 import './style.less';
 import TableSelecter from '@/components/KCIMTableSelector';
 import { renameChildListToChildren } from '@/utils/tooljs';
 import { searchTree } from '../accountingSubMana';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
 const tableSelectorColumns = [
-    {
-        title: 'Id',
-        width:60,
-        dataIndex: 'id',
-    },
-    // {
-    //     title: '会计科目编码',
-    //     width:300,
-    //     dataIndex: 'accountingCode',
-    // },
-    {
-        title: '成本收入项目',
-        dataIndex: 'name',
-    },
+  {
+    title: 'Id',
+    width: 60,
+    dataIndex: 'id',
+  },
+  // {
+  //     title: '会计科目编码',
+  //     width:300,
+  //     dataIndex: 'accountingCode',
+  // },
+  {
+    title: '成本收入项目',
+    dataIndex: 'name',
+  },
 ];
 
+function sortTreeByCode(
+  tree: any[],
+  codeKey = 'accountingCode',
+  childrenKey = 'children',
+) {
+  // 首先对当前层级的节点按照 codeKey 进行排序
+  tree.sort((a, b) => {
+    return Number(a[codeKey]) - Number(b[codeKey]); // 按照 code 从小到大排序
+  });
+
+  // 然后对于每个节点的子节点,不进行排序,只递归下去
+  tree.forEach((node) => {
+    if (node[childrenKey] && node[childrenKey].length > 0) {
+      sortTreeByCode(node[childrenKey], codeKey, childrenKey); // 递归处理子节点
+    }
+  });
 
-function sortTreeByCode(tree:any[], codeKey = 'accountingCode', childrenKey = 'children') {
-    // 首先对当前层级的节点按照 codeKey 进行排序
-    tree.sort((a, b) => {
-        return Number(a[codeKey]) - Number(b[codeKey]); // 按照 code 从小到大排序
-    });
-
-    // 然后对于每个节点的子节点,不进行排序,只递归下去
-    tree.forEach(node => {
-        if (node[childrenKey] && node[childrenKey].length > 0) {
-            sortTreeByCode(node[childrenKey], codeKey, childrenKey); // 递归处理子节点
-        }
-    });
-
-    return tree; // 返回排序后的树
+  return tree; // 返回排序后的树
 }
 
-
-let currentRow:any = undefined;
+let currentRow: any = undefined;
 
 export default function AccountingSubMap() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ accountType: 1 });
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [tabs, set_tabs] = useState<any[]>([]);
-    const [accountType, set_accountType] = useState<Key>(1);
-    const [tableSelecterVisible,set_tableSelecterVisible] = useState(false);
-    const columns: ProColumns[] = [
-
-        {
-            title: '会计科目名称',
-            width: 400,
-            ellipsis: true,
-            dataIndex: 'accountingName',
-        },
-        {
-            title: '会计科目编码',
-            width:300,
-            ellipsis:true,
-            dataIndex: 'accountingCode',
-        },
-        {
-            title: '收入项目',
-            dataIndex: 'productVOs',
-            ellipsis:true,
-            renderText(productVOs, record) {
-                if (Array.isArray(productVOs)) {
-                    return productVOs.map((item, index) => { return <Tag key={index}>{item.productName}</Tag> })
-                } else {
-                    return <></>
-                }
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 80,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                const { isParent } = record;
-                return !isParent ? [
-                  <a
-                    key="config"
-                    onClick={() => {
-                      currentRow = record;
-                      set_tableSelecterVisible(true);
-                    }}
-                  >
-                    设置对应
-                  </a>,
-                ] : []
-            },
-        },
-
-    ]
-    const columnsTwo: ProColumns[] = [
-
-        {
-            title: '会计科目名称',
-            width: 400,
-            ellipsis: true,
-            dataIndex: 'accountingName',
-        },
-        {
-            title: '会计科目编码',
-            width:300,
-            dataIndex: 'accountingCode',
-        },
-        {
-            title: '成本项目',
-            dataIndex: 'productVOs',
-            ellipsis:true,
-            renderText(productVOs, record) {
-                if (Array.isArray(productVOs)) {
-                    return productVOs.map((item, index) => { return <Tag key={index}>{item.productName}</Tag> })
-                } else {
-                    return <></>
-                }
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 80,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                const { isParent } = record;
-                return !isParent ? [
-                  <a
-                    key="config"
-                    onClick={() => {
-                      currentRow = record;
-                      set_tableSelecterVisible(true);
-                    }}
-                  >
-                    设置对应
-                  </a>,
-                ] : []
-            },
-        },
-
-    ]
-
-
-
-    const getTableData = async (params: any) => {
-        const {filter} = params;
-        const resp = await getAccountProductConnectList({ ...params, accountType,pageSize:500 });
-        if (resp) {
-            let data = [];
-            if(filter){
-                 data = searchTree(renameChildListToChildren(resp.list, 'child'),filter) 
-            }else{
-                data = renameChildListToChildren(resp.list, 'child')
-            }
-            return {
-                data: sortTreeByCode(data),
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({ accountType: 1 });
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [tabs, set_tabs] = useState<any[]>([]);
+  const [accountType, set_accountType] = useState<Key>(1);
+  const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
+  const columns: ProColumns[] = [
+    {
+      title: '会计科目名称',
+      width: 400,
+      ellipsis: true,
+      dataIndex: 'accountingName',
+    },
+    {
+      title: '会计科目编码',
+      width: 300,
+      ellipsis: true,
+      dataIndex: 'accountingCode',
+    },
+    {
+      title: '收入项目',
+      dataIndex: 'productVOs',
+      ellipsis: true,
+      renderText(productVOs, record) {
+        if (Array.isArray(productVOs)) {
+          return productVOs.map((item, index) => {
+            return <Tag key={index}>{item.productName}</Tag>;
+          });
+        } else {
+          return <></>;
         }
-        return []
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 80,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        const { isParent } = record;
+        return !isParent
+          ? [
+              <a
+                key="config"
+                onClick={() => {
+                  currentRow = record;
+                  set_tableSelecterVisible(true);
+                }}
+              >
+                设置对应
+              </a>,
+            ]
+          : [];
+      },
+    },
+  ];
+  const columnsTwo: ProColumns[] = [
+    {
+      title: '会计科目名称',
+      width: 400,
+      ellipsis: true,
+      dataIndex: 'accountingName',
+    },
+    {
+      title: '会计科目编码',
+      width: 300,
+      dataIndex: 'accountingCode',
+    },
+    {
+      title: '成本项目',
+      dataIndex: 'productVOs',
+      ellipsis: true,
+      renderText(productVOs, record) {
+        if (Array.isArray(productVOs)) {
+          return productVOs.map((item, index) => {
+            return <Tag key={index}>{item.productName}</Tag>;
+          });
+        } else {
+          return <></>;
+        }
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 80,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        const { isParent } = record;
+        return !isParent
+          ? [
+              <a
+                key="config"
+                onClick={() => {
+                  currentRow = record;
+                  set_tableSelecterVisible(true);
+                }}
+              >
+                设置对应
+              </a>,
+            ]
+          : [];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const { filter } = params;
+    const resp = await getAccountProductConnectList({
+      ...params,
+      accountType,
+      pageSize: 500,
+    });
+    if (resp) {
+      let data = [];
+      if (filter) {
+        data = searchTree(
+          renameChildListToChildren(resp.list, 'child'),
+          filter,
+        );
+      } else {
+        data = renameChildListToChildren(resp.list, 'child');
+      }
+      return {
+        data: sortTreeByCode(data),
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
     }
-
-
-    
-
-    const onTabChanged = (key: Key) => {
-        set_accountType(key);
-        tableRef.current?.reload();
+    return [];
+  };
+
+  const onTabChanged = (key: Key) => {
+    set_accountType(key);
+    tableRef.current?.reload();
+  };
+  //productCode,productName
+  const getTableSelectorData = async () => {
+    const { responsibilityId, productVOs = [] } = currentRow;
+    const defaultRows = productVOs
+      ? productVOs.map((a: any) => ({
+          id: a.id,
+          name: `${a.productName}[${a.productCode}]`,
+        }))
+      : [];
+    const resp = await getAccountProductConnectableList({
+      responsibilityId,
+      pageSize: 500,
+      current: 1,
+    });
+    if (resp) {
+      return [...resp, ...defaultRows];
     }
-//productCode,productName
-    const getTableSelectorData = async () => {
-        const {responsibilityId,productVOs = []} = currentRow;
-        const defaultRows = productVOs?productVOs.map((a:any)=>({id:a.id,name:`${a.productName}[${a.productCode}]`})):[];
-        const resp = await getAccountProductConnectableList({responsibilityId,pageSize:500,current:1});
-        if(resp){
-            return [...resp,...defaultRows]
-        }        
+  };
+
+  const tableSelecterCommit = async (keys: Key[], rows: any[]) => {
+    const { id } = currentRow;
+    const resp = await saveAccountProductConnected({ id, products: keys });
+    if (resp) {
+      set_tableSelecterVisible(false);
+      tableRef.current?.reload();
     }
+  };
 
-
-    const tableSelecterCommit = async (keys:Key[],rows:any[]) => {
-        const {id} = currentRow;
-        const resp = await saveAccountProductConnected({id,products:keys});
-        if(resp){
-             set_tableSelecterVisible(false)
-             tableRef.current?.reload();
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  useEffect(() => {
+    set_tabs([
+      {
+        label: '收入',
+        key: 1,
+      },
+      {
+        label: '支出',
+        key: 2,
+      },
+    ]);
+  }, []);
+
+  return (
+    <KCIMPagecontainer className="AccountingSubMap" title={false}>
+      <TableSelecter
+        columns={[...tableSelectorColumns]}
+        onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
+        title="关联成本收入项目"
+        rowKey={'id'}
+        request={getTableSelectorData}
+        defaultSelectedKeys={
+          currentRow && currentRow.productVOs
+            ? [...currentRow.productVOs.map((a: any) => a.id)]
+            : []
         }
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
-    }
-
-    useEffect(() => {
-        set_tabs([
-            {
-                label: '收入',
-                key: 1,
-            },
-            {
-                label: '支出',
-                key: 2,
-            },
-        ])
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='AccountingSubMap' title={false}>
-            <TableSelecter
-                columns={[...tableSelectorColumns]}
-                onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
-                title='关联成本收入项目'
-                rowKey={'id'}
-                request={getTableSelectorData}
-                defaultSelectedKeys={(currentRow&&currentRow.productVOs)?[...(currentRow.productVOs).map((a:any)=>a.id)]:[]}
-                record={currentRow}
-                open={tableSelecterVisible}
-                onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
-            />
-            <div className='toolBar' >
-                <Tabs
-                    defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
-                    items={tabs}
-                    key={'key'}
-                    onChange={(key) => onTabChanged(key)}
+        record={currentRow}
+        open={tableSelecterVisible}
+        onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+      />
+      <div className="toolBar">
+        <Tabs
+          defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
+          items={tabs}
+          key={'key'}
+          onChange={(key) => onTabChanged(key)}
+        />
+        <div
+          className="filter"
+          style={{
+            display: 'flex',
+            flexDirection: 'row',
+            justifyContent: 'space-between',
+            alignItems: 'center',
+          }}
+        >
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'会计科目编码/名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-               <div className='filter' style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'会计科目编码/名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        filter: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    filter: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-            </div>
-
-            <div>
-                <KCIMTable pagination={false} columns={(accountType == 1?columns:columnsTwo) as ProColumns[]} scroll={{ y: 'calc(100vh - 230px)' }} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    filter: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  filter: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          pagination={false}
+          columns={(accountType == 1 ? columns : columnsTwo) as ProColumns[]}
+          scroll={{ y: 'calc(100vh - 230px)' }}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 9 - 29
src/pages/baseSetting/accountingAccountSet/accountingSubMap/service.ts

@@ -7,48 +7,28 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { request } from 'umi';
 
 //获取table列表数据
-export const getAccountProductConnectList = (params:any) => {
+export const getAccountProductConnectList = (params: any) => {
   return request('/costAccount/accountProduct/list', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
+};
 
 //获取责任中心对应可绑定科室列表
-export const getAccountProductConnectableList = (params:any) => {
-  
+export const getAccountProductConnectableList = (params: any) => {
   return request('/costAccount/product/getProducts', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
+};
 
 //保存绑定信息
-export const saveAccountProductConnected = (body:any) => {
+export const saveAccountProductConnected = (body: any) => {
   return request('/costAccount/accountProduct/save', {
     method: 'POST',
-    data:{...body},
+    data: { ...body },
   });
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+};

+ 12 - 13
src/pages/baseSetting/accountingAccountSet/accountingSubMap/style.less

@@ -1,10 +1,9 @@
 .AccountingSubMap {
   padding: 16px;
   padding-top: 0;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -26,17 +25,17 @@
     }
 
     .btnGroup {
-        .add {
-          cursor: pointer;
-          display: inline-block;
-          font-size: 14px;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 24px;
-          padding: 0 14px;
-          background: #3377FF;
-          border-radius: 4px;
-        }
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377ff;
+        border-radius: 4px;
+      }
     }
   }
 }

+ 489 - 397
src/pages/baseSetting/accountingAccountSet/chargeItemMap/index.tsx

@@ -7,28 +7,44 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
 import { createFromIconfontCN } from '@ant-design/icons';
 import { ActionType } from '@ant-design/pro-components';
-import { ModalForm, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+import {
+  ModalForm,
+  ProFormSelect,
+  ProFormText,
+  ProFormTextArea,
+} from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
-import { Dropdown, Input, MenuProps, message, Tooltip, Popconfirm, TreeProps } from 'antd';
+import {
+  Dropdown,
+  Input,
+  MenuProps,
+  message,
+  Tooltip,
+  Popconfirm,
+  TreeProps,
+} from 'antd';
 
 import { Key } from 'react';
 import { useEffect, useRef, useState } from 'react';
 import DirectoryTree from 'antd/es/tree/DirectoryTree';
 import { DataNode } from 'antd/es/tree';
 
-import { getAccountingItemMap, addTableData, delData, getAccountingList, batchDelTableData } from './service';
-
+import {
+  getAccountingItemMap,
+  addTableData,
+  delData,
+  getAccountingList,
+  batchDelTableData,
+} from './service';
 
 import './style.less';
 
 import expandedIcon from '../../../../../static/treenode_open.png';
 import closeIcon from '../../../../../static/treenode_collapse.png';
 
-
-import '../../../../utils/zhongtaiB'
+import '../../../../utils/zhongtaiB';
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 import { getTargetDic } from '@/services/auth';
@@ -36,416 +52,492 @@ import TableSelecter from './tableSelector';
 import { getDeepestTreeData } from '@/utils/tooljs';
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 let _currentSelectedType: any = undefined;
 
 const ChargeItemMap = () => {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-
-    const [currentSelectedType, set_currentSelectedType] = useState<any | undefined>(undefined);
-    const [treeData, set_treeData] = useState<any[]>([]);
-    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<null | any>(null);
-    const [expandedKeys, set_expandedKeys] = useState<Key[]>([]);
-    const [autoExpandParent, set_autoExpandParent] = useState(true);
-    const [searchValue, set_searchValue] = useState('');
-    const [currentTreeDataFilter, set_currentTreeDataFilter] = useState({ name: '全部', code: 0 });
-    const [treeFilterVisible, set_treeFilterVisible] = useState(false);
-    const [selectedRowKeys,set_selectedRowKeys] = useState<Key[]>([]);
-
-    const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
-
-    const [treeDataDefault, set_treeDataDefault] = useState<any[]>([]);
-
-    const [leftDataSearchKeyVal, set_leftDataSearchKeyVal] = useState<undefined | string>(undefined);
-
-    const tableRef = useRef<ActionType>();
-
-    const column: ProColumns[] = [
-
-        {
-            title: '收费项目代码',
-            ellipsis: true,
-            width: 120,
-            dataIndex: 'itemCode',
-
-        },
-        {
-            title: '收费项目名称',
-            dataIndex: 'itemName',
-
-        },
-        {
-            title: '收费项目类别',
-            width: 100,
-            dataIndex: 'typeName',
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 60,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record.id)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ]
-            },
-        },
-    ]
-
-
-    const getTableData = async (params: any) => {
-
-        const resp = await getAccountingItemMap({ ...params });
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        } else {
-            return []
-        }
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+
+  const [currentSelectedType, set_currentSelectedType] = useState<
+    any | undefined
+  >(undefined);
+  const [treeData, set_treeData] = useState<any[]>([]);
+  const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<
+    null | any
+  >(null);
+  const [expandedKeys, set_expandedKeys] = useState<Key[]>([]);
+  const [autoExpandParent, set_autoExpandParent] = useState(true);
+  const [searchValue, set_searchValue] = useState('');
+  const [currentTreeDataFilter, set_currentTreeDataFilter] = useState({
+    name: '全部',
+    code: 0,
+  });
+  const [treeFilterVisible, set_treeFilterVisible] = useState(false);
+  const [selectedRowKeys, set_selectedRowKeys] = useState<Key[]>([]);
+
+  const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
+
+  const [treeDataDefault, set_treeDataDefault] = useState<any[]>([]);
+
+  const [leftDataSearchKeyVal, set_leftDataSearchKeyVal] = useState<
+    undefined | string
+  >(undefined);
+
+  const tableRef = useRef<ActionType>();
+
+  const column: ProColumns[] = [
+    {
+      title: '收费项目代码',
+      ellipsis: true,
+      width: 120,
+      dataIndex: 'itemCode',
+    },
+    {
+      title: '收费项目名称',
+      dataIndex: 'itemName',
+    },
+    {
+      title: '收费项目类别',
+      width: 100,
+      dataIndex: 'typeName',
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 60,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record.id)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getAccountingItemMap({ ...params });
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
+    } else {
+      return [];
     }
-
-
-    //获取左侧列表
-    const getPageLeftData = async () => {
-        const resp = await getAccountingList('', currentTreeDataFilter.code);
-        if(resp){
-            set_treeData(resp);
-            set_treeDataDefault(resp);
-            set_currentSelectedTreeNode(null);
-        } 
+  };
+
+  //获取左侧列表
+  const getPageLeftData = async () => {
+    const resp = await getAccountingList('', currentTreeDataFilter.code);
+    if (resp) {
+      set_treeData(resp);
+      set_treeDataDefault(resp);
+      set_currentSelectedTreeNode(null);
     }
+  };
 
-    const delTableData = async (id: number) => {
-        const resp = await delData(id);
-        if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-        }
+  const delTableData = async (id: number) => {
+    const resp = await delData(id);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
     }
-
-
-    const tableSelecterCommit = async (keys: Key[], rows: any[]) => {
-
-        const arr = rows.map((a, index) => ({
-            itemCode: a.itemCode,
-            itemName: a.itemName,
-            type: a.itemType,
-        }));
-        const result = {
-            accountingCode: currentSelectedTreeNode.accountingCode,
-            accountingName: currentSelectedTreeNode.accountingName,
-            itemMaps: arr
-        }
-        const resp = await addTableData(result);
-        if (resp) {
-            message.success('操作成功');
-            set_tableSelecterVisible(false);
-            tableRef.current?.reload();
-        }
+  };
+
+  const tableSelecterCommit = async (keys: Key[], rows: any[]) => {
+    const arr = rows.map((a, index) => ({
+      itemCode: a.itemCode,
+      itemName: a.itemName,
+      type: a.itemType,
+    }));
+    const result = {
+      accountingCode: currentSelectedTreeNode.accountingCode,
+      accountingName: currentSelectedTreeNode.accountingName,
+      itemMaps: arr,
+    };
+    const resp = await addTableData(result);
+    if (resp) {
+      message.success('操作成功');
+      set_tableSelecterVisible(false);
+      tableRef.current?.reload();
     }
-
-
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const batchDelHandle = async () => {
+    const resp = await batchDelTableData(selectedRowKeys);
+    if (resp) {
+      message.success('操作成功!');
+      set_selectedRowKeys([]);
+      tableRef.current?.reload();
     }
+  };
 
-    const batchDelHandle = async () => {
-        const resp = await batchDelTableData(selectedRowKeys);
-        if (resp) {
-            message.success('操作成功!');
-            set_selectedRowKeys([]);
-            tableRef.current?.reload();
-        }
+  const onSelect: TreeProps['onSelect'] = (selectedKeys, info: any) => {
+    const { node } = info;
+    if (!node.children || node.children.length == 0) {
+      set_currentSelectedTreeNode(node);
     }
-
-
-    const onSelect: TreeProps['onSelect'] = (selectedKeys, info: any) => {
-        const { node } = info;
-        if (!node.children || node.children.length == 0) {
-            set_currentSelectedTreeNode(node);
+  };
+
+  const onExpand = (newExpandedKeys: React.Key[]) => {
+    // setExpandedKeys(newExpandedKeys);
+    // setAutoExpandParent(false);
+    set_expandedKeys(newExpandedKeys);
+    set_autoExpandParent(false);
+  };
+
+  const dataList: any[] = [];
+
+  const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+    let parentKey: React.Key;
+    for (let i = 0; i < tree.length; i++) {
+      const node = tree[i];
+      if (node.children) {
+        if (
+          node.children.some(
+            (item: { accountingCode: React.Key }) =>
+              item.accountingCode === key,
+          )
+        ) {
+          parentKey = node.accountingCode;
+        } else if (getParentKey(key, node.children)) {
+          parentKey = getParentKey(key, node.children);
         }
-    };
-
-    const onExpand = (newExpandedKeys: React.Key[]) => {
-        // setExpandedKeys(newExpandedKeys);
-        // setAutoExpandParent(false);
-        set_expandedKeys(newExpandedKeys);
-        set_autoExpandParent(false);
-    };
-
-
-    const dataList: any[] = [];
-
-    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
-        let parentKey: React.Key;
-        for (let i = 0; i < tree.length; i++) {
-            const node = tree[i];
-            if (node.children) {
-                if (node.children.some((item: { accountingCode: React.Key; }) => item.accountingCode === key)) {
-                    parentKey = node.accountingCode;
-                } else if (getParentKey(key, node.children)) {
-                    parentKey = getParentKey(key, node.children);
-                }
-            }
-        }
-        return parentKey!;
-    };
-
-    const generateList = (data: any[]) => {
-        for (let i = 0; i < data.length; i++) {
-            const node = data[i];
-            dataList.push(node);
-            if (node.children) {
-                generateList(node.children);
-            }
-        }
-    };
-
-    generateList(treeData as any);
-
-
-    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-
-        const { value } = e.target;
-
-        const newExpandedKeys = dataList
-            .map((item) => {
-                if (item.accountingName.indexOf(value) > -1) {
-                    return getParentKey(item.accountingCode, treeData);
-                }
-                return null;
-            });
-
-        set_expandedKeys(newExpandedKeys as React.Key[]);
-        set_searchValue(value);
-        set_autoExpandParent(true);
+      }
     }
-
-    //左侧树结构筛选
-    const changeTreeDataFilter = (obj: any) => {
-
-        set_currentTreeDataFilter(obj);
-        set_treeFilterVisible(false);
+    return parentKey!;
+  };
+
+  const generateList = (data: any[]) => {
+    for (let i = 0; i < data.length; i++) {
+      const node = data[i];
+      dataList.push(node);
+      if (node.children) {
+        generateList(node.children);
+      }
     }
-
-
-
-    useEffect(() => {
-
-        if (currentSelectedTreeNode) {
-            set_tableDataFilterParams({ ...tableDataFilterParams, accountingCode: currentSelectedTreeNode.accountingCode });
-        }
-    }, [currentSelectedTreeNode])
-
-    useEffect(() => {
-        //初始化左侧树结构数据后
-        
-        if (treeData?.length > 0) {
-            if (!currentSelectedTreeNode) {
-                if (treeData[0].children && treeData[0].children.length > 0) {
-                    const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
-                    set_currentSelectedTreeNode(node);
-                    set_expandedKeys([nodeParent.accountingCode]);
-                } else {
-                    set_currentSelectedTreeNode(treeData[0]);
-                    set_expandedKeys([treeData[0].accountingCode]);
-                }
-
-            }
+  };
+
+  generateList(treeData as any);
+
+  const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    const { value } = e.target;
+
+    const newExpandedKeys = dataList.map((item) => {
+      if (item.accountingName.indexOf(value) > -1) {
+        return getParentKey(item.accountingCode, treeData);
+      }
+      return null;
+    });
+
+    set_expandedKeys(newExpandedKeys as React.Key[]);
+    set_searchValue(value);
+    set_autoExpandParent(true);
+  };
+
+  //左侧树结构筛选
+  const changeTreeDataFilter = (obj: any) => {
+    set_currentTreeDataFilter(obj);
+    set_treeFilterVisible(false);
+  };
+
+  useEffect(() => {
+    if (currentSelectedTreeNode) {
+      set_tableDataFilterParams({
+        ...tableDataFilterParams,
+        accountingCode: currentSelectedTreeNode.accountingCode,
+      });
+    }
+  }, [currentSelectedTreeNode]);
+
+  useEffect(() => {
+    //初始化左侧树结构数据后
+
+    if (treeData?.length > 0) {
+      if (!currentSelectedTreeNode) {
+        if (treeData[0].children && treeData[0].children.length > 0) {
+          const [node, nodeParent] = getDeepestTreeData(
+            treeData[0],
+            'children',
+          );
+          set_currentSelectedTreeNode(node);
+          set_expandedKeys([nodeParent.accountingCode]);
+        } else {
+          set_currentSelectedTreeNode(treeData[0]);
+          set_expandedKeys([treeData[0].accountingCode]);
         }
-    }, [treeData]);
-
-    useEffect(() => {
-        getPageLeftData();
-    }, [currentTreeDataFilter])
-
-    useEffect(() => {
-        getPageLeftData();
-    }, [])
-
-
-
-    return (
-        <KCIMPagecontainer title={false} className='ChargeItemMap'>
-            <TableSelecter
-                onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
-                title='添加'
-                rowKey={'itemCode'}
-                defaultSelectedKeys={[]}
-                record={_currentSelectedType}
-                open={tableSelecterVisible}
-                onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
-            />
-
-            {selectedRowKeys.length > 0 && (
-                <div className='bottomBar'>
-                    <span>已选择<a>{selectedRowKeys.length}</a>项</span>
-                    <a onClick={() => batchDelHandle()}>批量删除</a>
-                </div>
-            )}
-
-            {
-                treeFilterVisible && (
-                    <div className='selecterList'>
-                        <div onClick={() => changeTreeDataFilter({ name: '全部', code: 0 })} className={currentTreeDataFilter.code == 0 ? 'list on' : 'list'}>全部</div>
-                        <div onClick={() => changeTreeDataFilter({ name: '已对照', code: 1 })} className={currentTreeDataFilter.code == 1 ? 'list on' : 'list'}>{'已对照'}</div>
-                        <div onClick={() => changeTreeDataFilter({ name: '未对照', code: 3 })} className={currentTreeDataFilter.code == 3 ? 'list on' : 'list'}>{'未对照'}</div>
-                    </div>
-                )
-            }
-
-            <div className='left'>
-                <div className='toolbar'>
-                    <Input placeholder={'会计科目名称'} allowClear autoComplete='off'
-                        suffix={
-                            <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} />
-                        }
-                        value={leftDataSearchKeyVal}
-                        style={{ width: 156 }}
-                        onChange={onTreeSearchKeyChange}
-                    />
-                    <Tooltip placement="top" title={currentTreeDataFilter.name}>
-                        <div className={currentTreeDataFilter.code == 0 ? 'filter' : currentTreeDataFilter.code == 1 ? 'filter blue' : 'filter orange'} onClick={() => set_treeFilterVisible(true)}></div>
-                    </Tooltip>
-
-
-                </div>
-
-                <div className='wrap'>
-                    {
-                        treeData && treeData.length > 0 && currentSelectedTreeNode && (
-                            <DirectoryTree
-                                fieldNames={{ title: 'accountingName', key: 'accountingCode' }}
-                                rootStyle={{ height: '100%', paddingBottom: 50, padding: '0 16px' }}
-                                onSelect={onSelect}
-                                onExpand={onExpand}
-                                expandedKeys={expandedKeys}
-                                autoExpandParent={autoExpandParent}
-                                selectedKeys={[currentSelectedTreeNode.accountingCode]}
-                                blockNode={true}
-
-                                icon={() => null}
-
-                                titleRender={
-                                    (nodeData: any) => {
-                                        const strTitle = nodeData.accountingName as string;
-                                        const index = strTitle.indexOf(searchValue);
-                                        const beforeStr = strTitle.substring(0, index);
-                                        const afterStr = strTitle.slice(index + searchValue.length);
-                                        const title =
-                                            index > -1 ? (
-                                                <span>
-                                                    {beforeStr}
-                                                    <span className="site-tree-search-value" style={{ color: '#3377ff', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
-                                                    {afterStr}
-                                                </span>
-                                            ) : (
-                                                <span className='strTitle'>{strTitle}</span>
-                                            );
-                                        return <div style={{
-                                            display: 'flex', flexDirection: 'row',
-                                            width: '100%',
-                                            justifyContent: 'space-between', alignItems: 'center', height: 32,
-                                            borderRadius: '4px',
-                                            overflow: 'hidden',
-                                            color: '#17181A',
-                                            textOverflow: 'ellipsis',
-                                            whiteSpace: 'nowrap'
-
-                                        }}>
-                                            {title}
-                                            {!nodeData.map && <span className={nodeData.unitType ? 'point lastChild' : 'point'}></span>}
-                                        </div>
-                                    }
-                                }
-                                defaultSelectedKeys={[currentSelectedTreeNode.accountingCode]}
-                                treeData={treeData as unknown as DataNode[]}
-                                // treeData={treeDataNew}
-                                switcherIcon={(props: any) => {
-                                    const { expanded } = props;
-                                    return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
-                                }}
-                            />
-                        )
-                    }
-                </div>
-            </div>
-            <div className='right'>
-                <div className='toolBar'>
-                    <div className='filter'>
-                        <div className='filterItem'>
-                            <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                            <Input placeholder={'收费项目名称'} allowClear autoComplete='off'
-                                suffix={
-                                    <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('itemName')} />
-                                }
-                                onChange={(e) => {
-                                    set_tableDataSearchKeywords(e.target.value);
-                                    if (e.target.value.length == 0) {
-                                        set_tableDataFilterParams({
-                                            ...tableDataFilterParams,
-                                            itemName: ''
-                                        });
-                                    }
-                                }}
-                                onPressEnter={(e) => {
-
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        itemName: (e.target as HTMLInputElement).value
-                                    });
-                                }}
-
-                            />
-                        </div>
-                    </div>
-                    <div className='btnGroup'>
-                        <span className='add' onClick={() => set_tableSelecterVisible(true)}>添加</span>
-                    </div>
-                </div>
-                <div style={{ marginTop: 16 }}>
-                    {currentSelectedTreeNode && <KCIMTable actionRef={tableRef} columns={column}
-                        scroll={{ y: 500 }}
-                        rowKey='id'
-                        params={tableDataFilterParams}
-                        request={(params) => getTableData(params)}
-                        tableAlertRender={false}
-                        rowSelection={{
-                            onChange(selectedRowKeys, selectedRows, info) {
-                                set_selectedRowKeys(selectedRowKeys);
-                            },
+      }
+    }
+  }, [treeData]);
+
+  useEffect(() => {
+    getPageLeftData();
+  }, [currentTreeDataFilter]);
+
+  useEffect(() => {
+    getPageLeftData();
+  }, []);
+
+  return (
+    <KCIMPagecontainer title={false} className="ChargeItemMap">
+      <TableSelecter
+        onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
+        title="添加"
+        rowKey={'itemCode'}
+        defaultSelectedKeys={[]}
+        record={_currentSelectedType}
+        open={tableSelecterVisible}
+        onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+      />
+
+      {selectedRowKeys.length > 0 && (
+        <div className="bottomBar">
+          <span>
+            已选择<a>{selectedRowKeys.length}</a>项
+          </span>
+          <a onClick={() => batchDelHandle()}>批量删除</a>
+        </div>
+      )}
+
+      {treeFilterVisible && (
+        <div className="selecterList">
+          <div
+            onClick={() => changeTreeDataFilter({ name: '全部', code: 0 })}
+            className={currentTreeDataFilter.code == 0 ? 'list on' : 'list'}
+          >
+            全部
+          </div>
+          <div
+            onClick={() => changeTreeDataFilter({ name: '已对照', code: 1 })}
+            className={currentTreeDataFilter.code == 1 ? 'list on' : 'list'}
+          >
+            {'已对照'}
+          </div>
+          <div
+            onClick={() => changeTreeDataFilter({ name: '未对照', code: 3 })}
+            className={currentTreeDataFilter.code == 3 ? 'list on' : 'list'}
+          >
+            {'未对照'}
+          </div>
+        </div>
+      )}
+
+      <div className="left">
+        <div className="toolbar">
+          <Input
+            placeholder={'会计科目名称'}
+            allowClear
+            autoComplete="off"
+            suffix={<IconFont type="iconsousuo" style={{ color: '#99A6BF' }} />}
+            value={leftDataSearchKeyVal}
+            style={{ width: 156 }}
+            onChange={onTreeSearchKeyChange}
+          />
+          <Tooltip placement="top" title={currentTreeDataFilter.name}>
+            <div
+              className={
+                currentTreeDataFilter.code == 0
+                  ? 'filter'
+                  : currentTreeDataFilter.code == 1
+                  ? 'filter blue'
+                  : 'filter orange'
+              }
+              onClick={() => set_treeFilterVisible(true)}
+            ></div>
+          </Tooltip>
+        </div>
+
+        <div className="wrap">
+          {treeData && treeData.length > 0 && currentSelectedTreeNode && (
+            <DirectoryTree
+              fieldNames={{ title: 'accountingName', key: 'accountingCode' }}
+              rootStyle={{
+                height: '100%',
+                paddingBottom: 50,
+                padding: '0 16px',
+              }}
+              onSelect={onSelect}
+              onExpand={onExpand}
+              expandedKeys={expandedKeys}
+              autoExpandParent={autoExpandParent}
+              selectedKeys={[currentSelectedTreeNode.accountingCode]}
+              blockNode={true}
+              icon={() => null}
+              titleRender={(nodeData: any) => {
+                const strTitle = nodeData.accountingName as string;
+                const index = strTitle.indexOf(searchValue);
+                const beforeStr = strTitle.substring(0, index);
+                const afterStr = strTitle.slice(index + searchValue.length);
+                const title =
+                  index > -1 ? (
+                    <span>
+                      {beforeStr}
+                      <span
+                        className="site-tree-search-value"
+                        style={{
+                          color: '#3377ff',
+                          overflow: 'hidden',
+                          textOverflow: 'ellipsis',
+                          whiteSpace: 'nowrap',
                         }}
-                    />}
-                </div>
+                      >
+                        {searchValue}
+                      </span>
+                      {afterStr}
+                    </span>
+                  ) : (
+                    <span className="strTitle">{strTitle}</span>
+                  );
+                return (
+                  <div
+                    style={{
+                      display: 'flex',
+                      flexDirection: 'row',
+                      width: '100%',
+                      justifyContent: 'space-between',
+                      alignItems: 'center',
+                      height: 32,
+                      borderRadius: '4px',
+                      overflow: 'hidden',
+                      color: '#17181A',
+                      textOverflow: 'ellipsis',
+                      whiteSpace: 'nowrap',
+                    }}
+                  >
+                    {title}
+                    {!nodeData.map && (
+                      <span
+                        className={
+                          nodeData.unitType ? 'point lastChild' : 'point'
+                        }
+                      ></span>
+                    )}
+                  </div>
+                );
+              }}
+              defaultSelectedKeys={[currentSelectedTreeNode.accountingCode]}
+              treeData={treeData as unknown as DataNode[]}
+              // treeData={treeDataNew}
+              switcherIcon={(props: any) => {
+                const { expanded } = props;
+                return !expanded ? (
+                  <img
+                    style={{
+                      width: 20,
+                      height: 20,
+                      position: 'relative',
+                      top: 5,
+                    }}
+                    src={expandedIcon}
+                  />
+                ) : (
+                  <img
+                    style={{
+                      width: 20,
+                      height: 20,
+                      position: 'relative',
+                      top: 5,
+                    }}
+                    src={closeIcon}
+                  />
+                );
+              }}
+            />
+          )}
+        </div>
+      </div>
+      <div className="right">
+        <div className="toolBar">
+          <div className="filter">
+            <div className="filterItem">
+              <span className="label" style={{ whiteSpace: 'nowrap' }}>
+                {' '}
+                检索:
+              </span>
+              <Input
+                placeholder={'收费项目名称'}
+                allowClear
+                autoComplete="off"
+                suffix={
+                  <IconFont
+                    type="iconsousuo"
+                    style={{ color: '#99A6BF' }}
+                    onClick={() => tableDataSearchHandle('itemName')}
+                  />
+                }
+                onChange={(e) => {
+                  set_tableDataSearchKeywords(e.target.value);
+                  if (e.target.value.length == 0) {
+                    set_tableDataFilterParams({
+                      ...tableDataFilterParams,
+                      itemName: '',
+                    });
+                  }
+                }}
+                onPressEnter={(e) => {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    itemName: (e.target as HTMLInputElement).value,
+                  });
+                }}
+              />
             </div>
-        </KCIMPagecontainer>
-    )
-}
-
+          </div>
+          <div className="btnGroup">
+            <span
+              className="add"
+              onClick={() => set_tableSelecterVisible(true)}
+            >
+              添加
+            </span>
+          </div>
+        </div>
+        <div style={{ marginTop: 16 }}>
+          {currentSelectedTreeNode && (
+            <KCIMTable
+              actionRef={tableRef}
+              columns={column}
+              scroll={{ y: 500 }}
+              rowKey="id"
+              params={tableDataFilterParams}
+              request={(params) => getTableData(params)}
+              tableAlertRender={false}
+              rowSelection={{
+                onChange(selectedRowKeys, selectedRows, info) {
+                  set_selectedRowKeys(selectedRowKeys);
+                },
+              }}
+            />
+          )}
+        </div>
+      </div>
+    </KCIMPagecontainer>
+  );
+};
 
 export default ChargeItemMap;
 function getParentKey(code: any, treeData: any[]) {
-    throw new Error('Function not implemented.');
+  throw new Error('Function not implemented.');
 }
-

+ 23 - 32
src/pages/baseSetting/accountingAccountSet/chargeItemMap/service.ts

@@ -7,70 +7,61 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { string } from 'mathjs';
 import { Key } from 'react';
 import { request } from 'umi';
 
-
 //获取左侧数据
-export const getAccountingList = (accountingName:string,type:number) => {
+export const getAccountingList = (accountingName: string, type: number) => {
   return request('/costAccount/setting/getAccountingList', {
     method: 'GET',
-    params:{accountingName,type}
+    params: { accountingName, type },
   });
 };
 
 //获取右侧表格数据
 
-export const getAccountingItemMap = (params:{accountingCode:string,itemName?:string,pageSize:number,current:number}) => {
-    return request('/costAccount/setting/getAccountingItemMap', {
-      method: 'GET',
-      params:{...params}
-    });
+export const getAccountingItemMap = (params: {
+  accountingCode: string;
+  itemName?: string;
+  pageSize: number;
+  current: number;
+}) => {
+  return request('/costAccount/setting/getAccountingItemMap', {
+    method: 'GET',
+    params: { ...params },
+  });
 };
 
 //获取可添加列表
-export const getAddableTableData = (type:number,name?:string) => {
+export const getAddableTableData = (type: number, name?: string) => {
   return request('/costAccount/setting/getAccountingItemDictList', {
     method: 'GET',
-    params:{type,name}
+    params: { type, name },
   });
 };
 
-
-
 //新增表格数据
 
-export const addTableData = (data:any) => {
+export const addTableData = (data: any) => {
   return request('/costAccount/setting/addAccountingItemMap', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
-
-
 //删除表格操作
-export const delData = (id:number) => {
-    return request('/costAccount/setting/deleteAccountingItemMap', {
-      method: 'POST',
-      params:{id}
-    });
+export const delData = (id: number) => {
+  return request('/costAccount/setting/deleteAccountingItemMap', {
+    method: 'POST',
+    params: { id },
+  });
 };
 
-
 //批量删除表格数据
-export const batchDelTableData = (ids:Key[]) => {
+export const batchDelTableData = (ids: Key[]) => {
   return request('/costAccount/setting/batchDeleteAccountingItemMap', {
     method: 'POST',
-    data:[...ids]
+    data: [...ids],
   });
 };
-
-
-
-
-

+ 29 - 32
src/pages/baseSetting/accountingAccountSet/chargeItemMap/style.less

@@ -1,12 +1,10 @@
 .row-dragging {
-
   .cost-ant-table-cell {
     width: 130px;
   }
 }
 
 .TableSelecter {
-
   .pfm-ant-modal-footer {
     display: none !important;
   }
@@ -28,16 +26,15 @@
       cursor: pointer;
 
       &.ok {
-        color: #FFFFFF;
-        background: #3377FF;
+        color: #ffffff;
+        background: #3377ff;
         margin-left: 8px;
       }
 
       &.cancel {
-        border: 1px solid #DAE2F2;
+        border: 1px solid #dae2f2;
       }
     }
-
   }
 }
 
@@ -57,24 +54,24 @@
     flex-direction: row;
     justify-content: space-between;
     align-items: center;
-    background: #FFFFFF;
+    background: #ffffff;
     box-shadow: 0px -8px 16px 0px rgba(64, 85, 128, 0.1);
 
-    &>span {
+    & > span {
       font-size: 14px;
       font-weight: 400;
-      color: #17181A;
+      color: #17181a;
     }
 
-    &>a {
+    & > a {
       width: 80px;
       height: 24px;
       line-height: 24px;
       font-size: 14px;
       font-weight: 400;
-      color: #FFFFFF;
+      color: #ffffff;
       text-align: center;
-      background: #3377FF;
+      background: #3377ff;
       border-radius: 4px;
     }
   }
@@ -86,7 +83,7 @@
     left: 180px;
     width: 120px;
     height: 104px;
-    background: #FFFFFF;
+    background: #ffffff;
     box-shadow: 0px 8px 16px 0px rgba(64, 85, 128, 0.1);
     border-radius: 4px;
     padding: 4px;
@@ -101,7 +98,7 @@
       padding: 8px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #17181A;
+      color: #17181a;
 
       &.on {
         font-weight: 500;
@@ -129,8 +126,7 @@
     overflow: hidden;
     margin-right: 16px;
     padding: 16px 0px;
-    background: #FFFFFF;
-
+    background: #ffffff;
 
     .toolbar {
       display: flex;
@@ -143,9 +139,9 @@
         position: relative;
         width: 24px;
         height: 24px;
-        background: #FAFCFF;
+        background: #fafcff;
         border-radius: 4px;
-        border: 1px solid #DAE2F2;
+        border: 1px solid #dae2f2;
         margin-left: 8px;
         cursor: pointer;
         background: url('../../../../../static/filter.png');
@@ -164,7 +160,7 @@
             width: 4px;
             height: 4px;
             border-radius: 50%;
-            background: #FF9832;
+            background: #ff9832;
           }
         }
 
@@ -179,7 +175,7 @@
             width: 4px;
             height: 4px;
             border-radius: 50%;
-            background: #3377FF;
+            background: #3377ff;
           }
         }
       }
@@ -192,22 +188,25 @@
       overflow-y: scroll;
       // border: 1px solid red;
 
-      .cos-ant-tree.cos-ant-tree-directory .cos-ant-tree-treenode-selected:hover::before,
-      .cos-ant-tree.cos-ant-tree-directory .cos-ant-tree-treenode-selected::before {
+      .cos-ant-tree.cos-ant-tree-directory
+        .cos-ant-tree-treenode-selected:hover::before,
+      .cos-ant-tree.cos-ant-tree-directory
+        .cos-ant-tree-treenode-selected::before {
         border-radius: 4px;
         background: rgb(240 242 245 / 100%);
       }
 
-      .cos-ant-tree.cos-ant-tree-directory .cos-ant-tree-treenode .cos-ant-tree-node-content-wrapper.cos-ant-tree-node-selected {
+      .cos-ant-tree.cos-ant-tree-directory
+        .cos-ant-tree-treenode
+        .cos-ant-tree-node-content-wrapper.cos-ant-tree-node-selected {
         font-weight: bold;
-
       }
 
-      .cost-ant-tree.cost-ant-tree-directory .cost-ant-tree-treenode-selected::before {
+      .cost-ant-tree.cost-ant-tree-directory
+        .cost-ant-tree-treenode-selected::before {
         border-radius: 4px;
         background: rgb(240 242 245 / 100%);
       }
-
     }
   }
 
@@ -216,7 +215,7 @@
     width: calc(100% - 236px);
     padding: 16px;
     border-radius: 4px;
-    background: #FFFFFF;
+    background: #ffffff;
 
     .toolBar {
       display: flex;
@@ -245,16 +244,14 @@
           font-size: 14px;
           font-family: SourceHanSansCN-Normal, SourceHanSansCN;
           font-weight: 400;
-          color: #FFFFFF;
+          color: #ffffff;
           line-height: 24px;
           padding: 0 14px;
-          background: #3377FF;
+          background: #3377ff;
           border-radius: 4px;
           margin-left: 8px;
         }
       }
-
-
     }
   }
-}
+}

+ 217 - 187
src/pages/baseSetting/accountingAccountSet/chargeItemMap/tableSelector.tsx

@@ -1,201 +1,231 @@
-import React, { Key, useEffect, useState } from "react";
-import { Input, Select } from 'antd'
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
+import React, { Key, useEffect, useState } from 'react';
+import { Input, Select } from 'antd';
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
 
+import {
+  ModalForm,
+  ProColumns,
+  ProFormSelect,
+  ProFormText,
+} from '@ant-design/pro-components';
 
-import { ModalForm, ProColumns, ProFormSelect, ProFormText } from "@ant-design/pro-components";
-
-import { set } from "lodash";
-import { getAddableTableData } from "./service";
-
+import { set } from 'lodash';
+import { getAddableTableData } from './service';
 
 // import './style.less';
 
-
 interface TableSelecterProps {
-    record: any
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
-
-const TableSelecter = ({ record, open, title, onVisibleChange, rowKey = 'id', request, onFinish, defaultSelectedKeys }: {
-    record: any, open: boolean, title: string, onVisibleChange: (bool: boolean) => void, defaultSelectedKeys: Key[],
-    rowKey?: string, request?: (params: any) => Promise<any>, onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void
+const TableSelecter = ({
+  record,
+  open,
+  title,
+  onVisibleChange,
+  rowKey = 'id',
+  request,
+  onFinish,
+  defaultSelectedKeys,
+}: {
+  record: any;
+  open: boolean;
+  title: string;
+  onVisibleChange: (bool: boolean) => void;
+  defaultSelectedKeys: Key[];
+  rowKey?: string;
+  request?: (params: any) => Promise<any>;
+  onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void;
 }) => {
-
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-        const [selectedRows, set_selectedRows] = useState<any[]>([]);
-        const [showList, set_showList] = useState<any[]>([]);
-        const [type, set_type] = useState<number>(3);
-        const [keyword, set_keyword] = useState<string | undefined>(undefined);
-
-
-        const columns: ProColumns[] = [
-            {
-                title: '收费项目代码',
-                ellipsis:true,
-                dataIndex: 'itemCode',
-            },
-            {
-                title: '收费项目名称',
-                ellipsis:true,
-                dataIndex: 'itemName',
-            }
-        ];
-
-
-        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-            set_selectedRows([...selectedRows]);
-
-        };
-
-        const saveHandle = async () => {
-            const selectedRowCodes = selectedRows.map((a) => a[`${rowKey}`]);
-            const rows = datasource.filter((a) => selectedRowCodes.includes(a[`${rowKey}`]));
-            onFinish && onFinish(selectedKeys, rows);
-        }
-
-        const getTableData = async () => {
-            const resp = await getAddableTableData(type);
-
-            let selectedCodes: string[] = [];
-            let selectedRows: any[] = [];
-            if (resp) {
-                const data = resp.map((a: any) => {
-                    if (defaultSelectedKeys.includes(a[`${rowKey}`])) {
-                        selectedCodes.push(a[`${rowKey}`]);
-                        selectedRows.push(a);
-                        const needItem = record.departList.filter((b: any) => a[`${rowKey}`] == b[`${rowKey}`]);
-
-                        return {
-                            ...a,
-                            flag: needItem[0].isManager ? true : false
-                        }
-                    } else {
-                        return a
-                    }
-                });
-
-                set_showList(data);
-                set_selectedRows([...selectedRows]);
-                setSelectedKeys([...selectedCodes]);
-                set_datasource([...datasource, ...data]);
-            }
-
-
-            return Promise.resolve([]);
-        }
-
-        useEffect(() => {
-            // console.log({code, keyword});
-            const result = datasource.filter((a) => {
-                return a.itemName.indexOf(keyword) != -1 
-            });
-
-            set_showList([...result]);
-        }, [keyword]);
-
-        useEffect(()=>{
-            getTableData()
-        },[type]);
-
-
-        return (
-            <div >
-                <div className="filter" style={{marginBottom:8,display:'flex',flexDirection:'row',alignItems:'center'}}>
-                    <ProFormSelect
-                         noStyle
-                         style={{marginRight:8}}
-                         options={[
-                            {label:'药品',value:1},
-                            {label:'材料',value:2},
-                            {label:'项目',value:3}
-                         ]}
-                         fieldProps={{
-                             defaultValue:3,
-                             onChange(value, option) {
-                                set_type(value);
-                                set_keyword('');
-                             },
-                         }}
-                    />
-                    <ProFormText noStyle placeholder={'项目名称'}
-                        fieldProps={{
-                            value:keyword,
-                            suffix: <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />,
-                            onChange: (e) => {
-                                if (e.target.value.length != 0) {
-                                    set_keyword(e.target.value);
-                                } else {
-                                    set_keyword('');
-                                }
-                            }
-                        }}
-                    />
-                </div>
-
-                <KCIMTable columns={columns}
-                    options={{
-                        density: true,
-                        setting: {
-                            listsHeight: 100,
-                        },
-                    }}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    rowSelection={{
-                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
-                        // 注释该行则默认不显示下拉选项
-                        // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
-                        selectedRowKeys: selectedKeys,
-                        onChange: onSelectChange,
-                    }}
-                    pagination={{ showTitle: false, showSizeChanger: true,simple:true }}
-                    dataSource={showList}
-
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
-                </div>
-            </div>
-
-        )
-    });
-
-    const close = () => {
-        onVisibleChange && onVisibleChange(false);
-    }
-
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+    const [selectedRows, set_selectedRows] = useState<any[]>([]);
+    const [showList, set_showList] = useState<any[]>([]);
+    const [type, set_type] = useState<number>(3);
+    const [keyword, set_keyword] = useState<string | undefined>(undefined);
+
+    const columns: ProColumns[] = [
+      {
+        title: '收费项目代码',
+        ellipsis: true,
+        dataIndex: 'itemCode',
+      },
+      {
+        title: '收费项目名称',
+        ellipsis: true,
+        dataIndex: 'itemName',
+      },
+    ];
+
+    const onSelectChange = (
+      newSelectedRowKeys: React.Key[],
+      selectedRows: any,
+    ) => {
+      setSelectedKeys([...newSelectedRowKeys]);
+      set_selectedRows([...selectedRows]);
+    };
+
+    const saveHandle = async () => {
+      const selectedRowCodes = selectedRows.map((a) => a[`${rowKey}`]);
+      const rows = datasource.filter((a) =>
+        selectedRowCodes.includes(a[`${rowKey}`]),
+      );
+      onFinish && onFinish(selectedKeys, rows);
+    };
+
+    const getTableData = async () => {
+      const resp = await getAddableTableData(type);
+
+      let selectedCodes: string[] = [];
+      let selectedRows: any[] = [];
+      if (resp) {
+        const data = resp.map((a: any) => {
+          if (defaultSelectedKeys.includes(a[`${rowKey}`])) {
+            selectedCodes.push(a[`${rowKey}`]);
+            selectedRows.push(a);
+            const needItem = record.departList.filter(
+              (b: any) => a[`${rowKey}`] == b[`${rowKey}`],
+            );
+
+            return {
+              ...a,
+              flag: needItem[0].isManager ? true : false,
+            };
+          } else {
+            return a;
+          }
+        });
+
+        set_showList(data);
+        set_selectedRows([...selectedRows]);
+        setSelectedKeys([...selectedCodes]);
+        set_datasource([...datasource, ...data]);
+      }
+
+      return Promise.resolve([]);
+    };
+
+    useEffect(() => {
+      // console.log({code, keyword});
+      const result = datasource.filter((a) => {
+        return a.itemName.indexOf(keyword) != -1;
+      });
+
+      set_showList([...result]);
+    }, [keyword]);
+
+    useEffect(() => {
+      getTableData();
+    }, [type]);
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={400} submitter={{
-            render: false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-
-
-export default TableSelecter
+      <div>
+        <div
+          className="filter"
+          style={{
+            marginBottom: 8,
+            display: 'flex',
+            flexDirection: 'row',
+            alignItems: 'center',
+          }}
+        >
+          <ProFormSelect
+            noStyle
+            style={{ marginRight: 8 }}
+            options={[
+              { label: '药品', value: 1 },
+              { label: '材料', value: 2 },
+              { label: '项目', value: 3 },
+            ]}
+            fieldProps={{
+              defaultValue: 3,
+              onChange(value, option) {
+                set_type(value);
+                set_keyword('');
+              },
+            }}
+          />
+          <ProFormText
+            noStyle
+            placeholder={'项目名称'}
+            fieldProps={{
+              value: keyword,
+              suffix: (
+                <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
+              ),
+              onChange: (e) => {
+                if (e.target.value.length != 0) {
+                  set_keyword(e.target.value);
+                } else {
+                  set_keyword('');
+                }
+              },
+            }}
+          />
+        </div>
+
+        <KCIMTable
+          columns={columns}
+          options={{
+            density: true,
+            setting: {
+              listsHeight: 100,
+            },
+          }}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          rowSelection={{
+            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+            // 注释该行则默认不显示下拉选项
+            // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+            selectedRowKeys: selectedKeys,
+            onChange: onSelectChange,
+          }}
+          pagination={{ showTitle: false, showSizeChanger: true, simple: true }}
+          dataSource={showList}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认(${
+            selectedKeys.length > 0 && selectedKeys.length
+          })`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={400}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default TableSelecter;

+ 284 - 250
src/pages/baseSetting/accountingAccountSet/costIncomeProjectMana/index.tsx

@@ -7,16 +7,18 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 import FormItem from 'antd/es/form/FormItem';
 
-import { ActionType, ProFormInstance, ProFormText } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormInstance,
+  ProFormText,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Tag } from 'antd';
 import { useEffect, useRef, useState } from 'react';
@@ -24,269 +26,301 @@ import { useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { delData, editData, addCostProject, getCostProjecttList, importDataPost } from './service';
+import {
+  delData,
+  editData,
+  addCostProject,
+  getCostProjecttList,
+  importDataPost,
+} from './service';
 
 import './style.less';
 import KCIMUpload from '@/components/KCIMUpload';
 import { downloadTemplateReq } from '@/utils/tooljs';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
 export default function CostIncomeProjectMana() {
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const columns: ProColumns[] = [
+    {
+      title: 'Id',
+      dataIndex: 'id',
+    },
+    {
+      title: '成本编号',
+      dataIndex: 'productCode',
+    },
+    {
+      title: '成本项目名称',
+      dataIndex: 'productName',
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 120,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getCostProjecttList({ ...params });
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
+    }
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData(record.id);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
+    }
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    if (type == 'ADD') {
+      const result = { ...formVal };
+      const resp = await addCostProject(result);
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      try {
+        const {
+          responsibilityLevel = 0,
+          selectedSharelevel = [],
+          shareId,
+        } = formVal;
+        let body = {};
+        if (selectedSharelevel.length == 0) {
+          //没有修改分摊层级
+          body = { ...formVal };
+        }
 
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const columns: ProColumns[] = [
-
-        {
-            title: 'Id',
-            dataIndex: 'id',
-        },
-        {
-            title: '成本编号',
-            dataIndex: 'productCode',
-        },
-        {
-            title: '成本项目名称',
-            dataIndex: 'productName',
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 120,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getCostProjecttList({ ...params });
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
+        if (
+          Object.prototype.toString.call(selectedSharelevel) ==
+          '[object Object]'
+        ) {
+          //修改了分摊层级
+          //  console.log('修改了分摊层级');
+          body = {
+            ...formVal,
+            shareId: selectedSharelevel.id,
+            shareName: selectedSharelevel.shareName,
+            shareLevel: selectedSharelevel.leverSort,
+          };
         }
-        return []
-    }
 
-    const delTableData = async (record: any) => {
-        const resp = await delData(record.id);
+        const resp = await editData({ ...body });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      } catch (error) {
+        console.log({ error });
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-
-        if (type == 'ADD') {
-
-            const result = { ...formVal };
-            const resp = await addCostProject(result);
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}成本项目`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+              }
+            : {}
         }
-        if (type == 'EDIT') {
-            try {
-                const { responsibilityLevel = 0, selectedSharelevel = [], shareId } = formVal;
-                let body = {};
-                if (selectedSharelevel.length == 0) {
-                    //没有修改分摊层级
-                    body = { ...formVal }
-                }
-
-                if (Object.prototype.toString.call(selectedSharelevel) == '[object Object]') {
-                    //修改了分摊层级
-                    //  console.log('修改了分摊层级');
-                    body = { ...formVal, shareId: selectedSharelevel.id, shareName: selectedSharelevel.shareName, shareLevel: selectedSharelevel.leverSort }
-                }
-
-                const resp = await editData({ ...body });
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
-                }
-            } catch (error) {
-                console.log({ error });
-            }
-
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-        return true;
-
-    }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}成本项目`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record,
-                } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormText
-                    label="成本项目编码"
-                    rules={[
-                        {
-                            required: true,
-                            message: '成本项目编码是必填项',
-                        },
-                    ]}
-                    name="productCode"
-                />
-                <ProFormText
-                    label="成本项目名"
-                    rules={[
-                        {
-                            required: true,
-                            message: '成本项目名是必填项',
-                        },
-                    ]}
-                    name="productName"
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText
+          label="成本项目编码"
+          rules={[
+            {
+              required: true,
+              message: '成本项目编码是必填项',
+            },
+          ]}
+          name="productCode"
+        />
+        <ProFormText
+          label="成本项目名"
+          rules={[
+            {
+              required: true,
+              message: '成本项目名是必填项',
+            },
+          ]}
+          name="productName"
+        />
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const downloadTemplate = async () => {
+    await downloadTemplateReq('/costAccount/excel/getImportProductTemplate');
+  };
+
+  const importData = () => {
+    return (
+      <ModalForm
+        width={360}
+        title={`导入数据`}
+        trigger={
+          <a className="import" key="3">
+            导入
+          </a>
+        }
+        submitter={{
+          render: (props, defaultDoms) => {
+            const needBtn = defaultDoms.filter((b) => {
+              return b.key != 'rest';
+            });
+            return [...needBtn];
+          },
+        }}
+        onFinish={async (values) => {
+          const {
+            importFile: { fileList },
+          } = values;
+
+          let formData = new FormData();
+          formData.append('file', fileList[0].originFileObj);
+          const resp = await importDataPost(formData);
+
+          if (resp) {
+            tableRef.current?.reload();
+            return true;
+          }
+        }}
+      >
+        <FormItem name={'importFile'}>
+          <KCIMUpload downloadTemplateFile={() => downloadTemplate()} />
+        </FormItem>
+      </ModalForm>
+    );
+  };
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="CostIncomeProjectMana" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem" style={{ marginLeft: 16, width: 205 }}>
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'成本项目名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-            </ModalForm>
-        )
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
-    }
-
-    const downloadTemplate = async () => {
-        await downloadTemplateReq('/costAccount/excel/getImportProductTemplate');
-    };
-    
-      const importData = () => {
-        return (
-          <ModalForm
-            width={360}
-            title={`导入数据`}
-            trigger={
-              <a className="import" key="3">
-                导入
-              </a>
-            }
-            submitter={{
-              render: (props, defaultDoms) => {
-                const needBtn = defaultDoms.filter((b) => {
-                  return b.key != 'rest';
-                });
-                return [
-                  ...needBtn,
-                ];
-              },
-            }}
-            onFinish={async (values) => {
-              const {
-                importFile: { fileList },
-              } = values;
-    
-              let formData = new FormData();
-              formData.append('file', fileList[0].originFileObj);
-              const resp = await importDataPost(formData);
-     
-              if (resp) {
-                tableRef.current?.reload();  
-                return true;
               }
-            }}
-          >
-            <FormItem name={'importFile'}>
-              <KCIMUpload downloadTemplateFile={() => downloadTemplate()} />
-            </FormItem>
-          </ModalForm>                                                                                                                                                                                                                                                           
-        );
-      };
-
-    useEffect(() => {
-
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='CostIncomeProjectMana' title={false}>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem' style={{ marginLeft: 16, width: 205 }}>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'成本项目名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        filter: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    filter: ((e.target) as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                <div className='btnGroup'>
-                    {importData()}
-                    <UpDataActBtn record type='ADD' />
-                </div>
-            </div>
-
-            <div style={{ marginTop: 16 }}>
-                <KCIMTable scroll={{y:`calc(100vh - 235px)`}} columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    filter: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  filter: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">
+          {importData()}
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          scroll={{ y: `calc(100vh - 235px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 16 - 37
src/pages/baseSetting/accountingAccountSet/costIncomeProjectMana/service.ts

@@ -7,74 +7,53 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { request } from 'umi';
 
 //获取table列表数据
-export const getCostProjecttList = (params:any) => {
+export const getCostProjecttList = (params: any) => {
   return request('/costAccount/product/list', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  productCode:string,
-  productName:string
-}
-export async function addCostProject(body:AddTableDataType) {
+  productCode: string;
+  productName: string;
+};
+export async function addCostProject(body: AddTableDataType) {
   return request('/costAccount/product/save', {
     method: 'POST',
-    data:{...body},
+    data: { ...body },
   });
 }
 
-
 //导入
-export const importDataPost = (data:any) => {
+export const importDataPost = (data: any) => {
   return request('/costAccount/excel/importProduct', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/product/edit', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (id:string) => {
+export const delData = (id: string) => {
   return request('/costAccount/product/delete', {
     method: 'POST',
-    data:[id]
+    data: [id],
   });
 };
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+ 9 - 10
src/pages/baseSetting/accountingAccountSet/costIncomeProjectMana/style.less

@@ -1,9 +1,8 @@
 .CostIncomeProjectMana {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -25,32 +24,32 @@
     }
 
     .btnGroup {
-      .import,.export {
+      .import,
+      .export {
         cursor: pointer;
         display: inline-block;
         font-size: 14px;
         font-weight: 400;
-        color: #17181A;
+        color: #17181a;
         line-height: 24px;
         padding: 0 14px;
         margin-right: 8px;
-        background: #FAFCFF;
+        background: #fafcff;
         border-radius: 4px;
-        border: 1px solid #DAE2F2;
+        border: 1px solid #dae2f2;
       }
-      
+
       .add {
         cursor: pointer;
         display: inline-block;
         font-size: 14px;
         font-weight: 400;
-        color: #FFFFFF;
+        color: #ffffff;
         line-height: 24px;
         padding: 0 14px;
-        background: #3377FF;
+        background: #3377ff;
         border-radius: 4px;
       }
     }
-
   }
 }

+ 327 - 270
src/pages/baseSetting/costAllocationSet/allocationLevelSet/index.tsx

@@ -7,16 +7,20 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect, ProFormDigit } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+  ProFormDigit,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Form, Select } from 'antd';
 import { Key, useEffect, useRef, useState } from 'react';
@@ -24,287 +28,340 @@ import { Key, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, delData, editData, getApportionmentLevelList } from './service';
+import {
+  addData,
+  delData,
+  editData,
+  getApportionmentLevelList,
+} from './service';
 
 import './style.less';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
 export default function AllocationLevelSet() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ accountType: 1 });
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
-    const [selectableLevelList, setSelectableLevelList] = useState<any[]>([]);//可选的分摊层级列表
-
-    const columns: ProColumns[] = [
-
-        {
-            title: '分摊层级名',
-            dataIndex: 'shareName',
-        },
-        {
-            title: '分摊层级序号',
-            dataIndex: 'leverSort',
-        },
-        {
-            title: '目标层级',
-            dataIndex: 'targetLevel',
-        },
-        {
-            title: '计算方式',
-            dataIndex: 'calcType',
-            renderText(text, record) {
-                return <>{text == 0 ? '合并计算' : '分开计算'}</>
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 90,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getApportionmentLevelList({ ...params });
-        if (resp) {
-            const tempArr = resp.list&&resp.list.map((item:any) => ({ label: item.shareName, value: item.leverSort }))
-            setSelectableLevelList(tempArr);
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        }
-        return []
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({ accountType: 1 });
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
+  const [selectableLevelList, setSelectableLevelList] = useState<any[]>([]); //可选的分摊层级列表
+
+  const columns: ProColumns[] = [
+    {
+      title: '分摊层级名',
+      dataIndex: 'shareName',
+    },
+    {
+      title: '分摊层级序号',
+      dataIndex: 'leverSort',
+    },
+    {
+      title: '目标层级',
+      dataIndex: 'targetLevel',
+    },
+    {
+      title: '计算方式',
+      dataIndex: 'calcType',
+      renderText(text, record) {
+        return <>{text == 0 ? '合并计算' : '分开计算'}</>;
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 90,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getApportionmentLevelList({ ...params });
+    if (resp) {
+      const tempArr =
+        resp.list &&
+        resp.list.map((item: any) => ({
+          label: item.shareName,
+          value: item.leverSort,
+        }));
+      setSelectableLevelList(tempArr);
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
     }
-
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData([record.id]);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData([record.id]);
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    console.log({ formVal });
+
+    if (type == 'ADD') {
+      const { targetLevel } = formVal;
+      const result = {
+        ...formVal,
+        targetLevel: targetLevel.map((a: any) => a.value).join(','),
+      };
+
+      const resp = await addData(result);
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      try {
+        const { targetLevel } = formVal;
+        const resp = await editData({
+          ...formVal,
+          targetLevel: targetLevel
+            .map((a: any) => (a.value ? a.value : a))
+            .join(','),
+        });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      } catch (error) {
+        console.log({ error });
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-        console.log({formVal});
-
-        if (type == 'ADD') {
-  
-            const {targetLevel} = formVal;
-            const result = { ...formVal,targetLevel:(targetLevel.map((a:any) => a.value)).join(',') };
-
-            const resp = await addData(result);
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    setCurrentRow(record);
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}分摊层级`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+                targetLevel: record.targetLevel
+                  ? record.targetLevel.split(',').map((a: string) => Number(a))
+                  : [],
+              }
+            : { targetLevel: [] }
         }
-        if (type == 'EDIT') {
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
+        }
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormDigit
+          label="分摊层级序号"
+          rules={[
+            {
+              required: true,
+              message: '分摊层级序号是必填项',
+            },
+          ]}
+          name="leverSort"
+          min={1}
+          max={100}
+        />
+
+        <ProFormText
+          label="分摊层级名"
+          rules={[
+            {
+              required: true,
+              message: '分摊层级名是必填项',
+            },
+          ]}
+          name="shareName"
+        />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择计算方式',
+            },
+          ]}
+          options={[
+            {
+              value: 0,
+              label: '合并计算',
+            },
+            {
+              value: 1,
+              label: '分开计算',
+            },
+          ]}
+          name="calcType"
+          label="计算方式"
+        />
+        <ProFormDependency name={['leverSort']}>
+          {({ leverSort }) => {
             try {
-                const {targetLevel} = formVal;
-                const resp = await editData({ ...formVal,targetLevel:(targetLevel.map((a:any) => a.value?a.value:a)).join(',') });
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
+              const filteredArr = selectableLevelList.filter(
+                (item) => item.value >= leverSort,
+              );
+              if (filteredArr.length == 0) {
+                //当大于最大可选分摊层级
+                //formRef?.current?.setFieldsValue({ targetLevel: [{ value: `${leverSort}` }] });
+                formRef?.current?.setFieldValue('targetLevel', [
+                  { value: `${leverSort}` },
+                ]);
+                return <ProFormText name="targetLevel" hidden />;
+              } else {
+                if (type == 'ADD') {
+                  formRef?.current?.setFieldValue('targetLevel', []);
                 }
+                if (type == 'EDIT') {
+                  formRef?.current?.setFieldValue(
+                    'targetLevel',
+                    record.targetLevel
+                      ? record.targetLevel
+                          .split(',')
+                          .map((a: string) => Number(a))
+                      : [],
+                  );
+                }
+              }
+              return (
+                filteredArr.length > 0 && (
+                  <Form.Item
+                    name="targetLevel"
+                    label="目标层级"
+                    shouldUpdate
+                    style={{ width: 320 }}
+                    required
+                  >
+                    <Select
+                      mode="multiple"
+                      labelInValue={true}
+                      placeholder="请选择"
+                      maxTagCount={2}
+                    >
+                      {filteredArr.map((item, index) => (
+                        <Select.Option key={index} value={item.value}>
+                          {`${item.label}层级${item.value}`}
+                        </Select.Option>
+                      ))}
+                    </Select>
+                  </Form.Item>
+                )
+              );
             } catch (error) {
-                console.log({ error });
+              console.log({ error });
             }
-
-        }
-        return true;
-
-    }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-        setCurrentRow(record);
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}分摊层级`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record,
-                    targetLevel:record.targetLevel?record.targetLevel.split(',').map((a:string)=>Number(a)):[]
-                } : {targetLevel:[]}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormDigit
-                    label="分摊层级序号"
-                    rules={[
-                        {
-                            required: true,
-                            message: '分摊层级序号是必填项',
-                        },
-                    ]}
-                    name="leverSort"
-                    min={1} max={100}
-                />
-
-                <ProFormText
-                    label="分摊层级名"
-                    rules={[
-                        {
-                            required: true,
-                            message: '分摊层级名是必填项',
-                        },
-                    ]}
-                    name="shareName"
+          }}
+        </ProFormDependency>
+      </ModalForm>
+    );
+  };
+
+  return (
+    <KCIMPagecontainer className="AllocationLevelSet" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'分摊层级名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('name')}
                 />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择计算方式',
-                        },
-                    ]}
-                    options={[
-                        {
-                            value: 0,
-                            label: '合并计算',
-                        },
-                        {
-                            value: 1,
-                            label: '分开计算',
-                        },
-                    ]}
-                    name="calcType"
-                    label="计算方式"
-                />
-                <ProFormDependency name={['leverSort']}>
-                    {
-                        ({ leverSort }) => {
-                            try {
-                                const filteredArr = selectableLevelList.filter(item => item.value >= leverSort);
-                                if (filteredArr.length == 0) {
-                                    //当大于最大可选分摊层级
-                                    //formRef?.current?.setFieldsValue({ targetLevel: [{ value: `${leverSort}` }] });
-                                    formRef?.current?.setFieldValue('targetLevel',[{ value: `${leverSort}` }]);
-                                    return <ProFormText name='targetLevel' hidden />
-                                }else{
-                                    if(type == 'ADD'){
-                                        formRef?.current?.setFieldValue('targetLevel',[]);
-                                    }
-                                    if(type == 'EDIT'){
-                                        formRef?.current?.setFieldValue('targetLevel',record.targetLevel?record.targetLevel.split(',').map((a:string)=>Number(a)):[]);
-                                    }
-                                }
-                                return filteredArr.length > 0 && (
-                                    <Form.Item name='targetLevel' label="目标层级" shouldUpdate style={{width:320}} required >
-                                        <Select
-                                            mode="multiple"
-                                            labelInValue={true}
-                                            placeholder='请选择'
-                                            maxTagCount={2}
-                                        >
-                                            {filteredArr.map((item, index) => (
-                                                <Select.Option key={index} value={item.value}>
-                                                    {`${item.label}层级${item.value}`}
-                                                </Select.Option>
-                                            ))}
-                                        </Select>
-                                    </Form.Item>
-                                )
-                            } catch (error) {
-                                console.log({ error })
-                            }
-
-                        }
-                    }
-                </ProFormDependency>
-
-            </ModalForm>
-        )
-    }
-
-
-    return (
-        <KCIMPagecontainer className='AllocationLevelSet' title={false}>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'分摊层级名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo"  style={{color:'#99A6BF'}} onClick={() => tableDataSearchHandle('name')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        name: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    name: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
-                </div>
-            </div>
-
-            <div>
-                <KCIMTable scroll={{y:`calc(100vh - 234px)`}} columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    name: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  name: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          scroll={{ y: `calc(100vh - 234px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 16 - 36
src/pages/baseSetting/costAllocationSet/allocationLevelSet/service.ts

@@ -7,69 +7,49 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获取table列表数据
-export const getApportionmentLevelList = (params:any) => {
+export const getApportionmentLevelList = (params: any) => {
   return request('/costAccount/costsharelevel/list', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  leverSort:number,
-  shareName:string,
-  calcType:number,
-  targetLevel:any
-}
+  leverSort: number;
+  shareName: string;
+  calcType: number;
+  targetLevel: any;
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/costsharelevel/save', {
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/costsharelevel/update', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (ids:Key[]) => {
+export const delData = (ids: Key[]) => {
   return request('/costAccount/costsharelevel/delete', {
     method: 'POST',
-    data:[...ids]
+    data: [...ids],
   });
 };
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+ 12 - 13
src/pages/baseSetting/costAllocationSet/allocationLevelSet/style.less

@@ -1,9 +1,8 @@
 .AllocationLevelSet {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -26,17 +25,17 @@
     }
 
     .btnGroup {
-        .add {
-          cursor: pointer;
-          display: inline-block;
-          font-size: 14px;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 24px;
-          padding: 0 14px;
-          background: #3377FF;
-          border-radius: 4px;
-        }
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377ff;
+        border-radius: 4px;
+      }
     }
   }
 }

+ 211 - 188
src/pages/baseSetting/costAllocationSet/allocationParamsMap/editTableModal.tsx

@@ -1,200 +1,223 @@
-import React, { Key, useEffect, useState } from "react";
-import { Input, Select } from 'antd'
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
-
-
-import { EditableProTable, ModalForm, ProColumns, ProFormSelect, ProFormText } from "@ant-design/pro-components";
-
-import { set } from "lodash";
-import { getHasSetParamsList, getParamsSelectableList } from "./service";
-import { RecordKey } from "@ant-design/pro-utils/es/useEditableArray";
-
+import React, { Key, useEffect, useState } from 'react';
+import { Input, Select } from 'antd';
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import {
+  EditableProTable,
+  ModalForm,
+  ProColumns,
+  ProFormSelect,
+  ProFormText,
+} from '@ant-design/pro-components';
+
+import { set } from 'lodash';
+import { getHasSetParamsList, getParamsSelectableList } from './service';
+import { RecordKey } from '@ant-design/pro-utils/es/useEditableArray';
 
 // import './style.less';
 
-
 interface TableSelecterProps {
-    record: any
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-const EditTableModal = ({ record, open, title, onVisibleChange, rowKey = 'id', onFinish }: {
-    record: any, open: boolean, title: string, onVisibleChange: (bool: boolean) => void,
-    rowKey?: string, onFinish?: (selectedRows: any[]) => void
+const EditTableModal = ({
+  record,
+  open,
+  title,
+  onVisibleChange,
+  rowKey = 'id',
+  onFinish,
+}: {
+  record: any;
+  open: boolean;
+  title: string;
+  onVisibleChange: (bool: boolean) => void;
+  rowKey?: string;
+  onFinish?: (selectedRows: any[]) => void;
 }) => {
-
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        let currentSelectedRow:undefined|any = undefined;
-
-        const columns: ProColumns[] = [
-            {
-                title: '分摊参数',
-                dataIndex: 'shareParamCode',
-                ellipsis:true,
-                valueType:'select',
-                request:async ()=>{
-                     const resp = await getParamsSelectableList({pageSize:500,current:1,id:record.id});
-                     if(resp){
-                           return resp.list.map((a:any)=>({label: a.shareParamName,value: a.shareParamCode,id:a.id}))
-                     }
-                     return []
-                },
-                fieldProps:{
-                    showSearch:true,
-                    style: {
-                        width: '280px', // 设置你想要的宽度
-                    },
-                    onSelect:(a: any,b: any,c:any)=>{
-                        currentSelectedRow = b;
-                    }
-                }
-            },
-            {
-                title: '分摊比例',
-                width:90,
-                dataIndex: 'shareParamPopout',
-                ellipsis:true,
-                valueType:'digit',
-                fieldProps:{
-                    style:{
-                        width:'70px'
-                    }
-                }
-            }, 
-            {
-                title: '操作',
-                width:130,
-                valueType: 'option',
-                fieldProps:{
-                    style:{
-                        gap:'2px !important'
-                    }
-                },
-                render: (text, record, _, action) => [
-                  <a
-                    key="editable"
-                    onClick={() => {
-                      action?.startEditable?.(record.id);
-                    }}
-                  >
-                    编辑
-                  </a>,
-                  <a
-                    key="delete"
-                    onClick={() => {
-                        set_datasource(datasource.filter((item) => item.id !== record.id));
-                    }}
-                  >
-                    删除
-                  </a>,
-                ],
-            },
-        ];
-
-
-
-        const saveHandle = async () => {
-            onFinish && onFinish(datasource);
-        
-        }
-
-        const getTableData = async () => {
-
-            const resp = await getHasSetParamsList(record.id);
-            if(resp){
-                set_datasource(resp);
-            }else{
-                return Promise.resolve([]);
-            }
-        }
-
-        useEffect(() => {
-            getTableData()
-        }, [])
-
-
-        return (
-            <div >
-                <EditableProTable columns={columns}
-                    className='EditableProTable'
-                    options={false}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    recordCreatorProps={
-                       {
-                        record: () => ({ id: (Math.random() * 1000000).toFixed(0) }),
-                       }
-                    }
-                    editable={{
-                        onSave: async (rowKey, data, row) => {
-                            // console.log({rowKey, data, row,currentSelectedRow,datasource});                        
-                           
-                            const {index} = data;
-          
-                            if(index > datasource.length - 1){
-                                //新增
-                                const {id,label} = currentSelectedRow;
-                                set_datasource([...datasource,{
-                                    shareParamName:label,
-                                    shareParamCode:data.shareParamCode,
-                                    shareParamPopout:data.shareParamPopout,
-                                    id:id
-                                }]);
-                            }else {
-                                //编辑
-                                const newData = [...datasource];
-                                newData[index] = {
-                                    shareParamName:currentSelectedRow?currentSelectedRow.label:data.shareParamName,
-                                    shareParamCode:data.shareParamCode,
-                                    shareParamPopout:data.shareParamPopout,
-                                    id:currentSelectedRow?currentSelectedRow.id:data.id
-                                };
-                                set_datasource([...newData]);
-                            }
-                            
-                            currentSelectedRow = undefined;
-                        },
-                    }}
-                    value={datasource}
-                
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认`}</span>
-                </div>
-            </div>
-
-        )
-    });
-
-    const close = () => {
-        onVisibleChange && onVisibleChange(false);
-    }
-
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    let currentSelectedRow: undefined | any = undefined;
+
+    const columns: ProColumns[] = [
+      {
+        title: '分摊参数',
+        dataIndex: 'shareParamCode',
+        ellipsis: true,
+        valueType: 'select',
+        request: async () => {
+          const resp = await getParamsSelectableList({
+            pageSize: 500,
+            current: 1,
+            id: record.id,
+          });
+          if (resp) {
+            return resp.list.map((a: any) => ({
+              label: a.shareParamName,
+              value: a.shareParamCode,
+              id: a.id,
+            }));
+          }
+          return [];
+        },
+        fieldProps: {
+          showSearch: true,
+          style: {
+            width: '280px', // 设置你想要的宽度
+          },
+          onSelect: (a: any, b: any, c: any) => {
+            currentSelectedRow = b;
+          },
+        },
+      },
+      {
+        title: '分摊比例',
+        width: 90,
+        dataIndex: 'shareParamPopout',
+        ellipsis: true,
+        valueType: 'digit',
+        fieldProps: {
+          style: {
+            width: '70px',
+          },
+        },
+      },
+      {
+        title: '操作',
+        width: 130,
+        valueType: 'option',
+        fieldProps: {
+          style: {
+            gap: '2px !important',
+          },
+        },
+        render: (text, record, _, action) => [
+          <a
+            key="editable"
+            onClick={() => {
+              action?.startEditable?.(record.id);
+            }}
+          >
+            编辑
+          </a>,
+          <a
+            key="delete"
+            onClick={() => {
+              set_datasource(
+                datasource.filter((item) => item.id !== record.id),
+              );
+            }}
+          >
+            删除
+          </a>,
+        ],
+      },
+    ];
+
+    const saveHandle = async () => {
+      onFinish && onFinish(datasource);
+    };
+
+    const getTableData = async () => {
+      const resp = await getHasSetParamsList(record.id);
+      if (resp) {
+        set_datasource(resp);
+      } else {
+        return Promise.resolve([]);
+      }
+    };
+
+    useEffect(() => {
+      getTableData();
+    }, []);
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={550} submitter={{
-            render: false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-export default EditTableModal
+      <div>
+        <EditableProTable
+          columns={columns}
+          className="EditableProTable"
+          options={false}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          recordCreatorProps={{
+            record: () => ({ id: (Math.random() * 1000000).toFixed(0) }),
+          }}
+          editable={{
+            onSave: async (rowKey, data, row) => {
+              // console.log({rowKey, data, row,currentSelectedRow,datasource});
+
+              const { index } = data;
+
+              if (index > datasource.length - 1) {
+                //新增
+                const { id, label } = currentSelectedRow;
+                set_datasource([
+                  ...datasource,
+                  {
+                    shareParamName: label,
+                    shareParamCode: data.shareParamCode,
+                    shareParamPopout: data.shareParamPopout,
+                    id: id,
+                  },
+                ]);
+              } else {
+                //编辑
+                const newData = [...datasource];
+                newData[index] = {
+                  shareParamName: currentSelectedRow
+                    ? currentSelectedRow.label
+                    : data.shareParamName,
+                  shareParamCode: data.shareParamCode,
+                  shareParamPopout: data.shareParamPopout,
+                  id: currentSelectedRow ? currentSelectedRow.id : data.id,
+                };
+                set_datasource([...newData]);
+              }
+
+              currentSelectedRow = undefined;
+            },
+          }}
+          value={datasource}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={550}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default EditTableModal;

+ 477 - 417
src/pages/baseSetting/costAllocationSet/allocationParamsMap/index.tsx

@@ -7,16 +7,21 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect, ProFormTextArea, ProFormTreeSelect } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+  ProFormTextArea,
+  ProFormTreeSelect,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Tag, Tabs } from 'antd';
 import { Key, SetStateAction, useEffect, useRef, useState } from 'react';
@@ -24,9 +29,15 @@ import { Key, SetStateAction, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, copyParamsList, delData, editData, getCostshareparamConnectList, getResponsibilityCenterSelecterList, saveParamsList } from './service';
+import {
+  addData,
+  copyParamsList,
+  delData,
+  editData,
+  getCostshareparamConnectList,
+  getResponsibilityCenterSelecterList,
+  saveParamsList,
+} from './service';
 
 import './style.less';
 import { getAccountingSubjectList } from '../../accountingAccountSet/accountingSubMana/service';
@@ -34,432 +45,481 @@ import { getChilds } from '@/utils/tooljs';
 import EditTableModal from './editTableModal';
 import TableSelecter from './tableSelector';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
 export default function AllocationParamsMap() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>(undefined);
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
-    const [selectableLevelList, setSelectableLevelList] = useState([]);//可选的分摊层级列表
-    const [tabs, set_tabs] = useState<any[]>([]);
-    const [accountType, set_accountType] = useState<Key>(1);
-
-    const [selectedResponsibilityId, setSelectedResponsibilityId] = useState(null);
-    const [selectedResponsibility, setSelectedResponsibility] = useState(null);
-
-    const [editTableVisible, set_editTableVisible] = useState(false);
-    const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
-
-
-    const columns: ProColumns[] = [
-
-        {
-            title: '分摊级别',
-            width:80,
-            ellipsis: true,
-            dataIndex: 'shareLevel',
-        },
-        {
-            title: '责任中心编码',
-            ellipsis: true,
-            width:120,
-            dataIndex: 'responsibilityCode',
-        },
-        {
-            title: '责任中心名',
-            ellipsis: true,
-            width:120,
-            dataIndex: 'responsibilityName',
-        },
-        {
-            title: '分摊参数',
-            ellipsis: true,
-            dataIndex: 'shareParamMap',
-        },
-        {
-            title: '会计科目名称',
-            ellipsis: true,
-            dataIndex: 'accountingNames',
-        },
-        {
-            title: '会计科目编码',
-            ellipsis: true,
-            dataIndex: 'accountingCodes',
-        },
-        {
-            title: '别名',
-            ellipsis: true,
-            width:100,
-            dataIndex: 'alias',
-        },
-        {
-            title: '备注',
-            ellipsis: true,
-            width:200,
-            dataIndex: 'costNode',
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 200,
-            fixed:'right',
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-
-                    <a key='copy' onClick={() => { set_tableSelecterVisible(true); setCurrentRow(record); }}>复制</a>,
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                    <a key='share' onClick={() => { set_editTableVisible(true); setCurrentRow(record) }}>分摊参数</a>
-
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getCostshareparamConnectList({ ...params });
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        }
-        return []
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >(undefined);
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
+  const [selectableLevelList, setSelectableLevelList] = useState([]); //可选的分摊层级列表
+  const [tabs, set_tabs] = useState<any[]>([]);
+  const [accountType, set_accountType] = useState<Key>(1);
+
+  const [selectedResponsibilityId, setSelectedResponsibilityId] =
+    useState(null);
+  const [selectedResponsibility, setSelectedResponsibility] = useState(null);
+
+  const [editTableVisible, set_editTableVisible] = useState(false);
+  const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
+
+  const columns: ProColumns[] = [
+    {
+      title: '分摊级别',
+      width: 80,
+      ellipsis: true,
+      dataIndex: 'shareLevel',
+    },
+    {
+      title: '责任中心编码',
+      ellipsis: true,
+      width: 120,
+      dataIndex: 'responsibilityCode',
+    },
+    {
+      title: '责任中心名',
+      ellipsis: true,
+      width: 120,
+      dataIndex: 'responsibilityName',
+    },
+    {
+      title: '分摊参数',
+      ellipsis: true,
+      dataIndex: 'shareParamMap',
+    },
+    {
+      title: '会计科目名称',
+      ellipsis: true,
+      dataIndex: 'accountingNames',
+    },
+    {
+      title: '会计科目编码',
+      ellipsis: true,
+      dataIndex: 'accountingCodes',
+    },
+    {
+      title: '别名',
+      ellipsis: true,
+      width: 100,
+      dataIndex: 'alias',
+    },
+    {
+      title: '备注',
+      ellipsis: true,
+      width: 200,
+      dataIndex: 'costNode',
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 200,
+      fixed: 'right',
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <a
+            key="copy"
+            onClick={() => {
+              set_tableSelecterVisible(true);
+              setCurrentRow(record);
+            }}
+          >
+            复制
+          </a>,
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+          <a
+            key="share"
+            onClick={() => {
+              set_editTableVisible(true);
+              setCurrentRow(record);
+            }}
+          >
+            分摊参数
+          </a>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getCostshareparamConnectList({ ...params });
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
     }
-
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData([record.id]);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData([record.id]);
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    console.log({ formVal });
+    try {
+      const result = {
+        responsibilityId: formVal.responsibilityId,
+        accountingIds: formVal.accountingIds.join(','),
+        isShareCost: formVal.isShareCost,
+        alias: formVal.alias,
+        costNode: formVal.costNode,
+        responsibilityName: formVal.responsibility
+          ? formVal.responsibility.responsibilityName
+          : formVal.responsibilityName,
+        shareLevel: formVal.responsibility
+          ? formVal.responsibility.shareLevel
+          : formVal.shareLevel,
+        responsibilityCode: formVal.responsibility
+          ? formVal.responsibility.responsibilityCode
+          : formVal.responsibilityCode,
+      };
+
+      if (type == 'ADD') {
+        const resp = await addData(result);
+        if (resp) {
+          tableRef.current?.reload();
+          message.success('操作成功!');
+        }
+      }
+      if (type == 'EDIT') {
+        const resp = await editData({ ...result, id: formVal.id });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      }
+    } catch (error) {
+      console.log({ error });
     }
 
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-        console.log({formVal});
-        try {
-            const result = {
-                responsibilityId: formVal.responsibilityId,
-                accountingIds: formVal.accountingIds.join(','),
-                isShareCost: formVal.isShareCost,
-                alias: formVal.alias,
-                costNode: formVal.costNode,
-                responsibilityName: formVal.responsibility?formVal.responsibility.responsibilityName:formVal.responsibilityName,
-                shareLevel: formVal.responsibility?formVal.responsibility.shareLevel:formVal.shareLevel,
-                responsibilityCode: formVal.responsibility?formVal.responsibility.responsibilityCode:formVal.responsibilityCode
-            };
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    const [ifDisable, setIfDisable] = useState(false);
+    const [needDisableIds, set_needDisableIds] = useState<any[]>([]);
+
+    let accountingIds: Key[] = record.accountingIdList
+      ? record.accountingIdList.map((a: string) => Number(a))
+      : [];
+
+    useEffect(() => {
+      if (type == 'EDIT' && needDisableIds.length > 0) {
+        if (needDisableIds.includes(record.responsibilityId)) {
+          setIfDisable(false);
+        } else {
+          setIfDisable(true);
+        }
+      }
+    }, [needDisableIds]);
 
-            if (type == 'ADD') {
-                const resp = await addData(result);
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}成本分摊参数对应`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+                accountings: record.accountingIdList
+                  ? record.accountingIdList.map((a: string) => Number(a))
+                  : [],
+              }
+            : {}
+        }
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
+        }
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT'
+              ? { ...record, ...val, accountingIds }
+              : { ...val, accountingIds },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText name="responsibility" hidden />
+        <ProFormText name="responsibility" hidden />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择责任中心',
+            },
+          ]}
+          fieldProps={{
+            showSearch: true,
+            onChange: async (val, option: any) => {
+              const {} = option;
+              const resp = await getResponsibilityCenterSelecterList();
+
+              if (resp) {
+                const selected = resp.filter((item: any) => item.id == val);
+                if (selected[0]) {
+                  formRef.current?.setFieldValue('responsibility', selected[0]);
                 }
+              }
 
-            }
-            if (type == 'EDIT') {
-
-
-                const resp = await editData({...result,id:formVal.id});
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
+              if (needDisableIds.includes(val)) {
+                setIfDisable(false);
+              } else {
+                setIfDisable(true);
+              }
+            },
+          }}
+          request={async () => {
+            const resp = await getResponsibilityCenterSelecterList();
+            // const resp = [
+            //     {
+            //         calcType: 1,
+            //         id: 401,
+            //         responsibilityCode: "B0100",
+            //         responsibilityId: 401,
+            //         responsibilityName: "公共费用",
+            //         shareId: 59,
+            //         shareLevel: 1,
+            //         shareName: "公共费用",
+            //     }
+            // ]
+            if (resp) {
+              let tempArr: any[] = [];
+              const result = resp.map((item: any) => {
+                if (item.calcType == 1) {
+                  tempArr.push(item.id);
                 }
-
-
-            }
-
-        } catch (error) {
-            console.log({ error });
-        }
-
-        return true;
-
-    }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-        const [ifDisable, setIfDisable] = useState(false);
-        const [needDisableIds,set_needDisableIds] = useState<any[]>([]);
-
-        let accountingIds: Key[] = record.accountingIdList?record.accountingIdList.map((a:string)=>Number(a)):[];
-
-        useEffect(()=>{
-            if(type == 'EDIT'&&needDisableIds.length>0){
-                if (needDisableIds.includes(record.responsibilityId)) {
-                    setIfDisable(false);
-                } else {
-                    setIfDisable(true);
+                return {
+                  label: item.responsibilityName,
+                  value: item.id,
+                };
+              });
+              set_needDisableIds((prevIds) => {
+                if (
+                  prevIds.length === tempArr.length &&
+                  prevIds.every((id, index) => id === tempArr[index])
+                ) {
+                  return prevIds; // 保持原来的引用,不触发更新
                 }
+                return tempArr;
+              });
+              return result;
             }
-        },[needDisableIds])
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}成本分摊参数对应`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record,
-                    accountings:(record.accountingIdList)?record.accountingIdList.map((a:string)=>Number(a)):[],
-                } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val, accountingIds } : { ...val, accountingIds }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormText name="responsibility" hidden />
-                <ProFormText name="responsibility" hidden />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择责任中心',
-                        },
-                    ]}
-                    fieldProps={{
-                        showSearch:true,
-                        onChange: async (val, option: any) => {
-                            const { } = option;
-                            const resp = await getResponsibilityCenterSelecterList();
-                
-                            if (resp) {
-                                const selected = resp.filter((item: any) => item.id == val);
-                                if (selected[0]) {
-                                    formRef.current?.setFieldValue('responsibility', selected[0]);
-                                }
-                            }
-
-                            if (needDisableIds.includes(val)) {
-                                setIfDisable(false);
-                            } else {
-                                setIfDisable(true);
-                            }
-                        },
-                    }}
-                    request={async () => {
-                        const resp = await getResponsibilityCenterSelecterList();
-                        // const resp = [
-                        //     {
-                        //         calcType: 1,
-                        //         id: 401,
-                        //         responsibilityCode: "B0100",
-                        //         responsibilityId: 401,
-                        //         responsibilityName: "公共费用",
-                        //         shareId: 59,
-                        //         shareLevel: 1,
-                        //         shareName: "公共费用",
-                        //     }
-                        // ]
-                        if (resp) {
-                            let tempArr:any[] = [];
-                            const result =  resp.map((item: any) => {
-                                if (item.calcType == 1) {
-                                    tempArr.push(item.id);
-                                }
-                                return ({
-                                    label: item.responsibilityName,
-                                    value: item.id,
-                                })
-                            });
-                            set_needDisableIds((prevIds) => {
-                                if (prevIds.length === tempArr.length && prevIds.every((id, index) => id === tempArr[index])) {
-                                    return prevIds;  // 保持原来的引用,不触发更新
-                                }
-                                return tempArr;
-                            });
-                            return result
-                        }
-                        return []
-                    }}
-                    name="responsibilityId"
-                    label="请选择责任中心"
-                />
-                <ProFormTreeSelect
-                    disabled={ifDisable}
-                    allowClear
-                    rules={[
-                        {
-                            required: ifDisable ? false : true,
-                            message: '请选择会计科目',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getAccountingSubjectList({ accountType:2, pageSize: 500, current: 1 });
-
-                        if (resp) {
-                            return resp.list
-                        }
-                        return []
-                    }}
-                    fieldProps={{
-                        showSearch: true,
-                        multiple: true,
-                        maxTagCount:'responsive',
-                        maxTagPlaceholder:'...',
-                        treeCheckable: true,
-                        treeNodeFilterProp: 'accountingName',
-                        showCheckedStrategy: 'SHOW_CHILD',
-                        fieldNames: {
-                            label: 'accountingName',
-                            value: 'id'
-                        },
-                        onChange(value, labelList, extra) {
-                            // console.log({value,labelList,extra});
-                            accountingIds = value;
-                        },
-                        // onSelect: (value, opt) => {
-                        //     console.log({ value, opt });
-                        //     // console.log(getChilds(opt,'children'));
-                        //     if (opt.children && opt.children.length > 0) {
-                        //         const childs = getChilds(opt, 'children');
-                        //         const ids = childs.map((a) => a.id);
-                        //         accountingIds = ids;
-                        //     }
-                        // }
-                    }}
-                    name="accountings"
-                    label="选择会计科目"
-                />
-                <ProFormSelect
-                    disabled={ifDisable}
-                    rules={[
-                        {
-                            required: ifDisable ? false : true,
-                            message: '请选择',
-                        },
-                    ]}
-                    request={async () => [
-                        { label: '不包含分摊成本', value: 0 },
-                        { label: '包含分摊成本', value: 1 }
-                    ]}
-                    name="isShareCost"
-                    label="是否包含分摊成本"
-                />
-                <ProFormText
-                    name="alias"
-                    label="别名"
-                />
-                <ProFormTextArea
-                    name="costNode"
-                    label="备注"
-                    placeholder="请输入备注"
-                />
-            </ModalForm>
-        )
-    }
-
-    const shareParamsSetCommit = async (rows: any[]) => {
-        const resp = await saveParamsList({ id: currentRow.id, shareParamProportionVOList: rows });
-        if (resp) {
-            set_editTableVisible(false);
-            message.success('操作成功!');
-            tableRef.current?.reload();
-        }
+            return [];
+          }}
+          name="responsibilityId"
+          label="请选择责任中心"
+        />
+        <ProFormTreeSelect
+          disabled={ifDisable}
+          allowClear
+          rules={[
+            {
+              required: ifDisable ? false : true,
+              message: '请选择会计科目',
+            },
+          ]}
+          request={async () => {
+            const resp = await getAccountingSubjectList({
+              accountType: 2,
+              pageSize: 500,
+              current: 1,
+            });
+
+            if (resp) {
+              return resp.list;
+            }
+            return [];
+          }}
+          fieldProps={{
+            showSearch: true,
+            multiple: true,
+            maxTagCount: 'responsive',
+            maxTagPlaceholder: '...',
+            treeCheckable: true,
+            treeNodeFilterProp: 'accountingName',
+            showCheckedStrategy: 'SHOW_CHILD',
+            fieldNames: {
+              label: 'accountingName',
+              value: 'id',
+            },
+            onChange(value, labelList, extra) {
+              // console.log({value,labelList,extra});
+              accountingIds = value;
+            },
+            // onSelect: (value, opt) => {
+            //     console.log({ value, opt });
+            //     // console.log(getChilds(opt,'children'));
+            //     if (opt.children && opt.children.length > 0) {
+            //         const childs = getChilds(opt, 'children');
+            //         const ids = childs.map((a) => a.id);
+            //         accountingIds = ids;
+            //     }
+            // }
+          }}
+          name="accountings"
+          label="选择会计科目"
+        />
+        <ProFormSelect
+          disabled={ifDisable}
+          rules={[
+            {
+              required: ifDisable ? false : true,
+              message: '请选择',
+            },
+          ]}
+          request={async () => [
+            { label: '不包含分摊成本', value: 0 },
+            { label: '包含分摊成本', value: 1 },
+          ]}
+          name="isShareCost"
+          label="是否包含分摊成本"
+        />
+        <ProFormText name="alias" label="别名" />
+        <ProFormTextArea
+          name="costNode"
+          label="备注"
+          placeholder="请输入备注"
+        />
+      </ModalForm>
+    );
+  };
+
+  const shareParamsSetCommit = async (rows: any[]) => {
+    const resp = await saveParamsList({
+      id: currentRow.id,
+      shareParamProportionVOList: rows,
+    });
+    if (resp) {
+      set_editTableVisible(false);
+      message.success('操作成功!');
+      tableRef.current?.reload();
     }
-
-    const tableSelecterCommit = async (keys: Key[], rows: any) => {
-        const { id } = currentRow;
-        const resp = await copyParamsList({ id, responsibilityIds: keys });
-        if (resp) {
-            set_tableSelecterVisible(false);
-            message.success('操作成功!');
-            tableRef.current?.reload();
-        }
+  };
+
+  const tableSelecterCommit = async (keys: Key[], rows: any) => {
+    const { id } = currentRow;
+    const resp = await copyParamsList({ id, responsibilityIds: keys });
+    if (resp) {
+      set_tableSelecterVisible(false);
+      message.success('操作成功!');
+      tableRef.current?.reload();
     }
-
-    return (
-        <KCIMPagecontainer className='AllocationParamsMap' title={false}>
-            <EditTableModal
-                onVisibleChange={(bool) => set_editTableVisible(bool)}
-                title='分摊参数设置'
-                rowKey={'id'}
-                record={currentRow}
-                open={editTableVisible}
-                onFinish={(rows) => shareParamsSetCommit(rows)}
-            />
-            <TableSelecter
-                onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
-                title='选择复制目标'
-                rowKey={'id'}
-                defaultSelectedKeys={[]}
-                record={currentRow}
-                open={tableSelecterVisible}
-                onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+  };
+
+  return (
+    <KCIMPagecontainer className="AllocationParamsMap" title={false}>
+      <EditTableModal
+        onVisibleChange={(bool) => set_editTableVisible(bool)}
+        title="分摊参数设置"
+        rowKey={'id'}
+        record={currentRow}
+        open={editTableVisible}
+        onFinish={(rows) => shareParamsSetCommit(rows)}
+      />
+      <TableSelecter
+        onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
+        title="选择复制目标"
+        rowKey={'id'}
+        defaultSelectedKeys={[]}
+        record={currentRow}
+        open={tableSelecterVisible}
+        onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
+      />
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'责任中心名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('name')}
+                />
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    name: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  name: (e.target as HTMLInputElement).value,
+                });
+              }}
             />
-            <div className='toolBar' >
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'责任中心名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('name')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        name: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    name: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
-                </div>
-            </div>
-            
-            <div>
-                <KCIMTable  scroll={{x:2000,y:`calc(100vh - 234px)`}} columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+          </div>
+        </div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          scroll={{ x: 2000, y: `calc(100vh - 234px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 31 - 63
src/pages/baseSetting/costAllocationSet/allocationParamsMap/service.ts

@@ -7,129 +7,97 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获取table列表数据
-export const getCostshareparamConnectList = (params:any) => {
+export const getCostshareparamConnectList = (params: any) => {
   return request('/costAccount/costaccountshare/list', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
+};
 
 //获取当前成本已用本的分摊参数列表
-export const getHasSetParamsList = (id:number)=>{
+export const getHasSetParamsList = (id: number) => {
   return request(`/costAccount/costaccountshare/getShareParamById`, {
     method: 'GET',
-    params:{
-         id:id
+    params: {
+      id: id,
     },
   });
-
-}
-
+};
 
 //获取可选复制目标列表
-export async function getCopyableToList(params:any) {
+export async function getCopyableToList(params: any) {
   return request(`/costAccount/costaccountshare/getResponsibilityCalType`, {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-
 }
 
-
 //获取添加分摊参数时可选列表
-export async function getParamsSelectableList(params:any) {
+export async function getParamsSelectableList(params: any) {
   return request(`/costAccount/costaccountshare/getAllShareParamStatusById`, {
     method: 'GET',
-    params:{
-        ...params
+    params: {
+      ...params,
     },
   });
-
 }
 
-
-
 //新增
-export type AddTableDataType = any
+export type AddTableDataType = any;
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/costaccountshare/save', {
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/costaccountshare/update', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
 //保存成本分摊参数
-export const saveParamsList = (data:any) => {
+export const saveParamsList = (data: any) => {
   return request(`/costAccount/costaccountshare/updateShareParam`, {
     method: 'POST',
-    data
+    data,
   });
-}
-
-
+};
 
 //删除表格操作
-export const delData = (ids:Key[]) => {
-  console.log({ids});
+export const delData = (ids: Key[]) => {
+  console.log({ ids });
   return request('/costAccount/costaccountshare/delete', {
     method: 'POST',
-    data:ids
+    data: ids,
   });
 };
 
-
-
-
-
 //获取责任中心选择列表
-export const  getResponsibilityCenterSelecterList = ()=> {
+export const getResponsibilityCenterSelecterList = () => {
   // const {shareParamName,current,pageSize} = params;
   return request('/costAccount/responsibility/getLevelTwo', {
-    method: 'GET'
+    method: 'GET',
   });
-}
-
+};
 
 //复制数据
-export const copyParamsList = (body:any) => {
+export const copyParamsList = (body: any) => {
   return request(`/costAccount/costaccountshare/copyAccountShareData`, {
     method: 'POST',
-    data:body,
+    data: body,
   });
-
-}
-
-
-
-
-
-
-
-
-
-
-
+};

+ 45 - 49
src/pages/baseSetting/costAllocationSet/allocationParamsMap/style.less

@@ -1,57 +1,53 @@
-
 .TableSelecter {
-
   .pfm-ant-modal-footer {
     display: none !important;
   }
-  
-  .footer {
-       display: flex;
-       flex-direction:row;
-       justify-content: flex-end;
-       margin-top: 15px;
-       span {
-           display: inline-block;
-           width: 56px;
-           height: 24px;  
-           font-size: 14px;
-           line-height: 23px;
-           text-align: center;
-           border-radius: 4px;
-           cursor: pointer;
 
-           &.ok {
-               color: #FFFFFF;
-               background:#3377FF;
-               margin-left: 8px;
-           }
-           &.cancel {
-               border: 1px solid #DAE2F2;
-           }
-       }
+  .footer {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+    margin-top: 15px;
+    span {
+      display: inline-block;
+      width: 56px;
+      height: 24px;
+      font-size: 14px;
+      line-height: 23px;
+      text-align: center;
+      border-radius: 4px;
+      cursor: pointer;
 
+      &.ok {
+        color: #ffffff;
+        background: #3377ff;
+        margin-left: 8px;
+      }
+      &.cancel {
+        border: 1px solid #dae2f2;
+      }
+    }
   }
 }
 
 .EditableProTable {
-     .cost-ant-table-tbody {
-         .cost-ant-table-row {
-               .cost-ant-table-cell {
-                      &>div {
-                          display: flex;
-                          justify-content: left !important;
-                      }
-               }
-         }
-     }
+  .cost-ant-table-tbody {
+    .cost-ant-table-row {
+      .cost-ant-table-cell {
+        & > div {
+          display: flex;
+          justify-content: left !important;
+        }
+      }
+    }
+  }
 }
 
 .AllocationParamsMap {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -74,17 +70,17 @@
     }
 
     .btnGroup {
-        .add {
-          cursor: pointer;
-          display: inline-block;
-          font-size: 14px;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 24px;
-          padding: 0 14px;
-          background: #3377FF;
-          border-radius: 4px;
-        }
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377ff;
+        border-radius: 4px;
+      }
     }
   }
 }

+ 202 - 172
src/pages/baseSetting/costAllocationSet/allocationParamsMap/tableSelector.tsx

@@ -1,186 +1,216 @@
-import React, { Key, useEffect, useState } from "react";
-import { Input, Select } from 'antd'
-import { KCIMTable } from "@/components/KCIMTable";
-import { createFromIconfontCN } from "@ant-design/icons";
+import React, { Key, useEffect, useState } from 'react';
+import { Input, Select } from 'antd';
+import { KCIMTable } from '@/components/KCIMTable';
+import { createFromIconfontCN } from '@ant-design/icons';
 
+import {
+  ModalForm,
+  ProColumns,
+  ProFormSelect,
+  ProFormText,
+} from '@ant-design/pro-components';
 
-import { ModalForm, ProColumns, ProFormSelect, ProFormText } from "@ant-design/pro-components";
-
-import { set } from "lodash";
-import { getCopyableToList } from "./service";
-
+import { set } from 'lodash';
+import { getCopyableToList } from './service';
 
 // import './style.less';
 
-
 interface TableSelecterProps {
-    record: any
+  record: any;
 }
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
-
-
-const TableSelecter = ({ record, open, title, onVisibleChange, rowKey = 'id', request, onFinish, defaultSelectedKeys }: {
-    record: any, open: boolean, title: string, onVisibleChange: (bool: boolean) => void, defaultSelectedKeys: Key[],
-    rowKey?: string, request?: (params: any) => Promise<any>, onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void
+const TableSelecter = ({
+  record,
+  open,
+  title,
+  onVisibleChange,
+  rowKey = 'id',
+  request,
+  onFinish,
+  defaultSelectedKeys,
+}: {
+  record: any;
+  open: boolean;
+  title: string;
+  onVisibleChange: (bool: boolean) => void;
+  defaultSelectedKeys: Key[];
+  rowKey?: string;
+  request?: (params: any) => Promise<any>;
+  onFinish?: (selectedKeys: React.Key[], selectedRows: any[]) => void;
 }) => {
-
-
-    const Table = React.forwardRef(({ }: TableSelecterProps, ref) => {
-
-        const [datasource, set_datasource] = useState<any[]>([]);
-        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-        const [selectedRows, set_selectedRows] = useState<any[]>([]);
-        const [showList, set_showList] = useState<any[]>([]);
-        const [filter, set_filter] = useState<undefined | any>(undefined);
-        const [code, set_code] = useState<undefined | any>(undefined);
-        const [keyword, set_keyword] = useState<string | undefined>(undefined);
-
-
-        const columns: ProColumns[] = [
-            {
-                title: '责任中心Id',
-                dataIndex: 'id',
-            },
-            {
-                title: '责任中心名',
-                dataIndex: 'responsibilityName',
-            },
-        ];
-
-
-        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-            set_selectedRows([...selectedRows]);
-
-        };
-
-        const saveHandle = async () => {
-            const selectedRowkeys = selectedRows.map((a) => a[`${rowKey}`]);
-            const rows = datasource.filter((a) => selectedRowkeys.includes(a[`${rowKey}`]));
-            onFinish && onFinish(selectedKeys, rows);
-        }
-
-        const getTableData = async () => {
-
-            // const resp = await getAddableTableData(record.costTypeCode);
-
-            const {id:accountShareId} = record;
-            const resp = await getCopyableToList({accountShareId});
-
-            let selectedKeys: string[] = [];
-            let selectedRows: any[] = [];
-            if (resp) {
-                const data = resp.map((a: any) => {
-                    if (defaultSelectedKeys.includes(a[`${rowKey}`])) {
-                        selectedKeys.push(a[`${rowKey}`]);
-                        selectedRows.push(a);
-                        const needItem = record.departList.filter((b: any) => a[`${rowKey}`] == b[`${rowKey}`]);
-
-                        return {
-                            ...a,
-                        }
-                    } else {
-                        return a
-                    }
-                });
-
-                set_showList(data);
-                set_selectedRows([...selectedRows]);
-                setSelectedKeys([...selectedKeys]);
-                set_datasource([...datasource, ...data]);
-            }
-
-
-            return Promise.resolve([]);
-        }
-
-        useEffect(() => {
-            // console.log({code, keyword});
-            const result = datasource.filter((a) => {
-                 return a.responsibilityName?a.responsibilityName.indexOf(keyword) != -1:false
-            });
-
-            set_showList([...result]);
-        }, [keyword])
-
-        useEffect(() => {
-            getTableData()
-        }, [])
-
-
-        return (
-            <div >
-                <div className="filter" style={{ display: 'flex', flexDirection: 'row', marginBottom: 8 }}>
-                    <ProFormText noStyle placeholder={'请输入'}
-                        fieldProps={{
-                            suffix: <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />,
-                            onChange: (e) => {
-                                if (e.target.value.length != 0) {
-                                    set_keyword(e.target.value);
-                                } else {
-                                    set_keyword('');
-                                }
-                            }
-                        }}
-                    />
-                </div>
-
-                <KCIMTable columns={columns}
-                    options={{
-                        density: true,
-                        setting: {
-                            listsHeight: 100,
-                        },
-                    }}
-                    rowKey={rowKey}
-                    scroll={{ y: 400 }}
-                    tableAlertRender={false}
-                    rowSelection={{
-                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
-                        // 注释该行则默认不显示下拉选项
-                        // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
-                        selectedRowKeys: selectedKeys,
-                        onChange: onSelectChange,
-                    }}
-                    pagination={{ showTitle: false, showSizeChanger: false,simple:true }}
-                    dataSource={showList}
-
-                />
-                <div className='footer'>
-                    <span className='cancel' onClick={() => close()}>取消</span>
-                    <span className='ok' onClick={() => saveHandle()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
-                </div>
-            </div>
-
-        )
-    });
-
-    const close = () => {
-        onVisibleChange && onVisibleChange(false);
-    }
-
+  const Table = React.forwardRef(({}: TableSelecterProps, ref) => {
+    const [datasource, set_datasource] = useState<any[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+    const [selectedRows, set_selectedRows] = useState<any[]>([]);
+    const [showList, set_showList] = useState<any[]>([]);
+    const [filter, set_filter] = useState<undefined | any>(undefined);
+    const [code, set_code] = useState<undefined | any>(undefined);
+    const [keyword, set_keyword] = useState<string | undefined>(undefined);
+
+    const columns: ProColumns[] = [
+      {
+        title: '责任中心Id',
+        dataIndex: 'id',
+      },
+      {
+        title: '责任中心名',
+        dataIndex: 'responsibilityName',
+      },
+    ];
+
+    const onSelectChange = (
+      newSelectedRowKeys: React.Key[],
+      selectedRows: any,
+    ) => {
+      setSelectedKeys([...newSelectedRowKeys]);
+      set_selectedRows([...selectedRows]);
+    };
+
+    const saveHandle = async () => {
+      const selectedRowkeys = selectedRows.map((a) => a[`${rowKey}`]);
+      const rows = datasource.filter((a) =>
+        selectedRowkeys.includes(a[`${rowKey}`]),
+      );
+      onFinish && onFinish(selectedKeys, rows);
+    };
+
+    const getTableData = async () => {
+      // const resp = await getAddableTableData(record.costTypeCode);
+
+      const { id: accountShareId } = record;
+      const resp = await getCopyableToList({ accountShareId });
+
+      let selectedKeys: string[] = [];
+      let selectedRows: any[] = [];
+      if (resp) {
+        const data = resp.map((a: any) => {
+          if (defaultSelectedKeys.includes(a[`${rowKey}`])) {
+            selectedKeys.push(a[`${rowKey}`]);
+            selectedRows.push(a);
+            const needItem = record.departList.filter(
+              (b: any) => a[`${rowKey}`] == b[`${rowKey}`],
+            );
+
+            return {
+              ...a,
+            };
+          } else {
+            return a;
+          }
+        });
+
+        set_showList(data);
+        set_selectedRows([...selectedRows]);
+        setSelectedKeys([...selectedKeys]);
+        set_datasource([...datasource, ...data]);
+      }
+
+      return Promise.resolve([]);
+    };
+
+    useEffect(() => {
+      // console.log({code, keyword});
+      const result = datasource.filter((a) => {
+        return a.responsibilityName
+          ? a.responsibilityName.indexOf(keyword) != -1
+          : false;
+      });
+
+      set_showList([...result]);
+    }, [keyword]);
+
+    useEffect(() => {
+      getTableData();
+    }, []);
 
     return (
-        <ModalForm className="TableSelecter" title={title} width={400} submitter={{
-            render: false
-        }} open={open} modalProps={{
-            closable: false,
-        }}>
-            <Table
-                // ref={tableSelecterRef}
-                record={undefined}
-            ></Table>
-        </ModalForm>
-    )
-
-}
-
-
-
-
-export default TableSelecter
+      <div>
+        <div
+          className="filter"
+          style={{ display: 'flex', flexDirection: 'row', marginBottom: 8 }}
+        >
+          <ProFormText
+            noStyle
+            placeholder={'请输入'}
+            fieldProps={{
+              suffix: (
+                <IconFont style={{ color: '#99A6BF' }} type="iconsousuo" />
+              ),
+              onChange: (e) => {
+                if (e.target.value.length != 0) {
+                  set_keyword(e.target.value);
+                } else {
+                  set_keyword('');
+                }
+              },
+            }}
+          />
+        </div>
+
+        <KCIMTable
+          columns={columns}
+          options={{
+            density: true,
+            setting: {
+              listsHeight: 100,
+            },
+          }}
+          rowKey={rowKey}
+          scroll={{ y: 400 }}
+          tableAlertRender={false}
+          rowSelection={{
+            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+            // 注释该行则默认不显示下拉选项
+            // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+            selectedRowKeys: selectedKeys,
+            onChange: onSelectChange,
+          }}
+          pagination={{
+            showTitle: false,
+            showSizeChanger: false,
+            simple: true,
+          }}
+          dataSource={showList}
+        />
+        <div className="footer">
+          <span className="cancel" onClick={() => close()}>
+            取消
+          </span>
+          <span className="ok" onClick={() => saveHandle()}>{`确认(${
+            selectedKeys.length > 0 && selectedKeys.length
+          })`}</span>
+        </div>
+      </div>
+    );
+  });
+
+  const close = () => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  return (
+    <ModalForm
+      className="TableSelecter"
+      title={title}
+      width={400}
+      submitter={{
+        render: false,
+      }}
+      open={open}
+      modalProps={{
+        closable: false,
+      }}
+    >
+      <Table
+        // ref={tableSelecterRef}
+        record={undefined}
+      ></Table>
+    </ModalForm>
+  );
+};
+
+export default TableSelecter;

+ 503 - 392
src/pages/baseSetting/costAllocationSet/costAllocationParamsDeal/index.tsx

@@ -7,16 +7,21 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormInstance, ProFormText, ProFormSelect, ProFormCascader, ProFormDigit, ProFormDatePicker } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+  ProFormCascader,
+  ProFormDigit,
+  ProFormDatePicker,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Dropdown } from 'antd';
 import type { MenuProps } from 'antd';
@@ -25,9 +30,14 @@ import { Key, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, calculateMonthCostShareData, copyMonthCostShareData, delData, editData, getMonthCostShareDataList } from './service';
+import {
+  addData,
+  calculateMonthCostShareData,
+  copyMonthCostShareData,
+  delData,
+  editData,
+  getMonthCostShareDataList,
+} from './service';
 
 import './style.less';
 import moment from 'moment';
@@ -36,406 +46,507 @@ import { getResponsibilityCenterList } from '../../responsibilityCenterSet/respo
 import { renameChildListToChildren } from '@/utils/tooljs';
 import { tableColumnsWidObj } from '@/constant';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-const currentData = `${new Date().getFullYear()}-${(new Date().getMonth() + 1).toString().padStart(2, '0')}`;
-
-
-
-export default function CostAllocationParamsDeal(
-    { date, ifShowGetBtn, ifShowCancelBtn,responsibilityCode,
-        cancelHandle,getHandle
-     }: { date: string, ifShowGetBtn: boolean, ifShowCancelBtn: boolean,responsibilityCode:string,
-        cancelHandle: () => Promise<boolean>,
-        getHandle:() => Promise<boolean>,
-
+const currentData = `${new Date().getFullYear()}-${(new Date().getMonth() + 1)
+  .toString()
+  .padStart(2, '0')}`;
+
+export default function CostAllocationParamsDeal({
+  date,
+  ifShowGetBtn,
+  ifShowCancelBtn,
+  responsibilityCode,
+  cancelHandle,
+  getHandle,
+}: {
+  date: string;
+  ifShowGetBtn: boolean;
+  ifShowCancelBtn: boolean;
+  responsibilityCode: string;
+  cancelHandle: () => Promise<boolean>;
+  getHandle: () => Promise<boolean>;
+}) {
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({ computeDate: currentData });
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [computeDate, set_computeDate] = useState(currentData);
+  const [currentEditRow, set_currentEditRow] = useState<undefined | any>(
+    undefined,
+  );
+
+  const columns: ProColumns[] = [
+    {
+      title: '分摊参数',
+      dataIndex: 'shareParamName',
+      renderText(text, record, index, action) {
+        const { shareParamCode, shareParamName } = record;
+        return `[${shareParamCode}]${shareParamName}`;
+      },
+    },
+    {
+      title: '数值',
+      align: 'center',
+      dataIndex: 'valueNum',
+      renderText(num, record, index, action) {
+        return (
+          <div
+            style={{
+              display: 'flex',
+              flexDirection: 'row',
+              alignItems: 'center',
+              justifyContent: 'flex-end',
+              paddingRight: '30%',
+            }}
+          >
+            {currentEditRow && currentEditRow.id == record.id && (
+              <>
+                <ProFormDigit
+                  width={80}
+                  noStyle
+                  fieldProps={{
+                    value: num,
+                    onChange(value) {
+                      set_currentEditRow({
+                        ...record,
+                        valueNum: value ? value : 0,
+                      });
+                    },
+                  }}
+                />
+                <img
+                  onClick={() =>
+                    updateTable({ ...record, ...currentEditRow }, 'EDIT')
+                  }
+                  style={{
+                    width: 16,
+                    height: 16,
+                    display: 'inline-block',
+                    marginLeft: 8,
+                    cursor: 'pointer',
+                  }}
+                  src={require('../../../../../static/confirmIcon.png')}
+                />
+              </>
+            )}
+
+            {(!currentEditRow ||
+              (currentEditRow && currentEditRow.id != record.id)) && (
+              <>
+                <div>{num.toFixed(2)}</div>
+                <img
+                  onClick={() => set_currentEditRow(record)}
+                  style={{
+                    width: 16,
+                    height: 16,
+                    display: 'inline-block',
+                    marginLeft: 8,
+                    cursor: 'pointer',
+                  }}
+                  src={require('../../../../../static/editIcon.png')}
+                />
+              </>
+            )}
+          </div>
+        );
+      },
+    },
+    {
+      title: '责任中心',
+      dataIndex: 'responsibilityName',
+      renderText(text, record, index, action) {
+        const { responsibilityCode, responsibilityName } = record;
+        return `[${responsibilityCode}]${responsibilityName}`;
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 90,
+      fixed: 'right',
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+        ];
+      },
+    },
+  ];
+
+  const items: MenuProps['items'] = [
+    {
+      key: '1',
+      label: (
+        <a
+          onClick={() =>
+            cancelHandle().then((isok) => {
+              if (isok) tableRef.current?.reload();
+            })
+          }
+          style={{ display: ifShowCancelBtn ? 'inline-block' : 'none' }}
+        >
+          撤销
+        </a>
+      ),
+    },
+    {
+      key: '2',
+      label: (
+        <a
+          onClick={() =>
+            getHandle().then((isok) => {
+              if (isok) {
+                tableRef.current?.reload();
+              }
+            })
+          }
+          style={{ display: ifShowGetBtn ? 'inline-block' : 'none' }}
+        >
+          获取
+        </a>
+      ),
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const { computeDate, responsibilityCode } = params;
+    if (computeDate && responsibilityCode) {
+      const resp = await getMonthCostShareDataList({ ...params });
+      if (resp) {
+        return {
+          data: resp.list,
+          success: true,
+          total: resp.totalCount,
+          pageSize: resp.pageSize,
+          totalPage: resp.totalPage,
+        };
+      }
     }
-) {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ computeDate: currentData });
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [computeDate, set_computeDate] = useState(currentData);
-    const [currentEditRow, set_currentEditRow] = useState<undefined | any>(undefined);
-
-
-    const columns: ProColumns[] = [
-        {
-            title: '分摊参数',
-            dataIndex: 'shareParamName',
-            renderText(text, record, index, action) {
-                const {shareParamCode,shareParamName} = record;
-                return `[${shareParamCode}]${shareParamName}`
-            },
-        },
-        {
-            title: '数值',
-            align:'center',
-            dataIndex: 'valueNum',
-            renderText(num, record, index, action) {
-                return (
-                    <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center',justifyContent:'flex-end',paddingRight:'30%' }}>
-                        {
-                            (currentEditRow && currentEditRow.id == record.id) && (
-                                <>
-                                    <ProFormDigit
-                                        width={80}
-                                        noStyle
-                                        fieldProps={{
-                                            value: num,
-                                            onChange(value) {
-                                                set_currentEditRow({ ...record, valueNum: value ? value : 0 });
-                                            },
-                                        }}
-                                    />
-                                    <img onClick={() => updateTable({ ...record, ...currentEditRow }, 'EDIT')} style={{ width: 16, height: 16, display: 'inline-block', marginLeft: 8, cursor: 'pointer' }} src={require('../../../../../static/confirmIcon.png')} />
-                                </>
-                            )
-                        }
-
-                        {
-                            (!currentEditRow || (currentEditRow && currentEditRow.id != record.id)) && (
-                                <>
-                                    <div>{num.toFixed(2)}</div>
-                                    <img onClick={() => set_currentEditRow(record)} style={{ width: 16, height: 16, display: 'inline-block', marginLeft: 8, cursor: 'pointer' }} src={require('../../../../../static/editIcon.png')} />
-                                </>
-                            )
-                        }
-                    </div>
-                )
-            },
-        },
-        {
-            title: '责任中心',
-            dataIndex: 'responsibilityName',
-            renderText(text, record, index, action) {
-                const {responsibilityCode,responsibilityName} = record;
-                return `[${responsibilityCode}]${responsibilityName}`
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 90,
-            fixed: 'right',
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ]
-            },
-        },
-
-    ]
-
-    const items: MenuProps['items'] = [
-        {
-            key: '1',
-            label: (
-                <a onClick={()=>cancelHandle().then((isok)=>{
-                       if(isok)tableRef.current?.reload();
-                })} style={{ display: ifShowCancelBtn ? 'inline-block' : 'none' }}>
-                    撤销
-                </a>
-            ),
-        },
-        {
-            key: '2',
-            label: (
-                <a onClick={()=>getHandle().then((isok)=>{
-   
-                    if(isok){
-                        tableRef.current?.reload()
-                    };
-                })} style={{ display: ifShowGetBtn ? 'inline-block' : 'none' }}>
-                    获取
-                </a>
-            ),
-        },
-
-    ];
-
-
-    const getTableData = async (params: any) => {
-        const {computeDate,responsibilityCode} = params;
-        if(computeDate&&responsibilityCode){
-            const resp = await getMonthCostShareDataList({ ...params });
-            if (resp) {
-                return {
-                    data: resp.list,
-                    success: true,
-                    total: resp.totalCount,
-                    pageSize: resp.pageSize,
-                    totalPage: resp.totalPage,
-                }
-            }
-        }
-        return []
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData([record.id]);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
     }
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD' | 'COPY') => {
+    const result = {
+      date: computeDate.replace('-', ''),
+      shareParamCode: formVal.shareParamCode,
+      valueNum: formVal.valueNum,
+    };
 
-
-    const delTableData = async (record: any) => {
-        const resp = await delData([record.id]);
+    if (type == 'ADD') {
+      const resp = await addData({
+        ...result,
+        responsibilityCode:
+          formVal.responsibilityCode[formVal.responsibilityCode.length - 1],
+      });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      try {
+        const resp = await editData({
+          ...result,
+          id: formVal.id,
+          responsibilityCode:
+            typeof formVal.responsibilityCode == 'string'
+              ? formVal.responsibilityCode
+              : formVal.responsibilityCode[
+                  formVal.responsibilityCode.length - 1
+                ],
+        });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      } catch (error) {
+        console.log({ error });
+      }
     }
 
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
+    if (type == 'COPY') {
+      const { dataSourceType, toDate, date: fromDate } = formVal;
+      const resp = await copyMonthCostShareData({
+        dataSourceType,
+        toDate: moment(toDate).format('yyyyMM'),
+        fromDate: moment(fromDate).format('yyyyMM'),
+      });
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | "COPY") => {
-
-        const result = {
-            date: computeDate.replace('-', ''),
-            shareParamCode: formVal.shareParamCode,
-            valueNum: formVal.valueNum,
-        };
-
-        if (type == 'ADD') {
-            const resp = await addData({ ...result, responsibilityCode: formVal.responsibilityCode[formVal.responsibilityCode.length - 1] });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-
-        }
-        if (type == 'EDIT') {
-            try {
-                const resp = await editData({ ...result, id: formVal.id, responsibilityCode: typeof formVal.responsibilityCode == 'string' ? formVal.responsibilityCode : formVal.responsibilityCode[formVal.responsibilityCode.length - 1] });
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
-                }
-            } catch (error) {
-                console.log({ error });
-            }
-
-        }
-
-        if (type == 'COPY') {
-            const { dataSourceType, toDate, date: fromDate } = formVal;
-            const resp = await copyMonthCostShareData({ dataSourceType, toDate: moment(toDate).format('yyyyMM'), fromDate: moment(fromDate).format('yyyyMM') });
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-        }
-        return true;
-
+    return true;
+  };
+
+  const calculateHandle = async () => {
+    const resp = await calculateMonthCostShareData({
+      date: computeDate.replace('-', ''),
+    });
+    if (resp) {
+      message.success('计算成功!');
+      tableRef?.current?.reload();
     }
-
-    const calculateHandle = async () => {
-        const resp = await calculateMonthCostShareData({ date: computeDate.replace('-', '') });
-        if (resp) {
-            message.success('计算成功!');
-            tableRef?.current?.reload();
+  };
+
+  useEffect(() => {
+    if (date && responsibilityCode) {
+      set_computeDate(date);
+      set_tableDataFilterParams({
+        ...tableDataFilterParams,
+        computeDate: date,
+        responsibilityCode: responsibilityCode,
+      });
+    }
+  }, [date, responsibilityCode]);
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD' | 'COPY';
+  }) => {
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}成本分摊参数处理`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+              }
+            : {}
         }
-    };
-
-    useEffect(() => {
-        if (date&&responsibilityCode) {
-            set_computeDate(date);
-            set_tableDataFilterParams({
-                ...tableDataFilterParams,
-                computeDate: date,
-                responsibilityCode:responsibilityCode
-            });
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : type == 'COPY' ? (
+            <span>复制</span>
+          ) : (
+            <span>新增</span>
+          )
         }
-    }, [date,responsibilityCode])
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'COPY' }) => {
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}成本分摊参数处理`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record,
-                } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : type == 'COPY' ? <span>复制</span> : <span>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        {type == 'COPY' && (
+          <>
+            <ProFormDatePicker
+              name="date"
+              width={318}
+              rules={[
                 {
-                    type == 'COPY' && (
-                        <>
-                            <ProFormDatePicker
-                                name="date"
-                                width={318}
-                                rules={[
-                                    {
-                                        required: true,
-                                        message: '复制时间是必填项!',
-                                    },
-                                ]}
-                                label="复制数据年月"
-                                fieldProps={{ picker: 'month', locale: locale, format: 'YYYY-MM',autoComplete:'off' }}
-
-                            />
-                            <ProFormDatePicker
-                                name="toDate"
-                                width={318}
-                                label="目标年月"
-                                rules={[
-                                    {
-                                        required: true,
-                                        message: '目标时间是必填项!',
-                                    },
-                                ]}
-                                fieldProps={{ picker: 'month', locale: locale, format: 'YYYY-MM',autoComplete:'off' }}
-                            />
-                            <ProFormSelect
-                                options={[
-                                    {
-                                        value: 1,
-                                        label: '手动输入',
-                                    },
-                                    {
-                                        value: 2,
-                                        label: '文件导入',
-                                    },
-                                    {
-                                        value: 3,
-                                        label: '全部',
-                                    },
-                                ]}
-                                rules={[
-                                    {
-                                        required: true,
-                                        message: '数据类型是必填项!',
-                                    },
-                                ]}
-                                name="dataSourceType"
-                                label="数据类型"
-                            />
-                        </>
-                    )
+                  required: true,
+                  message: '复制时间是必填项!',
+                },
+              ]}
+              label="复制数据年月"
+              fieldProps={{
+                picker: 'month',
+                locale: locale,
+                format: 'YYYY-MM',
+                autoComplete: 'off',
+              }}
+            />
+            <ProFormDatePicker
+              name="toDate"
+              width={318}
+              label="目标年月"
+              rules={[
+                {
+                  required: true,
+                  message: '目标时间是必填项!',
+                },
+              ]}
+              fieldProps={{
+                picker: 'month',
+                locale: locale,
+                format: 'YYYY-MM',
+                autoComplete: 'off',
+              }}
+            />
+            <ProFormSelect
+              options={[
+                {
+                  value: 1,
+                  label: '手动输入',
+                },
+                {
+                  value: 2,
+                  label: '文件导入',
+                },
+                {
+                  value: 3,
+                  label: '全部',
+                },
+              ]}
+              rules={[
+                {
+                  required: true,
+                  message: '数据类型是必填项!',
+                },
+              ]}
+              name="dataSourceType"
+              label="数据类型"
+            />
+          </>
+        )}
+        {type != 'COPY' && (
+          <>
+            <ProFormSelect
+              name="shareParamCode"
+              label="选择分摊参数"
+              request={async (params) => {
+                const resp = await getCostshareparamList({
+                  ...params,
+                  pageSize: 500,
+                });
+                if (resp) {
+                  return resp.list.map((item: any) => ({
+                    label: item.shareParamName,
+                    value: item.shareParamCode,
+                  }));
                 }
+              }}
+              placeholder="请选择"
+              rules={[{ required: true, message: '分摊参数是必选项!' }]}
+            />
+            <ProFormCascader
+              label="责任中心"
+              name="responsibilityCode"
+              allowClear
+              placeholder="请选择"
+              request={async () => {
+                const resp = await getResponsibilityCenterList({
+                  pageSize: 500,
+                });
+                if (resp) {
+                  return resp.list;
+                }
+                return [];
+              }}
+              fieldProps={{
+                fieldNames: {
+                  label: 'responsibilityName',
+                  value: 'responsibilityCode',
+                  children: 'child',
+                },
+              }}
+            />
+            <ProFormDigit
+              label="数值"
+              name="valueNum"
+              rules={[
                 {
-                    type != 'COPY' && (
-                        <>
-                            <ProFormSelect
-                                name="shareParamCode"
-                                label="选择分摊参数"
-                                request={async (params) => {
-                                    const resp = await getCostshareparamList({ ...params, pageSize: 500 });
-                                    if (resp) {
-                                        return resp.list.map((item: any) => ({ label: item.shareParamName, value: item.shareParamCode }))
-                                    }
-                                }}
-                                placeholder="请选择"
-                                rules={[{ required: true, message: '分摊参数是必选项!' }]}
-                            />
-                            <ProFormCascader
-                                label='责任中心'
-                                name='responsibilityCode'
-                                allowClear
-                                placeholder="请选择"
-                                request={async () => {
-                                    const resp = await getResponsibilityCenterList({ pageSize: 500 });
-                                    if (resp) {
-                                        return resp.list
-                                    }
-                                    return [];
-                                }}
-                                fieldProps={{
-                                    fieldNames: { label: 'responsibilityName', value: 'responsibilityCode', children: 'child', },
-                                }}
-                            />
-                            <ProFormDigit
-                                label="数值"
-                                name="valueNum"
-                                rules={[
-                                    {
-                                        required: true,
-                                        message: '必选项!',
-                                    },
-                                ]}
-                            />
-                        </>
-                    )
+                  required: true,
+                  message: '必选项!',
+                },
+              ]}
+            />
+          </>
+        )}
+      </ModalForm>
+    );
+  };
+
+  return (
+    <KCIMPagecontainer className="CostAllocationParamsDeal" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'分摊参数代码/名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('shareParamCode')}
+                />
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    shareParamCode: '',
+                  });
                 }
-
-            </ModalForm>
-        )
-    }
-
-    return (
-        <KCIMPagecontainer className='CostAllocationParamsDeal' title={false}>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'分摊参数代码/名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('shareParamCode')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        shareParamCode: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    shareParamCode: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-            
-                </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='COPY' />
-                    <span onClick={() => calculateHandle()}>计算</span>
-                    <UpDataActBtn record type='ADD' />
-                    {
-                        (ifShowCancelBtn && ifShowGetBtn) && (
-                            <Dropdown menu={{ items }} placement="bottomRight">
-                                <IconFont type="icongengduochuizhi" />
-                            </Dropdown>
-                        )
-                    }
-                </div>
-            </div>
-
-            <div>
-                <KCIMTable scroll={{y:`calc(100vh - 343px)`}}  columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  shareParamCode: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="COPY" />
+          <span onClick={() => calculateHandle()}>计算</span>
+          <UpDataActBtn record type="ADD" />
+          {ifShowCancelBtn && ifShowGetBtn && (
+            <Dropdown menu={{ items }} placement="bottomRight">
+              <IconFont type="icongengduochuizhi" />
+            </Dropdown>
+          )}
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          scroll={{ y: `calc(100vh - 343px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 26 - 43
src/pages/baseSetting/costAllocationSet/costAllocationParamsDeal/service.ts

@@ -7,86 +7,69 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获月成本分摊参数值处理列表
-export const getMonthCostShareDataList = (params:any) => {
+export const getMonthCostShareDataList = (params: any) => {
   return request('/costAccount/shareParamValue/list', {
     method: 'GET',
-    params: {...params,date:params.computeDate.replace('-',''),computeDate:null},
+    params: {
+      ...params,
+      date: params.computeDate.replace('-', ''),
+      computeDate: null,
+    },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  date:string,
-  shareParamCode:string,
-  responsibilityCode:string,
-  valueNum:number
-}
+  date: string;
+  shareParamCode: string;
+  responsibilityCode: string;
+  valueNum: number;
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/shareParamValue/addData', {
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/shareParamValue/edit', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (ids:Key[]) => {
+export const delData = (ids: Key[]) => {
   return request('/costAccount/shareParamValue/delete', {
     method: 'POST',
-    data:ids
+    data: ids,
   });
 };
 
 //计算数据
-export const calculateMonthCostShareData = (params:any) => {
+export const calculateMonthCostShareData = (params: any) => {
   return request('/costAccount/shareParamValue/calcData', {
     method: 'POST',
-    params: {...params},
+    params: { ...params },
   });
-}
+};
 
 //复制数据
-export const copyMonthCostShareData = (body:any) => {
+export const copyMonthCostShareData = (body: any) => {
   return request('/costAccount/shareParamValue/copyData', {
     method: 'POST',
-    data: {...body},
+    data: { ...body },
   });
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+};

+ 9 - 11
src/pages/baseSetting/costAllocationSet/costAllocationParamsDeal/style.less

@@ -1,9 +1,8 @@
 .CostAllocationParamsDeal {
   // padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -31,35 +30,34 @@
         display: inline-block;
         font-size: 14px;
         font-weight: 400;
-        color: #FFFFFF;
+        color: #ffffff;
         line-height: 24px;
         padding: 0 14px;
-        background: #3377FF;
+        background: #3377ff;
         border-radius: 4px;
       }
 
-      &>span {
+      & > span {
         cursor: pointer;
         display: inline-block;
         font-size: 14px;
         font-weight: 400;
-        color: #17181A;
+        color: #17181a;
         line-height: 24px;
         padding: 0 14px;
-        background: #FAFCFF;
+        background: #fafcff;
         border-radius: 4px;
         margin-right: 8px;
         border-radius: 4px;
-        border: 1px solid #DAE2F2;
+        border: 1px solid #dae2f2;
 
         &:last-child {
           position: relative;
-          top:-2px;
+          top: -2px;
           padding: 0 4px;
           margin-right: 0;
-          
         }
       }
     }
   }
-}
+}

+ 341 - 282
src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/index.tsx

@@ -7,26 +7,33 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
-import { Input, message, Popconfirm, Modal,Switch,Tooltip } from 'antd';
+import { Input, message, Popconfirm, Modal, Switch, Tooltip } from 'antd';
 import { Key, useEffect, useRef, useState } from 'react';
 
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, delData, editData, getCostshareparamList, setAccountingSub } from './service';
+import {
+  addData,
+  delData,
+  editData,
+  getCostshareparamList,
+  setAccountingSub,
+} from './service';
 
 import './style.less';
 import React from 'react';
@@ -34,297 +41,349 @@ import TableTransfer from './transform';
 import { getAccountingSubjectList } from '../../accountingAccountSet/accountingSubMana/service';
 import { getNodesWithChildren } from '@/utils/tooljs';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 const transferTableColumn = [
+  {
+    title: '会计科目编码',
+    dataIndex: 'accountingCode',
+  },
+  {
+    title: '会计科目名称',
+    dataIndex: 'accountingName',
+  },
+];
+
+export default function CostAllocationParamsSet() {
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({});
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+
+  const columns: ProColumns[] = [
     {
-        title: '会计科目编码',
-        dataIndex: 'accountingCode',
+      title: '成本分摊参数名',
+      dataIndex: 'shareParamName',
     },
     {
-        title: '会计科目名称',
-        dataIndex: 'accountingName',
+      title: '成本分摊参数编号',
+      width: 160,
+      dataIndex: 'shareParamCode',
+      sorter: (a, b) => {
+        // 比较字符串数字部分大小
+        const codeA = parseInt(a.shareParamCode.slice(1), 10);
+        const codeB = parseInt(b.shareParamCode.slice(1), 10);
+        return codeA - codeB;
+      },
     },
-]
-
-export default function CostAllocationParamsSet() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({});
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    
-
-    const columns: ProColumns[] = [
-
-        {
-            title: '成本分摊参数名',
-            dataIndex: 'shareParamName',
-        },
-        {
-            title: '成本分摊参数编号',
-            width:160,
-            dataIndex: 'shareParamCode',
-            sorter: (a, b) => {
-                // 比较字符串数字部分大小
-                const codeA = parseInt(a.shareParamCode.slice(1), 10);
-                const codeB = parseInt(b.shareParamCode.slice(1), 10);
-                return codeA - codeB;
-            },
-        },
-        {
-            title: '计算方式',
-            dataIndex: 'calcType',
-            renderText(text, record) {
-                return text == 1 ? '手动填写' : '按对应会计科目计算'
-            },
-        },
-        {
-            title:()=><>启动<Tooltip title="停用的分摊参数在成本分摊报表里不显示"><IconFont style={{paddingLeft:6,fontSize:16,position:'relative',top:1}} type='iconshuoming' /></Tooltip></>,
-            dataIndex: 'status',
-            renderText(number, record) {
-                return <Switch checked={number} size='small' onChange={(bool)=>{
-                    updateTable({...record,status:bool?1:0},'EDIT');
-                }} />
-            },
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width:160,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                const {calcType} = record;
-                return calcType != 1?[
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                    <a key={'bind'} onClick={() => {oprnTableTransform(record)}}>会计科目</a>
-                ]:[
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ]
-            },
-        },
-
-    ]
-
-    
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getCostshareparamList({ ...params });
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        }
-        return []
+    {
+      title: '计算方式',
+      dataIndex: 'calcType',
+      renderText(text, record) {
+        return text == 1 ? '手动填写' : '按对应会计科目计算';
+      },
+    },
+    {
+      title: () => (
+        <>
+          启动
+          <Tooltip title="停用的分摊参数在成本分摊报表里不显示">
+            <IconFont
+              style={{
+                paddingLeft: 6,
+                fontSize: 16,
+                position: 'relative',
+                top: 1,
+              }}
+              type="iconshuoming"
+            />
+          </Tooltip>
+        </>
+      ),
+      dataIndex: 'status',
+      renderText(number, record) {
+        return (
+          <Switch
+            checked={number}
+            size="small"
+            onChange={(bool) => {
+              updateTable({ ...record, status: bool ? 1 : 0 }, 'EDIT');
+            }}
+          />
+        );
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 160,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        const { calcType } = record;
+        return calcType != 1
+          ? [
+              <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+              <Popconfirm
+                title="是否确认删除?"
+                key="del"
+                onConfirm={() => delTableData(record)}
+              >
+                <a>删除</a>
+              </Popconfirm>,
+              <a
+                key={'bind'}
+                onClick={() => {
+                  oprnTableTransform(record);
+                }}
+              >
+                会计科目
+              </a>,
+            ]
+          : [
+              <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+              <Popconfirm
+                title="是否确认删除?"
+                key="del"
+                onConfirm={() => delTableData(record)}
+              >
+                <a>删除</a>
+              </Popconfirm>,
+            ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getCostshareparamList({ ...params });
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
     }
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData([record.id]);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
+    }
+  };
 
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    if (type == 'ADD') {
+      const result = { ...formVal };
 
+      const resp = await addData(result);
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData([record.id]);
+    if (type == 'EDIT') {
+      try {
+        const resp = await editData({ ...formVal });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      } catch (error) {
+        console.log({ error });
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-
-        if (type == 'ADD') {
-            const result = { ...formVal };
-
-            const resp = await addData(result);
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}成本分摊参数`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+              }
+            : {}
         }
-        if (type == 'EDIT') {
-            try {
-                const resp = await editData({ ...formVal });
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
-                }
-            } catch (error) {
-                console.log({ error });
-            }
-
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-        return true;
-
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText
+          label="成本分摊参数名"
+          rules={[
+            {
+              required: true,
+              message: '成本分摊参数名是必填项',
+            },
+          ]}
+          name="shareParamName"
+        />
+        <ProFormText
+          label="成本分摊参数编号"
+          rules={[
+            {
+              required: true,
+              message: '成本分摊参数编号是必填项',
+            },
+          ]}
+          name="shareParamCode"
+        />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择计算方式',
+            },
+          ]}
+          options={[
+            {
+              value: 1,
+              label: '手动填写',
+            },
+            {
+              value: 2,
+              label: '按对应会计科目计算',
+            },
+          ]}
+          name="calcType"
+          label="计算方式"
+        />
+      </ModalForm>
+    );
+  };
+
+  const onSaveHandle = async (keys: Key[], rows: any[], record: any) => {
+    const { id } = record;
+    const resp = await setAccountingSub({
+      costShareParamId: id,
+      accountIds: keys,
+    });
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
     }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}成本分摊参数`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record,
-                } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormText
-                    label="成本分摊参数名"
-                    rules={[
-                        {
-                            required: true,
-                            message: '成本分摊参数名是必填项',
-                        },
-                    ]}
-                    name="shareParamName"
-                />
-                <ProFormText
-                    label="成本分摊参数编号"
-                    rules={[
-                        {
-                            required: true,
-                            message: '成本分摊参数编号是必填项',
-                        },
-                    ]}
-                    name="shareParamCode"
+  };
+
+  const oprnTableTransform = (record: any) => {
+    const ref = React.createRef<{ save: any }>();
+
+    Modal.confirm({
+      title: `选择会计科目`,
+      icon: <></>,
+      width: 750,
+      centered: true,
+      okText: '确定',
+      cancelText: '取消',
+      content: (
+        <TableTransfer
+          ref={ref}
+          keyName="id"
+          record={record}
+          onSave={(keys, rows) => onSaveHandle(keys, rows, record)}
+          leftColumns={transferTableColumn}
+          rightColumns={transferTableColumn}
+          dataSource={[]}
+        ></TableTransfer>
+      ),
+      onOk: () => {
+        return ref.current && ref.current.save();
+      },
+    });
+  };
+
+  return (
+    <KCIMPagecontainer className="CostAllocationParamsSet" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'成本分摊参数名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('name')}
                 />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择计算方式',
-                        },
-                    ]}
-                    options={[
-                        {
-                            value: 1,
-                            label: '手动填写',
-                        },
-                        {
-                            value: 2,
-                            label: '按对应会计科目计算',
-                        },
-                    ]}
-                    name="calcType"
-                    label="计算方式"
-                />
-            </ModalForm>
-        )
-    }
-
-    const onSaveHandle = async (keys:Key[],rows:any[],record:any) => {
-              const {id} = record;
-              const resp = await setAccountingSub({costShareParamId:id,accountIds:keys});
-              if(resp){
-                  message.success('操作成功!');
-                  tableRef.current?.reload();
               }
-
-    }
-
-
-    const oprnTableTransform = (record: any) => {
-
-        const ref = React.createRef<{ save: any; }>();
-
-        Modal.confirm({
-            title: `选择会计科目`,
-            icon: <></>,
-            width: 750,
-            centered: true,
-            okText: '确定',
-            cancelText: '取消',
-            content: <TableTransfer
-            ref={ref}
-            keyName="id"
-            record={record}
-            onSave={(keys,rows)=>onSaveHandle(keys,rows,record)}
-            leftColumns={transferTableColumn}
-            rightColumns={transferTableColumn} dataSource={[]}
-        ></TableTransfer>,
-            onOk: () => {
-                return ref.current && ref.current.save();
-            }
-        })
-    }
-
-
-    return (
-        <KCIMPagecontainer className='CostAllocationParamsSet' title={false}>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'成本分摊参数名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{color:'#99A6BF'}} onClick={() => tableDataSearchHandle('name')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        name: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    name: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
-                </div>
-            </div>
-
-            <div>
-                <KCIMTable scroll={{y:`calc(100vh - 234px)`}} columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    name: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  name: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          scroll={{ y: `calc(100vh - 234px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 27 - 45
src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/service.ts

@@ -7,81 +7,63 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获取table列表数据
-export const getCostshareparamList = (params:any) => {
+export const getCostshareparamList = (params: any) => {
   return request('/costAccount/costshareparam/list', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  shareParamName:string,
-  shareParamCode:string,
-  calcType:number
-}
+  shareParamName: string;
+  shareParamCode: string;
+  calcType: number;
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/costshareparam/save', {
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/costshareparam/update', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (ids:Key[]) => {
+export const delData = (ids: Key[]) => {
   return request('/costAccount/costshareparam/delete', {
     method: 'POST',
-    data:ids
+    data: ids,
   });
 };
 
-
-
 //为成本分摊设置会计科目
 type SetAccountingSubBody = {
-  costShareParamId:number,
-  accountIds:Key[]
-}
-export const setAccountingSub = (body:SetAccountingSubBody) => {
-  return request('/costAccount/costshareparam/updateCostShareParamByAccountId', {
-    method: 'POST',
-    data:{...body}
-  });
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
+  costShareParamId: number;
+  accountIds: Key[];
+};
+export const setAccountingSub = (body: SetAccountingSubBody) => {
+  return request(
+    '/costAccount/costshareparam/updateCostShareParamByAccountId',
+    {
+      method: 'POST',
+      data: { ...body },
+    },
+  );
+};

+ 12 - 13
src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/style.less

@@ -1,9 +1,8 @@
 .CostAllocationParamsSet {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -26,17 +25,17 @@
     }
 
     .btnGroup {
-        .add {
-          cursor: pointer;
-          display: inline-block;
-          font-size: 14px;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 24px;
-          padding: 0 14px;
-          background: #3377FF;
-          border-radius: 4px;
-        }
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377ff;
+        border-radius: 4px;
+      }
     }
   }
 }

+ 265 - 220
src/pages/baseSetting/costAllocationSet/costAllocationParamsSet/transform.tsx

@@ -1,281 +1,326 @@
-import React, { Key, useEffect, useImperativeHandle, useState } from "react";
+import React, { Key, useEffect, useImperativeHandle, useState } from 'react';
 import { Transfer } from 'antd';
 import { TransferItem, TransferProps } from 'antd/es/transfer';
-import { difference } from "lodash";
+import { difference } from 'lodash';
 import { TableRowSelection } from 'antd/es/table/interface';
-import { KCIMTable } from "@/components/KCIMTable";
-import { ProColumns } from "@ant-design/pro-components";
+import { KCIMTable } from '@/components/KCIMTable';
+import { ProColumns } from '@ant-design/pro-components';
 import { Tabs } from 'antd';
-import { getAccountingSubjectList } from "../../accountingAccountSet/accountingSubMana/service";
-
+import { getAccountingSubjectList } from '../../accountingAccountSet/accountingSubMana/service';
 
 function flatten(list: any[]) {
-    let result: any[] = [];
-    list.forEach(item => {
-        result.push(item);
-        if (item.children) {
-            result = result.concat(flatten(item.children));
-        }
-    });
-    return result;
+  let result: any[] = [];
+  list.forEach((item) => {
+    result.push(item);
+    if (item.children) {
+      result = result.concat(flatten(item.children));
+    }
+  });
+  return result;
 }
 
-
 function getUniqueSubsetsByProperty(treeData: any[], uniqueProperty: string) {
-    const result: any[] = [];
-    const uniqueSet = new Set();
-
-    function traverse(node: { [x: string]: any; children: string | any[]; }, isRoot = true) {
-        if (!node) return;
-
-        // 获取节点的唯一属性值
-        const uniqueValue = node[uniqueProperty];
-
-        // 如果节点是根节点,不添加到结果集,但处理它的子节点
-        if (!isRoot && !uniqueSet.has(uniqueValue)) {
-            result.push(node);
-            uniqueSet.add(uniqueValue);
-        }
-
-        // 递归处理子节点
-        if (node.children && node.children.length > 0) {
-            for (let child of node.children) {
-                traverse(child, false); // 子节点传递 isRoot = false
-            }
-        }
+  const result: any[] = [];
+  const uniqueSet = new Set();
+
+  function traverse(
+    node: { [x: string]: any; children: string | any[] },
+    isRoot = true,
+  ) {
+    if (!node) return;
+
+    // 获取节点的唯一属性值
+    const uniqueValue = node[uniqueProperty];
+
+    // 如果节点是根节点,不添加到结果集,但处理它的子节点
+    if (!isRoot && !uniqueSet.has(uniqueValue)) {
+      result.push(node);
+      uniqueSet.add(uniqueValue);
     }
 
-    for (let rootNode of treeData) {
-        traverse(rootNode);
+    // 递归处理子节点
+    if (node.children && node.children.length > 0) {
+      for (let child of node.children) {
+        traverse(child, false); // 子节点传递 isRoot = false
+      }
     }
+  }
 
-    return result;
-}
-
+  for (let rootNode of treeData) {
+    traverse(rootNode);
+  }
 
+  return result;
+}
 
 function removeSelectedKeys(nodes: any[], keysToRemove: string[]): any[] {
-    const result = nodes
-        .map(node => {
-            // 检查 id 是否存在
-            if (!node || node.id === undefined || node.id === null) {
-                return node; // 或者返回 null, 取决于你的业务逻辑
-            }
-
-            if (keysToRemove.includes(node.id)) {
-                return null;
-            }
-
-            if (node.children) {
-                node.children = removeSelectedKeys(node.children, keysToRemove);
-                if (node.children.length === 0) {
-                    return null;
-                }
-            }
+  const result = nodes
+    .map((node) => {
+      // 检查 id 是否存在
+      if (!node || node.id === undefined || node.id === null) {
+        return node; // 或者返回 null, 取决于你的业务逻辑
+      }
+
+      if (keysToRemove.includes(node.id)) {
+        return null;
+      }
+
+      if (node.children) {
+        node.children = removeSelectedKeys(node.children, keysToRemove);
+        if (node.children.length === 0) {
+          return null;
+        }
+      }
 
-            return node;
-        })
-        .filter(node => node !== null);
-    return result;
+      return node;
+    })
+    .filter((node) => node !== null);
+  return result;
 }
 
-
-
 interface TableTransferProps extends TransferProps<TransferItem> {
-    leftColumns: ProColumns[];
-    rightColumns: ProColumns[];
-    record: any,
-    keyName: string,
-    onSave: (selectedKeys: Key[], selectedRowKeys: any[]) => void;
+  leftColumns: ProColumns[];
+  rightColumns: ProColumns[];
+  record: any;
+  keyName: string;
+  onSave: (selectedKeys: Key[], selectedRowKeys: any[]) => void;
 }
 
-const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, keyName, record, onSave, ...restProps }: TableTransferProps, ref) => {
+const TableTransfer = React.forwardRef(
+  (
+    {
+      leftColumns,
+      rightColumns,
+      keyName,
+      record,
+      onSave,
+      ...restProps
+    }: TableTransferProps,
+    ref,
+  ) => {
     const [_data, _set_data] = useState<any>();
-    const [targetKeys, setTargetKeys] = useState<string[]>(record.accountingIds ? [...(record.accountingIds.map((a: string) => Number(a)))] : []);
+    const [targetKeys, setTargetKeys] = useState<string[]>(
+      record.accountingIds
+        ? [...record.accountingIds.map((a: string) => Number(a))]
+        : [],
+    );
     const [datasource, set_datasource] = useState<any[]>([]);
     const [filteredDataSource, setFilteredDataSource] = useState<any[]>([]);
-    const [selectedKeys, setSelectedKeys] = useState<string[]>(record.accountingIds ? [...(record.accountingIds.map((a: string) => Number(a)))] : []);
+    const [selectedKeys, setSelectedKeys] = useState<string[]>(
+      record.accountingIds
+        ? [...record.accountingIds.map((a: string) => Number(a))]
+        : [],
+    );
     const [accountType, set_accountType] = useState(1);
     const [tabs, set_tabs] = useState<any[]>([]);
 
     const getFuncList = async () => {
-        const resp = await getAccountingSubjectList({ accountType: 1, pageSize: 500, current: 1 });
-        if (resp) {
-            set_datasource(resp.list);
-            _set_data(resp.list);
-        }
+      const resp = await getAccountingSubjectList({
+        accountType: 1,
+        pageSize: 500,
+        current: 1,
+      });
+      if (resp) {
+        set_datasource(resp.list);
+        _set_data(resp.list);
+      }
     };
 
     const onChange = (nextTargetKeys: string[]) => {
-        setTargetKeys(nextTargetKeys);
-        const clonedDataSource = JSON.parse(JSON.stringify(datasource));
-        const filteredData = removeSelectedKeys(clonedDataSource, nextTargetKeys);
-        setFilteredDataSource(filteredData);
+      setTargetKeys(nextTargetKeys);
+      const clonedDataSource = JSON.parse(JSON.stringify(datasource));
+      const filteredData = removeSelectedKeys(clonedDataSource, nextTargetKeys);
+      setFilteredDataSource(filteredData);
     };
 
-    const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
-        setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+    const onSelectChange = (
+      sourceSelectedKeys: string[],
+      targetSelectedKeys: string[],
+    ) => {
+      setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
     };
 
     useEffect(() => {
-        // 过滤出左侧的待选项数据
-        const clonedDataSource = JSON.parse(JSON.stringify(datasource));
-        const filtered = removeSelectedKeys(clonedDataSource, targetKeys);
-        setFilteredDataSource(filtered);
+      // 过滤出左侧的待选项数据
+      const clonedDataSource = JSON.parse(JSON.stringify(datasource));
+      const filtered = removeSelectedKeys(clonedDataSource, targetKeys);
+      setFilteredDataSource(filtered);
     }, [datasource, targetKeys]);
 
     useImperativeHandle(ref, () => ({
-        save: async () => {
-            const items = flatten(datasource).filter(a => targetKeys.includes(a[`${keyName}`]));
-            onSave(targetKeys,getUniqueSubsetsByProperty(items,`${keyName}`));
-        }
+      save: async () => {
+        const items = flatten(datasource).filter((a) =>
+          targetKeys.includes(a[`${keyName}`]),
+        );
+        onSave(targetKeys, getUniqueSubsetsByProperty(items, `${keyName}`));
+      },
     }));
 
     const onTabChanged = (key: string) => {
-        set_accountType(Number(key));
+      set_accountType(Number(key));
     };
 
     const handleTreeItemSelect = (key: string, selected: boolean) => {
-        let newSelectedKeys = [...selectedKeys];
-        
-        const updateSelection = (node: TransferItem, isSelected: boolean) => {
-            const keyIndex = newSelectedKeys.indexOf(node[keyName]);
-            if (isSelected && keyIndex === -1) {
-                newSelectedKeys.push(node[keyName]);
-            } else if (!isSelected && keyIndex > -1) {
-                newSelectedKeys.splice(keyIndex, 1);
-            }
-    
-            if (node.children) {
-                node.children.forEach((child: any) => updateSelection(child, isSelected));
-            }
-        };
-    
-        const node = flatten(datasource).find(item => item[keyName] === key);
-    
-        if (node) {
-            updateSelection(node, selected);
+      let newSelectedKeys = [...selectedKeys];
+
+      const updateSelection = (node: TransferItem, isSelected: boolean) => {
+        const keyIndex = newSelectedKeys.indexOf(node[keyName]);
+        if (isSelected && keyIndex === -1) {
+          newSelectedKeys.push(node[keyName]);
+        } else if (!isSelected && keyIndex > -1) {
+          newSelectedKeys.splice(keyIndex, 1);
         }
-    
-        // 确保没有重复项
-        newSelectedKeys = Array.from(new Set(newSelectedKeys));
-        setSelectedKeys(newSelectedKeys);
+
+        if (node.children) {
+          node.children.forEach((child: any) =>
+            updateSelection(child, isSelected),
+          );
+        }
+      };
+
+      const node = flatten(datasource).find((item) => item[keyName] === key);
+
+      if (node) {
+        updateSelection(node, selected);
+      }
+
+      // 确保没有重复项
+      newSelectedKeys = Array.from(new Set(newSelectedKeys));
+      setSelectedKeys(newSelectedKeys);
     };
-    
-    
-    
 
     useEffect(() => {
-        getFuncList();
+      getFuncList();
     }, [accountType]);
 
     useEffect(() => {
-        set_tabs([
-            { label: '收入', key: 1 },
-            { label: '支出', key: 2 },
-        ]);
+      set_tabs([
+        { label: '收入', key: 1 },
+        { label: '支出', key: 2 },
+      ]);
     }, []);
 
     return (
-        <div>
-            <Tabs
-                defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
-                items={tabs}
-                onChange={(key) => onTabChanged(key)}
-            />
-            <Transfer
-                className='TableTransfer'
-                showSearch
-                titles={['待选项', '已选项']}
-                locale={{
-                    itemUnit: '项',
-                    itemsUnit: '项',
-                    searchPlaceholder: '请输入',
+      <div>
+        <Tabs
+          defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
+          items={tabs}
+          onChange={(key) => onTabChanged(key)}
+        />
+        <Transfer
+          className="TableTransfer"
+          showSearch
+          titles={['待选项', '已选项']}
+          locale={{
+            itemUnit: '项',
+            itemsUnit: '项',
+            searchPlaceholder: '请输入',
+          }}
+          oneWay={false}
+          onChange={onChange}
+          onSelectChange={onSelectChange}
+          dataSource={flatten(datasource)}
+          rowKey={(record) => record[`${keyName}`]}
+          targetKeys={targetKeys}
+          selectedKeys={selectedKeys}
+          filterOption={(inputValue, item) =>
+            item.accountingName.indexOf(inputValue) !== -1
+          }
+        >
+          {({
+            direction,
+            filteredItems,
+            onItemSelectAll,
+            onItemSelect,
+            selectedKeys: listSelectedKeys,
+            disabled: listDisabled,
+          }) => {
+            const columns = direction === 'left' ? leftColumns : rightColumns;
+
+            const rowSelection: TableRowSelection<TransferItem> = {
+              getCheckboxProps: (item) => ({
+                disabled: listDisabled || item.disabled,
+              }),
+              onSelectAll(selected, selectedRows) {
+                const treeSelectedKeys = selectedRows.map(
+                  (a) => a[`${keyName}`],
+                );
+                const diffKeys = selected
+                  ? difference(treeSelectedKeys, listSelectedKeys)
+                  : difference(listSelectedKeys, treeSelectedKeys);
+                onItemSelectAll(diffKeys as string[], selected);
+              },
+              onSelect(item, selected) {
+                onItemSelect(item[`${keyName}`], selected);
+                handleTreeItemSelect(item[`${keyName}`], selected);
+              },
+              selectedRowKeys: listSelectedKeys,
+            };
+
+            // 使用 filteredDataSource 作为数据源,确保左侧表格正确显示未选中的数据
+
+            const flattenAndFilter = (
+              list: any[],
+              targetKeys: string | any[],
+            ) => {
+              let result: any[] = [];
+              list.forEach((item: { [x: string]: any; children: any }) => {
+                if (targetKeys.includes(item[keyName])) {
+                  // 如果父节点已经选中,不再单独加入子节点
+                  result.push(item);
+                } else if (item.children) {
+                  // 递归处理子节点
+                  const filteredChildren = flattenAndFilter(
+                    item.children,
+                    targetKeys,
+                  );
+                  if (filteredChildren.length > 0) {
+                    result = result.concat(filteredChildren);
+                  }
+                }
+              });
+              return result;
+            };
+
+            const dataSourceToUse =
+              direction === 'left'
+                ? filteredDataSource // 左侧的未选中项
+                : flattenAndFilter(datasource, targetKeys); // 右侧的已选中项
+
+            return (
+              <KCIMTable
+                rowSelection={rowSelection}
+                columns={columns as TransferItem[]}
+                dataSource={dataSourceToUse}
+                size="small"
+                bordered={false}
+                rowKey={keyName}
+                scroll={{ y: 280 }}
+                pagination={{
+                  showTitle: false,
+                  pageSize: 9,
+                  showLessItems: false,
+                  simple: true,
+                  showTotal: () => false,
                 }}
-                oneWay={false}
-                onChange={onChange}
-                onSelectChange={onSelectChange}
-                dataSource={flatten(datasource)}
-                rowKey={record => record[`${keyName}`]}
-                targetKeys={targetKeys}
-                selectedKeys={selectedKeys}
-                filterOption={(inputValue, item) => item.accountingName.indexOf(inputValue) !== -1}
-            >
-                {({
-                    direction,
-                    filteredItems,
-                    onItemSelectAll,
-                    onItemSelect,
-                    selectedKeys: listSelectedKeys,
-                    disabled: listDisabled,
-                }) => {
-                    const columns = direction === 'left' ? leftColumns : rightColumns;
-
-                    const rowSelection: TableRowSelection<TransferItem> = {
-                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
-                        onSelectAll(selected, selectedRows) {
-                            const treeSelectedKeys = selectedRows.map(a => a[`${keyName}`]);
-                            const diffKeys = selected
-                                ? difference(treeSelectedKeys, listSelectedKeys)
-                                : difference(listSelectedKeys, treeSelectedKeys);
-                            onItemSelectAll(diffKeys as string[], selected);
-                        },
-                        onSelect(item, selected) {
-                            onItemSelect(item[`${keyName}`], selected);
-                            handleTreeItemSelect(item[`${keyName}`], selected);
-                        },
-                        selectedRowKeys: listSelectedKeys,
-                    };
-
-                    // 使用 filteredDataSource 作为数据源,确保左侧表格正确显示未选中的数据
-
-                    const flattenAndFilter = (list: any[], targetKeys: string | any[]) => {
-                        let result: any[] = [];
-                        list.forEach((item: { [x: string]: any; children: any; }) => {
-                            if (targetKeys.includes(item[keyName])) {
-                                // 如果父节点已经选中,不再单独加入子节点
-                                result.push(item);
-                            } else if (item.children) {
-                                // 递归处理子节点
-                                const filteredChildren = flattenAndFilter(item.children, targetKeys);
-                                if (filteredChildren.length > 0) {
-                                    result = result.concat(filteredChildren);
-                                }
-                            }
-                        });
-                        return result;
-                    };
-
-                    const dataSourceToUse = direction === 'left'
-                        ? filteredDataSource // 左侧的未选中项
-                        : flattenAndFilter(datasource, targetKeys); // 右侧的已选中项
-
-
-                    return (
-                        <KCIMTable
-                            rowSelection={rowSelection}
-                            columns={columns as TransferItem[]}
-                            dataSource={dataSourceToUse}
-                            size="small"
-                            bordered={false}
-                            rowKey={keyName}
-                            scroll={{ y: 280 }}
-                            pagination={{ showTitle: false, pageSize: 9, showLessItems: false, simple: true, showTotal: () => false }}
-                            tableAlertRender={false}
-                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
-                            onRow={(row) => ({
-                                onClick: () => {
-                                    const selected = !listSelectedKeys.includes(row[`${keyName}`]);
-                                    onItemSelect(row[`${keyName}`], selected);
-                                    handleTreeItemSelect(row[`${keyName}`], selected);
-                                },
-                            })}
-                        />
+                tableAlertRender={false}
+                style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+                onRow={(row) => ({
+                  onClick: () => {
+                    const selected = !listSelectedKeys.includes(
+                      row[`${keyName}`],
                     );
-                }}
-            </Transfer>
-        </div>
+                    onItemSelect(row[`${keyName}`], selected);
+                    handleTreeItemSelect(row[`${keyName}`], selected);
+                  },
+                })}
+              />
+            );
+          }}
+        </Transfer>
+      </div>
     );
-});
+  },
+);
 
 export default TableTransfer;

+ 360 - 326
src/pages/baseSetting/costAllocationSet/idleCostSetting/index.tsx

@@ -7,16 +7,20 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect, ProFormDigit } from '@ant-design/pro-components';
-import { ModalForm, ProFormCascader } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormText,
+  ProFormSelect,
+  ProFormDigit,
+} from '@ant-design/pro-components';
+import { ModalForm, ProFormCascader } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm, Form, Select } from 'antd';
 import { Key, useEffect, useRef, useState } from 'react';
@@ -24,205 +28,221 @@ import { Key, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, delData, editData, getAccountList, getIdleCostTableList, getIdleResponsibleList, getShareParamList } from './service';
+import {
+  addData,
+  delData,
+  editData,
+  getAccountList,
+  getIdleCostTableList,
+  getIdleResponsibleList,
+  getShareParamList,
+} from './service';
 
 import './style.less';
 import { getAccountingSubjectList } from '../../accountingAccountSet/accountingSubMana/service';
 import { getCostshareparamList } from '../costAllocationParamsSet/service';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-
 function filterTree(trees: any[]) {
-    // 递归筛选函数
-    function filterNode(node: any) {
-        // 如果是叶子节点,直接根据条件返回节点或null
-        if (!node.children || node.children.length === 0) {
-            return node.isBaseCost === 1 ? { ...node } : null;
-        }
-
-        // 对于非叶子节点,先递归筛选子节点
-        const filteredChildren = node.children.map(filterNode).filter((child: any) => child !== null);
+  // 递归筛选函数
+  function filterNode(node: any) {
+    // 如果是叶子节点,直接根据条件返回节点或null
+    if (!node.children || node.children.length === 0) {
+      return node.isBaseCost === 1 ? { ...node } : null;
+    }
 
-        // 如果子节点中有被保留的,或者当前节点自身满足条件,保留当前节点
-        // 注意这里的改变:我们不再检查非叶子节点是否直接满足条件,而是基于其子节点是否被保留
-        if (filteredChildren.length > 0) {
-            return { ...node, children: filteredChildren };
-        } else {
-            // 如果没有子节点被保留,且当前节点不满足条件,返回null
-            return null;
-        }
+    // 对于非叶子节点,先递归筛选子节点
+    const filteredChildren = node.children
+      .map(filterNode)
+      .filter((child: any) => child !== null);
+
+    // 如果子节点中有被保留的,或者当前节点自身满足条件,保留当前节点
+    // 注意这里的改变:我们不再检查非叶子节点是否直接满足条件,而是基于其子节点是否被保留
+    if (filteredChildren.length > 0) {
+      return { ...node, children: filteredChildren };
+    } else {
+      // 如果没有子节点被保留,且当前节点不满足条件,返回null
+      return null;
     }
+  }
 
-    // 遍历树结构集合并应用筛选函数
-    return trees.map(filterNode).filter(root => root !== null);
+  // 遍历树结构集合并应用筛选函数
+  return trees.map(filterNode).filter((root) => root !== null);
 }
 
-
-
-
-
 export default function IdleCostSetting() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ accountType: 1 });
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
-    const [selectableLevelList, setSelectableLevelList] = useState<any[]>([]);//可选的分摊层级列表
-
-    const columns: ProColumns[] = [
-
-        {
-            title: '闲置成本项目',
-            dataIndex: 'freeAccountName',
-        },
-        {
-            title: '设备成本项目',
-            dataIndex: 'accountName',
-        },
-        {
-            title: '可检查时间参数',
-            dataIndex: 'canParamName',
-        },
-        {
-            title: '实际检查时间参数',
-            dataIndex: 'actualParamName',
-        },
-        {
-            title: '归属责任中心',
-            dataIndex: 'freeResponsibilityName',
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 90,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getIdleCostTableList({ ...params });
-        if (resp) {
-            return {
-                data: resp,
-                success: true,
-                // total: resp.totalCount,
-                // pageSize: resp.pageSize,
-                // totalPage: resp.totalPage,
-            }
-        }
-        return []
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({ accountType: 1 });
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] =
+    useState<string>('');
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
+  const [selectableLevelList, setSelectableLevelList] = useState<any[]>([]); //可选的分摊层级列表
+
+  const columns: ProColumns[] = [
+    {
+      title: '闲置成本项目',
+      dataIndex: 'freeAccountName',
+    },
+    {
+      title: '设备成本项目',
+      dataIndex: 'accountName',
+    },
+    {
+      title: '可检查时间参数',
+      dataIndex: 'canParamName',
+    },
+    {
+      title: '实际检查时间参数',
+      dataIndex: 'actualParamName',
+    },
+    {
+      title: '归属责任中心',
+      dataIndex: 'freeResponsibilityName',
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 90,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return [
+          <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+          <Popconfirm
+            title="是否确认删除?"
+            key="del"
+            onConfirm={() => delTableData(record)}
+          >
+            <a>删除</a>
+          </Popconfirm>,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getIdleCostTableList({ ...params });
+    if (resp) {
+      return {
+        data: resp,
+        success: true,
+        // total: resp.totalCount,
+        // pageSize: resp.pageSize,
+        // totalPage: resp.totalPage,
+      };
     }
-
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData(record.id);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData(record.id);
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    const {
+      freeAccount = [],
+      account,
+      canParam,
+      actualParam,
+      freeResponsibility,
+    } = formVal;
+    const result = {
+      freeAccountCode: freeAccount.accountingCode,
+      freeAccountName: freeAccount.accountingName,
+      accountCode: account.accountingCode,
+      accountName: account.accountingName,
+      canParamCode: canParam.shareParamCode,
+      canParamName: canParam.shareParamName,
+      actualParamCode: actualParam.shareParamCode,
+      actualParamName: actualParam.shareParamName,
+      freeResponsibilityName: freeResponsibility.responsibilityName,
+      freeResponsibilityCode: freeResponsibility.responsibilityCode,
+    };
+
+    if (type == 'ADD') {
+      const resp = await addData(result);
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
+    }
+    if (type == 'EDIT') {
+      try {
+        const { id } = formVal;
+        const resp = await editData({ ...result, id });
         if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
+      } catch (error) {
+        console.log({ error });
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-    
-        const { freeAccount = [], account, canParam, actualParam,freeResponsibility } = formVal;
-            const result = {
-                freeAccountCode: freeAccount.accountingCode,
-                freeAccountName: freeAccount.accountingName,
-                accountCode: account.accountingCode,
-                accountName: account.accountingName,
-                canParamCode: canParam.shareParamCode,
-                canParamName: canParam.shareParamName,
-                actualParamCode: actualParam.shareParamCode,
-                actualParamName: actualParam.shareParamName,
-                freeResponsibilityName:freeResponsibility.responsibilityName,
-                freeResponsibilityCode:freeResponsibility.responsibilityCode,
-            };
-
-        if (type == 'ADD') {
-            const resp = await addData(result);
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
-
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    setCurrentRow(record);
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}闲置成本对应`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+                freeAccount: record.freeAccountCode,
+                account: record.accountCode,
+                canParam: record.canParamCode,
+                actualParam: record.actualParamCode,
+                freeResponsibility: record.freeResponsibilityCode,
+              }
+            : {}
         }
-        if (type == 'EDIT') {
-            try {
-                const { id } = formVal;
-                const resp = await editData({ ...result,id});
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
-                }
-            } catch (error) {
-                console.log({ error });
-            }
-
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-        return true;
-
-    }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-        setCurrentRow(record);
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}闲置成本对应`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record,
-                    freeAccount:record.freeAccountCode,
-                    account:record.accountCode,
-                    canParam: record.canParamCode,
-                    actualParam: record.actualParamCode,
-                    freeResponsibility:record.freeResponsibilityCode
-                } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
-                }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                {/* <ProFormText name='freeAccount' hidden />
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        {/* <ProFormText name='freeAccount' hidden />
                 <ProFormText name='account' hidden /> */}
-                {/* <ProFormCascader
+        {/* <ProFormCascader
                     rules={[
                         {
                             required: true,
@@ -267,150 +287,164 @@ export default function IdleCostSetting() {
                     name='equipmentCostItem'
                     label="设备成本项目"
                 /> */}
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择闲置成本项目',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getAccountList({ pageSize: 500, current: 1 });
-                        return resp
-                    }}
-
-                    fieldProps={{
-                        labelInValue: true,
-                        showSearch: true,
-                        fieldNames: { label: 'accountingName', value: 'accountingCode' },
-                    }}
-                    name="freeAccount"
-                    label="闲置成本项目"
-                />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择设备成本项目',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getAccountList({ pageSize: 500, current: 1 });
-                        return resp
-                    }}
-
-                    fieldProps={{
-                        labelInValue: true,
-                        showSearch: true,
-                        fieldNames: { label: 'accountingName', value: 'accountingCode' },
-                    }}
-                    name="account"
-                    label="设备成本项目"
-                />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择可检查时间参数',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getShareParamList({ pageSize: 500, current: 1 });
-                        return resp
-                    }}
-
-                    fieldProps={{
-                        labelInValue: true,
-                        showSearch: true,
-                        fieldNames: { label: 'shareParamName', value: 'shareParamCode' },
-                    }}
-                    name="canParam"
-                    label="可检查时间参数"
-                />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择实际检查时间参数',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getShareParamList({ pageSize: 500, current: 1 });
-                        return resp
-                    }}
-
-                    fieldProps={{
-                        labelInValue: true,
-                        showSearch: true,
-                        fieldNames: { label: 'shareParamName', value: 'shareParamCode' },
-                    }}
-                    name="actualParam"
-                    label="实际检查时间参数"
-                />
-                <ProFormSelect
-                    rules={[
-                        {
-                            required: true,
-                            message: '请选择归属责任中心',
-                        },
-                    ]}
-                    request={async () => {
-                        const resp = await getIdleResponsibleList({ pageSize: 500, current: 1 });
-                        return resp
-                    }}
-
-                    fieldProps={{
-                        labelInValue: true,
-                        showSearch: true,
-                        fieldNames: { label: 'responsibilityName', value: 'responsibilityCode' },
-                    }}
-                    name="freeResponsibility"
-                    label="归属责任中心"
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择闲置成本项目',
+            },
+          ]}
+          request={async () => {
+            const resp = await getAccountList({ pageSize: 500, current: 1 });
+            return resp;
+          }}
+          fieldProps={{
+            labelInValue: true,
+            showSearch: true,
+            fieldNames: { label: 'accountingName', value: 'accountingCode' },
+          }}
+          name="freeAccount"
+          label="闲置成本项目"
+        />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择设备成本项目',
+            },
+          ]}
+          request={async () => {
+            const resp = await getAccountList({ pageSize: 500, current: 1 });
+            return resp;
+          }}
+          fieldProps={{
+            labelInValue: true,
+            showSearch: true,
+            fieldNames: { label: 'accountingName', value: 'accountingCode' },
+          }}
+          name="account"
+          label="设备成本项目"
+        />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择可检查时间参数',
+            },
+          ]}
+          request={async () => {
+            const resp = await getShareParamList({ pageSize: 500, current: 1 });
+            return resp;
+          }}
+          fieldProps={{
+            labelInValue: true,
+            showSearch: true,
+            fieldNames: { label: 'shareParamName', value: 'shareParamCode' },
+          }}
+          name="canParam"
+          label="可检查时间参数"
+        />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择实际检查时间参数',
+            },
+          ]}
+          request={async () => {
+            const resp = await getShareParamList({ pageSize: 500, current: 1 });
+            return resp;
+          }}
+          fieldProps={{
+            labelInValue: true,
+            showSearch: true,
+            fieldNames: { label: 'shareParamName', value: 'shareParamCode' },
+          }}
+          name="actualParam"
+          label="实际检查时间参数"
+        />
+        <ProFormSelect
+          rules={[
+            {
+              required: true,
+              message: '请选择归属责任中心',
+            },
+          ]}
+          request={async () => {
+            const resp = await getIdleResponsibleList({
+              pageSize: 500,
+              current: 1,
+            });
+            return resp;
+          }}
+          fieldProps={{
+            labelInValue: true,
+            showSearch: true,
+            fieldNames: {
+              label: 'responsibilityName',
+              value: 'responsibilityCode',
+            },
+          }}
+          name="freeResponsibility"
+          label="归属责任中心"
+        />
+      </ModalForm>
+    );
+  };
+
+  return (
+    <KCIMPagecontainer className="IdleCostSetting" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'闲置成本项目编码/名称'}
+              allowClear
+              autoComplete="off"
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('filter')}
                 />
-
-            </ModalForm>
-        )
-    }
-
-
-    return (
-        <KCIMPagecontainer className='IdleCostSetting' title={false}>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                        <Input placeholder={'闲置成本项目编码/名称'} allowClear autoComplete='off'
-                            suffix={
-                                <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                            }
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        filter: ''
-                                    });
-                                }
-                            }}
-                            onPressEnter={(e) => {
-
-                                set_tableDataFilterParams({
-                                    ...tableDataFilterParams,
-                                    filter: (e.target as HTMLInputElement).value
-                                });
-                            }}
-
-                        />
-                    </div>
-                </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
-                </div>
-            </div>
-
-            <div>
-                <KCIMTable scroll={{y:`calc(100vh - 234px)`}} columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    filter: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  filter: (e.target as HTMLInputElement).value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          scroll={{ y: `calc(100vh - 234px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 29 - 50
src/pages/baseSetting/costAllocationSet/idleCostSetting/service.ts

@@ -7,98 +7,77 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获取table列表数据
-export const getIdleCostTableList = (params:any) => {
+export const getIdleCostTableList = (params: any) => {
   return request('/costAccount/freeCost/getList', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
+};
 
 //获取会计科目
-export const getAccountList = (params:any) => {
+export const getAccountList = (params: any) => {
   return request('/costAccount/freeCost/getAccountList', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
+};
 
 //获取分摊参数
-export const getShareParamList = (params:any) => {
+export const getShareParamList = (params: any) => {
   return request('/costAccount/freeCost/getShareParamList', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
+};
 
 //获取闲置责任中心
-export const getIdleResponsibleList = (params:any) => {
+export const getIdleResponsibleList = (params: any) => {
   return request('/costAccount/freeCost/getResponsibilityList', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  "freeAccountCode":string, //闲置成本代码
-  "freeAccountName":string, //闲置成本名称
-  "accountCode":string, //成本代码
-  "accountName": string, //成本名称
-  "canParamCode": string, //可检查时间参数代码
-  "canParamName":string, //可检查时间参数名称
-  "actualParamCode": string, //实际检查时间参数代码
-  "actualParamName": string //实际检查时间参数名称
-}
+  freeAccountCode: string; //闲置成本代码
+  freeAccountName: string; //闲置成本名称
+  accountCode: string; //成本代码
+  accountName: string; //成本名称
+  canParamCode: string; //可检查时间参数代码
+  canParamName: string; //可检查时间参数名称
+  actualParamCode: string; //实际检查时间参数代码
+  actualParamName: string; //实际检查时间参数名称
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/freeCost/addFreeCost', {
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/freeCost/editFreeCost', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (id:number) => {
+export const delData = (id: number) => {
   return request('/costAccount/freeCost/deleteFreeCost', {
     method: 'POST',
-    params:{id}
+    params: { id },
   });
 };
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+ 12 - 13
src/pages/baseSetting/costAllocationSet/idleCostSetting/style.less

@@ -1,9 +1,8 @@
 .IdleCostSetting {
   padding: 16px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -26,17 +25,17 @@
     }
 
     .btnGroup {
-        .add {
-          cursor: pointer;
-          display: inline-block;
-          font-size: 14px;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 24px;
-          padding: 0 14px;
-          background: #3377FF;
-          border-radius: 4px;
-        }
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377ff;
+        border-radius: 4px;
+      }
     }
   }
 }

+ 376 - 327
src/pages/baseSetting/costAllocationSet/revenueImputationSet/index.tsx

@@ -7,16 +7,19 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
-import { ActionType, ProFormDependency, ProFormInstance, ProFormSelect, ProFormDigit } from '@ant-design/pro-components';
-import { ModalForm, ProFormCascader } from '@ant-design/pro-form'
+import {
+  ActionType,
+  ProFormDependency,
+  ProFormInstance,
+  ProFormSelect,
+  ProFormDigit,
+} from '@ant-design/pro-components';
+import { ModalForm, ProFormCascader } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
 import { message, Popconfirm, Modal } from 'antd';
 import { Key, useEffect, useRef, useState } from 'react';
@@ -24,348 +27,394 @@ import { Key, useEffect, useRef, useState } from 'react';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, delData, editData, getIncomeCollectionList, incomeCollectionListConnectAccountingSubject } from './service';
+import {
+  addData,
+  delData,
+  editData,
+  getIncomeCollectionList,
+  incomeCollectionListConnectAccountingSubject,
+} from './service';
 
 import './style.less';
 import { getResponsibilityCenterList } from '../../responsibilityCenterSet/responsibilityCenter/service';
 import TableTransfer from './transform';
 import React from 'react';
 
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
 const transferTableColumn = [
+  {
+    title: '会计科目编码',
+    dataIndex: 'accountingCode',
+    ellipsis: true,
+  },
+  {
+    title: '会计科目名',
+    dataIndex: 'accountingName',
+    ellipsis: true,
+  },
+];
+
+export default function AccountingSubMana() {
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
+
+  const columns: ProColumns[] = [
     {
-        title: '会计科目编码',
-        dataIndex: 'accountingCode',
-        ellipsis: true,
+      title: '收入归集Id',
+      dataIndex: 'id',
     },
     {
-        title: '会计科目名',
-        dataIndex: 'accountingName',
-        ellipsis: true,
+      title: '开单科室状态',
+      dataIndex: 'openDepartmentStatus',
+      renderText(num) {
+        return num == 1 ? '收益中心' : '成本中心';
+      },
     },
-]
-
-export default function AccountingSubMana() {
-
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [currentRow, setCurrentRow] = useState<any | undefined>(undefined);
-
-    const columns: ProColumns[] = [
-
-        {
-            title: '收入归集Id',
-            dataIndex: 'id',
-        },
-        {
-            title: '开单科室状态',
-            dataIndex: 'openDepartmentStatus',
-            renderText(num) {
-                return num == 1 ? '收益中心' : '成本中心'
-            },
-        },
-        {
-            title: '开单科室分配比例',
-            align:'right',
-            dataIndex: 'openDepartmentProportion',
-        },
-        {
-            title: '执行科室',
-            dataIndex: 'startDepartmentStatus',
-            renderText(num) {
-                return num == 1 ? '收益中心' : '成本中心'
-            },
-        },
-        {
-            title: '执行科室比例',
-            align:'right',
-            dataIndex: 'startDepartmentProportion',
-        },
-        {
-            title: '归集到其他责任中心',
-            dataIndex: 'responsibilityName',
-            ellipsis: true,
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 200,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                const { accountStatus } = record;
-                return accountStatus == 0 ? [
-                    <UpDataActBtn key={'edit'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ] : [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>,
-                    <a key='ather' onClick={() => { oprnTableTransform(record); }}>排除会计科目</a>
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getIncomeCollectionList(params);
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        }
-        return []
+    {
+      title: '开单科室分配比例',
+      align: 'right',
+      dataIndex: 'openDepartmentProportion',
+    },
+    {
+      title: '执行科室',
+      dataIndex: 'startDepartmentStatus',
+      renderText(num) {
+        return num == 1 ? '收益中心' : '成本中心';
+      },
+    },
+    {
+      title: '执行科室比例',
+      align: 'right',
+      dataIndex: 'startDepartmentProportion',
+    },
+    {
+      title: '归集到其他责任中心',
+      dataIndex: 'responsibilityName',
+      ellipsis: true,
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 200,
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        const { accountStatus } = record;
+        return accountStatus == 0
+          ? [
+              <UpDataActBtn key={'edit'} record={record} type="EDIT" />,
+              <Popconfirm
+                title="是否确认删除?"
+                key="del"
+                onConfirm={() => delTableData(record)}
+              >
+                <a>删除</a>
+              </Popconfirm>,
+            ]
+          : [
+              <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+              <Popconfirm
+                title="是否确认删除?"
+                key="del"
+                onConfirm={() => delTableData(record)}
+              >
+                <a>删除</a>
+              </Popconfirm>,
+              <a
+                key="ather"
+                onClick={() => {
+                  oprnTableTransform(record);
+                }}
+              >
+                排除会计科目
+              </a>,
+            ];
+      },
+    },
+  ];
+
+  const getTableData = async (params: any) => {
+    const resp = await getIncomeCollectionList(params);
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+        pageSize: resp.pageSize,
+        totalPage: resp.totalPage,
+      };
     }
-
-    const delTableData = async (record: any) => {
-        const resp = await delData([record.id]);
-        if (resp) {
-            message.success('操作成功!');
-            tableRef.current?.reload();
-            // message.success('操作成功!');
-        }
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData([record.id]);
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
+      // message.success('操作成功!');
     }
-
-    const oprnTableTransform = (record: any) => {
-
-        const ref = React.createRef<{ save: any; }>();
-
-        Modal.confirm({
-            title: `排除会计科目`,
-            icon: <></>,
-            width: 750,
-            centered: true,
-            okText: '确定',
-            cancelText: '取消',
-            content: <TableTransfer
-                ref={ref}
-                keyName="accountingCode"
-                record={record}
-                onSave={(keys, rows) => onSaveHandle(keys, rows, record)}
-                leftColumns={transferTableColumn}
-                rightColumns={transferTableColumn} dataSource={[]}
-            ></TableTransfer>,
-            onOk: () => {
-                return ref.current && ref.current.save();
-            }
-        })
+  };
+
+  const oprnTableTransform = (record: any) => {
+    const ref = React.createRef<{ save: any }>();
+
+    Modal.confirm({
+      title: `排除会计科目`,
+      icon: <></>,
+      width: 750,
+      centered: true,
+      okText: '确定',
+      cancelText: '取消',
+      content: (
+        <TableTransfer
+          ref={ref}
+          keyName="accountingCode"
+          record={record}
+          onSave={(keys, rows) => onSaveHandle(keys, rows, record)}
+          leftColumns={transferTableColumn}
+          rightColumns={transferTableColumn}
+          dataSource={[]}
+        ></TableTransfer>
+      ),
+      onOk: () => {
+        return ref.current && ref.current.save();
+      },
+    });
+  };
+
+  const onSaveHandle = async (keys: Key[], rows: any[], record: any) => {
+    const { id } = record;
+    const resp = await incomeCollectionListConnectAccountingSubject({
+      id,
+      accountCodes: keys,
+    });
+    if (resp) {
+      message.success('操作成功!');
+      tableRef.current?.reload();
     }
-
-    const onSaveHandle = async (keys: Key[], rows: any[], record: any) => {
-    
-        const { id } = record;
-        const resp = await incomeCollectionListConnectAccountingSubject({ id, accountCodes: keys });
-        if(resp){
-               message.success('操作成功!');
-               tableRef.current?.reload();
-        }
-
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    const { openDepartmentProportion, startDepartmentProportion } = formVal;
+    const result = {
+      ...formVal,
+      responsibilityCodes: formVal.responsibilityCodes
+        ? formVal.responsibilityCodes.join('/')
+        : null,
+      startDepartmentProportion: startDepartmentProportion
+        ? startDepartmentProportion
+        : 0,
+      openDepartmentProportion: openDepartmentProportion
+        ? openDepartmentProportion
+        : 0,
+    };
+
+    if (type == 'ADD') {
+      const resp = await addData(result);
+      if (resp) {
+        tableRef.current?.reload();
+        message.success('操作成功!');
+      }
     }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-
-        const { openDepartmentProportion, startDepartmentProportion } = formVal;
-        const result = {
-            ...formVal,
-            responsibilityCodes: formVal.responsibilityCodes ? formVal.responsibilityCodes.join('/') : null,
-            startDepartmentProportion: startDepartmentProportion ? startDepartmentProportion : 0,
-            openDepartmentProportion: openDepartmentProportion ? openDepartmentProportion : 0
+    if (type == 'EDIT') {
+      try {
+        const resp = await editData(result);
+        if (resp) {
+          tableRef.current?.reload();
+          message.success('操作成功!');
         }
-
-        if (type == 'ADD') {
-            const resp = await addData(result);
-            if (resp) {
-                tableRef.current?.reload();
-                message.success('操作成功!');
-            }
+      } catch (error) {
+        console.log({ error });
+      }
+    }
+    return true;
+  };
+
+  const UpDataActBtn = ({
+    record,
+    type,
+  }: {
+    record: any;
+    type: 'EDIT' | 'ADD';
+  }) => {
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : '新增'}收入归集设置`}
+        width={350}
+        formRef={formRef}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+                responsibilityCodes: record.responsibilityCodes
+                  ? record.responsibilityCodes.split('/')
+                  : [],
+              }
+            : {}
         }
-        if (type == 'EDIT') {
-            try {
-                const resp = await editData(result);
-                if (resp) {
-                    tableRef.current?.reload();
-                    message.success('操作成功!');
-                }
-            } catch (error) {
-                console.log({ error });
-            }
-
+        trigger={
+          type == 'EDIT' ? (
+            <a key="edit">编辑</a>
+          ) : (
+            <span className="add">新增</span>
+          )
         }
-        return true;
-
-    }
-
-
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-        return (
-            <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}收入归集设置`}
-                width={350}
-                formRef={formRef}
-                initialValues={type == 'EDIT' ? {
-                    ...record, responsibilityCodes: record.responsibilityCodes ? record.responsibilityCodes.split('/') : []
-                } : {}}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
+        onFinish={(val) => {
+          return updateTable(
+            type == 'EDIT' ? { ...record, ...val } : { ...val },
+            type,
+          );
+        }}
+        modalProps={{ destroyOnClose: true }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormSelect
+          name="openDepartmentStatus"
+          label="开单科室状态"
+          options={[
+            { label: '收益中心', value: 1 },
+            { label: '成本中心', value: 2 },
+          ]}
+          placeholder="请选择状态"
+          rules={[{ required: true, message: '请选择开单科室状态!' }]}
+        />
+        <ProFormDependency name={['openDepartmentStatus']}>
+          {({ openDepartmentStatus }) => {
+            return openDepartmentStatus == 2 ? (
+              <ProFormDigit
+                disabled
+                label="开单科室比例"
+                initialValue={0}
+                rules={[
+                  {
+                    required: false,
+                    message: '开单科室比例是必填项!',
+                  },
+                ]}
+                name="openDepartmentProportion"
+              />
+            ) : (
+              <ProFormDigit
+                label="开单科室比例"
+                rules={[
+                  {
+                    required: true,
+                    message: '开单科室比例是必填项!',
+                  },
+                ]}
+                name="openDepartmentProportion"
+              />
+            );
+          }}
+        </ProFormDependency>
+        <ProFormSelect
+          name="startDepartmentStatus"
+          label="执行科室状态"
+          options={[
+            { label: '收益中心', value: 1 },
+            { label: '成本中心', value: 2 },
+          ]}
+          placeholder="请选择状态"
+          rules={[{ required: true, message: '请选择执行科室状态!' }]}
+        />
+        <ProFormDependency name={['startDepartmentStatus']}>
+          {({ startDepartmentStatus }) => {
+            return startDepartmentStatus == 2 ? (
+              <ProFormDigit
+                disabled
+                label="执行科室比例"
+                initialValue={0}
+                rules={[
+                  {
+                    required: false,
+                    message: '执行科室比例是必填项!',
+                  },
+                ]}
+                name="startDepartmentProportion"
+              />
+            ) : (
+              <ProFormDigit
+                label="执行科室比例"
+                rules={[
+                  {
+                    required: true,
+                    message: '执行科室比例是必填项!',
+                  },
+                ]}
+                name="startDepartmentProportion"
+              />
+            );
+          }}
+        </ProFormDependency>
+        <ProFormDependency
+          name={['openDepartmentStatus', 'startDepartmentStatus']}
+        >
+          {({ openDepartmentStatus, startDepartmentStatus }) => {
+            return openDepartmentStatus == 2 && startDepartmentStatus == 2 ? (
+              <ProFormCascader
+                placeholder={'请选择'}
+                label="选择责任中心:"
+                name="responsibilityCodes"
+                fieldProps={{
+                  fieldNames: {
+                    label: 'responsibilityName',
+                    value: 'responsibilityCode',
+                    children: 'child',
+                  },
+                  onChange: (val: any) => {},
                 }}
-                modalProps={{ destroyOnClose: true }}
-                colProps={{ span: 24 }}
-                grid
-            >
-                <ProFormSelect
-                    name="openDepartmentStatus"
-                    label="开单科室状态"
-                    options={[
-                        { label: '收益中心', value: 1 },
-                        { label: '成本中心', value: 2 }
-                    ]}
-                    placeholder="请选择状态"
-                    rules={[{ required: true, message: '请选择开单科室状态!' }]}
-                />
-                <ProFormDependency name={['openDepartmentStatus']}>
-                    {
-                        ({ openDepartmentStatus }) => {
-
-                            return openDepartmentStatus == 2 ? (
-                                <ProFormDigit
-                                    disabled
-                                    label="开单科室比例"
-                                    initialValue={0}
-                                    rules={[
-                                        {
-                                            required: false,
-                                            message: '开单科室比例是必填项!',
-                                        },
-                                    ]}
-                                    name="openDepartmentProportion"
-                                />
-                            ) : (
-                                <ProFormDigit
-                                    label="开单科室比例"
-                                    rules={[
-                                        {
-                                            required: true,
-                                            message: '开单科室比例是必填项!',
-                                        },
-                                    ]}
-                                    name="openDepartmentProportion"
-                                />
-                            )
-                        }
-                    }
-                </ProFormDependency>
-                <ProFormSelect
-                    name="startDepartmentStatus"
-                    label="执行科室状态"
-                    options={[
-                        { label: '收益中心', value: 1 },
-                        { label: '成本中心', value: 2 }
-                    ]}
-                    placeholder="请选择状态"
-                    rules={[{ required: true, message: '请选择执行科室状态!' }]}
-                />
-                <ProFormDependency name={['startDepartmentStatus']}>
-                    {
-                        ({ startDepartmentStatus }) => {
-                            return startDepartmentStatus == 2 ? (
-                                <ProFormDigit
-                                    disabled
-                                    label="执行科室比例"
-                                    initialValue={0}
-                                    rules={[
-                                        {
-                                            required: false,
-                                            message: '执行科室比例是必填项!',
-                                        },
-                                    ]}
-                                    name="startDepartmentProportion"
-                                />
-                            ) : (
-                                <ProFormDigit
-                                    label="执行科室比例"
-                                    rules={[
-                                        {
-                                            required: true,
-                                            message: '执行科室比例是必填项!',
-                                        },
-                                    ]}
-                                    name="startDepartmentProportion"
-                                />
-                            )
-                        }
-                    }
-                </ProFormDependency>
-                <ProFormDependency name={['openDepartmentStatus', 'startDepartmentStatus']}>
-                    {({ openDepartmentStatus, startDepartmentStatus }) => {
-
-                        return (openDepartmentStatus == 2 && startDepartmentStatus == 2) ? (
-                            <ProFormCascader
-                                placeholder={'请选择'}
-                                label='选择责任中心:'
-                                name='responsibilityCodes'
-                                fieldProps={{
-                                    fieldNames: { label: 'responsibilityName', value: 'responsibilityCode', children: 'child' },
-                                    onChange: (val: any) => {
-
-                                    }
-                                }}
-                                request={async () => {
-                                    const resp = await getResponsibilityCenterList({ pageSize: 50, current: 1 });
-                                    if (resp) {
-                                        return resp.list
-                                    }
-                                }}
-
-                            />
-                        ) : <></>
-                    }}
-                </ProFormDependency>
-            </ModalForm>
-        )
-    }
-
-    useEffect(() => {
-
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='AccountingSubMana' title={false}>
-            <div className='toolBar' style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
-                <div className='title'>收入归集设置</div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
-                </div>
-            </div>
-
-            <div>
-                <KCIMTable scroll={{y:`calc(100vh - 234px)`}} columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' request={(params) => getTableData(params)} />
-            </div>
-        </KCIMPagecontainer>
-    )
+                request={async () => {
+                  const resp = await getResponsibilityCenterList({
+                    pageSize: 50,
+                    current: 1,
+                  });
+                  if (resp) {
+                    return resp.list;
+                  }
+                }}
+              />
+            ) : (
+              <></>
+            );
+          }}
+        </ProFormDependency>
+      </ModalForm>
+    );
+  };
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="AccountingSubMana" title={false}>
+      <div
+        className="toolBar"
+        style={{
+          display: 'flex',
+          flexDirection: 'row',
+          justifyContent: 'space-between',
+          alignItems: 'center',
+        }}
+      >
+        <div className="title">收入归集设置</div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+
+      <div>
+        <KCIMTable
+          scroll={{ y: `calc(100vh - 234px)` }}
+          columns={columns as ProColumns[]}
+          actionRef={tableRef}
+          rowKey="id"
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
 }

+ 21 - 42
src/pages/baseSetting/costAllocationSet/revenueImputationSet/service.ts

@@ -7,86 +7,65 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获收入归集列表
-export async function getIncomeCollectionList(params:any) {
+export async function getIncomeCollectionList(params: any) {
   return request('/costAccount/costincomegroupset/list', {
     method: 'GET',
-    params: {...params},
+    params: { ...params },
   });
 }
 
 //获指定收入归集设置对应的会计科目
-export const getIncomeCollectionListHasConnected = (params:any) => {
-
+export const getIncomeCollectionListHasConnected = (params: any) => {
   return request('/costAccount/costincomegroupset/getIncomeAccountStatus', {
     method: 'GET',
-    params: {...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  openDepartmentStatus:number,
-  responsibilityCodes:string,
-  startDepartmentProportion:number,
-  startDepartmentStatus:number
-}
+  openDepartmentStatus: number;
+  responsibilityCodes: string;
+  startDepartmentProportion: number;
+  startDepartmentStatus: number;
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/costincomegroupset/addCostIncomeGroupSet', {
     method: 'POST',
-    data: {...data},
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/costincomegroupset/update', {
     method: 'POST',
-    data: {...data},
+    data: { ...data },
   });
 };
 
 //删除表格操作
-export const delData = (ids:Key[]) => {
+export const delData = (ids: Key[]) => {
   return request(`/costAccount/costincomegroupset/delete`, {
-    data:ids,
+    data: ids,
     method: 'POST',
   });
 };
 
 //收入归集设置添加会计科目
-export const incomeCollectionListConnectAccountingSubject = (data:any) => {
+export const incomeCollectionListConnectAccountingSubject = (data: any) => {
   return request(`/costAccount/costincomegroupset/addIncomeAccount`, {
-    data:data,
+    data: data,
     method: 'POST',
   });
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+};

+ 5 - 6
src/pages/baseSetting/costAllocationSet/revenueImputationSet/style.less

@@ -1,10 +1,9 @@
 .AccountingSubMana {
   padding: 16px;
   padding-top: 0;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
-
   .toolBar {
     display: flex;
     flex-direction: row;
@@ -15,7 +14,7 @@
     .title {
       font-size: 16px;
       font-weight: 500;
-      color: #17181A;
+      color: #17181a;
     }
 
     .btnGroup {
@@ -24,12 +23,12 @@
         display: inline-block;
         font-size: 14px;
         font-weight: 400;
-        color: #FFFFFF;
+        color: #ffffff;
         line-height: 24px;
         padding: 0 14px;
-        background: #3377FF;
+        background: #3377ff;
         border-radius: 4px;
       }
     }
   }
-}
+}

+ 150 - 123
src/pages/baseSetting/costAllocationSet/revenueImputationSet/transform.tsx

@@ -1,29 +1,37 @@
-import React, { Key, useEffect, useImperativeHandle, useState } from "react";
-import { Transfer } from 'antd'
+import React, { Key, useEffect, useImperativeHandle, useState } from 'react';
+import { Transfer } from 'antd';
 import { TransferItem, TransferProps } from 'antd/es/transfer';
 import { ColumnsType } from 'antd/es/table';
-import { difference } from "lodash";
+import { difference } from 'lodash';
 import { TableRowSelection } from 'antd/es/table/interface';
-import { KCIMTable } from "@/components/KCIMTable";
-import { ProColumns } from "@ant-design/pro-components";
-import { Tabs} from 'antd';
-
-import { log } from "mathjs";
-import { getAccountingSubjectList } from "../../accountingAccountSet/accountingSubMana/service";
-import { getIncomeCollectionListHasConnected } from "./service";
-
+import { KCIMTable } from '@/components/KCIMTable';
+import { ProColumns } from '@ant-design/pro-components';
+import { Tabs } from 'antd';
 
+import { log } from 'mathjs';
+import { getAccountingSubjectList } from '../../accountingAccountSet/accountingSubMana/service';
+import { getIncomeCollectionListHasConnected } from './service';
 
 interface TableTransferProps extends TransferProps<TransferItem> {
-    leftColumns: ProColumns[];
-    rightColumns: ProColumns[];
-    record: any,
-    keyName: string,
-    onSave: (selectedKeys: Key[], selectedRowKeys: any[]) => void;
+  leftColumns: ProColumns[];
+  rightColumns: ProColumns[];
+  record: any;
+  keyName: string;
+  onSave: (selectedKeys: Key[], selectedRowKeys: any[]) => void;
 }
 
-const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, keyName, record, onSave, ...restProps }: TableTransferProps, ref) => {
-    
+const TableTransfer = React.forwardRef(
+  (
+    {
+      leftColumns,
+      rightColumns,
+      keyName,
+      record,
+      onSave,
+      ...restProps
+    }: TableTransferProps,
+    ref,
+  ) => {
     const [_data, _set_data] = useState<any>();
     const [targetKeys, setTargetKeys] = useState<string[]>([]);
     const [datasource, set_datasource] = useState<any[]>([]);
@@ -31,125 +39,144 @@ const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, keyName, re
 
     //获取列表
     const getFuncList = async () => {
+      const { id } = record;
+      const resp = await getAccountingSubjectList({
+        accountType: 1,
+        shareParamId: id,
+        pageSize: 500,
+        current: 1,
+      });
+
+      if (resp) {
+        set_datasource(resp.list);
+        _set_data(resp.list);
+        // setTargetKeys(accountingIds);
+      }
+    };
 
-        const {id } = record;
-        const resp = await getAccountingSubjectList({ accountType:1, shareParamId: id, pageSize: 500, current: 1 });
-
-        if (resp) {
-
-            set_datasource(resp.list);
-            _set_data(resp.list);
-            // setTargetKeys(accountingIds);
-        }
-
-    }
-
-    const setInit = async ()=>{
-        const {id} = record;
-        const resp = await getIncomeCollectionListHasConnected({id});
-        if(resp){
-           const tempArr = resp?resp.map((item:any)=>item.accountingCode):[];
-           setTargetKeys([...tempArr]);
-        }
+    const setInit = async () => {
+      const { id } = record;
+      const resp = await getIncomeCollectionListHasConnected({ id });
+      if (resp) {
+        const tempArr = resp
+          ? resp.map((item: any) => item.accountingCode)
+          : [];
+        setTargetKeys([...tempArr]);
       }
+    };
 
     const onChange = (nextTargetKeys: string[]) => {
-        setTargetKeys(nextTargetKeys);
+      setTargetKeys(nextTargetKeys);
     };
 
-    const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
-        //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
-        setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+    const onSelectChange = (
+      sourceSelectedKeys: string[],
+      targetSelectedKeys: string[],
+    ) => {
+      //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+      setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
     };
 
     useImperativeHandle(ref, () => ({
-        save: async () => {
-            const items = datasource.filter(a => targetKeys.includes(a[`${keyName}`]));
-            onSave(targetKeys, items);
-        }
+      save: async () => {
+        const items = datasource.filter((a) =>
+          targetKeys.includes(a[`${keyName}`]),
+        );
+        onSave(targetKeys, items);
+      },
     }));
 
     useEffect(() => {
-        getFuncList();
-        setInit();
+      getFuncList();
+      setInit();
     }, []);
 
-
-
     return (
-        <div>
-            <Transfer className='TableTransfer' showSearch
-                titles={['待选项', '已选项']}
-                locale={{
-                    itemUnit: '项',
-                    itemsUnit: '项',
-                    searchPlaceholder: '请输入',
-                }}
-                oneWay={false}
-                onChange={onChange}
-                onSelectChange={onSelectChange}
-                dataSource={datasource}
-                rowKey={record => record[`${keyName}`]}
-                targetKeys={targetKeys}
-                selectedKeys={selectedKeys}
-                filterOption={(inputValue, item) => {
-                    return item.name!.indexOf(inputValue) !== -1
+      <div>
+        <Transfer
+          className="TableTransfer"
+          showSearch
+          titles={['待选项', '已选项']}
+          locale={{
+            itemUnit: '项',
+            itemsUnit: '项',
+            searchPlaceholder: '请输入',
+          }}
+          oneWay={false}
+          onChange={onChange}
+          onSelectChange={onSelectChange}
+          dataSource={datasource}
+          rowKey={(record) => record[`${keyName}`]}
+          targetKeys={targetKeys}
+          selectedKeys={selectedKeys}
+          filterOption={(inputValue, item) => {
+            return item.name!.indexOf(inputValue) !== -1;
+          }}
+        >
+          {({
+            direction,
+            filteredItems,
+            onItemSelectAll,
+            onItemSelect,
+            selectedKeys: listSelectedKeys,
+            disabled: listDisabled,
+          }) => {
+            // console.log({ filteredItems, listSelectedKeys,direction });
+            const columns = direction === 'left' ? leftColumns : rightColumns;
+
+            const rowSelection: TableRowSelection<TransferItem> = {
+              getCheckboxProps: (item) => ({
+                disabled: listDisabled || item.disabled,
+              }),
+              onSelectAll(selected, selectedRows) {
+                const treeSelectedKeys = selectedRows.map(
+                  (a) => a[`${keyName}`],
+                );
+                const diffKeys = selected
+                  ? difference(treeSelectedKeys, listSelectedKeys)
+                  : difference(listSelectedKeys, treeSelectedKeys);
+                onItemSelectAll(diffKeys as string[], selected);
+              },
+              onSelect(item, selected) {
+                onItemSelect(item[`${keyName}`], selected);
+              },
+              selectedRowKeys: listSelectedKeys,
+            };
+
+            return (
+              <KCIMTable
+                rowSelection={rowSelection}
+                columns={columns as TransferItem[]}
+                dataSource={filteredItems}
+                size="small"
+                bordered={false}
+                rowKey={`${keyName}`}
+                tableStyle={{ border: 'none' }}
+                pagination={{
+                  showTitle: false,
+                  pageSize: 9,
+                  showLessItems: false,
+                  simple: true,
+                  showTotal: () => false,
                 }}
-            >
-                {({
-                    direction,
-                    filteredItems,
-                    onItemSelectAll,
-                    onItemSelect,
-                    selectedKeys: listSelectedKeys,
-                    disabled: listDisabled,
-                }) => {
-
-                    // console.log({ filteredItems, listSelectedKeys,direction });
-                    const columns = direction === 'left' ? leftColumns : rightColumns;
-
-                    const rowSelection: TableRowSelection<TransferItem> = {
-                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
-                        onSelectAll(selected, selectedRows) {
-                            const treeSelectedKeys = selectedRows.map((a) => a[`${keyName}`]);
-                            const diffKeys = selected
-                                ? difference(treeSelectedKeys, listSelectedKeys)
-                                : difference(listSelectedKeys, treeSelectedKeys);
-                            onItemSelectAll(diffKeys as string[], selected);
-                        },
-                        onSelect(item, selected) {
-                            onItemSelect(item[`${keyName}`], selected);
-                        },
-                        selectedRowKeys: listSelectedKeys,
-                    };
-
-                    return (
-                        <KCIMTable
-                            rowSelection={rowSelection}
-                            columns={columns as TransferItem[]}
-                            dataSource={filteredItems}
-                            size="small"
-                            bordered={false}
-                            rowKey={`${keyName}`}
-                            tableStyle={{border:'none'}}
-                            pagination={{ showTitle: false, pageSize: 9, showLessItems: false, simple: true, showTotal: () => false }}
-                            tableAlertRender={false}
-                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
-                            onRow={(row) => ({
-                                onClick: () => {
-                                    if (row.itemDisabled || listDisabled) return;
-                                    onItemSelect(row[`${keyName}`], !listSelectedKeys.includes(row[`${keyName}`]));
-                                },
-                            })}
-                        />
+                tableAlertRender={false}
+                style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+                onRow={(row) => ({
+                  onClick: () => {
+                    if (row.itemDisabled || listDisabled) return;
+                    onItemSelect(
+                      row[`${keyName}`],
+                      !listSelectedKeys.includes(row[`${keyName}`]),
                     );
-                }}
-            </Transfer>
-        </div>
-
-    )
-});
-
-export default TableTransfer
-
-
+                  },
+                })}
+              />
+            );
+          }}
+        </Transfer>
+      </div>
+    );
+  },
+);
+
+export default TableTransfer;

+ 1399 - 813
src/pages/baseSetting/otherItemSet/departmentCostCalc/index.tsx

@@ -7,28 +7,40 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import KCIMPagecontainer from '@/components/KCIMPageContainer';
 import { KCIMTable } from '@/components/KCIMTable';
 
 import { createFromIconfontCN } from '@ant-design/icons';
 
-
 import { ActionType, ProFormInstance } from '@ant-design/pro-components';
-import { ModalForm } from '@ant-design/pro-form'
+import { ModalForm } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
-import { Modal, message, Drawer, Tabs, Input, DatePicker, Popover, Alert, Skeleton } from 'antd';
-import { Key, useEffect, useRef, useState } from 'react';
+import {
+  Modal,
+  message,
+  Drawer,
+  Tabs,
+  Input,
+  DatePicker,
+  Popover,
+  Alert,
+  Skeleton,
+} from 'antd';
+import { Key, useCallback, useEffect, useMemo, useRef, useState } from 'react';
 import * as XLSX from 'xlsx-js-style';
 import { saveAs } from 'file-saver';
 import moment from 'moment';
 import 'moment/locale/zh-cn';
 import locale from 'antd/es/date-picker/locale/zh_CN';
 
-
-
-import { addData, computeProfitReq, getReportDataReq, getReportProjectSettingList, getResponsibleCenters, saveReportRelation } from './service';
+import {
+  addData,
+  computeProfitReq,
+  getReportDataReq,
+  getReportProjectSettingList,
+  getResponsibleCenters,
+  saveReportRelation,
+} from './service';
 
 import './style.less';
 
@@ -41,910 +53,1484 @@ import { useModel } from '@umijs/max';
 import { getUserHasReports } from '@/pages/costAccounting/calcPageTemplate/service';
 
 const IconFont = createFromIconfontCN({
-    scriptUrl: '',
+  scriptUrl: '',
 });
 
-const DEFAULT_FONT_COLOR = 'rgba(0, 0, 0, 0.85)';
+const getRawReportFontColor = (record: any) => {
+  const rawColor =
+    record?.fontColor ||
+    record?.fontcolor ||
+    record?.font_color ||
+    record?.color ||
+    record?.font;
+  if (typeof rawColor !== 'string') return undefined;
+  const color = rawColor.trim().replace(/^['"]|['"]$/g, '');
+  if (!color) return undefined;
+  return color;
+};
 
-const normalizeColor = (rawColor: any) => {
-    if (typeof rawColor !== 'string') return DEFAULT_FONT_COLOR;
-    const color = rawColor.trim();
-    if (!color) return DEFAULT_FONT_COLOR;
-    return color;
+const toHex2 = (num: number) =>
+  Math.max(0, Math.min(255, Math.round(num)))
+    .toString(16)
+    .padStart(2, '0')
+    .toUpperCase();
+
+const cssColorCache = new Map<string, string | undefined>();
+
+const convertToExcelRgb = (rawColor: any) => {
+  if (typeof rawColor !== 'string') return undefined;
+  const color = rawColor.trim().replace(/^['"]|['"]$/g, '');
+  if (!color) return undefined;
+  if (cssColorCache.has(color)) return cssColorCache.get(color);
+  const hexColorMatch = color.match(
+    /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/,
+  );
+  if (hexColorMatch) {
+    const hex = hexColorMatch[1];
+    if (hex.length === 3) {
+      const r = hex[0] + hex[0];
+      const g = hex[1] + hex[1];
+      const b = hex[2] + hex[2];
+      const result = (r + g + b).toUpperCase();
+      cssColorCache.set(color, result);
+      return result;
+    }
+    if (hex.length === 6) {
+      const result = hex.toUpperCase();
+      cssColorCache.set(color, result);
+      return result;
+    }
+    // #RRGGBBAA 忽略 alpha,取 RRGGBB,兼容更多表格软件
+    const result = hex.slice(0, 6).toUpperCase();
+    cssColorCache.set(color, result);
+    return result;
+  }
+
+  const rgbaMatch = color.match(
+    /^rgba?\(\s*([0-9.]+)\s*,\s*([0-9.]+)\s*,\s*([0-9.]+)\s*(?:,\s*([0-9.]+)\s*)?\)$/i,
+  );
+  if (rgbaMatch) {
+    const r = Number(rgbaMatch[1]);
+    const g = Number(rgbaMatch[2]);
+    const b = Number(rgbaMatch[3]);
+    const result = `${toHex2(r)}${toHex2(g)}${toHex2(b)}`;
+    cssColorCache.set(color, result);
+    return result;
+  }
+
+  // 兜底:交给浏览器解析命名色/hsl 等 CSS 颜色格式
+  if (typeof document !== 'undefined') {
+    const temp = document.createElement('span');
+    temp.style.color = '';
+    temp.style.color = color;
+    if (temp.style.color) {
+      temp.style.display = 'none';
+      document.body.appendChild(temp);
+      const computed = window.getComputedStyle(temp).color;
+      document.body.removeChild(temp);
+      const computedMatch = computed.match(
+        /^rgba?\(\s*([0-9.]+)\s*,\s*([0-9.]+)\s*,\s*([0-9.]+)\s*(?:,\s*([0-9.]+)\s*)?\)$/i,
+      );
+      if (computedMatch) {
+        const r = Number(computedMatch[1]);
+        const g = Number(computedMatch[2]);
+        const b = Number(computedMatch[3]);
+        const result = `${toHex2(r)}${toHex2(g)}${toHex2(b)}`;
+        cssColorCache.set(color, result);
+        return result;
+      }
+    }
+  }
+
+  cssColorCache.set(color, undefined);
+  return undefined;
 };
 
-const getReportFontColor = (record: any) =>
-    normalizeColor(record?.fontColor || record?.fontcolor || record?.font_color || DEFAULT_FONT_COLOR);
+const DEFAULT_IGNORED_EXCEL_RGB = new Set(['000000', '17181A']);
+const pickMeaningfulColor = (excelRgb?: string) =>
+  excelRgb && !DEFAULT_IGNORED_EXCEL_RGB.has(excelRgb) ? excelRgb : undefined;
+
+const collectRenderedRowColorMap = () => {
+  const rowColorMap = new Map<string, string>();
+  if (typeof document === 'undefined') return rowColorMap;
+
+  const rows = document.querySelectorAll(
+    '.departmentCostCalcReportTable .cost-ant-table-body .cost-ant-table-row[data-row-key], .departmentCostCalcReportTable .virtual-table-row[data-row-key]',
+  );
+
+  rows.forEach((rowNode) => {
+    const row = rowNode as HTMLElement;
+    const rowKey = row.getAttribute('data-row-key');
+    if (!rowKey) return;
+
+    const rowStyle = window.getComputedStyle(row);
+    const cssVarColor = rowStyle.getPropertyValue('--report-font-color').trim();
+    const firstCell = row.querySelector(
+      'td, .virtual-table-cell',
+    ) as HTMLElement | null;
+    const renderedColor = firstCell
+      ? window.getComputedStyle(firstCell).color
+      : '';
+    const finalColor = cssVarColor || renderedColor;
+    if (finalColor) {
+      const excelRgb = pickMeaningfulColor(convertToExcelRgb(finalColor));
+      if (excelRgb) {
+        rowColorMap.set(rowKey, excelRgb);
+      }
+    }
+  });
 
+  return rowColorMap;
+};
 
+const buildTitleColumnColorMap = (
+  title: any[],
+  keyName: 'reportName' | 'responsibilityName',
+) => {
+  const map: Record<string, string> = {};
+
+  const getChildren = (node: any) => {
+    if (Array.isArray(node?.childTitle) && node.childTitle.length > 0)
+      return node.childTitle;
+    if (Array.isArray(node?.child) && node.child.length > 0) return node.child;
+    return [];
+  };
+
+  const walk = (nodes: any[], inheritedColor?: string) => {
+    nodes.forEach((node) => {
+      const currentColor = getRawReportFontColor(node) || inheritedColor;
+      const children = getChildren(node);
+      if (children.length > 0) {
+        walk(children, currentColor);
+        return;
+      }
+
+      const key =
+        keyName === 'responsibilityName'
+          ? node?.responsibilityCode
+          : node?.reportId;
+      if (key !== undefined && key !== null && currentColor) {
+        map[String(key)] = currentColor;
+      }
+    });
+  };
 
-function findAllParents(tree: any[]) {
-    let parents: any[] = [];
-    // 递归函数来遍历树并找到所有父节点
-    function traverse(nodes: any[]) {
-        for (const node of nodes) {
-            // 检查节点是否有子节点
-            if (node.children && node.children.length > 0) {
-                parents.push(node); // 添加到父节点列表
-                traverse(node.children); // 递归遍历子节点
-            }
-        }
+  walk(title || []);
+  return map;
+};
+
+const yieldToBrowser = () =>
+  new Promise<void>((resolve) => {
+    if (
+      typeof window === 'undefined' ||
+      typeof window.requestAnimationFrame !== 'function'
+    ) {
+      setTimeout(resolve, 0);
+      return;
     }
+    window.requestAnimationFrame(() => resolve());
+  });
+function findAllParentKeys(tree: any[]) {
+  const parentKeys: Key[] = [];
+
+  function traverse(nodes: any[]) {
+    for (const node of nodes) {
+      if (node.children && node.children.length > 0) {
+        parentKeys.push(node.id);
+        traverse(node.children);
+      }
+    }
+  }
 
-    traverse(tree); // 开始遍历树
-    return parents; // 返回所有父节点的数组
+  traverse(tree);
+  return parentKeys;
+}
+
+function findFirstLevelParentKeys(tree: any[]) {
+  return tree
+    .filter((node) => node.children && node.children.length > 0)
+    .map((node) => node.id);
 }
 
 function countLeafNodes(trees: any[]) {
-    let leafCount = 0;
+  let leafCount = 0;
 
-    // 遍历集合中的每棵树
-    for (let i = 0; i < trees.length; i++) {
-        leafCount += countLeafNodesRecursive(trees[i]);
-    }
+  // 遍历集合中的每棵树
+  for (let i = 0; i < trees.length; i++) {
+    leafCount += countLeafNodesRecursive(trees[i]);
+  }
 
-    return leafCount;
+  return leafCount;
 }
 
 function countLeafNodesRecursive(node: any) {
-    // 如果当前节点没有子节点,说明它是一个叶子节点
-    if (!node.children || node.children.length === 0) {
-        return 1;
-    }
+  // 如果当前节点没有子节点,说明它是一个叶子节点
+  if (!node.children || node.children.length === 0) {
+    return 1;
+  }
 
-    let leafCount = 0;
+  let leafCount = 0;
 
-    // 递归计算每个子节点的叶子节点数
-    for (let i = 0; i < node.children.length; i++) {
-        leafCount += countLeafNodesRecursive(node.children[i]);
-    }
+  // 递归计算每个子节点的叶子节点数
+  for (let i = 0; i < node.children.length; i++) {
+    leafCount += countLeafNodesRecursive(node.children[i]);
+  }
 
-    return leafCount;
+  return leafCount;
 }
 
-
 function searchTree(tree: any[], searchTerm: string) {
-    // 定义结果数组
-    let results = [];
+  // 定义结果数组
+  let results = [];
 
-    // 定义递归函数来搜索匹配的节点
-    function searchNode(node: any) {
-        // 创建一个变量来标记当前节点或其子节点是否匹配
-        let isMatch = false;
+  // 定义递归函数来搜索匹配的节点
+  function searchNode(node: any) {
+    // 创建一个变量来标记当前节点或其子节点是否匹配
+    let isMatch = false;
 
-        // 检查当前节点的 name 或 code 是否包含搜索词
-        if (node.reportName.includes(searchTerm)) {
-            isMatch = true;
-        }
+    // 检查当前节点的 name 或 code 是否包含搜索词
+    if (node.reportName.includes(searchTerm)) {
+      isMatch = true;
+    }
 
-        // 复制当前节点,避免修改原始数据
-        let newNode = { ...node, children: [] };
-
-        // 如果有子节点,递归搜索每个子节点
-        if (node.children) {
-            for (let child of node.children) {
-                let childMatch = searchNode(child);
-                // 如果子节点或其子树匹配,添加到新节点的子节点数组中
-                if (childMatch) {
-                    newNode.children.push(childMatch);
-                    isMatch = true;
-                }
-            }
+    // 复制当前节点,避免修改原始数据
+    let newNode = { ...node, children: [] };
+
+    // 如果有子节点,递归搜索每个子节点
+    if (node.children) {
+      for (let child of node.children) {
+        let childMatch = searchNode(child);
+        // 如果子节点或其子树匹配,添加到新节点的子节点数组中
+        if (childMatch) {
+          newNode.children.push(childMatch);
+          isMatch = true;
         }
+      }
+    }
 
-        // 如果当前节点或其任何子节点匹配,返回新节点
-        // 如果children为空,则不包含children属性
-        if (isMatch) {
-            if (newNode.children.length === 0) {
-                delete newNode.children;
-            }
-            return newNode;
-        } else {
-            return null;
-        }
+    // 如果当前节点或其任何子节点匹配,返回新节点
+    // 如果children为空,则不包含children属性
+    if (isMatch) {
+      if (newNode.children.length === 0) {
+        delete newNode.children;
+      }
+      return newNode;
+    } else {
+      return null;
     }
+  }
 
-    // 遍历树的每个顶级节点
-    for (let node of tree) {
-        let result = searchNode(node);
-        if (result) {
-            results.push(result);
-        }
+  // 遍历树的每个顶级节点
+  for (let node of tree) {
+    let result = searchNode(node);
+    if (result) {
+      results.push(result);
     }
+  }
 
-    return results;
+  return results;
 }
 
 function processTree(originalData: any[]) {
-    return originalData.map(node => {
-        // 深复制当前节点
-        const newNode = JSON.parse(JSON.stringify(node));
-
-        // 如果当前节点有profitList,处理它
-        if (newNode.profitList && Array.isArray(newNode.profitList)) {
-            newNode.profitList.forEach((profit: any) => {
-                // 添加新的键值对到新节点,保持原始值的精度
-                newNode[`${profit.reportId}`] = profit.value;
-            });
-        }
+  return (originalData || []).map((node) => {
+    const nextNode = {
+      ...node,
+      id:
+        node.id ||
+        node.responsibilityCode ||
+        node.reportId ||
+        Math.random().toString(36).substr(2, 9),
+    };
 
-        // 如果节点有子节点,递归处理子节点
-        if (node.child && Array.isArray(node.child)) {
-            newNode.children = processTree(node.child);
+    if (Array.isArray(node.profitList)) {
+      node.profitList.forEach((profit: any) => {
+        if (profit?.reportId !== undefined) {
+          nextNode[`${profit.reportId}`] = profit.value;
         }
+      });
+    }
 
-        return newNode;
-    });
+    if (Array.isArray(node.child) && node.child.length > 0) {
+      nextNode.children = processTree(node.child);
+    }
+
+    return nextNode;
+  });
 }
 
+const EMPTY_STYLE_OBJ = {};
 // 递归函数,用于处理多层级标题
-function generateColumns(item: any, titleIndex = 0, title: string, hideRatioColumns = false) {
-    // // 检查是否需要隐藏"占比"列,如果title包含"占比",且hideRatioColumns为true,则返回null
-    // if (hideRatioColumns && item[`${title}`].includes('占比')) {
-    //     return null;
-    // }
-
-    const column: any = title == 'responsibilityName' ? {
-        title: item[`${title}`],
-        dataIndex: `${item.responsibilityCode}`,
-        key: `${item.responsibilityCode}`,
-        align: (item.responsibilityCode.indexOf('amount') != -1) ? 'right' : 'right',
-        ellipsis: true,
-        renderText(num: number, record: any) {
+function generateColumns(
+  item: any,
+  titleIndex = 0,
+  title: string,
+  hideRatioColumns = false,
+  inheritedFontColor?: string,
+) {
+  // // 检查是否需要隐藏"占比"列,如果title包含"占比",且hideRatioColumns为true,则返回null
+  // if (hideRatioColumns && item[`${title}`].includes('占比')) {
+  //     return null;
+  // }
+
+  const currentFontColor = getRawReportFontColor(item) || inheritedFontColor;
+  const columnCellStyle = currentFontColor
+    ? { color: currentFontColor }
+    : undefined;
+  const cellProps = columnCellStyle
+    ? { style: columnCellStyle }
+    : EMPTY_STYLE_OBJ;
+
+  const column: any =
+    title == 'responsibilityName'
+      ? {
+          title: item[`${title}`],
+          dataIndex: `${item.responsibilityCode}`,
+          key: `${item.responsibilityCode}`,
+          fontColor: item?.fontColor || item?.fontcolor || item?.font_color,
+          onCell: () => cellProps,
+          onHeaderCell: () => cellProps,
+          align:
+            item.responsibilityCode.indexOf('amount') != -1 ? 'right' : 'right',
+          ellipsis: true,
+          renderText(num: number, record: any) {
             if (item.responsibilityCode.indexOf('amount') != -1) {
-                const { permil, decimalPlace, dataType } = record;
-                if (typeof num === 'number' && !isNaN(num)) {
-                    // 根据 dataType 判断渲染类型
-                    if (dataType === 2) {
-                        // 百分比类型
-                        return `${(num * 100).toFixed(decimalPlace || 2)}%`;
-                    } else {
-                        // 数值类型 (dataType === 1 或未定义)
-                        // 根据 permil 字段决定是否使用千位分隔符
-                        const useGrouping = permil === 1;
-
-                        // 解析 decimalPlace 字段,如果无效或未定义,则默认为2
-                        let fractionDigits = parseInt(decimalPlace, 10);
-                        if (isNaN(fractionDigits) || fractionDigits < 0) {
-                            fractionDigits = 2; // 默认保留两位小数
-                        }
-
-                        return num.toLocaleString('en-US', {
-                            minimumFractionDigits: fractionDigits,
-                            maximumFractionDigits: fractionDigits,
-                            useGrouping: useGrouping
-                        });
-                    }
+              const { permil, decimalPlace, dataType } = record;
+              if (typeof num === 'number' && !isNaN(num)) {
+                // 根据 dataType 判断渲染类型
+                if (dataType === 2) {
+                  // 百分比类型
+                  return `${(num * 100).toFixed(decimalPlace || 2)}%`;
                 } else {
-                    // 对于非数字或 null/undefined,返回空
-                    return '';
+                  // 数值类型 (dataType === 1 或未定义)
+                  // 根据 permil 字段决定是否使用千位分隔符
+                  const useGrouping = permil === 1;
+
+                  // 解析 decimalPlace 字段,如果无效或未定义,则默认为2
+                  let fractionDigits = parseInt(decimalPlace, 10);
+                  if (isNaN(fractionDigits) || fractionDigits < 0) {
+                    fractionDigits = 2; // 默认保留两位小数
+                  }
+
+                  return num.toLocaleString('en-US', {
+                    minimumFractionDigits: fractionDigits,
+                    maximumFractionDigits: fractionDigits,
+                    useGrouping: useGrouping,
+                  });
                 }
+              } else {
+                // 对于非数字或 null/undefined,返回空
+                return '';
+              }
             } else {
-                return num;
+              return num;
             }
-        },
-    } : {
-        title: item[`${title}`],
-        ellipsis: true,
-        dataIndex: `${item[`reportId`]}`,
-        key: `${item[`reportId`]}`,
-        align: 'right',
-        // 新增:根据 dataType 渲染不同格式
-        renderText(num: string) {
+          },
+        }
+      : {
+          title: item[`${title}`],
+          ellipsis: true,
+          dataIndex: `${item[`reportId`]}`,
+          key: `${item[`reportId`]}`,
+          fontColor: item?.fontColor || item?.fontcolor || item?.font_color,
+          onCell: () => cellProps,
+          onHeaderCell: () => cellProps,
+          align: 'right',
+          // 新增:根据 dataType 渲染不同格式
+          renderText(num: string) {
             // 使用 parseFloat 来保持数字精度
             const value = parseFloat(num);
             const { permil, decimalPlace, dataType } = item;
-        
+
             // 检查 value 是否为有效数字
             if (typeof value === 'number' && !isNaN(value)) {
-                if (dataType === 2) {
-                    // 百分比类型,保留 decimalPlace 位小数
-                    return `${(value * 100).toFixed(decimalPlace || 2)}%`;
-                } else {
-                    // 数值类型 (dataType === 1 或未定义)
-                    // 根据 permil 字段决定是否使用千位分隔符
-                    const useGrouping = permil === 1;
-                    // 解析 decimalPlace 字段,如果无效或未定义,则默认为2
-                    let fractionDigits = parseInt(decimalPlace, 10);
-                    if (isNaN(fractionDigits) || fractionDigits < 0) {
-                        fractionDigits = 2; // 默认保留两位小数
-                    }
-                    // 返回格式化后的数字
-                    return value.toLocaleString('en-US', {
-                        minimumFractionDigits: fractionDigits,
-                        maximumFractionDigits: fractionDigits,
-                        useGrouping: useGrouping
-                    });
+              if (dataType === 2) {
+                // 百分比类型,保留 decimalPlace 位小数
+                return `${(value * 100).toFixed(decimalPlace || 2)}%`;
+              } else {
+                // 数值类型 (dataType === 1 或未定义)
+                // 根据 permil 字段决定是否使用千位分隔符
+                const useGrouping = permil === 1;
+                // 解析 decimalPlace 字段,如果无效或未定义,则默认为2
+                let fractionDigits = parseInt(decimalPlace, 10);
+                if (isNaN(fractionDigits) || fractionDigits < 0) {
+                  fractionDigits = 2; // 默认保留两位小数
                 }
+                // 返回格式化后的数字
+                return value.toLocaleString('en-US', {
+                  minimumFractionDigits: fractionDigits,
+                  maximumFractionDigits: fractionDigits,
+                  useGrouping: useGrouping,
+                });
+              }
             } else {
-                // 非数字或 null/undefined 返回空
-                return '';
+              // 非数字或 null/undefined 返回空
+              return '';
             }
-        },
-    };
-
-    // 递归处理子列
-    if (item.childTitle && Array.isArray(item.childTitle) && item.childTitle.length > 0) {
-        column.children = item.childTitle
-            .map((a: any, aindex: number) => generateColumns(a, titleIndex + 1, title, hideRatioColumns))
-            .filter((col: any) => col !== null); // 过滤掉null项
-    }
-    if (item.child && Array.isArray(item.child) && item.child.length > 0) {
-        column.children = item.child
-            .map((a: any, aindex: number) => generateColumns(a, titleIndex + 1, title, hideRatioColumns))
-            .filter((col: any) => col !== null); // 过滤掉null项
-    }
-
-    return column;
+          },
+        };
+
+  // 强制以渲染层包裹颜色,避免被表格内部默认字体色覆盖
+  column.render = (_: any, record: any) => {
+    const value = record?.[column.dataIndex];
+    const text = column.renderText ? column.renderText(value, record) : value;
+    if (!currentFontColor) return text;
+    return <span style={{ color: currentFontColor }}>{text}</span>;
+  };
+
+  // 递归处理子列
+  if (
+    item.childTitle &&
+    Array.isArray(item.childTitle) &&
+    item.childTitle.length > 0
+  ) {
+    column.children = item.childTitle
+      .map((a: any, aindex: number) =>
+        generateColumns(
+          a,
+          titleIndex + 1,
+          title,
+          hideRatioColumns,
+          currentFontColor,
+        ),
+      )
+      .filter((col: any) => col !== null); // 过滤掉null项
+  }
+  if (item.child && Array.isArray(item.child) && item.child.length > 0) {
+    column.children = item.child
+      .map((a: any, aindex: number) =>
+        generateColumns(
+          a,
+          titleIndex + 1,
+          title,
+          hideRatioColumns,
+          currentFontColor,
+        ),
+      )
+      .filter((col: any) => col !== null); // 过滤掉null项
+  }
+
+  return column;
 }
 
-
-
-
-
 function transformTreeData(tree: any[]) {
-    // 遍历整个树
-    return tree.map(node => {
-        // 解构出data中的字段并添加到当前节点
-        if (Array.isArray(node.data)) {
-            node.data.forEach((item: any) => {
-                // 将data数组中的每个对象转换成当前节点的属性
-                if (item.code && item.value !== undefined) {
-                    node[item.code] = item.value;
-                }
-            });
-        }
+  return (tree || []).map((node) => {
+    const nextNode = {
+      ...node,
+      id:
+        node.id ||
+        node.responsibilityCode ||
+        node.reportId ||
+        Math.random().toString(36).substr(2, 9),
+    };
 
-        // 递归处理子节点,如果存在子节点
-        if (node.children) {
-            node.children = transformTreeData(node.children);
+    if (Array.isArray(node.data)) {
+      node.data.forEach((item: any) => {
+        if (item?.code && item.value !== undefined) {
+          nextNode[item.code] = item.value;
         }
+      });
+    }
 
-        // 返回处理后的节点
-        return node;
-    });
-}
-
-const getNextUnexpandedKeys = (data: any[], expandedKeys: any[] = []) => {
-    let keys: any[] = [];
+    if (Array.isArray(node.children) && node.children.length > 0) {
+      nextNode.children = transformTreeData(node.children);
+    }
 
-    const traverse = (nodes: any) => {
-        for (const node of nodes) {
-            // 如果当前节点还没有展开,就把它加入 keys
-            if (!expandedKeys.includes(node.id)) {
-                keys.push(node.id);
-            }
+    return nextNode;
+  });
+}
 
-            // 如果当前节点已经展开,继续遍历子节点
-            if (node.children && expandedKeys.includes(node.id)) {
-                traverse(node.children);
-            }
-        }
-    };
+const getNextUnexpandedKeys = (
+  data: any[],
+  expandedKeys: Iterable<any> = [],
+) => {
+  const expandedKeySet =
+    expandedKeys instanceof Set ? expandedKeys : new Set(expandedKeys);
+  let keys: any[] = [];
+
+  const traverse = (nodes: any) => {
+    for (const node of nodes) {
+      // 如果当前节点还没有展开,就把它加入 keys
+      if (!expandedKeySet.has(node.id)) {
+        keys.push(node.id);
+      }
+
+      // 如果当前节点已经展开,继续遍历子节点
+      if (node.children && expandedKeySet.has(node.id)) {
+        traverse(node.children);
+      }
+    }
+  };
 
-    traverse(data);
+  traverse(data);
 
-    return keys;
+  return keys;
 };
 
+import { VirtualRow } from '@/components/KCIMTable/VirtualRow';
 
+const drawerVirtualComponents = {
+  body: {
+    row: VirtualRow,
+  },
+};
 
 export default function DepartmentCostCalc() {
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ reportType: 0 });
-    const tableRef = useRef<ActionType>();
-    const formRef = useRef<ProFormInstance>();
-    const [tabs, set_tabs] = useState<any[]>([]);
-
-    const { initialState, setInitialState } = useModel('@@initialState');
-    const [computeDate, set_computeDate] = useState<string>(initialState ? initialState.computeDate : '');
-    const [responsibleCenters, set_responsibleCenters] = useState<any[]>([]);
-    const [currentTabKey, set_currentTabKey] = useState<any | undefined>(undefined);
-    const [currentTab, set_currentTab] = useState<any | undefined>(undefined);
-    const [currentSelectedRespon, set_currentSelectedRespon] = useState<any | undefined>(undefined);
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
-    const [allParentsKeys, set_allParentsKeys] = useState<Key[]>([]);
-    const [drawerTableVisible, set_drawerTableVisible] = useState(false);
-    const [dataSource, set_dataSource] = useState<any[]>([]);
-    const [tableColumns, set_tableColumns] = useState<any[]>([]);
-    const [calcResultText, set_calcResultText] = useState<undefined | string>(undefined);
-    const [loadingtransform, set_loadingtransform] = useState(false);
-    const [ifShowPercent, set_ifShowPercent] = useState(true);
-
-    const columns: ProColumns[] = [
-
-        {
-            title: '报表项目名称',
-            dataIndex: 'reportName',
-            width: '50%',
-            ellipsis: true,
-            renderText(text, record, index, action) {
-                const { description } = record;
-                return description ? <Popover content={() => <div dangerouslySetInnerHTML={{ __html: description }} />}><span style={{ cursor: 'pointer' }}>{text}</span><IconFont className="hover-icon" style={{ fontSize: 16, color: '#17181a', paddingLeft: 4, position: 'relative', top: 1 }} type={'iconshuoming'} /></Popover> : text
-            },
-        },
-        {
-            title: '金额(元)',
-            align: 'right',
-            dataIndex: 'amount',
-            renderText(num, record) {
-                const { calcType, permil, decimalPlace, dataType } = record;
-                if (record.children && calcType == '0') {
-                    return <React.Fragment></React.Fragment>
-                } else {
-                    // 检查 num 是否是有效数字
-                    if (typeof num === 'number' && !isNaN(num)) {
-                        // 根据 dataType 判断渲染类型
-                        if (dataType === 2) {
-                            // 百分比类型
-                            return `${(num * 100).toFixed(decimalPlace || 2)}%`;
-                        } else {
-                            // 数值类型 (dataType === 1 或未定义)
-                            // 根据 permil 字段决定是否使用千位分隔符
-                            const useGrouping = permil === 1;
-
-                            // 解析 decimalPlace 字段,如果无效或未定义,则默认为2
-                            let fractionDigits = parseInt(decimalPlace, 10);
-                            if (isNaN(fractionDigits) || fractionDigits < 0) {
-                                fractionDigits = 2; // 默认保留两位小数
-                            }
-
-                            return num.toLocaleString('en-US', {
-                                minimumFractionDigits: fractionDigits,
-                                maximumFractionDigits: fractionDigits,
-                                useGrouping: useGrouping
-                            });
-                        }
-                    } else {
-                        // 对于非数字或 null/undefined,返回空
-                        return '';
-                    }
-                }
-            },
-        },
-        {
-            title: '占比',
-            align: 'right',
-            hideInTable: !ifShowPercent,
-            dataIndex: 'percent',
-            renderText(num, record) {
-                const { calcType, decimalPlace } = record;
-                if (record.children && calcType == '0') {
-                    return <React.Fragment></React.Fragment>
-                } else {
-                    return num != null ? `${((num * 100).toFixed(decimalPlace))}%` : num
-                }
-
-            },
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<
+    any | undefined
+  >({ reportType: 0 });
+  const tableRef = useRef<ActionType>();
+  const formRef = useRef<ProFormInstance>();
+  const [tabs, set_tabs] = useState<any[]>([]);
+
+  const { initialState, setInitialState } = useModel('@@initialState');
+  const [computeDate, set_computeDate] = useState<string>(
+    initialState ? initialState.computeDate : '',
+  );
+  const [responsibleCenters, set_responsibleCenters] = useState<any[]>([]);
+  const [currentTabKey, set_currentTabKey] = useState<any | undefined>(
+    undefined,
+  );
+  const [currentTab, set_currentTab] = useState<any | undefined>(undefined);
+  const [currentSelectedRespon, set_currentSelectedRespon] = useState<
+    any | undefined
+  >(undefined);
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
+  const [allParentsKeys, set_allParentsKeys] = useState<Key[]>([]);
+  const [drawerTableVisible, set_drawerTableVisible] = useState(false);
+  const [mainTableDataSource, set_mainTableDataSource] = useState<any[]>([]);
+  const [drawerDataSource, set_drawerDataSource] = useState<any[]>([]);
+  const [drawerExpandedKeys, set_drawerExpandedKeys] = useState<Key[]>([]);
+  const [tableColumns, set_tableColumns] = useState<any[]>([]);
+  const [calcResultText, set_calcResultText] = useState<undefined | string>(
+    undefined,
+  );
+  const [loadingtransform, set_loadingtransform] = useState(false);
+  const [ifShowPercent, set_ifShowPercent] = useState(true);
+  const [titleColumnColorMap, set_titleColumnColorMap] = useState<
+    Record<string, string>
+  >({});
+
+  const columns = useMemo<ProColumns[]>(
+    () => [
+      {
+        title: '报表项目名称',
+        dataIndex: 'reportName',
+        width: '50%',
+        ellipsis: true,
+        renderText(text, record, index, action) {
+          const { description } = record;
+          return description ? (
+            <Popover
+              content={() => (
+                <div dangerouslySetInnerHTML={{ __html: description }} />
+              )}
+            >
+              <span style={{ cursor: 'pointer' }}>{text}</span>
+              <IconFont
+                className="hover-icon"
+                style={{
+                  fontSize: 16,
+                  color: '#17181a',
+                  paddingLeft: 4,
+                  position: 'relative',
+                  top: 1,
+                }}
+                type={'iconshuoming'}
+              />
+            </Popover>
+          ) : (
+            text
+          );
         },
-    ];
-
-
-    // 主函数,生成表格列
-    const generateTableColumns = (title: any[], titleKeyName: string) => {
-        return title.map((item: any, titleIndex: number) => generateColumns(item, titleIndex, titleKeyName, !ifShowPercent));
-    };
-
-
-    const getTableData = async (params: any) => {
-        const { responsibilityCode, filter = undefined } = params;
-        if (!responsibilityCode) return []
-        const resp = await getReportProjectSettingList({ ...params });
-
-        if (resp) {
-            if (filter) {
-                const filterData = searchTree(resp, filter);
-                const allParents = findAllParents(filterData);
-
-                set_allParentsKeys([...(allParents.map((a: any) => a.id))]);
-                set_dataSource([...filterData]);
-                return {
-                    data: filterData,
-                    success: true,
+      },
+      {
+        title: '金额(元)',
+        align: 'right',
+        dataIndex: 'amount',
+        renderText(num, record) {
+          const { calcType, permil, decimalPlace, dataType } = record;
+          if (record.children && calcType == '0') {
+            return <React.Fragment></React.Fragment>;
+          } else {
+            // 检查 num 是否是有效数字
+            if (typeof num === 'number' && !isNaN(num)) {
+              // 根据 dataType 判断渲染类型
+              if (dataType === 2) {
+                // 百分比类型
+                return `${(num * 100).toFixed(decimalPlace || 2)}%`;
+              } else {
+                // 数值类型 (dataType === 1 或未定义)
+                // 根据 permil 字段决定是否使用千位分隔符
+                const useGrouping = permil === 1;
+
+                // 解析 decimalPlace 字段,如果无效或未定义,则默认为2
+                let fractionDigits = parseInt(decimalPlace, 10);
+                if (isNaN(fractionDigits) || fractionDigits < 0) {
+                  fractionDigits = 2; // 默认保留两位小数
                 }
-            }
-            if (currentTab.value == '1') {
-                const allParents = findAllParents(resp);
-                set_allParentsKeys([...(allParents.map((a: any) => a.id))]);
-
-            }
-            set_dataSource([...resp]);
 
-            return {
-                data: resp,
-                success: true,
+                return num.toLocaleString('en-US', {
+                  minimumFractionDigits: fractionDigits,
+                  maximumFractionDigits: fractionDigits,
+                  useGrouping: useGrouping,
+                });
+              }
+            } else {
+              // 对于非数字或 null/undefined,返回空
+              return '';
             }
+          }
+        },
+      },
+      {
+        title: '占比',
+        align: 'right',
+        hideInTable: !ifShowPercent,
+        dataIndex: 'percent',
+        renderText(num, record) {
+          const { calcType, decimalPlace } = record;
+          if (record.children && calcType == '0') {
+            return <React.Fragment></React.Fragment>;
+          } else {
+            return num != null ? `${(num * 100).toFixed(decimalPlace)}%` : num;
+          }
+        },
+      },
+    ],
+    [ifShowPercent],
+  );
+
+  // 主函数,生成表格列
+  const generateTableColumns = useCallback(
+    (title: any[], titleKeyName: string) => {
+      return title.map((item: any, titleIndex: number) =>
+        generateColumns(item, titleIndex, titleKeyName, !ifShowPercent),
+      );
+    },
+    [ifShowPercent],
+  );
+
+  const getTableData = useCallback(
+    async (params: any) => {
+      const { responsibilityCode, filter = undefined } = params;
+      if (!responsibilityCode) return [];
+      const resp = await getReportProjectSettingList({ ...params });
+
+      if (resp) {
+        if (filter) {
+          const filterData = searchTree(resp, filter);
+          set_allParentsKeys(findAllParentKeys(filterData));
+          set_mainTableDataSource([...filterData]);
+          return {
+            data: filterData,
+            success: true,
+          };
         }
-        return []
-    }
-
-    const getIfshowPercent = async () => {
-        const { systemId } = JSON.parse(localStorage.getItem('currentSelectedTab') as string)
-        const resp = await getParamsDataBySysId(systemId, '1851077044079824896');
-        if (resp) {
-            set_ifShowPercent(resp.value == '1' ? true : false);
+        if (currentTab?.value == '1') {
+          set_allParentsKeys(findFirstLevelParentKeys(resp));
         }
+        set_mainTableDataSource([...resp]);
+
+        return {
+          data: resp,
+          success: true,
+        };
+      }
+      return [];
+    },
+    [currentTab?.value],
+  );
+
+  const getIfshowPercent = async () => {
+    const { systemId } = JSON.parse(
+      localStorage.getItem('currentSelectedTab') as string,
+    );
+    const resp = await getParamsDataBySysId(systemId, '1851077044079824896');
+    if (resp) {
+      set_ifShowPercent(resp.value == '1' ? true : false);
     }
-
-
-    const onTabChanged = (key: Key) => {
-        set_currentTabKey(key);
-        const needItem = tabs.filter((a) => a.key == key);
-        if (needItem.length > 0) set_currentTab(needItem[0])
+  };
+
+  const onTabChanged = (key: Key) => {
+    set_currentTabKey(key);
+    const needItem = tabs.filter((a) => a.key == key);
+    if (needItem.length > 0) set_currentTab(needItem[0]);
+  };
+
+  const getTabs = async () => {
+    // const { systemId } = JSON.parse((localStorage.getItem('currentSelectedTab')) as string)
+    // const resp = await getDicDataBySysId(systemId, 'PROFIT_REPORT_TYPE');
+    const resp = await getUserHasReports();
+    if (resp) {
+      const { dataVoList } = resp;
+      const tempArr = dataVoList.map((a: any) => ({
+        label: a.name,
+        key: Number(a.code),
+        value: a.value,
+      }));
+      const arr = tempArr.filter((a: any) => a.value != '2');
+      set_tabs([...arr]);
+      set_currentTabKey(arr[0].key);
+      set_currentTab(arr[0]);
     }
+  };
 
-    const getTabs = async () => {
-
-        // const { systemId } = JSON.parse((localStorage.getItem('currentSelectedTab')) as string)
-        // const resp = await getDicDataBySysId(systemId, 'PROFIT_REPORT_TYPE');
-        const resp = await getUserHasReports();
+  const getResponsibleCenterList = async (reportType: string) => {
+    const resp = await getResponsibleCenters(reportType);
+    if (resp) {
+      set_responsibleCenters(resp);
+    }
+  };
+
+  const onLeftChange = (currentSelected: any) => {
+    set_currentSelectedRespon(currentSelected);
+  };
+
+  const tableDataSearchHandle = useCallback(
+    (paramName: string) => {
+      set_tableDataFilterParams((prev: any) => ({
+        ...prev,
+        [`${paramName}`]: tableDataSearchKeywords,
+      }));
+    },
+    [tableDataSearchKeywords],
+  );
+
+  const onekeyComputeProfitHandle = async () => {
+    Modal.confirm({
+      title: '注意',
+      content: '一键计算操作会覆盖当月已计算的数据,是否继续操作?',
+      okText: '确定',
+      cancelText: '取消',
+      onOk: async () => {
+        try {
+          const promises = tabs.map((tab) =>
+            computeProfitReq(computeDate, tab.key),
+          ); // 对每个tab创建一个请求
+          const results = await Promise.all(promises); // 等待所有请求完成
+
+          const allSuccess = results.every((resp) => resp); // 检查所有请求是否都成功
+          if (allSuccess) {
+            message.success('操作成功!');
+            set_calcResultText('一键计算成功!');
+          } else {
+            set_calcResultText('一键计算部分失败!');
+          }
+
+          tableRef.current?.reload(); // 重新加载表格数据
+        } catch (error) {
+          message.error('操作失败,请重试!');
+          set_calcResultText('一键计算失败!');
+        }
+      },
+    });
+  };
+
+  const computeProfitHandle = async () => {
+    Modal.confirm({
+      title: '注意',
+      content: '计算操作会覆盖当月已计算的数据,是否继续操作?',
+      okText: '确定',
+      cancelText: '取消',
+      onOk: async (...args) => {
+        const resp = await computeProfitReq(computeDate, currentTabKey);
         if (resp) {
-            const { dataVoList } = resp;
-            const tempArr = dataVoList.map((a: any) => ({ label: a.name, key: Number(a.code), value: a.value }));
-            const arr = (tempArr.filter((a: any) => a.value != '2'));
-            set_tabs([...arr]);
-            set_currentTabKey(arr[0].key);
-            set_currentTab(arr[0]);
+          message.success('操作成功!');
+          set_calcResultText('计算成功!');
+          tableRef.current?.reload();
+        } else {
+          set_calcResultText('计算失败!');
         }
-    }
-
-    const getResponsibleCenterList = async (reportType: string) => {
-        const resp = await getResponsibleCenters(reportType);
+      },
+    });
+  };
+
+  const openTableDataDrawer = async () => {
+    set_drawerTableVisible(true);
+    set_loadingtransform(true);
+    try {
+      if (currentTab?.value == '3') {
+        const resp = await getReportDataReq(currentTabKey, computeDate, '3');
         if (resp) {
-            set_responsibleCenters(resp);
+          await yieldToBrowser();
+          const { title = [], data = [] } = resp;
+          const defaultColumns: ProColumns[] = [
+            {
+              title: '报表项目名称',
+              dataIndex: 'reportName',
+              key: 'reportName',
+              width: 220,
+              fixed: 'left',
+            },
+          ];
+          const nextTableColumns = generateTableColumns(
+            title,
+            'responsibilityName',
+          );
+          const nextDataSource = transformTreeData(data);
+          set_tableColumns([...defaultColumns, ...nextTableColumns]);
+          set_titleColumnColorMap(
+            buildTitleColumnColorMap(title, 'responsibilityName'),
+          );
+          set_drawerDataSource(nextDataSource);
+          set_drawerExpandedKeys(findFirstLevelParentKeys(nextDataSource));
         }
-    }
-
-    const onLeftChange = (currentSelected: any) => {
-        set_currentSelectedRespon(currentSelected);
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-    }
-
-    const onekeyComputeProfitHandle = async () => {
-        Modal.confirm({
-            title: '注意',
-            content: '一键计算操作会覆盖当月已计算的数据,是否继续操作?',
-            okText: '确定',
-            cancelText: '取消',
-            onOk: async () => {
-                try {
-                    const promises = tabs.map(tab => computeProfitReq(computeDate, tab.key));  // 对每个tab创建一个请求
-                    const results = await Promise.all(promises);  // 等待所有请求完成
-
-                    const allSuccess = results.every(resp => resp);  // 检查所有请求是否都成功
-                    if (allSuccess) {
-                        message.success('操作成功!');
-                        set_calcResultText('一键计算成功!');
-                    } else {
-                        set_calcResultText('一键计算部分失败!');
-                    }
-
-                    tableRef.current?.reload();  // 重新加载表格数据
-                } catch (error) {
-                    message.error('操作失败,请重试!');
-                    set_calcResultText('一键计算失败!');
-                }
+      } else if (currentTab?.value) {
+        const resp = await getReportDataReq(
+          currentTabKey,
+          computeDate,
+          currentTab.value,
+        );
+        if (resp) {
+          await yieldToBrowser();
+          const { title = [], data = [] } = resp;
+          const defaultColumns = [
+            {
+              title: '科室名称',
+              dataIndex: 'responsibilityName',
+              key: 'responsibilityName',
+              width: 220,
+              fixed: 'left',
             },
+          ];
+
+          const nextTableColumns = generateTableColumns(title, 'reportName');
+          const nextDataSource = processTree(data);
+          set_tableColumns([...defaultColumns, ...nextTableColumns]);
+          set_titleColumnColorMap(
+            buildTitleColumnColorMap(title, 'reportName'),
+          );
+          set_drawerDataSource(nextDataSource);
+          set_drawerExpandedKeys(findFirstLevelParentKeys(nextDataSource));
+        }
+      }
+    } finally {
+      set_loadingtransform(false);
+    }
+  };
+
+  const getHeaderRows = (
+    columns: any[],
+    level = 0,
+    headerRows: any[] = [],
+    maxLevel = 0,
+  ) => {
+    // 规则变更:将叶子列标题统一下沉至最底行(maxLevel - 1),
+    // 上方各层以空白占位,避免纵向合并导致“高单元格”。
+    headerRows[level] = headerRows[level] || [];
+    columns.forEach((col: { title: any; children: any }) => {
+      const colSpan = getColSpan(col);
+      if (col.children) {
+        // 父节点仅进行横向合并,不做纵向合并
+        headerRows[level].push({ title: col.title, colSpan, rowSpan: 1 });
+        getHeaderRows(col.children, level + 1, headerRows, maxLevel);
+      } else {
+        // 叶子:从当前层到倒数第二层使用空白占位,叶子标题写入最底层
+        for (let i = level; i < maxLevel - 1; i++) {
+          headerRows[i] = headerRows[i] || [];
+          headerRows[i].push({ title: '', colSpan: 1, rowSpan: 1 });
+        }
+        headerRows[maxLevel - 1] = headerRows[maxLevel - 1] || [];
+        headerRows[maxLevel - 1].push({
+          title: col.title,
+          colSpan: 1,
+          rowSpan: 1,
         });
-    };
-
-
-    const computeProfitHandle = async () => {
-
-        Modal.confirm({
-            title: '注意',
-            content: '计算操作会覆盖当月已计算的数据,是否继续操作?',
-            okText: '确定',
-            cancelText: '取消',
-            onOk: async (...args) => {
+      }
+    });
+    return headerRows;
+  };
+
+  const getColSpan: any = (col: { children: any[] }) => {
+    if (!col.children) return 1;
+    return col.children.reduce((sum, child) => sum + getColSpan(child), 0);
+  };
+
+  const getMaxLevel = (col: any) => {
+    if (!col.children) return 1;
+    return 1 + Math.max(...col.children.map(getMaxLevel));
+  };
+
+  const extractLeafColumnsWithInheritedColor = (
+    columns: any[],
+    inheritedColor?: string,
+  ) => {
+    let leafColumns: Array<{ column: any; color?: string }> = [];
+    columns.forEach((col) => {
+      const currentColor = getRawReportFontColor(col) || inheritedColor;
+      if (col.children && col.children.length > 0) {
+        leafColumns = leafColumns.concat(
+          extractLeafColumnsWithInheritedColor(col.children, currentColor),
+        );
+      } else {
+        leafColumns.push({ column: col, color: currentColor });
+      }
+    });
+    return leafColumns;
+  };
+
+  const addRowWithIndentation = (
+    record: any,
+    level: number,
+    leafColumns: any[],
+    worksheetData: any[],
+    dataRowColors: Array<string | undefined>,
+    renderedRowColorMap: Map<string, string>,
+  ) => {
+    const row = leafColumns.map((col) => {
+      let value = record[col.dataIndex] ?? '';
+
+      // 应用 renderText 函数来格式化导出数据,保持与表格渲染时一致
+      if (col.renderText) {
+        value = col.renderText(value, record);
+      }
+
+      return value;
+    });
 
-                const resp = await computeProfitReq(computeDate, currentTabKey);
-                if (resp) {
-                    message.success('操作成功!');
-                    set_calcResultText('计算成功!');
-                    tableRef.current?.reload();
-                } else {
-                    set_calcResultText('计算失败!');
-                }
-            },
-        })
+    // 在第一列前添加缩进空格以表示层级
+    row[0] = ' '.repeat(level * 4) + row[0]; // 每一级增加 4 个空格作为缩进
+
+    worksheetData.push(row);
+    const rowKey = (record?.id ?? record?.key ?? '') as string | number;
+    const renderedRowColor =
+      rowKey !== ''
+        ? pickMeaningfulColor(renderedRowColorMap.get(String(rowKey)))
+        : undefined;
+    const explicitRowColor = pickMeaningfulColor(
+      convertToExcelRgb(getRawReportFontColor(record)),
+    );
+    dataRowColors.push(explicitRowColor || renderedRowColor);
+
+    // 递归处理子节点
+    if (record.children) {
+      record.children.forEach((child: any) =>
+        addRowWithIndentation(
+          child,
+          level + 1,
+          leafColumns,
+          worksheetData,
+          dataRowColors,
+          renderedRowColorMap,
+        ),
+      );
     }
-
-    const openTableDataDrawer = async () => {
-        set_drawerTableVisible(true);
-        set_loadingtransform(true);
-        if (currentTab.value == '3') {
-            const resp = await getReportDataReq(currentTabKey, computeDate, '3');
-            if (resp) {
-                const { title = [], data = [] } = resp;
-                const defaultColumns: ProColumns[] = [
-                    {
-                        title: '报表项目名称',
-                        dataIndex: 'reportName',
-                        key: 'reportName',
-                        width: 220,
-                        fixed: 'left'
-                    }
-                ];
-
-                const tableColumns = generateTableColumns(title, 'responsibilityName');
-                const dataSource = transformTreeData(data);
-                set_tableColumns([...defaultColumns, ...tableColumns]);
-                set_dataSource(dataSource);
-                set_loadingtransform(false);
-                // console.log({ columns: [...defaultColumns, ...tableColumns], dataSource })
-
-            }
-        } else {
-            const resp = await getReportDataReq(currentTabKey, computeDate, currentTab.value);
-            if (resp) {
-                const { title = [], data = [] } = resp;
-                const defaultColumns = [{
-                    title: '科室名称',
-                    dataIndex: 'responsibilityName',
-                    key: 'responsibilityName',
-                    width: 220,
-                    fixed: 'left'
-                }];
-
-                const tableColumns = generateTableColumns(title, 'reportName');
-                const dataSource = processTree(data);
-                set_tableColumns([...defaultColumns, ...tableColumns]);
-
-                set_dataSource(dataSource);
-                set_loadingtransform(false);
-
-                // console.log({ columns: [...defaultColumns, ...tableColumns], dataSource })
-
+  };
+
+  const handleExport = () => {
+    try {
+      const workbook = XLSX.utils.book_new();
+      const worksheetData: any[] = [];
+
+      // 获取最大层级
+      const maxLevel = tableColumns.reduce(
+        (max, col) => Math.max(max, getMaxLevel(col)),
+        0,
+      );
+
+      // 生成多层级表头
+      const headerRows = getHeaderRows(tableColumns, 0, [], maxLevel);
+
+      // 构建表头行
+      headerRows.forEach((row: any, rowIndex) => {
+        const rowData: string[] = [];
+        row.forEach(
+          (cell: { title: any; colSpan: number; rowSpan: number }) => {
+            rowData.push(cell.title);
+            for (let i = 1; i < cell.colSpan; i++) {
+              rowData.push('');
             }
+          },
+        );
+        worksheetData.push(rowData);
+      });
+
+      // 填充单层表头的空白行
+      if (maxLevel > 1) {
+        const numColumns = headerRows[0].reduce(
+          (sum: any, cell: { colSpan: any }) => sum + cell.colSpan,
+          0,
+        );
+        for (let i = 1; i < maxLevel; i++) {
+          while (worksheetData[i].length < numColumns) {
+            worksheetData[i].push('');
+          }
         }
-    }
-
-
-    const getHeaderRows = (columns: any[], level = 0, headerRows: any[] = [], maxLevel = 0) => {
-        // 规则变更:将叶子列标题统一下沉至最底行(maxLevel - 1),
-        // 上方各层以空白占位,避免纵向合并导致“高单元格”。
-        headerRows[level] = headerRows[level] || [];
-        columns.forEach((col: { title: any; children: any; }) => {
-            const colSpan = getColSpan(col);
-            if (col.children) {
-                // 父节点仅进行横向合并,不做纵向合并
-                headerRows[level].push({ title: col.title, colSpan, rowSpan: 1 });
-                getHeaderRows(col.children, level + 1, headerRows, maxLevel);
-            } else {
-                // 叶子:从当前层到倒数第二层使用空白占位,叶子标题写入最底层
-                for (let i = level; i < maxLevel - 1; i++) {
-                    headerRows[i] = headerRows[i] || [];
-                    headerRows[i].push({ title: '', colSpan: 1, rowSpan: 1 });
-                }
-                headerRows[maxLevel - 1] = headerRows[maxLevel - 1] || [];
-                headerRows[maxLevel - 1].push({ title: col.title, colSpan: 1, rowSpan: 1 });
-            }
+      }
+
+      // 提取最内层表头列,并继承 title 树上的 fontColor(父级颜色可作用到整列)
+      const leafColumnsWithColor =
+        extractLeafColumnsWithInheritedColor(tableColumns);
+      const leafColumns = leafColumnsWithColor.map((item) => item.column);
+      const dataRowColors: Array<string | undefined> = [];
+      const columnColors: Array<string | undefined> = leafColumnsWithColor.map(
+        (item) => {
+          const dataIndexKey =
+            item?.column?.dataIndex !== undefined
+              ? String(item.column.dataIndex)
+              : '';
+          const titleColor = dataIndexKey
+            ? titleColumnColorMap[dataIndexKey]
+            : undefined;
+          return pickMeaningfulColor(
+            convertToExcelRgb(titleColor || item.color),
+          );
+        },
+      );
+      const renderedRowColorMap = collectRenderedRowColorMap();
+
+      // 添加数据并处理树结构
+      drawerDataSource.forEach((record) =>
+        addRowWithIndentation(
+          record,
+          0,
+          leafColumns,
+          worksheetData,
+          dataRowColors,
+          renderedRowColorMap,
+        ),
+      );
+
+      const worksheet = XLSX.utils.aoa_to_sheet(worksheetData);
+
+      // 初始化合并单元格数组
+      worksheet['!merges'] = worksheet['!merges'] || [];
+
+      // 合并单元格
+      headerRows.forEach((row: any, rowIndex) => {
+        let colIndex = 0;
+        row.forEach((cell: { colSpan: number; rowSpan: number }) => {
+          if (cell.colSpan > 1 || cell.rowSpan > 1) {
+            worksheet['!merges']!.push({
+              // 使用非空断言 '!'
+              s: { r: rowIndex, c: colIndex },
+              e: {
+                r: rowIndex + cell.rowSpan - 1,
+                c: colIndex + cell.colSpan - 1,
+              },
+            });
+          }
+          colIndex += cell.colSpan;
         });
-        return headerRows;
-    };
-
-    const getColSpan: any = (col: { children: any[]; }) => {
-        if (!col.children) return 1;
-        return col.children.reduce((sum, child) => sum + getColSpan(child), 0);
-    };
-
-    const getMaxLevel = (col: any) => {
-        if (!col.children) return 1;
-        return 1 + Math.max(...col.children.map(getMaxLevel));
-    };
-
-    const extractLeafColumns = (columns: any[]) => {
-        let leafColumns: any[] = [];
-        columns.forEach(col => {
-            if (col.children) {
-                leafColumns = leafColumns.concat(extractLeafColumns(col.children));
-            } else {
-                leafColumns.push(col);
+      });
+
+      // 设置单元格对齐方式
+      Object.keys(worksheet).forEach((cell) => {
+        if (cell[0] !== '!') {
+          worksheet[cell].s = {
+            alignment: { vertical: 'center', horizontal: 'center' },
+          };
+        }
+      });
+
+      // 表头加粗:对 headerRows 对应的单元格区域(含横向合并范围)统一设置加粗
+      headerRows.forEach((row: any, rowIndex: number) => {
+        let colIndex = 0;
+        row.forEach((cell: { colSpan: number; rowSpan?: number }) => {
+          const spanCols = cell.colSpan || 1;
+          const spanRows = cell.rowSpan || 1;
+          for (let r = rowIndex; r < rowIndex + spanRows; r++) {
+            for (let c = colIndex; c < colIndex + spanCols; c++) {
+              const cellRef = XLSX.utils.encode_cell({ r, c });
+              if (!worksheet[cellRef]) {
+                (worksheet as any)[cellRef] = { t: 's', v: '' };
+              }
+              const prevStyle = (worksheet as any)[cellRef].s || {};
+              (worksheet as any)[cellRef].s = {
+                ...prevStyle,
+                font: {
+                  name: '微软雅黑',
+                  sz: 11,
+                  ...(prevStyle.font || {}),
+                  bold: true,
+                },
+                alignment: prevStyle.alignment || {
+                  vertical: 'center',
+                  horizontal: 'center',
+                },
+              };
             }
+          }
+          colIndex += spanCols;
         });
-        return leafColumns;
-    };
-
-    const addRowWithIndentation = (record: any, level: number, leafColumns: any[], worksheetData: any[]) => {
-        const row = leafColumns.map(col => {
-            let value = record[col.dataIndex] ?? '';
-
-            // 应用 renderText 函数来格式化导出数据,保持与表格渲染时一致
-            if (col.renderText) {
-                value = col.renderText(value, record);
-            }
-
-            return value;
+      });
+
+      // 表头字体颜色:按叶子列的颜色映射到最底层表头(与列颜色保持一致)
+      const headerRowsCount = headerRows.length;
+      const leafHeaderRowIndex = Math.max(0, headerRowsCount - 1);
+      for (let colIndex = 0; colIndex < leafColumns.length; colIndex++) {
+        const cellColor = columnColors[colIndex];
+        if (!cellColor) continue;
+        const excelColor =
+          cellColor.length === 6 ? `FF${cellColor}` : cellColor;
+        const cellRef = XLSX.utils.encode_cell({
+          r: leafHeaderRowIndex,
+          c: colIndex,
         });
-
-        // 在第一列前添加缩进空格以表示层级
-        row[0] = ' '.repeat(level * 4) + row[0]; // 每一级增加 4 个空格作为缩进
-
-        worksheetData.push(row);
-
-        // 递归处理子节点
-        if (record.children) {
-            record.children.forEach((child: any) => addRowWithIndentation(child, level + 1, leafColumns, worksheetData));
+        if (!worksheet[cellRef]) continue;
+        const prevStyle = worksheet[cellRef].s || {};
+        worksheet[cellRef].s = {
+          ...prevStyle,
+          font: {
+            name: '微软雅黑',
+            sz: 11,
+            ...(prevStyle.font || {}),
+            bold: true,
+            color: { rgb: excelColor },
+          },
+          alignment: prevStyle.alignment || {
+            vertical: 'center',
+            horizontal: 'center',
+          },
+        };
+      }
+
+      dataRowColors.forEach((rowColor, index) => {
+        const rowIndex = headerRowsCount + index;
+        for (let colIndex = 0; colIndex < leafColumns.length; colIndex++) {
+          const cellColor = rowColor || columnColors[colIndex];
+          if (!cellColor) continue;
+          const excelColor =
+            cellColor.length === 6 ? `FF${cellColor}` : cellColor;
+          const cellRef = XLSX.utils.encode_cell({ r: rowIndex, c: colIndex });
+          if (!worksheet[cellRef]) continue;
+          const prevStyle = worksheet[cellRef].s || {};
+          worksheet[cellRef].s = {
+            ...prevStyle,
+            font: {
+              name: '微软雅黑',
+              sz: 11,
+              ...(prevStyle.font || {}),
+              color: { rgb: excelColor },
+            },
+            alignment: prevStyle.alignment || {
+              vertical: 'center',
+              horizontal: 'center',
+            },
+          };
         }
-    };
+      });
 
-    const handleExport = () => {
-        try {
-            const workbook = XLSX.utils.book_new();
-            const worksheetData: any[] = [];
-
-            // 获取最大层级
-            const maxLevel = tableColumns.reduce((max, col) => Math.max(max, getMaxLevel(col)), 0);
-
-            // 生成多层级表头
-            const headerRows = getHeaderRows(tableColumns, 0, [], maxLevel);
-
-            // 构建表头行
-            headerRows.forEach((row: any, rowIndex) => {
-                const rowData: string[] = [];
-                row.forEach((cell: { title: any; colSpan: number; rowSpan: number; }) => {
-                    rowData.push(cell.title);
-                    for (let i = 1; i < cell.colSpan; i++) {
-                        rowData.push('');
-                    }
-                });
-                worksheetData.push(rowData);
-            });
-
-            // 填充单层表头的空白行
-            if (maxLevel > 1) {
-                const numColumns = headerRows[0].reduce((sum: any, cell: { colSpan: any; }) => sum + cell.colSpan, 0);
-                for (let i = 1; i < maxLevel; i++) {
-                    while (worksheetData[i].length < numColumns) {
-                        worksheetData[i].push('');
-                    }
-                }
-            }
-
-            // 提取最内层表头列
-            const leafColumns = extractLeafColumns(tableColumns);
-
-            // 添加数据并处理树结构
-            dataSource.forEach(record => addRowWithIndentation(record, 0, leafColumns, worksheetData));
+      XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
 
-            const worksheet = XLSX.utils.aoa_to_sheet(worksheetData);
-
-            // 初始化合并单元格数组
-            worksheet['!merges'] = worksheet['!merges'] || [];
-
-            // 合并单元格
-            headerRows.forEach((row: any, rowIndex) => {
-                let colIndex = 0;
-                row.forEach((cell: { colSpan: number; rowSpan: number; }) => {
-                    if (cell.colSpan > 1 || cell.rowSpan > 1) {
-                        worksheet['!merges']!.push({  // 使用非空断言 '!'
-                            s: { r: rowIndex, c: colIndex },
-                            e: { r: rowIndex + cell.rowSpan - 1, c: colIndex + cell.colSpan - 1 }
-                        });
-                    }
-                    colIndex += cell.colSpan;
-                });
-            });
-
-            // 设置单元格对齐方式
-            Object.keys(worksheet).forEach(cell => {
-                if (cell[0] !== '!') {
-                    worksheet[cell].s = {
-                        alignment: { vertical: 'center', horizontal: 'center' }
-                    };
-                }
-            });
-
-            // 表头加粗:对 headerRows 对应的单元格区域(含横向合并范围)统一设置加粗
-            headerRows.forEach((row: any, rowIndex: number) => {
-                let colIndex = 0;
-                row.forEach((cell: { colSpan: number; rowSpan?: number }) => {
-                    const spanCols = cell.colSpan || 1;
-                    const spanRows = cell.rowSpan || 1;
-                    for (let r = rowIndex; r < rowIndex + spanRows; r++) {
-                        for (let c = colIndex; c < colIndex + spanCols; c++) {
-                            const cellRef = XLSX.utils.encode_cell({ r, c });
-                            if (!worksheet[cellRef]) {
-                                (worksheet as any)[cellRef] = { t: 's', v: '' };
-                            }
-                            const prevStyle = (worksheet as any)[cellRef].s || {};
-                            (worksheet as any)[cellRef].s = {
-                                ...prevStyle,
-                                font: { name: '微软雅黑', sz: 11, ...(prevStyle.font || {}), bold: true },
-                                alignment: prevStyle.alignment || { vertical: 'center', horizontal: 'center' }
-                            };
-                        }
-                    }
-                    colIndex += spanCols;
-                });
-            });
-
-            XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
-
-            // 使用库自带的 writeFile 以最大化样式兼容性
-            XLSX.writeFile(workbook, currentTab ? `${currentTab.label}.xlsx` : 'table_data.xlsx');
-        } catch (error) {
-            console.error('Export failed:', error);
+      // 使用 write + saveAs,避免浏览器环境下 writeFile 的样式兼容差异
+      const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
+      const blob = new Blob([wbout], { type: 'application/octet-stream' });
+      saveAs(blob, currentTab ? `${currentTab.label}.xlsx` : 'table_data.xlsx');
+    } catch (error) {
+      console.error('Export failed:', error);
+    }
+  };
+
+  const handleExpandNext = useCallback(() => {
+    set_allParentsKeys((prev) => {
+      const keysToExpand = getNextUnexpandedKeys(
+        mainTableDataSource,
+        new Set(prev),
+      );
+      if (keysToExpand.length === 0) return prev;
+      return Array.from(new Set([...prev, ...keysToExpand]));
+    });
+  }, [mainTableDataSource]);
+
+  const handleCollapseAll = useCallback(() => {
+    set_allParentsKeys([]);
+  }, []);
+
+  const handleMainTableExpand = useCallback(
+    (expanded: boolean, record: any) => {
+      const { id } = record;
+      set_allParentsKeys((prev) => {
+        if (!expanded) {
+          return prev.filter((key) => key != id);
         }
-    };
-
-
-    const handleExpandNext = () => {
-        // 当前所有未展开的节点,第一层优先展开
-        const keysToExpand = getNextUnexpandedKeys(dataSource, allParentsKeys);
-        set_allParentsKeys((prev) => Array.from(new Set([...prev, ...keysToExpand])));
-    };
+        if (prev.includes(id)) {
+          return prev;
+        }
+        return [...prev, id];
+      });
+    },
+    [],
+  );
+
+  const mainTableRowClassName = useCallback(
+    (record: any) =>
+      `${
+        record.children ? 'has-children ' : ''
+      }hover-row report-font-color-row`,
+    [],
+  );
+
+  const drawerTableRowClassName = useCallback(
+    (record: any) =>
+      `${record.children ? 'has-children ' : ''}report-font-color-row`,
+    [],
+  );
+
+  const emptyRowProps = useMemo(() => ({}), []);
+
+  const getReportRowProps = useCallback(
+    (record: any) => {
+      const color = getRawReportFontColor(record);
+      if (!color) return emptyRowProps;
+      return {
+        style: {
+          ['--report-font-color' as any]: color,
+        } as React.CSSProperties,
+      };
+    },
+    [emptyRowProps],
+  );
+
+  const handleDrawerExpand = useCallback((expanded: boolean, record: any) => {
+    const { id } = record;
+    set_drawerExpandedKeys((prev) => {
+      if (!expanded) {
+        return prev.filter((key) => key != id);
+      }
+      if (prev.includes(id)) {
+        return prev;
+      }
+      return [...prev, id];
+    });
+  }, []);
 
-    const handleCollapseAll = () => {
-        set_allParentsKeys([]);
+  useEffect(() => {
+    if (computeDate && currentTabKey != undefined) {
+      getResponsibleCenterList(currentTabKey);
+    }
+    set_allParentsKeys([]);
+    set_mainTableDataSource([]);
+    set_drawerDataSource([]);
+    set_drawerExpandedKeys([]);
+  }, [computeDate, currentTabKey]);
+
+  useEffect(() => {
+    if (currentSelectedRespon) {
+      set_tableDataFilterParams((prev: any) => ({
+        ...prev,
+        responsibilityCode: currentSelectedRespon.responsibilityCode,
+        reportType: currentTabKey,
+        computeDate: computeDate,
+      }));
+    }
+    set_allParentsKeys([]);
+    set_mainTableDataSource([]);
+    set_drawerDataSource([]);
+    set_drawerExpandedKeys([]);
+  }, [computeDate, currentSelectedRespon, currentTabKey]);
+
+  useEffect(() => {
+    getTabs();
+    getIfshowPercent();
+  }, []);
+
+  const drawerTableScroll = useMemo(() => {
+    return {
+      x: countLeafNodes(tableColumns) * 200,
+      y: `calc(100vh - ${
+        84 +
+        tableColumns.reduce((max, col) => Math.max(max, getMaxLevel(col)), 0) *
+          38
+      }px)`,
     };
-
-
-    useEffect(() => {
-        if (computeDate && currentTabKey != undefined) {
-            getResponsibleCenterList(currentTabKey);
-        }
-        set_allParentsKeys([]);
-        set_dataSource([]);
-    }, [computeDate, currentTabKey]);
-
-    useEffect(() => {
-        if (currentSelectedRespon) {
-            set_tableDataFilterParams({
-                ...tableDataFilterParams,
-                responsibilityCode: currentSelectedRespon.responsibilityCode,
-                reportType: currentTabKey,
-                computeDate: computeDate
-            })
-        }
-        set_allParentsKeys([]);
-        set_dataSource([]);
-    }, [currentSelectedRespon])
-
-
-    useEffect(() => {
-        getTabs();
-        getIfshowPercent();
-    }, [])
-
-    return (
-        <KCIMPagecontainer className='DepartmentCostCalc' title={false}>
-
-            <Drawer className='drawerTable' contentWrapperStyle={{}} bodyStyle={{ padding: 16 }} title={false} open={drawerTableVisible} width={1000} headerStyle={{ display: 'none' }}>
-                <div className='header'>
-                    <div className='title'>{currentTab ? currentTab.label : ''}(单位:元)</div>
-
-                    <div className='btns'>
-                        <span onClick={() => set_drawerTableVisible(false)}>关闭</span>
-                        <span className='close' onClick={() => handleExport()}>导出</span>
-
-                    </div>
-                </div>
-                {/* {loadingtransform && <Skeleton />} */}
-                <KCIMTable loading={loadingtransform} expandable={{ defaultExpandAllRows: true }} className='departmentCostCalcReportTable'
-                    dataSource={dataSource} bordered pagination={false}
-                    rowClassName={(record) => `${record.children ? 'has-children ' : ''}report-font-color-row`}
-                    onRow={(record: any) => ({
-                        style: {
-                            ['--report-font-color' as any]: getReportFontColor(record),
-                        } as React.CSSProperties,
-                    })}
-                    scroll={{ x: countLeafNodes(tableColumns) * 200, y: `calc(100vh - ${84 + ((tableColumns.reduce((max, col) => Math.max(max, getMaxLevel(col)), 0)) * 38)}px)` }}
-                    columns={tableColumns as ProColumns[]} rowKey='id' />
-
-            </Drawer>
-
-            <div className='header'>
-                <div className="search">
-                    <span>核算年月:</span>
-                    <DatePicker
-                        onChange={(data, dateString) => {
-                            set_computeDate(dateString);
-                            setInitialState((s: any) => ({ ...s, computeDate: dateString, }))
-                            set_tableDataFilterParams({
-                                ...tableDataFilterParams,
-                                computeDate: dateString,
-                            });
-                        }}
-                        picker="month"
-                        locale={locale}
-                        defaultValue={moment(computeDate, 'YYYY-MM')}
-                        format="YYYY-MM"
-                        autoComplete="off"
-                        placeholder="选择年月"
+  }, [tableColumns]);
+
+  return (
+    <KCIMPagecontainer className="DepartmentCostCalc" title={false}>
+      <Drawer
+        className="drawerTable"
+        contentWrapperStyle={{}}
+        bodyStyle={{ padding: 16 }}
+        title={false}
+        open={drawerTableVisible}
+        width={1000}
+        headerStyle={{ display: 'none' }}
+      >
+        <div className="header">
+          <div className="title">
+            {currentTab ? currentTab.label : ''}(单位:元)
+          </div>
+
+          <div className="btns">
+            <span onClick={() => set_drawerTableVisible(false)}>关闭</span>
+            <span className="close" onClick={() => handleExport()}>
+              导出
+            </span>
+          </div>
+        </div>
+        {/* {loadingtransform && <Skeleton />} */}
+        <KCIMTable
+          loading={loadingtransform}
+          expandable={{
+            defaultExpandedRowKeys: drawerExpandedKeys,
+          }}
+          components={drawerVirtualComponents}
+          className="departmentCostCalcReportTable"
+          key={drawerDataSource.length ? 'loaded' : 'empty'}
+          dataSource={drawerDataSource}
+          bordered
+          pagination={false}
+          rowClassName={drawerTableRowClassName}
+          onRow={getReportRowProps}
+          scroll={drawerTableScroll}
+          columns={tableColumns as ProColumns[]}
+          rowKey="id"
+        />
+      </Drawer>
+
+      <div className="header">
+        <div className="search">
+          <span>核算年月:</span>
+          <DatePicker
+            onChange={(data, dateString) => {
+              set_computeDate(dateString);
+              setInitialState((s: any) => ({ ...s, computeDate: dateString }));
+              set_tableDataFilterParams((prev: any) => ({
+                ...prev,
+                computeDate: dateString,
+              }));
+            }}
+            picker="month"
+            locale={locale}
+            defaultValue={moment(computeDate, 'YYYY-MM')}
+            format="YYYY-MM"
+            autoComplete="off"
+            placeholder="选择年月"
+          />
+        </div>
+        <div className="btnGoup">
+          <span
+            className="onekeyCalcBtn"
+            onClick={() => onekeyComputeProfitHandle()}
+          >
+            一键计算
+          </span>
+        </div>
+      </div>
+      <div className="content">
+        <Tabs
+          defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
+          items={tabs}
+          key={'key'}
+          onChange={(key) => onTabChanged(key)}
+        />
+        {calcResultText && (
+          <Alert
+            showIcon
+            onClose={() => set_calcResultText(undefined)}
+            icon={
+              <IconFont
+                type={
+                  calcResultText.indexOf('失败') != -1
+                    ? 'icon-cuowutishi'
+                    : 'icon-chenggongtishi'
+                }
+              />
+            }
+            closable
+            style={{
+              padding: '4px 12px',
+              marginBottom: 16,
+              borderRadius: 4,
+              border:
+                calcResultText.indexOf('失败') != -1 ? '1px solid #73E6BF' : '',
+              background:
+                calcResultText.indexOf('失败') != -1 ? '#FFF1F3' : '#EBFFF8',
+            }}
+            message={calcResultText}
+            type={calcResultText.indexOf('失败') != -1 ? 'error' : 'success'}
+          />
+        )}
+        <div className="inner">
+          <div className="left">
+            <KCIMLeftList
+              fieldNames={{
+                title: 'responsibilityName',
+                key: 'responsibilityCode',
+                children: 'children',
+              }}
+              rowKey={'responsibilityCode'}
+              dataSource={responsibleCenters}
+              searchKey={'responsibilityName'}
+              onChange={onLeftChange}
+              contentH={`100%`}
+              // placeholder={leftListSearchPlaceHolder}
+              listType={'tree'}
+            />
+          </div>
+          <div className="right">
+            <div className="toolBar">
+              <div className="filterItem" style={{ width: 228 }}>
+                <span className="label" style={{ whiteSpace: 'nowrap' }}>
+                  {' '}
+                  检索:
+                </span>
+                <Input
+                  placeholder={'报表项目代码/名称'}
+                  allowClear
+                  autoComplete="off"
+                  suffix={
+                    <IconFont
+                      type="iconsousuo"
+                      style={{ color: '#99A6BF' }}
+                      onClick={() => tableDataSearchHandle('filter')}
                     />
-                </div>
-                <div className='btnGoup'>
-                    <span className='onekeyCalcBtn' onClick={() => onekeyComputeProfitHandle()}>一键计算</span>
-                </div>
-            </div>
-            <div className='content'>
-                <Tabs
-                    defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
-                    items={tabs}
-                    key={'key'}
-                    onChange={(key) => onTabChanged(key)}
+                  }
+                  onChange={(e) => {
+                    set_tableDataSearchKeywords(e.target.value);
+                    if (e.target.value.length == 0) {
+                      set_tableDataFilterParams((prev: any) => ({
+                        ...prev,
+                        filter: '',
+                      }));
+                    }
+                  }}
+                  onPressEnter={(e) => {
+                    set_tableDataFilterParams((prev: any) => ({
+                      ...prev,
+                      filter: (e.target as HTMLInputElement).value,
+                    }));
+                  }}
                 />
-                {calcResultText && <Alert showIcon onClose={() => set_calcResultText(undefined)} icon={<IconFont type={(calcResultText.indexOf('失败') != -1) ? 'icon-cuowutishi' : 'icon-chenggongtishi'} />} closable style={{ padding: '4px 12px', marginBottom: 16, borderRadius: 4, border: (calcResultText.indexOf('失败') != -1) ? '1px solid #73E6BF' : '', background: (calcResultText.indexOf('失败') != -1) ? '#FFF1F3' : '#EBFFF8' }} message={calcResultText} type={calcResultText.indexOf('失败') != -1 ? 'error' : 'success'} />}
-                <div className='inner'>
-                    <div className='left'>
-                        <KCIMLeftList
-                            fieldNames={{ title: 'responsibilityName', key: 'responsibilityCode', children: 'children' }}
-                            rowKey={'responsibilityCode'}
-                            dataSource={responsibleCenters} searchKey={'responsibilityName'}
-                            onChange={onLeftChange}
-                            contentH={`100%`}
-                            // placeholder={leftListSearchPlaceHolder} 
-                            listType={'tree'}
-
-                        />
-                    </div>
-                    <div className='right'>
-                        <div className='toolBar'>
-                            <div className='filterItem' style={{ width: 228 }}>
-                                <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
-                                <Input placeholder={'报表项目代码/名称'} allowClear autoComplete='off'
-                                    suffix={
-                                        <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
-                                    }
-                                    onChange={(e) => {
-                                        set_tableDataSearchKeywords(e.target.value);
-                                        if (e.target.value.length == 0) {
-                                            set_tableDataFilterParams({
-                                                ...tableDataFilterParams,
-                                                filter: ''
-                                            });
-                                        }
-                                    }}
-                                    onPressEnter={(e) => {
-                                        set_tableDataFilterParams({
-                                            ...tableDataFilterParams,
-                                            filter: ((e.target) as HTMLInputElement).value
-                                        });
-                                    }}
-
-                                />
-                            </div>
-                            <div className='btnGroup'>
-                                <span className='btn' onClick={() => handleCollapseAll()}>全部折叠</span>
-                                <span className='btn' style={{ marginRight: 16 }} onClick={() => handleExpandNext()}>展开下一层</span>
-                                <span className='btn' onClick={() => openTableDataDrawer()}>报表数据</span>
-                                <span className='calc' onClick={() => computeProfitHandle()}>计算</span>
-                            </div>
-                        </div>
-                        <KCIMTable pagination={false}
-                            rowClassName={(record) => `${record.children ? 'has-children ' : ''}hover-row report-font-color-row`}
-                            onRow={(record: any) => ({
-                                style: {
-                                    ['--report-font-color' as any]: getReportFontColor(record),
-                                } as React.CSSProperties,
-                            })}
-                            expandable={{
-                                expandedRowKeys: allParentsKeys,
-                                onExpand(expanded, record) {
-                                    const { id } = record;
-                                    if (!expanded) {
-                                        const expandedKeys = allParentsKeys.filter(a => a != id);
-                                        set_allParentsKeys([...expandedKeys]);
-                                    } else {
-                                        set_allParentsKeys([...allParentsKeys, id]);
-                                    }
-                                },
-                            }} columns={columns as ProColumns[]} scroll={{ y: `calc(100vh - 302px)` }} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
-                    </div>
-                </div>
-
-
+              </div>
+              <div className="btnGroup">
+                <span className="btn" onClick={() => handleCollapseAll()}>
+                  全部折叠
+                </span>
+                <span
+                  className="btn"
+                  style={{ marginRight: 16 }}
+                  onClick={() => handleExpandNext()}
+                >
+                  展开下一层
+                </span>
+                <span className="btn" onClick={() => openTableDataDrawer()}>
+                  报表数据
+                </span>
+                <span className="calc" onClick={() => computeProfitHandle()}>
+                  计算
+                </span>
+              </div>
             </div>
-        </KCIMPagecontainer>
-    )
+            <KCIMTable
+              pagination={false}
+              rowClassName={mainTableRowClassName}
+              onRow={getReportRowProps}
+              expandable={{
+                expandedRowKeys: allParentsKeys,
+                onExpand: handleMainTableExpand,
+              }}
+              columns={columns as ProColumns[]}
+              scroll={{ y: `calc(100vh - 302px)` }}
+              actionRef={tableRef}
+              rowKey="id"
+              params={tableDataFilterParams}
+              request={(params) => getTableData(params)}
+            />
+          </div>
+        </div>
+      </div>
+    </KCIMPagecontainer>
+  );
 }
-    

+ 49 - 63
src/pages/baseSetting/otherItemSet/departmentCostCalc/service.ts

@@ -7,124 +7,110 @@
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
 import { Key } from 'react';
 import { request } from 'umi';
 
 //获取table列表数据
-export const getReportProjectSettingList = (params:any) => {
+export const getReportProjectSettingList = (params: any) => {
   return request('/costAccount/costdepartmentprofit/getComputeProfitList', {
     method: 'GET',
-    params:{...params},
+    params: { ...params },
   });
-}
-
-
+};
 
 //新增
 export type AddTableDataType = {
-  calcFormula?:string,
-  calcType?:number,
-  isLoss?:number,
-  parentId?:number,
-  reportName?:string,
-  reportType?:number,
-  sort?:number
-}
+  calcFormula?: string;
+  calcType?: number;
+  isLoss?: number;
+  parentId?: number;
+  reportName?: string;
+  reportType?: number;
+  sort?: number;
+};
 
-export const addData = (data:AddTableDataType) => {
+export const addData = (data: AddTableDataType) => {
   return request('/costAccount/reportForm/save', {
     method: 'POST',
-    data:{...data}
+    data: { ...data },
   });
 };
 
-
-
 //编辑表格数据
 
 export type TableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType;
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/costAccount/reportForm/edit', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (ids:Key[]) => {
+export const delData = (ids: Key[]) => {
   return request('/costAccount/reportForm/delete', {
     method: 'POST',
-    data:ids
+    data: ids,
   });
 };
 
-
 //根据关系类型,获取已绑定的关系数据
-export const getHasSetReportRelation = (params:any) => {
+export const getHasSetReportRelation = (params: any) => {
   return request('/costAccount/reportForm/getRelationList', {
     method: 'GET',
-    params: {...params},
+    params: { ...params },
   });
-}
+};
 
 //保存对应设置
-export const saveReportRelation = (body:any) => {
+export const saveReportRelation = (body: any) => {
   return request('/costAccount/reportForm/saveReportRelation', {
     method: 'POST',
-    data: {...body},
+    data: { ...body },
   });
-}
+};
 
 //复制数据
-export const copyDataToSelectedType = (body:any) => {
+export const copyDataToSelectedType = (body: any) => {
   return request('/costAccount/reportForm/copyReport', {
     method: 'POST',
-    data: {...body},
+    data: { ...body },
   });
-}
+};
 
 //获取执行责任中心
-export const getResponsibleCenters = (reportType:string) => {
+export const getResponsibleCenters = (reportType: string) => {
   return request('/costAccount/costdepartmentprofit/getProfitResponsibility', {
     method: 'GET',
-    params:{reportType}
+    params: { reportType },
   });
-}
-
+};
 
 //获取报表数据
-export const getReportDataReq = (reportType:string,computeDate:string,tabkey:string) => {
-  return request(tabkey == '3'?'/costAccount/costdepartmentprofit/getComputeProfitCollect':'/costAccount/costdepartmentprofit/computeProfitReport', {
-    method: 'GET',
-    params:{reportType,computeDate}
-  });
-}
+export const getReportDataReq = (
+  reportType: string,
+  computeDate: string,
+  tabkey: string,
+) => {
+  return request(
+    tabkey == '3'
+      ? '/costAccount/costdepartmentprofit/getComputeProfitCollect'
+      : '/costAccount/costdepartmentprofit/computeProfitReport',
+    {
+      method: 'GET',
+      params: { reportType, computeDate },
+    },
+  );
+};
 
 //损益计算
 
-export const computeProfitReq = (computeDate:string,reportType:string) => {
+export const computeProfitReq = (computeDate: string, reportType: string) => {
   return request('/costAccount/costdepartmentprofit/computeProfit', {
     method: 'POST',
-    params: {computeDate,reportType},
+    params: { computeDate, reportType },
   });
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+};

+ 49 - 49
src/pages/baseSetting/otherItemSet/departmentCostCalc/style.less

@@ -10,7 +10,7 @@
     .title {
       font-weight: 500;
       font-size: 16px;
-      color: #17181A;
+      color: #17181a;
     }
     .btns {
       span {
@@ -19,15 +19,15 @@
         padding: 0 14px;
         height: 24px;
         line-height: 24px;
-        background: #FAFCFF;
+        background: #fafcff;
         border-radius: 4px;
         font-weight: 400;
         font-size: 14px;
-        color: #17181A;
-        border: 1px solid #DAE2F2;
+        color: #17181a;
+        border: 1px solid #dae2f2;
         &.close {
           color: #fff;
-          background: #3377FF;
+          background: #3377ff;
           margin-left: 8px;
         }
       }
@@ -37,6 +37,9 @@
   .departmentCostCalcReportTable {
     .cost-ant-table-body {
       .cost-ant-table-row {
+        content-visibility: auto;
+        contain-intrinsic-size: 38px;
+
         &.has-children {
           .cost-ant-table-cell-with-append {
             font-weight: bold;
@@ -49,10 +52,10 @@
           > td.cost-ant-table-cell-fix-right,
           > td.cost-ant-table-cell-fix-left-last,
           > td.cost-ant-table-cell-fix-right-first {
-            color: var(--report-font-color, #17181A) !important;
+            color: var(--report-font-color, #17181a) !important;
 
             * {
-              color: var(--report-font-color, #17181A) !important;
+              color: var(--report-font-color, #17181a) !important;
             }
           }
         }
@@ -62,7 +65,7 @@
 }
 
 .DepartmentCostCalc {
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 4px;
 
   .header {
@@ -73,26 +76,26 @@
     border-radius: 4px;
     padding: 16px;
     background-color: #fff;
-    border-bottom: 16px solid #F7F9FC;
+    border-bottom: 16px solid #f7f9fc;
 
     .btnGoup {
-      &>span {
+      & > span {
         cursor: pointer;
         display: inline-block;
-        color: #17181A;
+        color: #17181a;
         line-height: 24px;
         padding: 0 14px;
         border-radius: 4px;
-        border: 1px solid #DAE2F2;
-        background: #FAFCFF;
+        border: 1px solid #dae2f2;
+        background: #fafcff;
         margin-right: 8px;
         font-weight: 400;
         font-size: 14px;
-        color: #17181A;
+        color: #17181a;
 
         &.onekeyCalcBtn {
           color: #fff;
-          background: #3377FF;
+          background: #3377ff;
         }
       }
     }
@@ -116,8 +119,7 @@
         border-radius: 4px;
         padding-top: 8px;
         margin-right: 16px;
-        border: 1px solid #DAE2F2;
-
+        border: 1px solid #dae2f2;
       }
 
       .right {
@@ -138,23 +140,23 @@
           }
 
           .btnGroup {
-            &>span {
+            & > span {
               cursor: pointer;
               display: inline-block;
-              color: #17181A;
+              color: #17181a;
               line-height: 24px;
               padding: 0 14px;
               border-radius: 4px;
-              border: 1px solid #DAE2F2;
-              background: #FAFCFF;
+              border: 1px solid #dae2f2;
+              background: #fafcff;
               margin-right: 8px;
               font-weight: 400;
               font-size: 14px;
-              color: #17181A;
+              color: #17181a;
 
               &.calc {
                 color: #fff;
-                background: #3377FF;
+                background: #3377ff;
               }
             }
           }
@@ -164,45 +166,43 @@
             .hover-icon {
               visibility: hidden;
             }
-               &:hover {
-                .hover-icon {
-                  visibility: visible;
-                }
-               }
+            &:hover {
+              .hover-icon {
+                visibility: visible;
+              }
+            }
           }
           .cost-ant-table-header {
-                .cost-ant-table-thead {
-                    .cost-ant-table-cell {
-                        
-                    }
-                }
+            .cost-ant-table-thead {
+              .cost-ant-table-cell {
+              }
+            }
           }
           .cost-ant-table-body {
             .cost-ant-table-row {
-                &.has-children {
-                     .cost-ant-table-cell-with-append {
-                         font-weight: bold;
-                     }
+              &.has-children {
+                .cost-ant-table-cell-with-append {
+                  font-weight: bold;
                 }
+              }
 
-                &.report-font-color-row {
-                  > td,
-                  > td.cost-ant-table-cell-fix-left,
-                  > td.cost-ant-table-cell-fix-right,
-                  > td.cost-ant-table-cell-fix-left-last,
-                  > td.cost-ant-table-cell-fix-right-first {
-                    color: var(--report-font-color, #17181A) !important;
-
-                    * {
-                      color: var(--report-font-color, #17181A) !important;
-                    }
+              &.report-font-color-row {
+                > td,
+                > td.cost-ant-table-cell-fix-left,
+                > td.cost-ant-table-cell-fix-right,
+                > td.cost-ant-table-cell-fix-left-last,
+                > td.cost-ant-table-cell-fix-right-first {
+                  color: var(--report-font-color, #17181a) !important;
+
+                  * {
+                    color: var(--report-font-color, #17181a) !important;
                   }
                 }
+              }
             }
           }
         }
       }
     }
   }
-
 }

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini