فهرست منبع

Initial commit

code4eat 1 سال پیش
کامیت
6ec6ad33c0
100فایلهای تغییر یافته به همراه8661 افزوده شده و 0 حذف شده
  1. BIN
      .DS_Store
  2. 3 0
      .eslintrc.js
  3. 12 0
      .gitignore
  4. 4 0
      .husky/commit-msg
  5. 4 0
      .husky/pre-commit
  6. 17 0
      .lintstagedrc
  7. 2 0
      .npmrc
  8. 3 0
      .prettierignore
  9. 8 0
      .prettierrc
  10. 3 0
      .stylelintrc.js
  11. 128 0
      .umirc.ts
  12. 4 0
      .vscode/settings.json
  13. 3 0
      README.md
  14. 11 0
      config/proxy.ts
  15. 60 0
      mock/home.ts
  16. 242 0
      mock/monthlyData.ts
  17. 205 0
      mock/monthlyInfo.ts
  18. 54 0
      mock/monthlySet.ts
  19. 20 0
      mock/userAPI.ts
  20. 42 0
      package.json
  21. BIN
      src/.DS_Store
  22. 79 0
      src/access.ts
  23. 468 0
      src/app.tsx
  24. 0 0
      src/assets/.gitkeep
  25. 4 0
      src/components/Guide/Guide.less
  26. 23 0
      src/components/Guide/Guide.tsx
  27. 2 0
      src/components/Guide/index.ts
  28. 22 0
      src/components/KCIMDrawerForm/index.tsx
  29. 20 0
      src/components/KCIMDrawerForm/style.less
  30. 42 0
      src/components/KCIMModalForm/index.tsx
  31. 101 0
      src/components/KCIMPageContainer/index.tsx
  32. 132 0
      src/components/KCIMPageContainer/style.less
  33. 64 0
      src/components/KCIMTable/index.tsx
  34. 241 0
      src/components/KCIMTable/style.less
  35. 78 0
      src/components/KCIMUpload/index.tsx
  36. 30 0
      src/components/KCIMUpload/style.less
  37. 1 0
      src/constants/index.ts
  38. 781 0
      src/global.less
  39. 62 0
      src/menuIcons.js
  40. 13 0
      src/models/global.ts
  41. 29 0
      src/pages/Home/index.tsx
  42. 60 0
      src/pages/Home/service.ts
  43. 262 0
      src/pages/Home/style.less
  44. 261 0
      src/pages/baseInfoMana/checkGroupMana/index.tsx
  45. 96 0
      src/pages/baseInfoMana/checkGroupMana/service.ts
  46. 43 0
      src/pages/baseInfoMana/checkGroupMana/style.less
  47. 120 0
      src/pages/baseInfoMana/checkGroupMana/tableSelector.tsx
  48. 319 0
      src/pages/baseInfoMana/empMana/index.tsx
  49. 106 0
      src/pages/baseInfoMana/empMana/service.ts
  50. 80 0
      src/pages/baseInfoMana/empMana/style.less
  51. 250 0
      src/pages/baseInfoMana/empMana/tableSelector.tsx
  52. 134 0
      src/pages/baseInfoMana/empMana/transform.tsx
  53. 270 0
      src/pages/baseInfoMana/unitMana/index.tsx
  54. 62 0
      src/pages/baseInfoMana/unitMana/service.ts
  55. 78 0
      src/pages/baseInfoMana/unitMana/style.less
  56. 198 0
      src/pages/baseInfoMana/unitMana/tableSelector.tsx
  57. 221 0
      src/pages/monthlyInfoSearch/empCostDataImport/index.js
  58. 78 0
      src/pages/monthlyInfoSearch/empCostDataImport/service.js
  59. 88 0
      src/pages/monthlyInfoSearch/empCostDataImport/style.less
  60. 321 0
      src/pages/monthlyInfoSearch/patientChargeItemsImport/index.js
  61. 86 0
      src/pages/monthlyInfoSearch/patientChargeItemsImport/service.js
  62. 96 0
      src/pages/monthlyInfoSearch/patientChargeItemsImport/style.less
  63. 309 0
      src/pages/monthlyInfoSearch/patientInfoImport/index.js
  64. 78 0
      src/pages/monthlyInfoSearch/patientInfoImport/service.js
  65. 88 0
      src/pages/monthlyInfoSearch/patientInfoImport/style.less
  66. 363 0
      src/pages/setting/fenyeTemplate/index.tsx
  67. 81 0
      src/pages/setting/fenyeTemplate/service.ts
  68. 43 0
      src/pages/setting/fenyeTemplate/style.less
  69. 340 0
      src/pages/setting/qualitativeOptionsMana/index.tsx
  70. 99 0
      src/pages/setting/qualitativeOptionsMana/service.ts
  71. 43 0
      src/pages/setting/qualitativeOptionsMana/style.less
  72. 41 0
      src/services/auth.ts
  73. 96 0
      src/services/demo/UserController.ts
  74. 7 0
      src/services/demo/index.ts
  75. 68 0
      src/services/demo/typings.d.ts
  76. 55 0
      src/services/getDic.ts
  77. 33 0
      src/typings.d.ts
  78. 67 0
      src/utils/devicePixelRatio.js
  79. 20 0
      src/utils/format.ts
  80. 85 0
      src/utils/tableToExcel.ts
  81. 281 0
      src/utils/tableToMultiHeaderExcel.ts
  82. 194 0
      src/utils/tooljs.ts
  83. 8 0
      src/utils/zhongtaiA.js
  84. 8 0
      src/utils/zhongtaiB.js
  85. 8 0
      src/utils/zhongtaiC.js
  86. BIN
      static/A@2x.png
  87. BIN
      static/B@2x.png
  88. BIN
      static/C@2x.png
  89. BIN
      static/addIcon_black.png
  90. BIN
      static/arrow_blue.png
  91. BIN
      static/arrow_gray.png
  92. BIN
      static/bingzhuantu.png
  93. BIN
      static/bingzhuantu_green.png
  94. BIN
      static/calcu.png
  95. BIN
      static/confirmIcon.png
  96. BIN
      static/editIcon.png
  97. BIN
      static/editIcon_gray.png
  98. BIN
      static/filter.png
  99. BIN
      static/gou_blue.png
  100. BIN
      static/homeMenuIcon.png

BIN
.DS_Store


+ 3 - 0
.eslintrc.js

@@ -0,0 +1,3 @@
+module.exports = {
+  extends: require.resolve('@umijs/max/eslint'),
+};

+ 12 - 0
.gitignore

@@ -0,0 +1,12 @@
+/node_modules
+/.env.local
+/.umirc.local.ts
+/config/config.local.ts
+/src/.umi
+/src/.umi-production
+/src/.umi-test
+/.umi
+/.umi-production
+/.umi-test
+/dist
+/.mfsu

+ 4 - 0
.husky/commit-msg

@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx --no-install max verify-commit $1

+ 4 - 0
.husky/pre-commit

@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx --no-install lint-staged --quiet

+ 17 - 0
.lintstagedrc

@@ -0,0 +1,17 @@
+{
+  "*.{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"
+  ],
+  "*.ts?(x)": [
+    "max lint --fix --eslint-only",
+    "prettier --cache --parser=typescript --write"
+  ]
+}

+ 2 - 0
.npmrc

@@ -0,0 +1,2 @@
+registry=https://registry.npmjs.org/
+

+ 3 - 0
.prettierignore

@@ -0,0 +1,3 @@
+node_modules
+.umi
+.umi-production

+ 8 - 0
.prettierrc

@@ -0,0 +1,8 @@
+{
+  "printWidth": 80,
+  "singleQuote": true,
+  "trailingComma": "all",
+  "proseWrap": "never",
+  "overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }],
+  "plugins": ["prettier-plugin-organize-imports", "prettier-plugin-packagejson"]
+}

+ 3 - 0
.stylelintrc.js

@@ -0,0 +1,3 @@
+module.exports = {
+  extends: require.resolve('@umijs/max/stylelint'),
+};

+ 128 - 0
.umirc.ts

@@ -0,0 +1,128 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-14 14:14:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-23 09:59:34
+ * @FilePath: /BudgetManaSystem/.umirc.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+import { defineConfig } from '@umijs/max';
+
+
+const { REACT_APP_ENV } = process.env;
+
+
+export default defineConfig({
+  antd: {
+    configProvider: {
+      prefixCls: 'pfm-ant',
+    },
+  },
+  qiankun: {
+    slave: {},
+  },
+  mfsu:false,
+  lessLoader: {
+    modifyVars: { 
+      '@ant-prefix': 'pfm-ant',
+      '@primary-color': '#3377FF',
+      '@border-color-base':'#dae2f2'
+    },  
+    javascriptEnabled: true,
+  }, //对应修改生成的 antd 样式类名
+
+
+
+  access: {},
+  model: {},
+
+  initialState: {},
+  request: {},
+  layout: {
+    title: '追踪方法学后台管理',
+    layout: 'side',
+    menuProps: {
+      theme: 'light',
+    }
+  },
+  manifest: {
+    basePath: '/',
+  },
+  publicPath: REACT_APP_ENV == 'dev' ? '/' : '/pfmManager/',
+  proxy: {
+
+    '/gateway': {
+      target: 'http://120.27.235.181:5000/gateway',//开发
+      //target:'http://47.96.149.190:5000/gateway', //演示
+      changeOrigin: true,
+      // pathRewrite: { '^/gateway': '' },
+
+    }
+  },
+  routes: [
+    {
+      path: '/',
+      redirect: '/setting/fenyeTemplate',
+    },
+    {
+      path: '/monthlyInfoSearch',
+      name: '月度信息采集',
+      routes: [
+        {
+          path: '/monthlyInfoSearch/empCostDataImport',
+          name: '人事成本数据导入',
+          component: './monthlyInfoSearch/empCostDataImport/index',
+        },
+        {
+          path: '/monthlyInfoSearch/patientChargeItemsImport',
+          name: '患者收费项目导入',
+          component: './monthlyInfoSearch/patientChargeItemsImport/index',
+        },
+        {
+          path: '/monthlyInfoSearch/patientInfoImport',
+          name: '患者信息导入',
+          component: './monthlyInfoSearch/patientInfoImport/index',
+        },
+      ],
+    },
+    {
+      name: '基础信息管理',
+      path: '/baseInfoMana',
+      routes:[
+        {
+          name: '人员管理',
+          path: '/baseInfoMana/empMana',
+          component:'./baseInfoMana/empMana'
+        },
+        {
+          name: '单位管理',
+          path: '/baseInfoMana/unitMana',
+          component:'./baseInfoMana/unitMana'
+        },
+        {
+          name: '查核组管理',
+          path: '/baseInfoMana/checkGroupMana',
+          component:'./baseInfoMana/checkGroupMana'
+        },
+      ]
+    },
+    {
+      name: '通用设置',
+      path: '/setting',
+      routes:[
+        {
+          name: '定性选项管理',
+          path: '/setting/qualitativeOptionsMana',
+          component:'./setting/qualitativeOptionsMana'
+        },
+        {
+          name: '分页模板管理',
+          path: '/setting/fenyeTemplate',
+          component:'./setting/fenyeTemplate'
+        }
+      ]
+    },
+  ],
+  npmClient: 'yarn',
+});
+

+ 4 - 0
.vscode/settings.json

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

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# README
+
+`@umijs/max` 模板项目,更多功能参考 [Umi Max 简介](https://next.umijs.org/zh-CN/docs/max/introduce)

+ 11 - 0
config/proxy.ts

@@ -0,0 +1,11 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-01-10 17:40:43
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-01-10 17:53:38
+ * @FilePath: /BudgetManaSystem/config/proxy.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+

+ 60 - 0
mock/home.ts

@@ -0,0 +1,60 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-01-05 11:01:37
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-01-05 16:46:11
+ * @FilePath: /BudgetManaSystem/mock/home.ts
+ * @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()}`
+        })
+    }
+
+};

+ 242 - 0
mock/monthlyData.ts

@@ -0,0 +1,242 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-01-09 15:27:55
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-01-10 16:55:27
+ * @FilePath: /BudgetManaSystem/mock/monthlyData.ts
+ * @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",
+
+                        "deptName": "内科1",
+
+                        "empNo": "90084",
+
+                        "empName": "程静静",
+
+                        "salaryType": "1",
+
+                        "salaryTypeName": "学历工资",
+
+                        "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": "护理",
+
+                        "unitCode": "1",
+
+                        "unitName": "四病区护理组",
+
+                        "deptCode": 1,
+
+                        "deptName": "内科1",
+
+                        "assessmentCode": "1",
+
+                        "assessmentName": "最看红按头还",
+
+                        "distributionType": 1,
+
+                        "targetValue": "02032",
+
+                        "targetValueName": "程静静",
+
+                        "describe": "测试说明"
+                    },
+                    {
+                        "unitType": "1",
+
+                        "unitTypeName": "护理",
+
+                        "unitCode": "1",
+
+                        "unitName": "四病区护理组",
+
+                        "deptCode": 1,
+
+                        "deptName": "内科1",
+
+                        "assessmentCode": "2",
+
+                        "assessmentName": "最看红按头还",
+
+                        "distributionType": 1,
+
+                        "targetValue": "02032",
+
+                        "targetValueName": "程静静",
+
+                        "describe": "测试说明"
+                    }
+                ],
+                pageSize: 10,
+                totalCount: 0,
+                totalPage: 0
+            }
+
+        })
+    },
+    'GET /performance/kpi/getAssessmentList': (req: any, res: any) => {
+        res.json({
+            success: true,
+            data: [
+                {
+                    "code": "听现音红当",
+
+                    "name": "物军动前压",
+
+                    "child": [
+                        {
+                            "code": "太必世八目花电速点这动务史主不车每他象身民作或物员做",
+
+                            "name": "文时较清斗最程后作给水",
+
+                            "child": []
+
+                        }
+                    ]
+
+                }
+            ],
+
+        })
+    },
+    'GET /performance/getAssessmentData': (req: any, res: any) => {
+        res.json({
+            success: true,
+            data: {
+                current: 1,
+                list: [
+                    {
+                        "itemCode": "1",
+
+                        "itemName": "腹腔引流袋",
+
+                        "itemType": "1",
+
+                        "itemTypeName": "收费项目",
+
+                        "pointValue": 50,
+
+                        "value": 10000,
+
+                        "createUser": "低基林算几安",
+
+                        "createTime": "位派济查却精义"
+                    },
+                    {
+                        "itemCode": "1",
+
+                        "itemName": "腹腔引流袋",
+
+                        "itemType": "1",
+
+                        "itemTypeName": "收费项目",
+
+                        "pointValue": 50,
+
+                        "value": 10000,
+
+                        "createUser": "低基林算几安",
+
+                        "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": "护理组",
+
+                        "deptCode": "1",
+
+                        "deptName": "内科",
+
+                        "CMIData": {
+                            "targetValue": 1.1,
+
+                            "value": 1.2,
+
+                            "score": 27.7
+
+                        },
+
+                        "totalScore": 100
+
+                    }
+                ],
+                pageSize: 10,
+                totalCount: 0,
+                totalPage: 0
+            }
+
+        })
+    },
+}

+ 205 - 0
mock/monthlyInfo.ts

@@ -0,0 +1,205 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-01-06 14:26:54
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-01-09 13:50:07
+ * @FilePath: /BudgetManaSystem/mock/monthlyInfo.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+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",
+    }
+});
+
+
+const users = [
+    { 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: "心内科病区",
+
+                                child: [
+                                    {
+                                        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
+            }
+
+        })
+    },
+
+
+};

+ 54 - 0
mock/monthlySet.ts

@@ -0,0 +1,54 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-01-05 15:17:29
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-01-05 17:29:17
+ * @FilePath: /BudgetManaSystem/mock/monthlySet.ts
+ * @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
+        })
+    }
+};

+ 20 - 0
mock/userAPI.ts

@@ -0,0 +1,20 @@
+const users = [
+  { id: 0, name: 'Umi', nickName: 'U', gender: 'MALE' },
+  { id: 1, name: 'Fish', nickName: 'B', gender: 'FEMALE' },
+];
+
+export default {
+  'GET /api/v1/queryUserList': (req: any, res: any) => {
+    res.json({
+      success: true,
+      data: { list: users },
+      errorCode: 0,
+    });
+  },
+  'PUT /api/v1/user/': (req: any, res: any) => {
+    res.json({
+      success: true,
+      errorCode: 0,
+    });
+  },
+};

+ 42 - 0
package.json

@@ -0,0 +1,42 @@
+{
+  "name": "CostAccountingSys",
+  "private": true,
+  "author": "code4eat <awesomedema@gmail.com>",
+  "scripts": {
+    "build": "max build",
+    "dev": "cross-env REACT_APP_ENV=dev MOCK=none max dev",
+    "format": "prettier --cache --write .",
+    "postinstall": "max setup",
+    "mock": "max dev",
+    "prepare": "husky install",
+    "setup": "max setup",
+    "start": "npm run dev"
+  },
+  "dependencies": {
+    "@ant-design/icons": "^4.7.0",
+    "@ant-design/pro-components": "^2.0.1",
+    "@umijs/max": "^4.0.51",
+    "axios": "^1.3.3",
+    "file-saver": "^2.0.5",
+    "json-bigint": "^1.0.0",
+    "lodash": "^4.17.21",
+    "mathjs": "^11.6.0",
+    "react-sortable-hoc": "^2.0.0",
+    "umi-request": "^1.4.0",
+    "xlsx": "^0.18.5"
+  },
+  "devDependencies": {
+    "@types/file-saver": "^2.0.5",
+    "@types/json-bigint": "^1.0.1",
+    "@types/lodash": "^4.14.192",
+    "@types/react": "^18.0.0",
+    "@types/react-dom": "^18.0.0",
+    "cross-env": "^7.0.3",
+    "husky": "^8.0.1",
+    "lint-staged": "^13.0.3",
+    "prettier": "^2.7.1",
+    "prettier-plugin-organize-imports": "^2",
+    "prettier-plugin-packagejson": "^2",
+    "typescript": "^4.1.2"
+  }
+}

BIN
src/.DS_Store


+ 79 - 0
src/access.ts

@@ -0,0 +1,79 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-14 14:14:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-08-10 13:56:50
+ * @FilePath: /BudgetManaSystem/src/access.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+
+
+interface MenuItem {
+  function: any;
+  path: string;
+  name: string;
+  children?: 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;
+      }
+  }
+}
+
+
+
+
+
+export default (initialState: { name: string;memuData:any[] }) => {
+  // 在这里按照初始化数据定义项目中的权限,统一管理
+  // 参考文档 https://next.umijs.org/docs/max/access
+  
+  //console.log({initialState});
+
+  const {memuData} = initialState;
+  
+  const canSeeAdmin = !!(
+    initialState && initialState.name !== 'dontHaveAccess'
+  );
+
+  const whatCanIDoInThisPage = (pagePath:string)=>{
+       
+        if(memuData){
+          const thisPageData = findMenuItem(memuData,pagePath);
+          // console.log({pagePath,thisPageData});
+          if(thisPageData){
+            return thisPageData.function?thisPageData.function:[];
+          }
+          return [];
+        }
+
+  }
+
+  const canIReadThisPage = (pagePath:string)=>{
+    if(memuData){
+      const thisPageData = findMenuItem(memuData,pagePath);
+      // console.log({pagePath,thisPageData});
+      if(thisPageData){
+        return true;
+      }
+      return false;
+    }
+  }
+ 
+
+  return {
+    canSeeAdmin,
+    whatCanIDoInThisPage,
+    canIReadThisPage
+  };
+};

+ 468 - 0
src/app.tsx

@@ -0,0 +1,468 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-14 14:14:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-12 09:38:06
+ * @FilePath: /BudgetManaSystem/src/app.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+// 运行时配置
+
+// 全局初始化数据配置,用于 Layout 用户信息和权限初始化
+// 更多信息见文档:https://next.umijs.org/docs/api/runtime-config#getinitialstate
+
+
+
+
+import { AxiosResponse, history } from '@umijs/max';
+import { message, notification } from 'antd';
+import type { RequestConfig } from 'umi';
+
+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 { getPlatformMenu } from '@/services/auth';
+import { Key, useState } from 'react';
+
+
+import './utils/zhongtaiC'
+import { RuntimeAntdConfig } from '@umijs/max';
+
+
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
+
+
+// 错误处理方案: 错误类型
+enum ErrorShowType {
+  SILENT = 0,
+  WARN_MESSAGE = 1,
+  ERROR_MESSAGE = 2,
+  NOTIFICATION = 3,
+  REDIRECT = 9,
+}
+// 与后端约定的响应数据格式
+interface ResponseStructure {
+  success?: boolean;
+  code?: string;
+  data: any;
+  errorCode?: number;
+  errorMessage?: string;
+  showType?: ErrorShowType;
+}
+
+interface UserData {
+  name?: string,
+  ruleVersion?: string,
+  token?: string,
+  userId?: number,
+  youshuToken?: string
+}
+
+
+
+export async function getInitialState(): Promise<{
+  isCollapsed: boolean, spacicalPageParamsType?: any[], userData: UserData, memuData: any[]
+}> {
+
+  new DevicePixelRatio().init();
+
+  return { isCollapsed: false, spacicalPageParamsType: [], userData: {}, memuData: [] };
+}
+
+export const request: RequestConfig = {
+  // 统一的请求设定
+  timeout: 100000000,
+  headers: { 'X-Requested-With': 'XMLHttpRequest' },
+  // transformResponse:[function (data) {
+  //   try {
+  //     // 如果转换成功则返回转换的数据结果
+  //     return JSONbig.parse(data);
+  //   } catch (error) {
+  //     // 如果转换失败,则包装为统一数据格式并返回
+  //     return data
+  //   }
+  // }],
+  // 错误处理: umi@3 的错误处理方案。
+  errorConfig: {
+    // 错误抛出
+    errorThrower: (res: ResponseStructure) => {
+      const { success, data, errorCode, errorMessage, showType } = res;
+      //console.log({success, data, errorCode, errorMessage, showType});
+      if (!success) {
+        const error: any = new Error(errorMessage);
+        error.name = 'BizError';
+        error.info = { errorCode, errorMessage, showType, data };
+        throw error; // 抛出自制的错误
+      }
+    },
+    // 错误接收及处理
+    errorHandler: (error: any, opts: any) => {
+      if (opts?.skipErrorHandler) throw error;
+      // 我们的 errorThrower 抛出的错误。
+      if (error.name === 'BizError') {
+        const errorInfo: ResponseStructure | undefined = error.info;
+        if (errorInfo) {
+          const { errorMessage, errorCode } = errorInfo;
+          switch (errorInfo.showType) {
+            case ErrorShowType.SILENT:
+              // do nothing
+              break;
+            case ErrorShowType.WARN_MESSAGE:
+              message.warning(errorMessage);
+              break;
+            case ErrorShowType.ERROR_MESSAGE:
+              message.error(errorMessage);
+              break;
+            case ErrorShowType.NOTIFICATION:
+              notification.open({
+                description: errorMessage,
+                message: errorCode,
+              });
+              break;
+            case ErrorShowType.REDIRECT:
+              // TODO: redirect
+              break;
+            default:
+              message.error(errorMessage);
+          }
+        }
+      } else if (error.response) {
+        // Axios 的错误
+        // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
+        message.error(`Response status:${error.response.status}`);
+      } else if (error.request) {
+        // 请求已经成功发起,但没有收到响应
+        // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例,
+        // 而在node.js中是 http.ClientRequest 的实例
+        message.error('None response! Please retry.');
+      } else {
+        // 发送请求时出了点问题
+        message.error('Request error, please retry.');
+      }
+    },
+
+  },
+
+  // 请求拦截器
+  requestInterceptors: [
+    (config: RequestConfig) => {
+      // 拦截请求配置,进行个性化处理。
+      const userData = localStorage.getItem('userData');
+      const { token = '' } = JSON.parse(userData as any);
+      return { ...config, url: `/gateway${config.url}`, headers: { token } }
+      // return { ...config }
+    }
+  ],
+
+  // 响应拦截器
+  responseInterceptors: [
+    (response: AxiosResponse) => {
+      // 拦截响应数据,进行个性化处理
+
+      const { status, data: { status: code, errorMessage,msg }, config: { method } } = response;
+
+      try {
+
+        if (status == 200) {
+          // 网络请求成功
+
+          if (method == 'post') {
+
+            if (code == 200) {
+
+              return response.data.data == null ? {
+                success: true,
+                data: true
+              } : response.data
+
+            } else {
+              notification.error({
+                message: '',
+                description: errorMessage||msg,
+                placement: 'topRight',
+                icon: <></>
+              })
+              return false
+            }
+          } else {
+            if (status != 200) {
+              message.error('请求失败!');
+              return false
+            } else {
+              if (code == 200) {
+                //console.log({code,'response.data':response.data});
+                return response.data
+              } else {
+
+                notification.error({
+                  message: '',
+                  description: errorMessage||msg,
+                  placement: 'topRight',
+                  icon: <></>
+                })
+                return false;
+              }
+            }
+
+          }
+
+        } else {
+          return false
+        }
+
+      } catch (error) {
+        console.log({ error });
+      }
+    }
+  ]
+};
+
+
+
+export type menuDataItemType = {
+  path: string,
+  name: string,
+  icon: any,
+  component?: string,
+  softUrl?: string, // 帆软url
+  children?: menuDataItemType[]
+}
+
+// 将服务端获取的菜单 icon 字符串映射为对应的 icon Dom
+const mappingIcon = (menuData: menuDataItemType[]) => {
+  if (menuData.length == 0) {
+    return [
+      {
+        path: '',
+        name: '',
+        icon: '',
+        component: './404',
+      }
+    ]
+  }
+  const mappingMenu: menuDataItemType[] = menuData.map(item => ({
+    ...item,
+    icon: item.icon && iconEnum[item.icon],
+    children: item.children ? mappingIcon(item.children) : [],
+  }));
+  return mappingMenu;
+};
+
+
+
+const imgNode = (props: any) => {
+  return <IconFont type='icon-shouye' {...props} />
+};
+const fileIcon = () => {
+  return <IconFont type='icon-jixiaoguanli' />
+};
+
+const setting = () => {
+  return <IconFont type='icon-xitongshezhi' />
+};
+
+const secondaryDistribute = () => {
+  return <IconFont type='icon-ercifenpei' />
+};
+
+const reportCheck = () => {
+  return <IconFont type='icon-baobiaochaxun' />
+};
+
+
+
+
+
+//布局配置
+
+
+export const layout = ({ initialState, setInitialState }: { initialState: any, setInitialState: any }) => {
+
+  const { isCollapsed } = initialState;
+  const [openKeys, set_openKeys] = useState<string[]>([]);
+  const [selectedKeys, set_selectedKeys] = useState<string[]>([]);
+
+  const onCollapse = (isCollapsed: boolean): void => {
+    setInitialState({ ...initialState, isCollapsed }).then();
+  };
+
+
+  return {
+    menuHeaderRender: false,
+    token: {
+      sider: {
+
+        colorMenuBackground: '#fff',
+        colorTextMenuActive: '#3376FE',
+        colorTextMenuSelected: '#3376FE',
+        colorTextMenuTitle: '#17181A',
+        colorTextMenu: '#17181A',
+        //colorBgMenuItemHover:'##f0f2f5',
+        colorBgMenuItemSelected: '#F2F6FF',
+
+        // colorBgMenuItemCollapsedHover:'#f0f2f5',
+        // //colorBgMenuItemCollapsedSelected:'blue'
+
+      }
+
+    },
+    siderWidth: 200,
+    menuProps: {
+      openKeys: [...openKeys],
+      selectedKeys: [...selectedKeys],
+      onSelect: ({ selectedKeys }: { selectedKeys: string[] }) => {
+        set_selectedKeys(selectedKeys);
+        localStorage.setItem('selectedKeys', JSON.stringify(selectedKeys));
+      },
+      onOpenChange: (keys: string[]) => {
+        set_openKeys([...keys]);
+        localStorage.setItem('openKeys', JSON.stringify(keys));
+      },
+    },
+    menu: {
+      locale: false,
+      request: async () => {
+        const userData = localStorage.getItem('userData');
+        const currentSelectedTab = localStorage.getItem('currentSelectedTab');
+        if (currentSelectedTab) {
+          const { menuId } = JSON.parse(currentSelectedTab);
+          const systemId = menuId;
+          const data: any[] = await getPlatformMenu(systemId);
+
+          if (data) {
+
+            const selectedKeys = localStorage.getItem('selectedKeys');
+            const openKeys = localStorage.getItem('openKeys');
+
+            if (selectedKeys && openKeys) {
+              const _selectedKeys = JSON.parse(selectedKeys);
+              const _openKeys = JSON.parse(openKeys);
+              set_openKeys(_openKeys);
+              set_selectedKeys(_selectedKeys);
+            } else {
+              if (data[0].children && data[0].children.length > 0) {
+
+                const childs = data[0].children;
+                set_openKeys([data[0].key]);
+                set_selectedKeys([childs[0].key]);
+                localStorage.setItem('openKeys', JSON.stringify([data[0].key]));
+                localStorage.setItem('selectedKeys', JSON.stringify([childs[0].key]));
+                history.push(`${childs[0].path}`);
+
+              } else {
+                if (data[0]) {
+                  set_openKeys([data[0].key]);
+                  set_selectedKeys([data[0].key]);
+                  localStorage.setItem('openKeys', JSON.stringify([data[0].key]));
+                  localStorage.setItem('selectedKeys', JSON.stringify([data[0].key]));
+                  history.push(`${data[0].path}`);
+                }
+              }
+            }
+
+
+
+            const getVFromTree = (data: any[], key: string) => {
+              let result: any[] = [];
+              function looper(data: any[], key: string) {
+                data.forEach((t) => {
+                  if (t[key] && t[key] != 0) {
+                    //非一般页面
+                    if (t[key] == 1 || t[key] == 2 || t[key] == 3) {
+                      //网易有数页面
+                      result.push({
+                        contentType: t[key],
+                        path: t['path'],
+                        reportId: t['reportId'],
+                        url: t['youshuUrl'],
+                      });
+                    }
+                    if (t[key] == 5) {
+                      result.push({
+                        contentType: t[key],
+                        path: t['path'],
+                        reportId: t['reportId'],
+                        url: t['softUrl'],
+                      });
+                    }
+
+                  }
+                  if (t.children && t.children.length > 0) {
+                    looper(t.children, key);
+                  }
+                });
+              }
+              looper(data, key);
+              return result;
+            };
+
+            const _menu = getVFromTree(data, 'contentType');
+
+
+            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)) {
+                if (node.path == '/home') {
+                  node.icon = <Icon component={imgNode} />;
+                }
+                if (node.path == '/baseInfoMana') {
+                  node.icon = <Icon component={fileIcon} />;
+                }
+                if (node.path == '/setting') {
+                  node.icon = <Icon component={setting} />;
+                }
+                
+              }
+              if (node.children) {
+                node.children.forEach((child: any) => addIconToPath(child, paths));
+              }
+            }
+
+            data.forEach((item: any) => {
+              addIconToPath(item, ['/home', '/baseInfoMana', '/setting',]);
+            });
+
+
+
+            return data
+          }
+        }
+
+      },
+    },
+    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={
+          () => {
+            onCollapse(isCollapsed ? false : true);
+          }
+        }><IconFont className='menuCollapseIcon' type={isCollapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'} /></div>
+      )
+    },
+    collapsed: isCollapsed,
+    contentStyle: {
+      border: '16px solid #F7F9FC',
+      //height: '94.5vh',  //以去除顶部导航高度
+      borderRadius: '22px',
+      background: '#F7F9FC',
+      height: 'calc(100vh - 48px)'
+      // overflow:'scroll',
+      // margin:'20px 20px'
+    },
+  };
+};

+ 0 - 0
src/assets/.gitkeep


+ 4 - 0
src/components/Guide/Guide.less

@@ -0,0 +1,4 @@
+.title {
+  margin: 0 auto;
+  font-weight: 200;
+}

+ 23 - 0
src/components/Guide/Guide.tsx

@@ -0,0 +1,23 @@
+import { Layout, Row, Typography } from 'antd';
+import React from 'react';
+import styles from './Guide.less';
+
+interface Props {
+  name: string;
+}
+
+// 脚手架示例组件
+const Guide: React.FC<Props> = (props) => {
+  const { name } = props;
+  return (
+    <Layout>
+      <Row>
+        <Typography.Title level={3} className={styles.title}>
+          欢迎使用 <strong>{name}</strong> !
+        </Typography.Title>
+      </Row>
+    </Layout>
+  );
+};
+
+export default Guide;

+ 2 - 0
src/components/Guide/index.ts

@@ -0,0 +1,2 @@
+import Guide from './Guide';
+export default Guide;

+ 22 - 0
src/components/KCIMDrawerForm/index.tsx

@@ -0,0 +1,22 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-10-07 10:34:43
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-07 10:48:53
+ * @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 './style.less';
+
+
+const KCIMDrawerForm: React.FC<DrawerFormProps> = (props) => {
+    // 在这里可以添加任何自定义逻辑或样式
+
+    return <DrawerForm {...props} />;
+};
+
+
+export default KCIMDrawerForm;
+

+ 20 - 0
src/components/KCIMDrawerForm/style.less

@@ -0,0 +1,20 @@
+
+
+
+.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;
+                                  }
+                             }
+                       }
+                }
+           }
+      }
+}

+ 42 - 0
src/components/KCIMModalForm/index.tsx

@@ -0,0 +1,42 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-02-09 15:47:28
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-26 10:31:29
+ * @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 & {
+
+}
+
+
+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

+ 101 - 0
src/components/KCIMPageContainer/index.tsx

@@ -0,0 +1,101 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-15 09:20:58
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-26 10:32:05
+ * @FilePath: /BudgetManaSystem/src/components/BMSPageContainer/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+import { createFromIconfontCN } from '@ant-design/icons';
+import { PageContainer, PageContainerProps } from '@ant-design/pro-components';
+import { useModel } from '@umijs/max';
+import { useState } from 'react';
+import './style.less';
+import '../../utils/zhongtaiA'
+
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
+
+
+export type KCIMPagecontainerPropType = PageContainerProps & {
+
+}
+
+interface MenuItem {
+  function: any;
+  path: string;
+  name: string;
+  description?: string;
+  children?: MenuItem[];
+}
+
+function findMenuItem(menu: MenuItem[], path: string): MenuItem | undefined {
+  for (let i = 0; i < menu.length; i++) {
+    if (`/budgetManaSystem${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;
+    }
+  }
+}
+
+const KCIMPagecontainer = (props: KCIMPagecontainerPropType) => {
+
+  const { children, header, ...rest } = props;
+
+  const { initialState } = useModel('@@initialState');
+
+  const [open,set_open] = useState(false);
+
+  let description: undefined | string = undefined;
+
+  if (initialState) {
+    const thisPageData = findMenuItem(initialState.memuData, location.pathname);
+    description = thisPageData?.description
+  }
+
+
+  return (
+    <PageContainer {...rest}
+      header={{
+        ...header,
+        breadcrumb: {},
+        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)
+            }}
+          >
+            <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>
+              <div className='content'>
+                <img src={require('../../../static/mingcijieshi.png')} alt="" />
+                <div className='container'>
+                  <div className='inner' dangerouslySetInnerHTML={{ __html: description ? description : '' }}></div>
+                </div>
+              </div>
+            </div>
+            <IconFont className='boolIcon' type="icon-bangzhuzhongxin-weixuanzhong" />
+          </div>
+        )
+      }
+
+    </PageContainer>
+  )
+}
+
+
+export default KCIMPagecontainer

+ 132 - 0
src/components/KCIMPageContainer/style.less

@@ -0,0 +1,132 @@
+.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;
+}
+
+
+.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;
+}
+
+.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;
+}
+
+.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);
+    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;
+        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;
+                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;
+                    }
+                 }
+            }
+        }
+
+        &.open {
+         width: 320px;
+         height: 600px;
+         top: -616px;
+        }
+    }
+
+    .anticon {
+        font-size: 27px;
+        color: #6B7A99;
+    }
+
+    &.active {
+        .anticon {
+            font-size: 27px;
+            color: #17181A;
+        }
+    }
+
+    &:hover {
+        .anticon {
+            font-size: 27px;
+            color: #17181A;
+        }
+    }
+}

+ 64 - 0
src/components/KCIMTable/index.tsx

@@ -0,0 +1,64 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-20 15:24:11
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-09 13:53:34
+ * @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 './style.less'
+
+export type KCIMTablePropsType<T, U, ValueType> = ProTableProps<T, U, ValueType> & {
+    
+}
+
+export const KCIMTablePageDefaultConfig = {
+    defaultPageSize:10
+}
+
+export const KCIMTable = (props: KCIMTablePropsType<any, any, any>) => {
+
+    const { params,options = false,request,...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}
+            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} 
+        />
+    )
+}

+ 241 - 0
src/components/KCIMTable/style.less

@@ -0,0 +1,241 @@
+.cost-ant-table-wrapper {
+    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-row-indent+.cost-ant-table-row-expand-icon {
+        //margin-top: -2px !important;
+    }
+}
+
+.cost-ant-table .cost-ant-table-header {
+    border-radius: 4px !important;
+}
+
+.cost-ant-pro-table .cost-ant-pro-card .cost-ant-pro-card-body {
+     padding-inline: 0 !important;
+}
+
+.cost-ant-table-thead > tr > th {
+    padding: 8px 8px !important;
+    background: #eef3fa !important;
+
+    &::before {
+        display: none !important;
+    }
+}
+
+
+.cost-ant-table-wrapper .cost-ant-table-pagination.cost-ant-pagination {
+    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;
+}
+
+
+
+.KCIMTable {
+    .cost-ant-table {
+        .cost-ant-space-align-center {
+            gap: 0 !important;
+        }
+
+        .cost-ant-table-thead {
+            .cost-ant-table-cell {
+                border-bottom: none !important;
+                padding: 8px 8px !important;
+                //border-top:1px solid #dae2f2 !important ;
+                background: rgb(238 243 250 / 100%) !important;
+                //border-right: 1px solid  #dae2f2 !important;
+
+                a {
+                    color: #3376FE;
+                }
+
+                .cost-ant-table-selection {
+                    .cost-ant-table-selection-extra {
+                        top: 5px;
+                    }
+                }
+
+                &::before {
+                    display: none;
+                }
+
+                &:hover {
+                    background: rgb(238 243 250 / 100%) !important;
+                }
+
+                &:last-child {
+                    border-right: none;
+                }
+            }
+
+            .cost-ant-table-cell-fix-right {
+                &:last-child {
+                    right: 0 !important;
+                }
+            }
+        }
+
+        .cost-ant-table-tbody {
+            &>tr {
+                &.cost-ant-table-measure-row {
+                    border: none !important;
+                    &>td {
+                        border-inline-end:none !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;
+                        }
+    
+                        &.cost-ant-table-cell-with-append {
+                            .cost-ant-table-row-expand-icon {
+                                 
+                            }
+                        }
+    
+                        // &: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-summary {
+            &>tr>td {
+                text-align: left !important;
+                padding: 12px 8px !important;
+                border-top: 1px solid #dae2f2 !important;
+            }
+        }
+
+       
+
+        &.cost-ant-table-bordered {
+            .cost-ant-table-container {
+                border-left: none !important;
+                .cost-ant-table-header {
+                    table {
+                        border-top: 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-body {
+                    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 .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:last-child {
+    border-start-end-radius: 4px !important;
+}
+
+.cost-ant-empty-normal {
+    margin-block: 80px !important;
+    color: rgb(0 0 0 / 25%);
+}

+ 78 - 0
src/components/KCIMUpload/index.tsx

@@ -0,0 +1,78 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-02-15 16:48:56
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-26 10:49:17
+ * @FilePath: /BudgetManaSystem/src/components/BMSUpload/index.tsx
+ * @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';
+import { Upload } from 'antd';
+
+import './style.less';
+
+const { Dragger } = Upload;
+
+type KCIMUploadPropsType = {
+    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 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()
+    }
+
+    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;

+ 30 - 0
src/components/KCIMUpload/style.less

@@ -0,0 +1,30 @@
+.KCIMUpload {
+  .cost-ant-form-item {
+    margin-bottom: 0 !important;
+  }
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 16px;
+    margin-top: 16px;
+
+    &>span {
+      display: inline-block;
+      height: 15px;
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #17181A;
+      line-height:15px;
+
+      &:last-child {
+           cursor: pointer;
+           color: #3376FE;
+      }
+    }
+  }
+  
+}

+ 1 - 0
src/constants/index.ts

@@ -0,0 +1 @@
+export const DEFAULT_NAME = 'Umi Max';

+ 781 - 0
src/global.less

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

+ 62 - 0
src/menuIcons.js

@@ -0,0 +1,62 @@
+/*
+ * @Author: your name
+ * @Date: 2021-08-05 15:54:27
+ * @LastEditTime: 2021-10-18 11:43:09
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: /CostAccountManaSys/src/menuIcons.js
+ */
+
+
+import React from 'react';
+import { SmileOutlined,
+     HomeOutlined, 
+     PicLeftOutlined, 
+     SettingOutlined,
+     NodeExpandOutlined,
+     BorderOuterOutlined,
+     CopyrightOutlined,
+     ProfileOutlined,
+     AccountBookOutlined,
+     ControlOutlined,
+     CrownOutlined,
+     ToolOutlined,
+     TableOutlined,
+     FileDoneOutlined
+} from '@ant-design/icons';
+
+const iconEnum = {
+  smile: <SmileOutlined />,
+  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 />
+};
+
+// const iconEnum = {
+//   smile:SmileOutlined,
+//   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
+// };
+
+export default iconEnum;

+ 13 - 0
src/models/global.ts

@@ -0,0 +1,13 @@
+// 全局共享数据示例
+import { DEFAULT_NAME } from '@/constants';
+import { useState } from 'react';
+
+const useUser = () => {
+  const [name, setName] = useState<string>(DEFAULT_NAME);
+  return {
+    name,
+    setName,
+  };
+};
+
+export default useUser;

+ 29 - 0
src/pages/Home/index.tsx

@@ -0,0 +1,29 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-14 14:14:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-26 15:36:15
+ * @FilePath: /BudgetManaSystem/src/pages/Home/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+
+ */
+
+import React from 'react';
+
+import './style.less';
+
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+
+
+
+const HomePage: React.FC = () => {
+
+
+  return (
+    <KCIMPagecontainer className='HomePage'  ghost>
+        HomePage
+    </KCIMPagecontainer>
+  );
+};
+
+export default HomePage;

+ 60 - 0
src/pages/Home/service.ts

@@ -0,0 +1,60 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-15 15:14:12
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-07-24 13:44:24
+ * @FilePath: /BudgetManaSystem/src/pages/Home/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+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},
+       })
+}
+
+
+//获取当前计算年月
+
+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}
+    });
+}
+
+
+
+

+ 262 - 0
src/pages/Home/style.less

@@ -0,0 +1,262 @@
+.HomePage {
+  padding: 16px;
+  height: 100%;
+  padding-bottom: 36px;
+  background: #fff;
+  overflow-y: scroll;
+  .tabWrap {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    background: #F7F9FC;
+    border-radius: 4px;
+    padding: 16px 28px;
+    margin-top: 16px;
+
+    .tab {
+      position: relative;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      width: 88px;
+      height: 88px;
+      cursor: pointer;
+
+      .index {
+        position: relative;
+        width: 32px;
+        height: 32px;
+        border-radius: 8px;
+        text-align: center;
+        line-height: 32px;
+        font-size: 16px;
+        font-family: Roboto-Bold, Roboto;
+        font-weight: bold;
+        color: #FFF;
+        margin-bottom: 16px;
+        background: #CFD6E6;
+
+        .point {
+          position: absolute;
+          width: 8px;
+          height: 8px;
+          top: -2px;
+          right: -2px;
+          background: #FFC34D;
+          border-radius: 2px;
+          border: 2px solid #FFF;
+        }
+
+        &.active {
+          background: #37F;
+        }
+
+      }
+
+      .name {
+        font-size: 12px;
+        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+        font-weight: 500;
+        color: #7A8599;
+      }
+
+
+      // &::after {
+      //   right: -79%;
+      //   top: -1px;
+      //   position: absolute;
+      //   display: block;
+      //   content: '...';
+      //   font-size: 33px;
+      //   color: #DAE2F2;
+      // }
+
+
+      &.on {
+        background: #FAFCFF;
+        border-radius: 8px;
+        border: 1px solid #DAE2F2;
+      }
+
+      &.active {
+        &::after {
+          color: #37F;
+        }
+      }
+
+      &:last-child {
+        &::after {
+          display: none;
+        }
+      }
+
+
+    }
+
+    .point {
+      position: relative;
+      top: -7px;
+      // right:-22.5px;
+      font-size: 33px;
+      color: #DAE2F2;
+
+    }
+  }
+
+  .tabRelaContent {
+    margin-top: 24px;
+    min-height: 80px;
+
+    .step {
+      padding: 0 8px;
+      cursor: pointer;
+
+      .title {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: center;
+        height: 17px;
+        font-size: 16px;
+        cursor: pointer;
+        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+        font-weight: 500;
+        color: #17181A;
+        line-height: 17px;
+        margin-bottom: 10px;
+
+
+        &>span {
+          display: inline-block;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          cursor: pointer;
+          margin-left: 8px;
+        }
+
+
+      }
+
+      .detail {
+        height: 42px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #525866;
+        line-height: 21px;
+        word-break: break-all;
+        text-overflow: ellipsis;
+        display: box;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: 2;
+
+        /* 这里是超出几行省略 */
+        overflow: hidden;
+        
+      }
+
+      &.active {
+          &:hover {
+            .title { 
+              color: rgb(51 119 255 / 100%);
+
+              &>span {
+                color: rgb(51 119 255 / 100%);
+              }
+            }
+          }
+      
+      }
+    }
+
+    .multiStep {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: flex-start;
+      padding: 0 8px;
+
+      .block {
+        width: 28%;
+        cursor: pointer;
+
+        .title {
+          cursor: pointer;
+          display: flex;
+          flex-direction: row;
+          justify-content: flex-start;
+          align-items: center;
+          height: 17px;
+          font-size: 16px;
+          font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+          font-weight: 500;
+          color: #17181A;
+          line-height: 17px;
+          margin-bottom: 10px;
+
+          &>span {
+            display: inline-block;
+            font-size: 14px;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            cursor: pointer;
+            margin-left: 8px;
+          }
+
+
+        }
+
+        .detail {
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #525866;
+          line-height: 21px;
+          word-break: break-all;
+          text-overflow: ellipsis;
+          display: box;
+          -webkit-box-orient: vertical;
+          -webkit-line-clamp: 2;
+          
+          /* 这里是超出几行省略 */
+          overflow: hidden;
+
+        }
+
+        &.active {
+          &:hover {
+              .title {
+                color: rgb(51 119 255 / 100%);
+  
+                &>span {
+                  color: rgb(51 119 255 / 100%);
+                }
+              }
+          
+  
+          }
+        }
+      }
+
+      
+    }
+  }
+
+  .map {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    // border:1px solid red;
+    background: url('../../../static/shouyechatu.png');
+    // background-size: 50vw 25vw;
+    background-size: 850px 425px;
+    background-repeat: no-repeat;
+    background-position: center;
+
+    &>img {
+        
+    }
+  }
+}

+ 261 - 0
src/pages/baseInfoMana/checkGroupMana/index.tsx

@@ -0,0 +1,261 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-13 11:17:25
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @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 { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Popconfirm } from 'antd';
+import { useEffect, useRef, useState } from 'react'
+
+import { addData, delData, editData, getChackGroupData } from './service';
+
+import './style.less';
+
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMDrawerForm from '@/components/KCIMDrawerForm';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '',
+});
+
+type TableDataResponse = {
+    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 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('操作成功!');
+            }
+        }
+
+        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: '名称不能为空!' }]}
+                />
+                <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
+                            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
+                            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'>
+                    <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>
+    )
+}

+ 96 - 0
src/pages/baseInfoMana/checkGroupMana/service.ts

@@ -0,0 +1,96 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-12 18:16:15
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @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
+}
+
+
+export const getChackGroupData = (params?:any) => {
+  return request<{
+       currPage: number;
+       current:number;
+       list:any[];
+       pageSize:number;
+       totalCount:number;
+       totalPage:number;
+  }>('/manager/CheckGroup/getCheckGroupList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+//获取查核组字典
+export const getCheckData = (params?:any) => {
+  return request<{
+       currPage: number;
+       current:number;
+       list:any[];
+       pageSize:number;
+       totalCount:number;
+       totalPage:number;
+  }>('/manager/CheckGroup/getCheckGroup', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+//新增表格数据 
+export type AddTableDataType = {
+  name:string;
+  content:string;
+  remark:string;
+}
+export const addData = (data:AddTableDataType) => {
+  return request('/manager/setting/addPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//编辑表格数据
+
+export const editData = (data:{id:number}&AddTableDataType) => {
+  return request('/manager/setting/editPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+
+export const delData = (id:string) => {
+  return request('/manager/setting/deletePageTemplate', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+
+
+
+
+
+

+ 43 - 0
src/pages/baseInfoMana/checkGroupMana/style.less

@@ -0,0 +1,43 @@
+.checkGroupMana {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+    }
+
+  }
+}

+ 120 - 0
src/pages/baseInfoMana/checkGroupMana/tableSelector.tsx

@@ -0,0 +1,120 @@
+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
+}
+
+const IconFont = createFromIconfontCN({
+    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
+                    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

+ 319 - 0
src/pages/baseInfoMana/empMana/index.tsx

@@ -0,0 +1,319 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-13 16:40:53
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @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 { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Switch } from 'antd';
+import { createRef, useEffect, useRef, useState } from 'react'
+
+import { addData, bindCheckGroupReq, bindUnitReq, delData, editData, getData } from './service';
+
+import './style.less';
+
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMDrawerForm from '@/components/KCIMDrawerForm';
+import TableTransfer from './transform';
+import TableSelecter from './tableSelector';
+import { getCheckData } from '../checkGroupMana/service';
+import { debounce } from 'lodash';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '',
+});
+
+type TableDataResponse = {
+    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('操作成功!');
+            }
+
+        }
+        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>>();
+
+        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>
+        )
+    }
+
+    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();
+            }
+        }
+        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
+                            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 style={{ marginTop: 16 }}>
+                <KCIMTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
+            </div>
+        </KCIMPagecontainer>
+    )
+}

+ 106 - 0
src/pages/baseInfoMana/empMana/service.ts

@@ -0,0 +1,106 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-12 15:56:04
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @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
+}
+
+
+export const getData = (params?:any) => {
+  return request('/manager/Employee/getEmployee', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+//新增表格数据 
+export type AddTableDataType = {
+  name:string;
+  content:string;
+  remark:string;
+}
+export const addData = (data:AddTableDataType) => {
+  return request('/manager/setting/addPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//编辑权限
+export const editData = (data:{id:number,account:string,name:string,employeeId:number,permission:string}) => {
+  return request('/manager/Employee/editEmployeePermission', {
+    method: 'POST',
+    data
+  });
+};
+
+//关联单位
+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
+  });
+};
+
+//关联查核组
+export const bindCheckGroupReq = (data:{
+  employeeId:string,
+  employeeName:string,
+  groupList:{
+    code:string,
+    name:string,
+    isManager:number,
+  }[]
+}) => {
+  return request('/manager/Employee/editCheckGroup', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+
+export const delData = (id:string) => {
+  return request('/manager/setting/deletePageTemplate', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+
+
+
+
+
+

+ 80 - 0
src/pages/baseInfoMana/empMana/style.less

@@ -0,0 +1,80 @@
+
+
+
+.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;
+           }
+       }
+
+  }
+}
+
+.empMana {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+    }
+
+  }
+}

+ 250 - 0
src/pages/baseInfoMana/empMana/tableSelector.tsx

@@ -0,0 +1,250 @@
+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 './style.less';
+
+
+interface TableSelecterProps {
+    record: any
+}
+
+const IconFont = createFromIconfontCN({
+    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 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 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
+                        }
+                    });
+
+                    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]);
+                }
+            }
+
+            return Promise.resolve([]);
+        }
+
+ 
+
+        useEffect(() => {
+            getTableData()
+        }, [])
+
+
+        return (
+            <div >
+                <Input placeholder={tableSelecterType == 'UNIT'?'请输入单位名称':'请输入查核组名称'} allowClear
+                    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

+ 134 - 0
src/pages/baseInfoMana/empMana/transform.tsx

@@ -0,0 +1,134 @@
+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 { TableRowSelection } from 'antd/es/table/interface';
+import { KCIMTable } from "@/components/KCIMTable";
+
+
+interface TableTransferProps extends TransferProps<TransferItem> {
+    leftColumns: ColumnsType<any>;
+    rightColumns: ColumnsType<any>;
+}
+
+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[]>([]);
+    const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+
+    //获取单元
+    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 onChange = (nextTargetKeys: string[]) => {
+        setTargetKeys(nextTargetKeys);
+    };
+
+    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();
+            // }
+        }
+    }));
+
+    useEffect(() => {
+        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
+
+

+ 270 - 0
src/pages/baseInfoMana/unitMana/index.tsx

@@ -0,0 +1,270 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-13 11:20:45
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @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 { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Popconfirm } from 'antd';
+import React, { useEffect, useRef, useState } from 'react'
+
+import { addData, delData, editData, getData } from './service';
+
+import './style.less';
+
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMDrawerForm from '@/components/KCIMDrawerForm';
+import TableSelecter from './tableSelector';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '',
+});
+
+type TableDataResponse = {
+    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,
+            }
+            
+        }
+        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 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="请输入"
+                />
+
+                
+            </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
+                            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 style={{ marginTop: 16 }}>
+                <KCIMTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
+            </div>
+        </KCIMPagecontainer>
+    )
+}

+ 62 - 0
src/pages/baseInfoMana/unitMana/service.ts

@@ -0,0 +1,62 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-12 17:11:48
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @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) => {
+  return request('/manager/Department/getDepartmentList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+//新增表格数据 
+export type AddTableDataType = {
+  name:string;
+  content:string;
+  remark:string;
+}
+export const addData = (data:AddTableDataType) => {
+  return request('/manager/setting/addPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//编辑表格数据
+
+export const editData = (data:{id:number}&AddTableDataType) => {
+  return request('/manager/setting/editPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+
+export const delData = (id:string) => {
+  return request('/manager/setting/deletePageTemplate', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+
+
+
+
+
+

+ 78 - 0
src/pages/baseInfoMana/unitMana/style.less

@@ -0,0 +1,78 @@
+
+.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;
+           }
+       }
+
+  }
+}
+
+.unitMana {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+    }
+
+  }
+}

+ 198 - 0
src/pages/baseInfoMana/unitMana/tableSelector.tsx

@@ -0,0 +1,198 @@
+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 './style.less';
+
+
+interface TableSelecterProps {
+    record: any
+}
+
+const IconFont = createFromIconfontCN({
+    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 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 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 (
+            <div >
+                <Input placeholder={'请输入名称'} allowClear
+                    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

+ 221 - 0
src/pages/monthlyInfoSearch/empCostDataImport/index.js

@@ -0,0 +1,221 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-20 17:32:10
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import {
+  ProFormDependency,
+  ProFormDigit,
+  ProFormRadio,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import { ModalForm, ProFormText } from '@ant-design/pro-form';
+import FormItem from 'antd/es/form/FormItem';
+import {DatePicker,Input} from 'antd';
+import { useEffect, useRef, useState } from 'react';
+
+import { getData, downloadTemplateReq, importDataPost } from './service';
+
+import './style.less';
+import moment from 'moment';
+import 'moment/locale/zh-cn';
+import locale from 'antd/es/date-picker/locale/zh_CN';
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMUpload from '@/components/KCIMUpload';
+
+
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
+
+const currentData =  `${new Date().getFullYear()}-${(new Date().getMonth()+1).toString().padStart(2, '0')}`
+
+export default function empCostDataImport() {
+  const [computeDate,set_computeDate] = useState(currentData);
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState({computeDate:currentData});
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
+  const tableRef = useRef();
+
+  const columns = [
+    {
+      title: '工号',
+      dataIndex: 'empCode',
+    },
+    {
+      title: '姓名',
+      dataIndex: 'empName',
+    },
+    {
+      title: '总工时',
+      dataIndex: 'hour',
+    },
+    {
+      title: '固定薪资',
+      dataIndex: 'salary',
+    },
+    {
+      title: '变动薪资',
+      dataIndex: 'variableCompensation',
+    },
+    {
+      title: '总成本',
+      dataIndex: 'cost',
+    },
+  ];
+
+  const getTableData = async (params) => {
+    const resp = await getData({ ...params,...tableDataFilterParams});
+    const { status, data } = resp;
+    if (status == 200) {
+      const { list, totalCount, pageSize, totalPage } = data;
+      if (resp.totalCount == 0 && resp.currPage != 1) {
+        return getTableData({ ...params, current: resp.currPage - 1 });
+      } else {
+        return {
+          data: list,
+          success: true,
+          total: totalCount,
+          pageSize: pageSize,
+          totalPage: totalPage,
+        };
+      }
+    }
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName) => {
+
+
+    set_tableDataFilterParams({
+        ...tableDataFilterParams,
+        [`${paramName}`]: tableDataSearchKeywords
+    })
+  }
+
+  const downloadTemplate = async () => {
+    await downloadTemplateReq();
+  };
+
+  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 [
+              // <Button
+              //     key="ok"
+              //     onClick={auditType == '0' ? () => downloadTemplate(index) : () => { }}
+              // >
+              //     下载模板
+              // </Button>,
+              ...needBtn,
+            ];
+          },
+        }}
+        onFinish={async (values) => {
+          const {
+            importFile: { fileList },
+          } = values;
+
+          let formData = new FormData();
+          formData.append('file', fileList[0].originFileObj);
+          formData.append('computeDate',computeDate);
+
+          const resp = await importDataPost(formData);
+
+          if (resp) {
+            tableRef.current?.reload();
+            return true;
+          }
+        }}
+      >
+        <FormItem name={'importFile'}>
+          <KCIMUpload downloadTemplateFile={() => downloadTemplate()} />
+        </FormItem>
+      </ModalForm>
+    );
+  };
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="empCostDataImport" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            {
+              <div className="search">
+                <span>核算年月:</span>
+                <DatePicker
+                  onChange={(data, dateString) => {
+                    set_computeDate(dateString);
+                    set_tableDataFilterParams({
+                      ...tableDataFilterParams,
+                      computeDate: dateString,
+                    });
+                  }}
+                  picker="month"
+                  locale={locale}
+                  defaultValue={moment(`${new Date().getFullYear()}-${(new Date().getMonth()+1).toString().padStart(2, '0')}`, 'YYYY-MM')}
+                  format="YYYY-MM"
+                  placeholder="选择年月"
+                />
+              </div>
+            }
+          </div>
+          <div className='filterItem' style={{ marginLeft: 16, width: 205 }}>
+              <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
+              <Input placeholder={'输入工号,姓名'} allowClear
+                  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.value
+                      });
+                  }}
+
+              />
+          </div>
+        </div>
+        <div className="btnGroup">{importData()}</div>
+      </div>
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          columns={columns}
+          actionRef={tableRef}
+          rowKey="id"
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
+}

+ 78 - 0
src/pages/monthlyInfoSearch/empCostDataImport/service.js

@@ -0,0 +1,78 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-19 18:21:51
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import { request } from 'umi';
+import axios from 'axios';
+
+//获取table列表数据
+
+export const getData = (params) => {
+  return request('/costAccount/computeImport/getEmpCostList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+//导入数据
+export const importDataPost = (data) => {
+  return request('/costAccount/computeImport/importEmpCostList', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//下载模板
+
+export const downloadTemplateReq = () => {
+
+
+  let path = '/gateway/costAccount/computeImport/exportEmpCostList';
+
+  const userData = localStorage.getItem('userData');
+  const { token = '' } = JSON.parse(userData);
+
+  axios({
+      method: 'get',
+      url: path,
+      responseType: 'blob',
+      headers: { token },
+  })
+      .then(function (response) {
+          //console.log({ 'chunk': response });
+          const filename = decodeURI(response.headers["content-disposition"]);
+          const objectUrl = URL.createObjectURL(
+              new Blob([response.data], {
+                  type: 'application/vnd.ms-excel',
+              })
+          )
+          const link = document.createElement('a')
+          // 设置导出的文件名称
+          link.download = `${filename}` + '.xls'
+          link.style.display = 'none'
+          link.href = objectUrl
+          link.click()
+          document.body.appendChild(link)
+
+      });
+
+
+
+}
+
+
+
+
+
+
+
+
+

+ 88 - 0
src/pages/monthlyInfoSearch/empCostDataImport/style.less

@@ -0,0 +1,88 @@
+
+
+
+.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;
+           }
+       }
+
+  }
+}
+
+.empCostDataImport {
+  position: relative;
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      
+      .import ,.copy{
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+      .copy {
+          color: #17181A;
+          border: 1px solid #DAE2F2;
+          background: #FAFCFF;
+          margin-right: 8px;
+      }
+    }
+
+  }
+}

+ 321 - 0
src/pages/monthlyInfoSearch/patientChargeItemsImport/index.js

@@ -0,0 +1,321 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-20 17:36:37
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import {
+  ProFormDependency,
+  ProFormDigit,
+  ProFormRadio,
+  ProFormSelect,
+} from '@ant-design/pro-components';
+import { ModalForm, ProFormText } from '@ant-design/pro-form';
+import FormItem from 'antd/es/form/FormItem';
+import { DatePicker, Input } from 'antd';
+import { useEffect, useRef, useState } from 'react';
+
+import { getData, downloadTemplateReq, importDataPost,getTotalNumReq } from './service';
+
+import './style.less';
+import moment from 'moment';
+import 'moment/locale/zh-cn';
+import locale from 'antd/es/date-picker/locale/zh_CN';
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMUpload from '@/components/KCIMUpload';
+import {getTargetDic} from '../../../services/user';
+
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
+
+const currentData = `${new Date().getFullYear()}-${(new Date().getMonth() + 1)
+  .toString()
+  .padStart(2, '0')}`;
+
+export default function patientChargeItemsImport() {
+  const [computeDate,set_computeDate] = useState(currentData);
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState({ computeDate: currentData });
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
+  const tableRef = useRef();
+  const [totalNum,set_totalNum] = useState(0);
+
+  const columns = [
+    {
+      title: '住院号/门诊号',
+      dataIndex: 'visitNo',
+    },
+    {
+      title: '病人ID',
+      dataIndex: 'patientNo',
+    },
+    {
+      title: '患者姓名',
+      dataIndex: 'orderUserName',
+    },
+    {
+      title: '项目代码',
+      dataIndex: 'itemCode',
+    },
+    {
+      title: '项目名称',
+      dataIndex: 'itemName',
+    },
+    {
+      title: '项目类别',
+      dataIndex: 'itemType',
+    },
+    {
+      title: '开单科室代码',
+      dataIndex: 'orderDepartmentCode',
+    },
+    {
+      title: '开单科室名称',
+      dataIndex: 'orderDepartmentName',
+    },
+    {
+      title: '开单人工号',
+      dataIndex: 'orderUserCode',
+    },
+    {
+      title: '开单人姓名',
+      dataIndex: 'orderUserName',
+    },
+    {
+      title: '执行科室代码',
+      dataIndex: 'executeDepartmentCode',
+    },
+    {
+      title: '执行科室名称',
+      dataIndex: 'executeDepartmentName',
+    },
+    {
+      title: '执行人工号',
+      dataIndex: 'executeUserCode',
+    },
+    {
+      title: '执行人姓名',
+      dataIndex: 'executeUserName',
+    },
+    {
+      title: '数量',
+      dataIndex: 'amount',
+    },
+    {
+      title: '单价',
+      dataIndex: 'price',
+    },
+    {
+      title: '金额',
+      dataIndex: 'cost',
+    },
+    {
+      title: '费用发生时间',
+      dataIndex: 'executeTime',
+    },
+  ];
+
+  const getTableData = async (params) => {
+    const resp = await getData({ ...params, ...tableDataFilterParams });
+    const { status, data } = resp;
+    if (status == 200) {
+      const { list, totalCount, pageSize, totalPage } = data;
+      if (resp.totalCount == 0 && resp.currPage != 1) {
+        return getTableData({ ...params, current: resp.currPage - 1 });
+      } else {
+        return {
+          data: list,
+          success: true,
+          total: totalCount,
+          pageSize: pageSize,
+          totalPage: totalPage,
+        };
+      }
+    }
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const getTotalNum = async ()=>{
+      const resp = await getTotalNumReq(computeDate);
+      const {status,data} = resp;
+      if(status == 200){
+          set_totalNum(data);
+      }
+  }
+
+  const downloadTemplate = async () => {
+    await downloadTemplateReq();
+  };
+
+
+
+  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 [
+              // <Button
+              //     key="ok"
+              //     onClick={auditType == '0' ? () => downloadTemplate(index) : () => { }}
+              // >
+              //     下载模板
+              // </Button>,
+              ...needBtn,
+            ];
+          },
+        }}
+        onFinish={async (values) => {
+          const {
+            importFile: { fileList },
+          } = values;
+
+          let formData = new FormData();
+          formData.append('file', fileList[0].originFileObj);
+          formData.append('computeDate', computeDate);
+
+          const resp = await importDataPost(formData);
+
+          if (resp) {
+            tableRef.current?.reload();
+            return true;
+          }
+        }}
+      >
+        <FormItem name={'importFile'}>
+          <KCIMUpload downloadTemplateFile={() => downloadTemplate()} />
+        </FormItem>
+      </ModalForm>
+    );
+  };
+
+  useEffect(() => {
+    getTotalNum();
+  }, []);
+
+  return (
+    <KCIMPagecontainer className="patientChargeItemsImport" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            {
+              <div className="search">
+                <span>核算年月:</span>
+                <DatePicker
+                  onChange={(data, dateString) => {
+                    set_computeDate(dateString);
+                    set_tableDataFilterParams({
+                      ...tableDataFilterParams,
+                      computeDate: dateString,
+                    });
+                  }}
+                  picker="month"
+                  locale={locale}
+                  defaultValue={moment(
+                    `${new Date().getFullYear()}-${(new Date().getMonth() + 1)
+                      .toString()
+                      .padStart(2, '0')}`,
+                    'YYYY-MM',
+                  )}
+                  format="YYYY-MM"
+                  placeholder="选择年月"
+                />
+              </div>
+            }
+          </div>
+    
+          <div className='filterItem' style={{ marginLeft: 16 }}>
+              <span className='label'>项目类别:</span>
+              <ProFormSelect
+                  noStyle
+                  allowClear
+                  placeholder="请选择"
+                  style={{ width: 160, marginRight: 16 }}
+                  request={async () => {
+                    const resp = await getTargetDic('CHARGE_ITEM_TYPE');
+                    const { data, status } = resp;
+                    if (status == 200) {
+                      const { dataVoList } = data;
+                      return dataVoList.map((a) => ({ label: a.name, value: a.value }));
+                    }
+                    return [];
+                  }}
+                  fieldProps={{
+                      onChange(value, option) {
+                          set_tableDataFilterParams({ ...tableDataFilterParams,itemType: value })
+                      },
+                  }}
+              />
+          </div>
+          <div className="filterItem" style={{ marginLeft: 16, width: 205 }}>
+            <span className="label" style={{ whiteSpace: 'nowrap' }}>
+              {' '}
+              检索:
+            </span>
+            <Input
+              placeholder={'开单科室'}
+              allowClear
+              suffix={
+                <IconFont
+                  type="iconsousuo"
+                  style={{ color: '#99A6BF' }}
+                  onClick={() => tableDataSearchHandle('departmentName')}
+                />
+              }
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    departmentName: '',
+                  });
+                }
+              }}
+              onPressEnter={(e) => {
+                set_tableDataFilterParams({
+                  ...tableDataFilterParams,
+                  departmentName: e.target.value,
+                });
+              }}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">{importData()}</div>
+      </div>
+      <div className='total'>总金额:{totalNum}</div>
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          columns={columns}
+          actionRef={tableRef}
+          rowKey="id"
+          scroll={{x:2000}}
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
+}

+ 86 - 0
src/pages/monthlyInfoSearch/patientChargeItemsImport/service.js

@@ -0,0 +1,86 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-20 11:15:06
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import { request } from 'umi';
+import axios from 'axios';
+
+//获取table列表数据
+
+export const getData = (params) => {
+  return request('/costAccount/computeImport/getPatientItemList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+//获取总数
+export const getTotalNumReq = (computeDate) => {
+  return request('/costAccount/computeImport/getComputeTotal', {
+    method: 'GET',
+    params:{computeDate}
+  });
+};
+
+//导入数据
+export const importDataPost = (data) => {
+  return request('/costAccount/computeImport/importPatientItem', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//下载模板
+
+export const downloadTemplateReq = () => {
+
+
+  let path = '/gateway/costAccount/computeImport/exportPatientItem';
+
+  const userData = localStorage.getItem('userData');
+  const { token = '' } = JSON.parse(userData);
+
+  axios({
+      method: 'get',
+      url: path,
+      responseType: 'blob',
+      headers: { token },
+  })
+      .then(function (response) {
+          //console.log({ 'chunk': response });
+          const filename = decodeURI(response.headers["content-disposition"]);
+          const objectUrl = URL.createObjectURL(
+              new Blob([response.data], {
+                  type: 'application/vnd.ms-excel',
+              })
+          )
+          const link = document.createElement('a')
+          // 设置导出的文件名称
+          link.download = `${filename}` + '.xls'
+          link.style.display = 'none'
+          link.href = objectUrl
+          link.click()
+          document.body.appendChild(link)
+
+      });
+
+
+
+}
+
+
+
+
+
+
+
+
+

+ 96 - 0
src/pages/monthlyInfoSearch/patientChargeItemsImport/style.less

@@ -0,0 +1,96 @@
+
+
+
+.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;
+           }
+       }
+
+  }
+}
+
+.patientChargeItemsImport {
+  position: relative;
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      
+      .import ,.copy{
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+      .copy {
+          color: #17181A;
+          border: 1px solid #DAE2F2;
+          background: #FAFCFF;
+          margin-right: 8px;
+      }
+    }
+
+  }
+  .total {
+    height: 16px;
+    font-size: 16px;
+    font-weight: 500;
+    color: #17181A;
+    line-height: 16px;
+    margin: 16px 0;
+  }
+}

+ 309 - 0
src/pages/monthlyInfoSearch/patientInfoImport/index.js

@@ -0,0 +1,309 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-20 17:35:08
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import { ModalForm, ProFormText } from '@ant-design/pro-form';
+import FormItem from 'antd/es/form/FormItem';
+import {DatePicker,Input} from 'antd';
+import { useEffect, useRef, useState } from 'react';
+
+import { getData, downloadTemplateReq, importDataPost } from './service';
+
+import './style.less';
+import moment from 'moment';
+import 'moment/locale/zh-cn';
+import locale from 'antd/es/date-picker/locale/zh_CN';
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMUpload from '@/components/KCIMUpload';
+
+
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
+
+const currentData =  `${new Date().getFullYear()}-${(new Date().getMonth()+1).toString().padStart(2, '0')}`
+
+export default function patientInfoImport() {
+  const [computeDate,set_computeDate] = useState(currentData);
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState({computeDate:currentData});
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
+  const tableRef = useRef();
+
+  const columns = [
+    {
+      title: '住院号/门诊号',
+      dataIndex: 'visitNo',
+    },
+    {
+      title: '病人ID',
+      dataIndex: 'patientNo',
+    },
+    {
+      title: '患者姓名',
+      dataIndex: 'name',
+    },
+    {
+      title: '就诊类别',
+      dataIndex: 'type',
+      renderText(type, record, index, action) {
+        if(type==1)return '门诊';
+        if(type==3)return '住院';
+        if(type==2)return '急诊'
+      },
+    },
+    {
+      title: '科室代码',
+      dataIndex: 'departmentCode',
+    },
+    {
+      title: '科室名称',
+      dataIndex: 'departmentName',
+    },
+    {
+      title: '主诊断代码',
+      dataIndex: 'primaryDiagCode',
+    },
+    {
+      title: '主诊断名称',
+      dataIndex: 'primaryDiagName',
+    },
+    {
+      title: '次诊断代码',
+      ellipsis: true,
+      dataIndex: 'secondaryDiagCode',
+    },
+    {
+      title: '次诊断名称',
+      ellipsis: true,
+      dataIndex: 'secondaryDiagName',
+    },
+    {
+      title: '主手术/操作代码',
+      dataIndex: 'primaryOperationCode',
+    },
+    {
+      title: '主手术/操作名称',
+      dataIndex: 'primaryOperationName',
+    },
+    {
+      title: '次手术/操作代码',
+      ellipsis: true,
+      dataIndex: 'secondaryOperationCode',
+    },
+    {
+      title: '次手术/操作名称',
+      ellipsis: true,
+      dataIndex: 'secondaryOperationName',
+    },
+    {
+      title: 'DRG/DIP分组代码',
+      dataIndex: 'groupCode',
+    },
+    {
+      title: 'DRG/DIP分组名称',
+      dataIndex: 'groupMame',
+    },
+    {
+      title: '临床路径代码',
+      dataIndex: 'clinicalPathwayCode',
+    },
+    {
+      title: '临床路径名称',
+      dataIndex: 'clinicalPathwayName',
+    },
+    {
+      title: '入院日期',
+      dataIndex: 'inHospitalTime',
+    },
+    {
+      title: '出院日期',
+      dataIndex: 'outHospitalTime',
+    },
+    {
+      title: '住院天数',
+      dataIndex: 'inHospitalDays',
+    },
+  ];
+
+  const getTableData = async (params) => {
+    const resp = await getData({ ...params,...tableDataFilterParams});
+    const { status, data } = resp;
+    if (status == 200) {
+      const { list, totalCount, pageSize, totalPage } = data;
+      if (resp.totalCount == 0 && resp.currPage != 1) {
+        return getTableData({ ...params, current: resp.currPage - 1 });
+      } else {
+        return {
+          data: list,
+          success: true,
+          total: totalCount,
+          pageSize: pageSize,
+          totalPage: totalPage,
+        };
+      }
+    }
+    return [];
+  };
+
+  const tableDataSearchHandle = (paramName) => {
+
+
+    set_tableDataFilterParams({
+        ...tableDataFilterParams,
+        [`${paramName}`]: tableDataSearchKeywords
+    })
+  }
+
+  const downloadTemplate = async () => {
+    await downloadTemplateReq();
+  };
+
+  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 [
+              // <Button
+              //     key="ok"
+              //     onClick={auditType == '0' ? () => downloadTemplate(index) : () => { }}
+              // >
+              //     下载模板
+              // </Button>,
+              ...needBtn,
+            ];
+          },
+        }}
+        onFinish={async (values) => {
+          const {
+            importFile: { fileList },
+          } = values;
+
+          let formData = new FormData();
+          formData.append('file', fileList[0].originFileObj);
+          formData.append('computeDate',computeDate);
+
+          const resp = await importDataPost(formData);
+
+          if (resp) {
+            tableRef.current?.reload();
+            return true;
+          }
+        }}
+      >
+        <FormItem name={'importFile'}>
+          <KCIMUpload downloadTemplateFile={() => downloadTemplate()} />
+        </FormItem>
+      </ModalForm>
+    );
+  };
+
+  useEffect(() => {}, []);
+
+  return (
+    <KCIMPagecontainer className="patientInfoImport" title={false}>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            {
+              <div className="search">
+                <span>核算年月:</span>
+                <DatePicker
+                  onChange={(data, dateString) => {
+                    set_computeDate(dateString);
+                    set_tableDataFilterParams({
+                      ...tableDataFilterParams,
+                      computeDate: dateString,
+                    });
+                  }}
+                  picker="month"
+                  locale={locale}
+                  defaultValue={moment(`${new Date().getFullYear()}-${(new Date().getMonth()+1).toString().padStart(2, '0')}`, 'YYYY-MM')}
+                  format="YYYY-MM"
+                  placeholder="选择年月"
+                />
+              </div>
+            }
+          </div>
+          <div className='filterItem' style={{ marginLeft: 16, width: 205 }}>
+              <span className='label' style={{ whiteSpace: 'nowrap' }}> 科室名称:</span>
+              <Input placeholder={'请输入'} allowClear
+                  suffix={
+                      <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('departmentName')} />
+                  }
+                  onChange={(e) => {
+                      set_tableDataSearchKeywords(e.target.value);
+                      if (e.target.value.length == 0) {
+                          set_tableDataFilterParams({
+                              ...tableDataFilterParams,
+                              departmentName: ''
+                          });
+                      }
+                  }}
+                  onPressEnter={(e) => {
+                      set_tableDataFilterParams({
+                          ...tableDataFilterParams,
+                          departmentName: e.target.value
+                      });
+                  }}
+
+              />
+          </div>
+          <div className='filterItem' style={{ marginLeft: 16, width: 205 }}>
+              <span className='label' style={{ whiteSpace: 'nowrap' }}> 患者名称:</span>
+              <Input placeholder={'请输入'} allowClear
+                  suffix={
+                      <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('patientName')} />
+                  }
+                  onChange={(e) => {
+                      set_tableDataSearchKeywords(e.target.value);
+                      if (e.target.value.length == 0) {
+                          set_tableDataFilterParams({
+                              ...tableDataFilterParams,
+                              patientName: ''
+                          });
+                      }
+                  }}
+                  onPressEnter={(e) => {
+                      set_tableDataFilterParams({
+                          ...tableDataFilterParams,
+                          patientName: e.target.value
+                      });
+                  }}
+
+              />
+          </div>
+        </div>
+        <div className="btnGroup">{importData()}</div>
+      </div>
+      <div style={{ marginTop: 16 }}>
+        <KCIMTable
+          columns={columns}
+          actionRef={tableRef}
+          rowKey="id"
+          scroll={{x:2500}}
+          params={tableDataFilterParams}
+          request={(params) => getTableData(params)}
+        />
+      </div>
+    </KCIMPagecontainer>
+  );
+}

+ 78 - 0
src/pages/monthlyInfoSearch/patientInfoImport/service.js

@@ -0,0 +1,78 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-20 11:23:54
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import { request } from 'umi';
+import axios from 'axios';
+
+//获取table列表数据
+
+export const getData = (params) => {
+  return request('/costAccount/computeImport/getPatientInfoList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+//导入数据
+export const importDataPost = (data) => {
+  return request('/costAccount/computeImport/importPatientInfo', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//下载模板
+
+export const downloadTemplateReq = () => {
+
+
+  let path = '/gateway/costAccount/computeImport/exportPatientInfo';
+
+  const userData = localStorage.getItem('userData');
+  const { token = '' } = JSON.parse(userData);
+
+  axios({
+      method: 'get',
+      url: path,
+      responseType: 'blob',
+      headers: { token },
+  })
+      .then(function (response) {
+          //console.log({ 'chunk': response });
+          const filename = decodeURI(response.headers["content-disposition"]);
+          const objectUrl = URL.createObjectURL(
+              new Blob([response.data], {
+                  type: 'application/vnd.ms-excel',
+              })
+          )
+          const link = document.createElement('a')
+          // 设置导出的文件名称
+          link.download = `${filename}` + '.xls'
+          link.style.display = 'none'
+          link.href = objectUrl
+          link.click()
+          document.body.appendChild(link)
+
+      });
+
+
+
+}
+
+
+
+
+
+
+
+
+

+ 88 - 0
src/pages/monthlyInfoSearch/patientInfoImport/style.less

@@ -0,0 +1,88 @@
+
+
+
+.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;
+           }
+       }
+
+  }
+}
+
+.patientInfoImport {
+  position: relative;
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      
+      .import ,.copy{
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+      .copy {
+          color: #17181A;
+          border: 1px solid #DAE2F2;
+          background: #FAFCFF;
+          margin-right: 8px;
+      }
+    }
+
+  }
+}

+ 363 - 0
src/pages/setting/fenyeTemplate/index.tsx

@@ -0,0 +1,363 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-09 14:51:33
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @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 { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Popconfirm } from 'antd';
+import { useEffect, useRef, useState } from 'react'
+
+import { addData, delData, editData, getData } from './service';
+
+import './style.less';
+
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+import KCIMDrawerForm from '@/components/KCIMDrawerForm';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '',
+});
+
+type TableDataResponse = {
+    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: 'date',
+        },
+        {
+            title: '创建人',
+            dataIndex: 'createUserName',
+        },
+        {
+            title: '备注说明',
+            dataIndex: 'remark',
+        },
+        {
+            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):Promise<TableDataResponse|any[]> => {
+        const resp = await getData(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 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('操作成功!');
+            }
+        }
+
+        return true;
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+
+        const editableFormRef = useRef<EditableFormInstance>();
+        const formRef = useRef<ProFormInstance<any>>();
+        const editorFormRef = useRef<EditableFormInstance<any>>();
+        
+
+        const editableColumns: ProColumns[] = [
+            {
+                title: '标题',
+                dataIndex: 'title',
+                editable: () => true
+            },
+            {
+                title: '类型',
+                dataIndex: 'filedType',
+                editable: () => false
+            },
+            {
+                title: '是否必填',
+                dataIndex: 'required',
+                request: async () => [
+                    {
+                        value: 1,
+                        label: '是',
+                    },
+                    {
+                        value: 0,
+                        label: '否',
+                    },
+                ],
+                fieldProps: (_, { rowIndex }) => {
+                    return {
+                        onSelect: () => {
+                            // 每次选中重置参数
+                            editableFormRef.current?.setRowData?.(rowIndex, { fraction: [] });
+                        },
+                    };
+                },
+                renderText(text) {
+                    return text ? '是' : '否'
+                },
+            },
+            {
+                title: '是否展示信息',
+                dataIndex: 'showFiled',
+                request: async () => [
+                    {
+                        value: 1,
+                        label: '是',
+                    },
+                    {
+                        value: 0,
+                        label: '否',
+                    },
+                ],
+                fieldProps: (_, { rowIndex }) => {
+                    return {
+                        onSelect: () => {
+                            // 每次选中重置参数
+                            editableFormRef.current?.setRowData?.(rowIndex, { fraction: [] });
+                        },
+                    };
+                },
+                renderText(text) {
+                    return text ? '是' : '否'
+                },
+            },
+            {
+                title: '操作',
+                valueType: 'option',
+                render: (text, record, _, action) => [
+                    <a
+                        key="editable"
+                        onClick={() => {
+                            console.log({record});
+                            action?.startEditable?.(record.tempId);
+                        }}
+                    >
+                        编辑
+                    </a>,
+                    <a
+                        key="delete"
+                        onClick={() => {
+                            const tableDataSource = formRef.current?.getFieldValue(
+                                'table',
+                            ) as any[];
+                            formRef.current?.setFieldsValue({
+                                table: tableDataSource.filter((item) => item.tempId !== record.tempId),
+                            });
+                        }}
+                    >
+                        删除
+                    </a>,
+                ],
+            },
+        ];
+
+        let defaultTableData = JSON.parse(record.content ? record.content : '[]');
+        defaultTableData = defaultTableData.map((a: any) => ({ ...a, tempId: (Math.random() * 1000000).toFixed(0) }));
+
+        const [tempData, setTempData] = useState<any[]>(defaultTableData);
+        // console.log({defaultTableData});
+
+        return (
+            <KCIMDrawerForm
+                title={`${type == 'EDIT' ? '编辑' : '新增'}模板数据`}
+                width={800}
+                initialValues={type == 'EDIT' ? { ...record, table: defaultTableData, 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}
+                drawerProps={{ destroyOnClose: true }}
+                colProps={{ span: 24 }}
+                grid
+            >
+                <ProFormText
+                    name="name"
+                    label="模板名称:"
+                    placeholder="请输入"
+                    width={300}
+                    rules={[{ required: true, message: '名称不能为空!' }]}
+                />
+                <ProFormTextArea
+                    name="remark"
+                    label="备注说明:"
+                    placeholder="请输入"
+                />
+
+                <EditableProTable
+                    className='pfm-EditableProTable'
+                    name='table'
+                    style={{margin:'0 4px'}}
+                    rowKey={'tempId'}
+                    editableFormRef={editorFormRef}
+                    tableStyle={{ padding: 0 }}
+                    columns={editableColumns}
+                    // controlled
+                    editable={{}}
+                    recordCreatorProps={{
+                        record: () => ({ tempId: (Math.random() * 1000000).toFixed(0), filedType: 'Text' }),
+                        
+                    }}
+                />
+            </KCIMDrawerForm>
+        )
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+    }
+
+
+    useEffect(() => {
+
+    }, [])
+
+    return (
+        <KCIMPagecontainer className='FenyeTemplate' 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
+                            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 style={{ marginTop: 16 }}>
+                <KCIMTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
+            </div>
+        </KCIMPagecontainer>
+    )
+}

+ 81 - 0
src/pages/setting/fenyeTemplate/service.ts

@@ -0,0 +1,81 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-27 14:40:28
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @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
+}
+
+
+export const getData = (params?:any) => {
+  return request<{
+       currPage: number;
+       current:number;
+       list:FenyeTemplateItemType[];
+       pageSize:number;
+       totalCount:number;
+       totalPage:number;
+  }>('/manager/setting/getPageTemplateList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+//新增表格数据 
+export type AddTableDataType = {
+  name:string;
+  content:string;
+  remark:string;
+}
+export const addData = (data:AddTableDataType) => {
+  return request('/manager/setting/addPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+//编辑表格数据
+
+export const editData = (data:{id:number}&AddTableDataType) => {
+  return request('/manager/setting/editPageTemplate', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+export const delData = (id:string) => {
+  return request('/manager/setting/deletePageTemplate', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+
+
+
+
+
+

+ 43 - 0
src/pages/setting/fenyeTemplate/style.less

@@ -0,0 +1,43 @@
+.FenyeTemplate {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+    }
+
+  }
+}

+ 340 - 0
src/pages/setting/qualitativeOptionsMana/index.tsx

@@ -0,0 +1,340 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-10-09 14:49:36
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+
+
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import { ActionType, 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 { addData, delData, editData, getColorFromDic, getData } from './service';
+
+import './style.less';
+
+import KCIMPagecontainer from '@/components/KCIMPageContainer';
+import { KCIMTable } from '@/components/KCIMTable';
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '',
+});
+
+type TableDataResponse = {
+    data: any[]; 
+    success: boolean; 
+    total: number; 
+    pageSize: number; 
+    totalPage: number;
+};
+
+const resultTypeList = [
+    {
+        label: '无需操作', value: 1
+    },
+    {
+        label: '需改善回复', value: 2
+    },
+    {
+        label: '需使用改善工具', value: 3
+    }
+]
+
+export default function DicClassfication() {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const tableRef = useRef<ActionType>();
+    const modalFormRef = useRef<ProFormInstance>();
+    const [pagination,set_pagination] = useState({total:0,pageSize:10,current:1});
+
+    const columns: ProColumns[] = [
+
+        {
+            title: 'ID',
+            dataIndex: 'id',
+        },
+        {
+            title: '定性选项',
+            dataIndex: 'name',
+        },
+        {
+            title: '选项编码',
+            dataIndex: 'code',
+        },
+        {
+            title: '类型',
+            dataIndex: 'resultTypeName',
+        },
+        {
+            title: '是否默认',
+            dataIndex: 'defaultFlag',
+            renderText(num, record, index, action) {
+                return num == 1 ? '是' : '否'
+            },
+        },
+        {
+            title: '排序序号',
+            dataIndex: 'sort',
+        },
+        {
+            title: '默认颜色',
+            dataIndex: 'color',
+            renderText(text, record, index, action) {
+                return <span style={{ display: 'inline-block', backgroundColor: `#${text}`, padding: 2, borderRadius: 4, color: '#fff' }}>{text}</span>
+            },
+        },
+        {
+            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):Promise<TableDataResponse|any[]> => {
+        const resp = await getData({...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 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 currentHosp = localStorage.getItem('currentSelectedSubHop');
+            const currentUser = localStorage.getItem('userData');
+            if (currentHosp && currentUser) {
+                const { id } = JSON.parse(currentHosp);
+                const { userId } = JSON.parse(currentUser);
+                const result = {
+                    hiId: id,
+                    code: formVal.code,
+                    name: formVal.name,
+                    resultType: formVal.resultType,
+                    defaultFlag: formVal.defaultFlag,
+                    sort: formVal.sort,
+                    delFlag: '',
+                    createUser: userId,
+                    createTime: new Date().getTime(),
+                    color: formVal.color
+
+                }
+                const resp = await addData({ ...formVal });
+                if (resp) {
+                    tableRef.current?.reload();
+                    message.success('操作成功!');
+                }
+            }
+
+        }
+        if (type == 'EDIT') {
+
+            const resp = await editData({ ...formVal });
+            if (resp) {
+                tableRef.current?.reload();
+                message.success('操作成功!');
+            }
+        }
+
+        return true;
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+
+        return (
+            <ModalForm
+                title={`${type == 'EDIT' ? '编辑' : '新增'}定性选项`}
+                width={352}
+                initialValues={type == 'EDIT' ? { ...record} : {}}
+                trigger={
+                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
+                }
+                formRef={modalFormRef}
+                onFinish={(val) => {
+                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
+                }}
+                modalProps={{ destroyOnClose: true }}
+                colProps={{ span: 24 }}
+                grid
+            >
+
+                <ProFormText
+                    name="name"
+                    label="定性选项:"
+                    placeholder="请输入"
+                    rules={[{ required: true, message: '定性不能为空!' }]}
+                />
+                <ProFormText
+                    name="code"
+                    label="选项编码:"
+                    placeholder="请输入"
+                    rules={[{ required: true, message: '编码不能为空!' }]}
+                />
+                <ProFormSelect label='类型:' name='resultType'
+                    request={async () => {
+                        return resultTypeList
+                    }}
+                    rules={[{ required: true, message: '类型不能为空!' }]}
+                />
+
+                <ProFormSelect label='是否默认:' name='defaultFlag'
+                    request={async () => {
+                        return [
+                            { label: '是', value: 1 },
+                            { label: '否', value: 0 }
+                        ]
+                    }}
+                />
+                <ProFormDigit
+                    name="sort"
+                    label="排序序号:"
+                    placeholder="请输入"
+                />
+                <ProFormSelect label='默认颜色:' name='color'
+                    request={ async () => {
+                        const currentSys = localStorage.getItem('currentSelectedTab');
+                        if(currentSys){
+                            const {systemId} = JSON.parse(currentSys);
+                            const resp = await getColorFromDic({ dictType: "COLOR_TYPE",systemId:systemId });
+
+                            if (resp && resp.length > 0) {
+                                 const list = resp[0].dataVoList.map((a:any)=>{
+                                      if(type == 'ADD'&&a.defaultValue){
+                                        modalFormRef.current?.setFieldValue('color',a.value);
+                                      }
+                                      return {
+                                        label:<span style={{background:`#${a.value}`,color:'#fff',width:20,height:15,display:'inline-block',position:'relative',top:1}}>{}</span>,
+                                        value: a.value
+                                      }
+                                 });
+                                 return list
+                                
+                            } 
+                        }
+
+                        return []
+                        
+                        
+                    }}
+                />
+            </ModalForm>
+        )
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+    }
+
+
+    useEffect(() => {
+
+    }, [])
+
+    return (
+        <KCIMPagecontainer className='QualitativeOptMana' 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
+                            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='filterItem'>
+                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 类型:</span>
+                        <ProFormSelect
+                            noStyle
+                            allowClear
+                            placeholder="请选择"
+                            style={{ width: 160, marginRight: 16 }}
+                            request={async () => {
+                                return resultTypeList
+                            }}
+                            fieldProps={{
+                                onChange(value, option) {
+                                    set_tableDataFilterParams({ ...tableDataFilterParams, resultType: 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>
+    )
+}

+ 99 - 0
src/pages/setting/qualitativeOptionsMana/service.ts

@@ -0,0 +1,99 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-28 10:25:52
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import { request } from 'umi';
+
+//获取table列表数据
+
+export type QualitativeOptionItemType = {
+  id:number;
+  hiId:number;
+  code:string;
+  name:string;
+  resultType:number;
+  resultTypeName:string;
+  defaultFlag:number;
+  sort:number;
+  delFlag:number;
+  color:string
+}
+
+
+export const getData = (params?:any) => {
+  return request<{
+       currPage: any;
+       current:number;
+       list:QualitativeOptionItemType[];
+       pageSize:number;
+       totalCount:number;
+       totalPage:number;
+  }>('/manager/setting/getResultConfigList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+//新增表格数据
+export type AddTableDataType = {
+  //hospId:number;
+  hiId:string;
+  code:string;
+  name:string;
+  resultType:string;
+  defaultFlag:number;
+  sort:number;
+  delFlag:number;
+  createUser:string;
+  createTime:string;
+  color:string;
+}
+export const addData = (data:AddTableDataType) => {
+  return request('/manager/setting/addResultConfig', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+//编辑表格数据
+
+export const editData = (data:QualitativeOptionItemType) => {
+  return request('/manager/setting/editResultConfig', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+export const delData = (id:string) => {
+  return request('/manager/setting/deleteResultConfig', {
+    method: 'POST',
+    params:{id}
+  });
+};
+//获取颜色字典
+export const getColorFromDic = (params:{dictType:string,systemId:number}) => {
+  return request('/centerSys/sysdictdata/getDictData', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+
+
+
+
+
+
+

+ 43 - 0
src/pages/setting/qualitativeOptionsMana/style.less

@@ -0,0 +1,43 @@
+.QualitativeOptMana {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .toolBar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .filter {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .filterItem {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    .btnGroup {
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+    }
+
+  }
+}

+ 41 - 0
src/services/auth.ts

@@ -0,0 +1,41 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-01-30 16:53:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-17 10:05:31
+ * @FilePath: /BudgetManaSystem/src/services/oah.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+//获取当前审核状态
+
+import { request } from "@umijs/max"
+import { Key } from "react";
+
+export const getCurrentCheckStatus = (computeDate:string) => {
+    
+    return request('/performance/check/getStatus', {
+        method: 'GET',
+        params:{computeDate}
+    })
+    
+}
+
+
+// 获取当前登录用户菜单数据
+export const getMenus = (systemId:number)=>{
+    return request(`/pfm/menu/nav`, {
+      method: 'GET',
+      params:{systemId}
+    });
+}
+
+//获取平台菜单
+export const getPlatformMenu = (systemId?:Key) => {
+    return request('/centerSys/user/getMenuNav', {
+      method: 'GET',
+      params: { systemId },
+    });
+};

+ 96 - 0
src/services/demo/UserController.ts

@@ -0,0 +1,96 @@
+/* eslint-disable */
+// 该文件由 OneAPI 自动生成,请勿手动修改!
+import { request } from '@umijs/max';
+
+/** 此处后端没有提供注释 GET /api/v1/queryUserList */
+export async function queryUserList(
+  params: {
+    // query
+    /** keyword */
+    keyword?: string;
+    /** current */
+    current?: number;
+    /** pageSize */
+    pageSize?: number;
+  },
+  options?: { [key: string]: any },
+) {
+  return request<API.Result_PageInfo_UserInfo__>('/api/v1/queryUserList', {
+    method: 'GET',
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 POST /api/v1/user */
+export async function addUser(
+  body?: API.UserInfoVO,
+  options?: { [key: string]: any },
+) {
+  return request<API.Result_UserInfo_>('/api/v1/user', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 GET /api/v1/user/${param0} */
+export async function getUserDetail(
+  params: {
+    // path
+    /** userId */
+    userId?: string;
+  },
+  options?: { [key: string]: any },
+) {
+  const { userId: param0 } = params;
+  return request<API.Result_UserInfo_>(`/api/v1/user/${param0}`, {
+    method: 'GET',
+    params: { ...params },
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 PUT /api/v1/user/${param0} */
+export async function modifyUser(
+  params: {
+    // path
+    /** userId */
+    userId?: string;
+  },
+  body?: API.UserInfoVO,
+  options?: { [key: string]: any },
+) {
+  const { userId: param0 } = params;
+  return request<API.Result_UserInfo_>(`/api/v1/user/${param0}`, {
+    method: 'PUT',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    params: { ...params },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 DELETE /api/v1/user/${param0} */
+export async function deleteUser(
+  params: {
+    // path
+    /** userId */
+    userId?: string;
+  },
+  options?: { [key: string]: any },
+) {
+  const { userId: param0 } = params;
+  return request<API.Result_string_>(`/api/v1/user/${param0}`, {
+    method: 'DELETE',
+    params: { ...params },
+    ...(options || {}),
+  });
+}

+ 7 - 0
src/services/demo/index.ts

@@ -0,0 +1,7 @@
+/* eslint-disable */
+// 该文件由 OneAPI 自动生成,请勿手动修改!
+
+import * as UserController from './UserController';
+export default {
+  UserController,
+};

+ 68 - 0
src/services/demo/typings.d.ts

@@ -0,0 +1,68 @@
+/* eslint-disable */
+// 该文件由 OneAPI 自动生成,请勿手动修改!
+
+declare namespace API {
+  interface PageInfo {
+    /** 
+1 */
+    current?: number;
+    pageSize?: number;
+    total?: number;
+    list?: Array<Record<string, any>>;
+  }
+
+  interface PageInfo_UserInfo_ {
+    /** 
+1 */
+    current?: number;
+    pageSize?: number;
+    total?: number;
+    list?: Array<UserInfo>;
+  }
+
+  interface Result {
+    success?: boolean;
+    errorMessage?: string;
+    data?: Record<string, any>;
+  }
+
+  interface Result_PageInfo_UserInfo__ {
+    success?: boolean;
+    errorMessage?: string;
+    data?: PageInfo_UserInfo_;
+  }
+
+  interface Result_UserInfo_ {
+    success?: boolean;
+    errorMessage?: string;
+    data?: UserInfo;
+  }
+
+  interface Result_string_ {
+    success?: boolean;
+    errorMessage?: string;
+    data?: string;
+  }
+
+  type UserGenderEnum = 'MALE' | 'FEMALE';
+
+  interface UserInfo {
+    id?: string;
+    name?: string;
+    /** nick */
+    nickName?: string;
+    /** email */
+    email?: string;
+    gender?: UserGenderEnum;
+  }
+
+  interface UserInfoVO {
+    name?: string;
+    /** nick */
+    nickName?: string;
+    /** email */
+    email?: string;
+  }
+
+  type definitions_0 = null;
+}

+ 55 - 0
src/services/getDic.ts

@@ -0,0 +1,55 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-04-20 14:06:17
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-11 17:27:16
+ * @FilePath: /BudgetManaSystem/src/services/getDic.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+
+
+
+import { request } from "@umijs/max"
+
+
+//从公共字典获取数据
+export const getPubDicData =  () => {
+    
+    return request('/performance/dict', {
+        method: 'GET',
+    });    
+}
+
+// 筛选指定的字典数据
+
+export const getDataByKeyFromDic = (dicData:any[],key: string) => {
+
+    let result = dicData.filter((t: any) => (t.code == key));
+
+    if (result.length > 0) {
+
+      let dataArr = result[0].dataVoList;
+
+      let defaultValue = dataArr.filter((t:any) => t.defaultValue == 1);
+
+      dataArr.sort((prev:any, next:any) => {
+        return prev.sort - next.sort;
+      });
+
+      return {
+        defaultvalue: defaultValue[0] ? defaultValue[0].value : '',
+        list: dataArr.map((t:any) => {
+          return ({ label: t.name, value: t.code })
+        })
+      }
+    }
+
+    return {
+      defaultvalue: '',
+      list: []
+    };
+  }

+ 33 - 0
src/typings.d.ts

@@ -0,0 +1,33 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-15 17:40:13
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-12-15 17:41:08
+ * @FilePath: /BudgetManaSystem/src/typings.d.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+declare module 'slash2';
+declare module '*.css';
+declare module '*.less';
+declare module '*.scss';
+declare module '*.sass';
+declare module '*.svg';
+declare module '*.png';
+declare module '*.jpg';
+declare module '*.jpeg';
+declare module '*.gif';
+declare module '*.bmp';
+declare module '*.tiff';
+declare module 'omit.js';
+declare module 'numeral';
+declare module '@antv/data-set';
+declare module 'mockjs';
+declare module 'react-fittext';
+declare module 'bizcharts-plugin-slider';
+declare module '*.js';
+
+// preview.pro.ant.design only do not use in your production ;
+// preview.pro.ant.design Dedicated environment variable, please do not use it in your project.
+declare let ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: 'site' | undefined;
+
+declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false;

+ 67 - 0
src/utils/devicePixelRatio.js

@@ -0,0 +1,67 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-02-03 10:52:22
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-02-03 10:52:38
+ * @FilePath: /BudgetManaSystem/src/utils/devicePixelRatio.js
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+ class DevicePixelRatio {
+	constructor() {
+		//this.flag = false;
+	}
+	//获取系统类型
+	_getSystem() {
+		let flag = false;
+		var agent = navigator.userAgent.toLowerCase();
+		//		var isMac = /macintosh|mac os x/i.test(navigator.userAgent);
+		//		if(isMac) {
+		//			return false;
+		//		}
+		//现只针对windows处理,其它系统暂无该情况,如有,继续在此添加
+		if(agent.indexOf("windows") >= 0) {
+			return true;
+		}
+	}
+	//获取页面缩放比例
+	//	_getDevicePixelRatio() {
+	//		let t = this;
+	//	}
+	//监听方法兼容写法
+	_addHandler(element, type, handler) {
+		if(element.addEventListener) {
+			element.addEventListener(type, handler, false);
+		} else if(element.attachEvent) {
+			element.attachEvent("on" + type, handler);
+		} else {
+			element["on" + type] = handler;
+		}
+	}
+	//校正浏览器缩放比例
+	_correct() {
+		let t = this;
+		//页面devicePixelRatio(设备像素比例)变化后,计算页面body标签zoom修改其大小,来抵消devicePixelRatio带来的变化。
+		document.getElementsByTagName('body')[0].style.zoom = 1 / window.devicePixelRatio;
+	}
+	//监听页面缩放
+	_watch() {
+		let t = this;
+		t._addHandler(window, 'resize', function() { //注意这个方法是解决全局有两个window.resize
+			//重新校正
+			t._correct()
+		})
+	}
+	//初始化页面比例
+	init() {
+		let t = this;
+		if(t._getSystem()) { //判断设备,目前只在windows系统下校正浏览器缩放比例
+			//初始化页面校正浏览器缩放比例
+			t._correct();
+			//开启监听页面缩放
+			t._watch();
+		}
+	}
+}
+export default DevicePixelRatio;

+ 20 - 0
src/utils/format.ts

@@ -0,0 +1,20 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-14 14:14:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-06-08 15:27:39
+ * @FilePath: /BudgetManaSystem/src/utils/format.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+// 示例方法,没有实际意义
+export function trim(str: string) {
+  return str.trim();
+}
+
+//金额数字转换
+export function formatMoneyNumber(num:number) {
+  if (typeof num !== 'number' || isNaN(num)) {
+    return '-';
+  } 
+  return new Intl.NumberFormat('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 2 }).format(num);
+}

+ 85 - 0
src/utils/tableToExcel.ts

@@ -0,0 +1,85 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-05-31 11:18:30
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-05 15:08:17
+ * @FilePath: /BudgetManaSystem/src/utils/tableToExcel.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+import * as XLSX from 'xlsx';
+import { saveAs } from 'file-saver';
+
+type DataType = { [key: string]: string | number | null };
+
+type Column = {
+  title: string;
+  dataIndex: string;
+  key: string;
+  children?: Column[];
+};
+
+type Merge = {
+  s: { r: number; c: number };
+  e: { r: number; c: number };
+};
+
+function getMerges(columns: Column[], startRow = 0, startCol = 0): Merge[] {
+  let merges: Merge[] = [];
+  let colIndex = startCol;
+
+  for (const column of columns) {
+    let endRow = startRow;
+    let endCol = colIndex;
+
+    if (column.children) {
+      // 如果有子列,递归处理子列
+      const childMerges = getMerges(column.children, startRow + 1, colIndex);
+      merges = merges.concat(childMerges);
+
+      // 计算结束列的位置
+      endCol += column.children.length - 1;
+    }
+
+    // 添加合并项
+    merges.push({ s: { r: startRow, c: colIndex }, e: { r: endRow, c: endCol } });
+
+    // 更新列索引
+    colIndex = endCol + 1;
+  }
+
+  return merges;
+}
+
+function exportTableToExcel(tableData: DataType[], columns: Column[], fileName = 'data') {
+  // 获取列标题
+  const columnHeaders = columns.map(column => column.title);
+  
+  // 将列标题和表格数据合并
+  const allData = [columnHeaders as any].concat(tableData.map(row => Object.values(row)));
+
+
+  // 获取合并项
+  const merges = getMerges(columns);
+
+  // 创建一个新的工作簿
+  const wb = XLSX.utils.book_new();
+
+  // 将数据转化为工作表
+  const ws = XLSX.utils.aoa_to_sheet(allData);
+
+  // 设置合并项
+  ws['!merges'] = merges;
+
+  // 将工作表添加到工作簿中
+  XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
+
+  // 将工作簿转化为blob
+  const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
+  const blob = new Blob([wbout], { type: 'application/octet-stream' });
+
+  // 使用file-saver保存文件
+  saveAs(blob, `${fileName}.xlsx`);
+}
+
+
+export default exportTableToExcel;

+ 281 - 0
src/utils/tableToMultiHeaderExcel.ts

@@ -0,0 +1,281 @@
+//exportTableToMultiExcel
+
+import * as XLSX from 'xlsx';
+import { saveAs } from 'file-saver';
+
+
+type DataType = { [key: string]: string | number | null };
+
+type Column = {
+    title: string;
+    dataIndex: string;
+    key: string;
+    children?: Column[];
+};
+
+type Merge = {
+    s: { r: number; c: number };
+    e: { r: number; c: number };
+};
+
+
+function getMaxDepth(columns: Column[]): number {
+    let maxDepth = 0;
+    for (const column of columns) {
+        if (column.children) {
+            // 如果有子列,递归计算子列的深度
+            const depth = 1 + getMaxDepth(column.children);
+            maxDepth = Math.max(maxDepth, depth);
+        } else {
+            // 如果没有子列,深度为1
+            maxDepth = Math.max(maxDepth, 1);
+        }
+    }
+    return maxDepth;
+}
+
+
+
+
+function processColumns(columns: Column[], startRow = 0, startCol = 0, maxDepth = 0,colLength=0): { headers: any[][], merges: Merge[] } {
+
+    let headers: any[][] = Array.from({ length: maxDepth }, () => Array(colLength).fill(''));
+
+    let merges: Merge[] = [];
+    let colIndex = startCol;
+
+    // console.log({columns});
+
+    for (const column of columns) {
+        let endRow = startRow;
+        let endCol = colIndex;
+
+        if (column.children) {
+
+            const result = processColumns(column.children, startRow + 1, colIndex, maxDepth,colLength);
+
+            headers = headers.map((row, i) => {
+                
+                if (i === startRow) {
+                    return [...row.slice(0, colIndex), ...result.headers[i], ...row.slice(colIndex + result.headers[i].length)];
+                } else {
+                    return [...row.slice(0, colIndex), ...result.headers[i].slice(colIndex, result.headers[i].length), ...row.slice(colIndex + result.headers[i].length)];
+                }
+            });
+
+            merges = [...merges, ...result.merges];
+            endCol += getAllColumns(column.children).length - 1;  // 根据所有子列的总数来更新 endCol
+            endRow = startRow;  // 父列的标题应该在子列标题的上一行
+
+        } else {
+            endRow = maxDepth - 1;
+        }
+
+        for (let i = startRow; i <= endRow; i++) {
+            headers[i][colIndex] = i === startRow ? column.title : '';
+        }
+        
+        merges.push({ s: { r: startRow, c: colIndex }, e: { r: endRow, c: endCol } });
+        colIndex = endCol + 1;
+    }
+     
+    return { headers, merges };
+}
+
+
+function exportTableToMultiExcel(tableData: DataType[], columns: Column[], fileName = 'data', needSummary = false) {
+    const allColumns = getAllColumns(columns);  // 获取所有列(包括子列)
+
+    // 计算总结信息
+    const summary: DataType = {};
+    if (needSummary) {
+        allColumns.forEach(column => {
+            summary[column.dataIndex] = tableData.reduce((total, row) => {
+                if (typeof row[column.dataIndex] === 'number') {
+                    return total + (row[column.dataIndex] as number);
+                }
+                return total;
+            }, 0);
+        });
+        summary[allColumns[0].dataIndex] = '总计';  // 设置第一列的值为'总计'
+    }
+
+    const dataValues = [...tableData.map(row => {
+        const rowData = [];
+        for (const column of allColumns) {
+            rowData.push(row[column.dataIndex]);
+        }
+        return rowData;
+    }), needSummary ? Object.values(summary) : []];  // 如果需要汇总,那么在数据数组的末尾添加总结信息
+
+    const maxDepth = getMaxDepth(columns);
+    const { headers, merges } = processColumns(columns, 0, 0, maxDepth,columns.length);
+
+    const wb = XLSX.utils.book_new();
+    const ws = XLSX.utils.aoa_to_sheet([...headers, ...dataValues]);
+
+    // 计算每一列的最大字符长度
+    const colWidths = allColumns.map((column, i) => {
+        let maxLength = column.title.length * 2; // 初始值设为列标题的长度的两倍
+        dataValues.forEach(row => {
+            const cellValue = row[i];
+            if (cellValue) {
+                const cellLength = cellValue.toString().length;
+                // 对于宽字符,使用较大的系数;对于窄字符,使用较小的系数
+                const cellWidth = /[\u4e00-\u9fa5]/.test(cellValue.toString()) ? cellLength * 2 : cellLength;
+                maxLength = Math.max(maxLength, cellWidth);
+            }
+        });
+        return { wch: maxLength };
+    });
+
+    // 设置每一列的宽度
+    ws['!cols'] = colWidths;
+
+    // 设置单元格样式为水平和垂直居中
+    const range = XLSX.utils.decode_range(ws['!ref'] as string);
+    for (let R = range.s.r; R <= range.e.r; ++R) {
+        for (let C = range.s.c; C <= range.e.c; ++C) {
+            const cell_address = { c: C, r: R };
+            const cell_ref = XLSX.utils.encode_cell(cell_address);
+            if (!ws[cell_ref]) ws[cell_ref] = {};
+            ws[cell_ref].s = {
+                alignment: {
+                    horizontal: 'center',
+                    vertical: 'center'
+                }
+            };
+        }
+    }
+
+    // 设置表头的背景色
+    for (let r = 0; r < maxDepth; r++) {
+        for (let c = 0; c < headers[r].length; c++) {
+            if (!ws[XLSX.utils.encode_cell({ r, c })]) {
+                ws[XLSX.utils.encode_cell({ r, c })] = {};
+            }
+            ws[XLSX.utils.encode_cell({ r, c })].s = {
+                fill: {
+                    fgColor: { rgb: "FFFF00" }  // 设置为黄色
+                },
+                alignment: {
+                    horizontal: 'center',
+                    vertical: 'center'
+                }
+            };
+        }
+    }
+
+    ws['!merges'] = merges;
+    XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
+    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
+    const blob = new Blob([wbout], { type: 'application/octet-stream' });
+    saveAs(blob, `${fileName}.xlsx`);
+}
+
+
+
+
+function getAllColumns(columns: Column[]): Column[] {
+    let allColumns: Column[] = [];
+    for (const column of columns) {
+        if (column.children) {
+            allColumns = [...allColumns, ...getAllColumns(column.children)];
+        } else {
+            allColumns.push(column);
+        }
+    }
+    return allColumns;
+}
+
+export default exportTableToMultiExcel;
+
+
+
+const columns = [
+    {
+        dataIndex: "unitName",
+        ellipsis: true,
+        fixed: "left",
+        key: "unitName",
+        title: "核算单元",
+        width: 140
+    },
+    {
+        dataIndex: "key-23",
+        ellipsis: true,
+        key: "key-23",
+        title: "单元管理绩效",
+        width: 200
+    },
+    {
+        dataIndex: "key-1679019958216040448",
+        ellipsis: true,
+        key: "key-1679019958216040448",
+        title: "临床诊察积分奖金",
+        width: 200,
+        children: [
+            {
+                dataIndex: "key-6",
+                ellipsis: true,
+                key: "key-6",
+                title: "临床诊察积分-节假日奖金",
+                width: 200,
+                children: [
+                    {
+                        dataIndex: "key-4",
+                        ellipsis: true,
+                        key: "key-4",
+                        title: "临床诊察积分-节假日",
+                        width: 200
+                    },
+                    {
+                        dataIndex: "key-5",
+                        ellipsis: true,
+                        key: "key-5",
+                        title: "临床诊察积分-节假日点值",
+                        width: 200
+                    }
+                ]
+            },
+            {
+                dataIndex: "key-3",
+                ellipsis: true,
+                key: "key-3",
+                title: "临床诊察积分-工作日奖金",
+                width: 200,
+                children: [
+                    {
+                        dataIndex: "key-1",
+                        ellipsis: true,
+                        key: "key-1",
+                        title: "临床诊察积分-工作日",
+                        width: 200
+                    },
+                    {
+                        dataIndex: "key-2",
+                        ellipsis: true,
+                        key: "key-2",
+                        title: "临床诊察积分-工作日点值",
+                        width: 200
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        dataIndex: "totalScore",
+        ellipsis: true,
+        fixed: "right",
+        key: "totalScore",
+        title: "总奖金",
+        width: 140
+    }
+]
+
+
+
+
+
+
+

+ 194 - 0
src/utils/tooljs.ts

@@ -0,0 +1,194 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-02-20 14:31:06
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-21 14:38:08
+ * @FilePath: /BudgetManaSystem/src/utils/tooljs.js
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+let parent:any = undefined;
+
+export const getDeepestTreeData:any= (tree:any,childrenName:string)=>{
+     
+      if(tree[`${childrenName}`]&&tree[`${childrenName}`].length>0){
+           parent = tree;
+           return getDeepestTreeData(tree[`${childrenName}`][0],childrenName)    
+      }
+
+      return  [tree,parent] 
+}
+
+
+
+
+
+/*
+ * @param x {Object} 对象1
+ * @param y {Object} 对象2
+ * @return  {Boolean} true 为相等,false 为不等
+ */
+export  const deepEqual = (x: { [x: string]: any; } | null, y: { [x: string]: any; hasOwnProperty?: any; } | null) => {
+      // 指向同一内存时
+      if (x === y) {
+        return true;
+      } else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
+        if (Object.keys(x).length !== Object.keys(y).length) {
+          return false;
+        }
+        for (var prop in x) {
+          if (y.hasOwnProperty(prop)) {  
+            if (!deepEqual(x[prop], y[prop])) return false;
+          } else {
+            return false;
+          }
+        }
+        return true;
+      } else {
+        return false;
+      }
+}
+
+
+// 查找父节点的函数
+
+interface Node {
+  code: string;
+  parentCode: number;
+  children?: Node[];
+}
+
+export const findAllParents = (data: Node[], parentCode:string): Node[] => {
+  let result: Node[] = [];
+
+  function findNodeRecursively(node: Node, path: Node[]): boolean {
+      if (node.code === `${parentCode}`) {
+          result = [...path, node];
+          return true;
+      }
+
+      if (node.children) {
+          for (const child of node.children) {
+              if (findNodeRecursively(child, [...path, node])) {
+                  return true;
+              }
+          }
+      }
+
+      return false;
+  }
+
+  for (const node of data) {
+      if (parentCode != '0' && findNodeRecursively(node, [])) {
+          break;
+      }
+  }
+
+  return result;
+}
+
+
+//获取所有children节点的code
+
+interface TreeNode {
+  code: string;
+  [key:string]:any,
+  children?: TreeNode[];
+}
+
+
+export const getNodesWithChildren = (tree: TreeNode[]): TreeNode[] => {
+  let nodes: TreeNode[] = [];
+
+  function helper(node: TreeNode) {
+    if (node.children && node.children.length > 0) {
+      // 当前节点包含 children,添加整个节点
+      nodes.push(node);
+      // 递归处理子节点
+      for (const child of node.children) {
+        helper(child);
+      }
+    }
+  }
+
+  // 在这个版本中,我们对每个根节点进行操作
+  for (const node of tree) {
+    helper(node);
+  }
+
+  return nodes;
+}
+
+
+//找出所有父节点的code
+
+
+
+export const  findParentCodes = (node: TreeNode, parentCodes: string[] = []): string[] => {
+  if (node.children && node.children.length > 0) {
+    parentCodes.push(node.code);
+
+    for (let child of node.children) {
+      findParentCodes(child, parentCodes);
+    }
+  }
+
+  return parentCodes;
+}
+
+
+
+//将动态表头转换
+
+type JsonStructure = {
+  code: string;
+  name: string;
+  expand?: number;
+  childTitle?: JsonStructure[];
+};
+
+type Column = {
+  title: string;
+  dataIndex: string;
+  key: string;
+  children?: Column[];
+};
+ 
+export const  convertToColumns = (json: JsonStructure[]): Column[] => {
+  return json.map((item) => {
+    let column: Column = {
+      title: item.name,
+      dataIndex: item.code,
+      key: item.code,
+    };
+
+    if (item.expand === 1 && item.childTitle && item.childTitle.length > 0) {
+      column.children = convertToColumns(item.childTitle);
+    }
+
+    return column;
+  });
+}
+
+
+//搜索树结构中叶子节点的某一个属性,并返回所有匹配的集合
+
+export const searchLeaves = (nodes:any[], keywords:string|undefined, keyName: string, childrenKey: string, results: any[] = []): any[] => {
+  for (const node of nodes) {
+      if (!Array.isArray(node[childrenKey])) {
+          if (node[keyName].indexOf(keywords) != -1) {
+              results.push(node);
+          }
+      } else if (Array.isArray(node[childrenKey])) {
+          searchLeaves(node[childrenKey], keywords, keyName, childrenKey, results);
+      }
+  }
+  return results;
+}
+
+
+
+
+
+

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8 - 0
src/utils/zhongtaiA.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8 - 0
src/utils/zhongtaiB.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8 - 0
src/utils/zhongtaiC.js


BIN
static/A@2x.png


BIN
static/B@2x.png


BIN
static/C@2x.png


BIN
static/addIcon_black.png


BIN
static/arrow_blue.png


BIN
static/arrow_gray.png


BIN
static/bingzhuantu.png


BIN
static/bingzhuantu_green.png


BIN
static/calcu.png


BIN
static/confirmIcon.png


BIN
static/editIcon.png


BIN
static/editIcon_gray.png


BIN
static/filter.png


BIN
static/gou_blue.png


BIN
static/homeMenuIcon.png


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است