Forráskód Böngészése

合并dev分之所有功能

code4eat 1 éve
szülő
commit
262bcbb929
100 módosított fájl, 8398 hozzáadás és 5095 törlés
  1. 0 0
      KC-MiddlePlatform
  2. 123 121
      config/config.ts
  3. 15 4
      config/proxy.ts
  4. BIN
      public/images/HBI.png
  5. BIN
      public/images/HBI_gray.png
  6. BIN
      public/images/avatar.png
  7. BIN
      public/images/close.png
  8. BIN
      public/images/copy.png
  9. BIN
      public/images/empty.png
  10. BIN
      public/images/feiyi.png
  11. BIN
      public/images/feiyi_gray.png
  12. BIN
      public/images/guanlizhongxin.png
  13. BIN
      public/images/guanlizhongxin_gray.png
  14. BIN
      public/images/icon-box.png
  15. BIN
      public/images/icon-gangwei.png
  16. BIN
      public/images/icon-keshi.png
  17. BIN
      public/images/icon-leibie.png
  18. BIN
      public/images/icon-zhicheng.png
  19. BIN
      public/images/initAvatar.png
  20. BIN
      public/images/jingyiyiliao.png
  21. BIN
      public/images/jingyiyiliao_gray.png
  22. BIN
      public/images/suoding.png
  23. BIN
      public/images/threePoint_white_more.png
  24. 0 0
      public/images/tixiicon0.png
  25. BIN
      public/images/tixiicon1.png
  26. BIN
      public/images/tixiicon2.png
  27. BIN
      public/images/tixiicon3.png
  28. BIN
      public/images/tixiicon4.png
  29. BIN
      public/images/tixiicon5.png
  30. BIN
      public/images/tokenUpdateModalbg.png
  31. BIN
      public/images/tongyong_tixi.png
  32. BIN
      public/images/welcom_bg.png
  33. BIN
      public/images/zanwuneirong.png
  34. BIN
      public/images/zhongtaiguanli.png
  35. BIN
      public/images/zhongtaiguanli_gray.png
  36. 9 0
      public/zhongtaiC.js
  37. 154 99
      src/app.tsx
  38. 1 1
      src/components/KCModal/index.tsx
  39. 164 132
      src/components/NavSelecter/index.tsx
  40. 53 15
      src/components/NavSelecter/style.less
  41. 16 7
      src/components/kcTable/style.less
  42. 323 169
      src/components/topBar/index.tsx
  43. 481 53
      src/components/topBar/style.less
  44. 2 2
      src/components/topBar/typings.d.ts
  45. 3 1
      src/constant.ts
  46. 83 71
      src/global.less
  47. 4 2
      src/global.tsx
  48. 123 72
      src/layouts/index.tsx
  49. 167 166
      src/pages/index/components/FastEntry/index.tsx
  50. 28 14
      src/pages/index/components/FastEntry/style.less
  51. 51 50
      src/pages/index/components/RecentlyVisited/index.tsx
  52. 52 53
      src/pages/index/components/TodoList/index.tsx
  53. 93 71
      src/pages/index/components/TodoList/style.less
  54. 432 221
      src/pages/index/index.less
  55. 172 121
      src/pages/index/index.tsx
  56. 131 59
      src/pages/login/index.tsx
  57. 2 1
      src/pages/personalCenter/components/security.tsx
  58. 10 0
      src/pages/personalCenter/index.tsx
  59. 15 0
      src/pages/personalCenter/style.less
  60. 220 80
      src/pages/platform/_layout.tsx
  61. 113 141
      src/pages/platform/components/TreeEditer/index.tsx
  62. 64 87
      src/pages/platform/components/menuEditer/menu.tsx
  63. 24 57
      src/pages/platform/components/usersEditer/index.tsx
  64. 98 3
      src/pages/platform/index.less
  65. 1 1
      src/pages/platform/setting/departmentMana/index.tsx
  66. 473 467
      src/pages/platform/setting/hospManage/index.tsx
  67. 77 62
      src/pages/platform/setting/hospManage/modals/modal.tsx
  68. 3 6
      src/pages/platform/setting/hospManage/model.ts
  69. 22 7
      src/pages/platform/setting/hospManage/style.less
  70. 4 2
      src/pages/platform/setting/hospManage/typings.d.ts
  71. 494 0
      src/pages/platform/setting/hospParamsMana/index.tsx
  72. 107 0
      src/pages/platform/setting/hospParamsMana/service.ts
  73. 138 0
      src/pages/platform/setting/hospParamsMana/style.less
  74. 219 0
      src/pages/platform/setting/kcClassification/index.tsx
  75. 75 0
      src/pages/platform/setting/kcClassification/service.ts
  76. 42 0
      src/pages/platform/setting/kcClassification/style.less
  77. 205 226
      src/pages/platform/setting/menuManage/modals/modal.tsx
  78. 5 5
      src/pages/platform/setting/notificationTemplate/index.tsx
  79. 1 1
      src/pages/platform/setting/notificationTemplate/style.less
  80. 253 168
      src/pages/platform/setting/paramsMana/index.tsx
  81. 13 5
      src/pages/platform/setting/paramsMana/service.ts
  82. 123 0
      src/pages/platform/setting/paramsMana/style.less
  83. 429 302
      src/pages/platform/setting/pubDicMana/index.tsx
  84. 30 11
      src/pages/platform/setting/pubDicMana/service.ts
  85. 60 22
      src/pages/platform/setting/pubDicMana/style.less
  86. 348 167
      src/pages/platform/setting/pubDicTypeMana/index.tsx
  87. 52 50
      src/pages/platform/setting/pubDicTypeMana/service.ts
  88. 99 25
      src/pages/platform/setting/pubDicTypeMana/style.less
  89. 8 6
      src/pages/platform/setting/reports/index.tsx
  90. 460 438
      src/pages/platform/setting/roleManage/index.tsx
  91. 4 4
      src/pages/platform/setting/roleManage/modals/modal.tsx
  92. 11 7
      src/pages/platform/setting/roleManage/model.ts
  93. 212 0
      src/pages/platform/setting/roleManage/style.less
  94. 52 0
      src/pages/platform/setting/static/index.tsx
  95. 663 716
      src/pages/platform/setting/systemNavMana/index.tsx
  96. 107 137
      src/pages/platform/setting/systemNavMana/service.ts
  97. 79 87
      src/pages/platform/setting/userManage/index.tsx
  98. 263 276
      src/pages/platform/setting/userManage/modal.tsx
  99. 36 22
      src/pages/platform/setting/userManage/model.ts
  100. 4 2
      src/pages/platform/setting/userManage/typings.d.ts

+ 0 - 0
KC-MiddlePlatform


+ 123 - 121
config/config.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:04:20
- * @LastEditTime: 2023-03-21 09:31:27
+ * @LastEditTime: 2023-12-07 10:49:07
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/config/config.ts
@@ -17,7 +17,7 @@ export default defineConfig({
   nodeModulesTransform: {
     type: 'none',
   },
-  title:false,
+  title: false,
   publicPath: '/',
   dva: {
     immer: true,
@@ -30,11 +30,12 @@ export default defineConfig({
     },
   },
   lessLoader: {
-    modifyVars: { '@ant-prefix': 'kcmp-ant','root-entry-name': 'default' },
-  }, //
+    modifyVars: { '@ant-prefix': 'kcmp-ant', 'root-entry-name': 'default' },
+  },
+
   theme: {
     '@primary-color': '#3376FE',
-    '@primary-color-hover':'#3376FE',
+    '@primary-color-hover': '#3376FE',
     // '@root-entry-name':'root-entry-name'
   },
   routes: [
@@ -45,6 +46,11 @@ export default defineConfig({
         {
           path: '/app1',
           microApp: 'app1',
+          // access: 'canVisitThisApp'
+          microAppProps: {
+            autoSetLoading: true,
+            autoCaptureError: true,
+          },
         },
         // {
         //   path: '/costMana',
@@ -53,14 +59,64 @@ export default defineConfig({
         {
           path: '/PFMBackC',
           microApp: 'PFMBackC',
+          microAppProps: {
+            autoSetLoading: true,
+            autoCaptureError: true,
+          },
         },
         {
           path: '/reviewMana',
           microApp: 'reviewMana',
+          microAppProps: {
+            autoSetLoading: true,
+            autoCaptureError: true,
+          },
         },
         {
           path: '/budgetManaSystem',
           microApp: 'budgetManaSystem',
+          microAppProps: {
+            autoSetLoading: true,
+            autoCaptureError: true,
+          },
+          // wrappers: [
+          //   '@/wrappers/auth',
+          // ],
+        },
+        {
+          path: '/pfmBackMana',
+          microApp: 'pfmBackMana',
+          microAppProps: {
+            autoSetLoading: true,
+            autoCaptureError: true,
+          },
+        },
+        {
+          path: '/CostAccountingSys',
+          microApp: 'CostAccountingSys',
+          microAppProps: {
+            autoCaptureError: true,
+            //loader: (loading:boolean) => <div>loading</div>,
+          },
+          // access: 'canVisitThisApp'
+        },
+        {
+          path: '/devServer',
+          microApp: 'devServer',
+          microAppProps: {
+            autoCaptureError: true,
+            //loader: (loading:boolean) => <div>loading</div>,
+          },
+          // access: 'canVisitThisApp'
+        },
+        {
+          path: '/personnelManaSystem',
+          microApp: 'personnelManaSystem',
+          microAppProps: {
+            autoCaptureError: true,
+            //loader: (loading:boolean) => <div>loading</div>,
+          },
+          // access: 'canVisitThisApp'
         },
         {
           path: '/channelIndex/channelIndexOne',
@@ -68,11 +124,11 @@ export default defineConfig({
         },
         {
           path: '/index',
-          title:'欢迎进入医管平台',
+          title: '欢迎进入医管平台',
           component: '@/pages/index/index.tsx',
         },
         {
-          title:'精益管管理中台',
+          title: '精益管管理中台',
           path: '/platform',
           component: '@/pages/platform/_layout.tsx',
           routes: [
@@ -81,122 +137,67 @@ export default defineConfig({
               component: '@/pages/platform/sqlediter/index.tsx',
             },
             {
-              path: '/platform/setting/userManage',
-              component: '@/pages/platform/setting/userManage/index.tsx',
-            },
-            {
-              path: '/platform/setting/hospManage',
-              component: '@/pages/platform/setting/hospManage/index.tsx',
-            },
-            {
-              path: '/platform/setting/menuManage',
-              component: '@/pages/platform/setting/menuManage/index.tsx',
-            },
-            {
-              path: '/platform/setting/roleManage',
-              component: '@/pages/platform/setting/roleManage/index.tsx',
-            },
-            // {
-            //   path: '/platform/setting/reports',
-            //   component: '@/pages/platform/setting/reports/index.tsx',
-            // },
-            {
-              path: '/platform/setting/departmentMana',
-              component: '@/pages/platform/setting/departmentMana/index.tsx',
-            },
-            {
-              path: '/platform/setting/pubDicTypeMana',
-              component: '@/pages/platform/setting/pubDicTypeMana/index.tsx',
-            },
-            {
-              path: '/platform/setting/pubDicMana',
-              component: '@/pages/platform/setting/pubDicMana/index.tsx',
-            },
-            {
-              path: '/platform/setting/indicatorMana',
-              component: '@/pages/platform/setting/indicatorMana/index.tsx',
-            },
-            {
-              path: '/platform/setting/paramsMana',
-              component: '@/pages/platform/setting/paramsMana/index.tsx',
-            },
-            {
-              path: '/platform/setting/systemNavMana',
-              component: '@/pages/platform/setting/systemNavMana/index.tsx',
-            },
-            {
-              path: '/platform/setting/notificationTemplate',
-              component: '@/pages/platform/setting/notificationTemplate/index.tsx',
-            },
-
-
-
-            {
-              path: '/platform/setting/reports/0',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/1',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/2',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/3',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/4',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/5',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/6',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/7',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/8',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/9',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/10',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/11',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/12',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/13',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/14',
-              component: '@/pages/platform/setting/reports/index.tsx',
-            },
-            {
-              path: '/platform/setting/reports/15',
-              component: '@/pages/platform/setting/reports/index.tsx',
+              path: '/platform/setting',
+              routes: [
+                {
+                  path: '/platform/setting/userManage',
+                  component: '@/pages/platform/setting/userManage/index.tsx',
+                },
+                {
+                  path: '/platform/setting/hospManage',
+                  component: '@/pages/platform/setting/hospManage/index.tsx',
+                },
+                {
+                  path: '/platform/setting/menuManage',
+                  component: '@/pages/platform/setting/menuManage/index.tsx',
+                },
+                {
+                  path: '/platform/setting/roleManage',
+                  component: '@/pages/platform/setting/roleManage/index.tsx',
+                },
+                // {
+                //   path: '/platform/setting/reports',
+                //   component: '@/pages/platform/setting/reports/index.tsx',
+                // },
+                {
+                  path: '/platform/setting/departmentMana',
+                  component: '@/pages/platform/setting/departmentMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/pubDicTypeMana',
+                  component: '@/pages/platform/setting/pubDicTypeMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/hospParamsMana',
+                  component: '@/pages/platform/setting/hospParamsMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/pubDicMana/:type',
+                  component: '@/pages/platform/setting/pubDicMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/indicatorMana',
+                  component: '@/pages/platform/setting/indicatorMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/paramsMana',
+                  component: '@/pages/platform/setting/paramsMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/systemNavMana',
+                  component: '@/pages/platform/setting/systemNavMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/notificationTemplate',
+                  component: '@/pages/platform/setting/notificationTemplate/index.tsx',
+                },
+                {
+                  path: '/platform/setting/kcClassification',
+                  component: '@/pages/platform/setting/kcClassification/index.tsx',
+                },
+              ],
             },
           ],
-          
         },
         {
           path: '/personalCenter',
@@ -206,6 +207,7 @@ export default defineConfig({
       ],
     },
   ],
+  // hash:true,
   proxy: proxy[REACT_APP_ENV || 'dev'],
   manifest: {
     basePath: '/',

+ 15 - 4
config/proxy.ts

@@ -1,7 +1,11 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:00:52
+<<<<<<< HEAD
  * @LastEditTime: 2023-04-20 13:31:09
+=======
+ * @LastEditTime: 2024-03-18 18:04:31
+>>>>>>> dev
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/config/proxy.ts
@@ -14,19 +18,26 @@
 
 const proxy: { [key: string]: any } = {
   dev: {
-    '/master': {
-      target: 'http://47.97.190.5:7004',
-      //target: 'http://118.31.245.65:7005/',
+    //绩效管理
+    '/gateway': {
+      //target: 'http://47.96.149.190:5000',
+      target: 'http://120.27.235.181:5000',
       changeOrigin: true,
       // pathRewrite: { '^/master': '' },
     },
+    //老版评审管理
     '/api': {
-      target: 'http://47.97.190.5:8804/',
+      target: 'http://120.27.235.181:8083/',
       changeOrigin: true,
       pathRewrite: { '^/api': '' },
     },
+    //新版评审管理
     '/view': {
+<<<<<<< HEAD
       target: 'http://47.97.190.5:8807',
+=======
+      target: 'http://120.27.235.181:8085/',
+>>>>>>> dev
       changeOrigin: true,
       // pathRewrite: { '^/view': '' },
     },

BIN
public/images/HBI.png


BIN
public/images/HBI_gray.png


BIN
public/images/avatar.png


BIN
public/images/close.png


BIN
public/images/copy.png


BIN
public/images/empty.png


BIN
public/images/feiyi.png


BIN
public/images/feiyi_gray.png


BIN
public/images/guanlizhongxin.png


BIN
public/images/guanlizhongxin_gray.png


BIN
public/images/icon-box.png


BIN
public/images/icon-gangwei.png


BIN
public/images/icon-keshi.png


BIN
public/images/icon-leibie.png


BIN
public/images/icon-zhicheng.png


BIN
public/images/initAvatar.png


BIN
public/images/jingyiyiliao.png


BIN
public/images/jingyiyiliao_gray.png


BIN
public/images/suoding.png


BIN
public/images/threePoint_white_more.png


+ 0 - 0
public/images/zhilianganquan.png → public/images/tixiicon0.png


BIN
public/images/tixiicon1.png


BIN
public/images/tixiicon2.png


BIN
public/images/tixiicon3.png


BIN
public/images/tixiicon4.png


BIN
public/images/tixiicon5.png


BIN
public/images/tokenUpdateModalbg.png


BIN
public/images/tongyong_tixi.png


BIN
public/images/welcom_bg.png


BIN
public/images/zanwuneirong.png


BIN
public/images/zhongtaiguanli.png


BIN
public/images/zhongtaiguanli_gray.png


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 9 - 0
public/zhongtaiC.js


+ 154 - 99
src/app.tsx

@@ -1,15 +1,16 @@
 import { useState } from 'react';
 import { PageLoading } from '@ant-design/pro-layout';
-import { notification, Modal } from 'antd';
-import { RequestConfig, history, useModel } from 'umi';
+import { notification, Modal, message } from 'antd';
+import { RequestConfig, history } from 'umi';
 import type { RequestOptionsInit } from 'umi-request';
-import { getHospSubSystemList, UserDataType } from '@/service/login';
+import { UserDataType, getQiankunMicroApps } from '@/service/login';
 
 import { BasicLayoutProps } from '@ant-design/pro-layout';
 import { logoutHandle } from './global';
 import { Platforms } from './constant';
 import { SpacicalPageParamsType } from './typings';
 
+window.isParentApp = true;
 
 const loginPath = '/login';
 
@@ -34,7 +35,7 @@ type InitialStateType = {
   openedSysLists?: TopBar.Tab[]; //当前已打开的系统列表
   currentSelectedSys?: TopBar.Tab; //当前选中的tab
   logout?: () => Promise<boolean>;
-  childAppIsShowMenu?:boolean; 
+  childAppIsShowMenu?: boolean;
   spacicalPageParamsType?: SpacicalPageParamsType[];
   getHospSubSystemListFunc?: () => Promise<any[]>;
 };
@@ -59,16 +60,16 @@ export async function getInitialState(): Promise<InitialStateType> {
 
   //获取当前账号所有子应用列表
   const getHospSubSystemListFunc = async () => {
-    const data = await getHospSubSystemList();
-    if (data) {
-      const _data = data.map((t) => ({
-        ...t,
-        icon: getAppIcon(t.name),
-        path: t.path,
-      }));
-
-      return _data;
-    }
+    // const data = await getHospSubSystemList();
+    // if (data) {
+    //   const _data = data.map((t) => ({
+    //     ...t,
+    //     icon: getAppIcon(t.name),
+    //     path: t.path,
+    //   }));
+
+    //   return _data;
+    // }
     return [];
   };
 
@@ -105,42 +106,59 @@ const requestInterceptorsHandle = (url: string, options: RequestOptionsInit) =>
     authHeader.token = token;
   }
 
- 
-
   return {
-    url: `/master${url}`,
-    options: { ...options, interceptors: true, headers: authHeader,timeout:100000000, },
+    url: `/gateway${url}`,
+    options: { ...options, interceptors: true, headers: authHeader, timeout: 100000000 },
   };
 };
 
 const responseInterceptorsHandle = async (response: Response, options: RequestOptionsInit) => {
-
-
+  const { url, method } = options;
   const _response: {
+    errorMessage: any;
+    message: any;
     data?: any;
     status: number;
+    errorCode?: number;
     success?: boolean;
     msg?: string;
   } = await response.clone().json();
 
-  
+  if (_response.errorCode == 401) {
+    Modal.confirm({
+      title: '抱歉,你的登录已过期,请重新登录!',
+      okText: '确定',
+      cancelText: '取消',
+      maskClosable: false,
+      // cancelButtonProps:
+      onOk: () => {
+        logoutHandle();
+        return Promise.resolve(true);
+      },
+    });
+    return;
+  }
+
   if (_response.status == 200) {
-    if (_response.data) {
-      return _response.data;
+    if (url != '/centerSys/menu/checkKeygen' && method == 'POST') {
+      message.success({
+        content: `操作成功!`,
+        duration: 1,
+      });
     }
 
-    notification.success({
-      message: `操作成功!`,
-    });
-    return {
-      status: _response.status,
-      success: true,
-    };
+    if (_response.data != null || _response.data != undefined) {
+      return _response.data;
+    } else {
+      return true;
+    }
   } else {
+    console.log({ _response });
     notification.error({
-      message:`${_response.msg}`,
+      message: '错误:',
+      description: `${_response.msg ? _response.msg : _response.message ? _response.message : _response.errorMessage}`,
     });
-    return false
+    return false;
   }
 };
 
@@ -161,16 +179,18 @@ interface ResponseErr extends Error {
 }
 
 const errorHandlerFunc = (error: ResponseErr) => {
-
   try {
     const { info } = error;
-    const { errorCode , errorMessage } = info;
-    
-    if (errorCode == 499) {
+    const { errorCode, errorMessage } = info;
+
+    console.log({ info });
+
+    if (errorCode == 499 || errorCode == 401) {
       //token过期
       Modal.confirm({
         title: '抱歉,你的登录已过期,请重新登录!',
-        // closable:false,
+        okText: '确定',
+        cancelText: '取消',
         maskClosable: false,
         // cancelButtonProps:
         onOk: () => {
@@ -186,9 +206,11 @@ const errorHandlerFunc = (error: ResponseErr) => {
         message: ` ${errorCode}:出现错误!`,
         description: errorMessage,
       });
+    } else if (false) {
     } else {
       notification.error({
-        message: ` ${errorCode}:${errorMessage}`,
+        message: '错误',
+        description: ` ${errorCode}:${errorMessage}`,
       });
     }
   } catch (err) {
@@ -203,7 +225,6 @@ export const request: RequestConfig = {
   timeout: 10000,
   errorConfig: {
     adaptor: (resData) => {
-
       if (!resData.success && resData.status != 200) {
         return {
           ...resData,
@@ -230,44 +251,70 @@ export const request: RequestConfig = {
 };
 
 // 从接口中获取子应用配置,export 出的 qiankun 变量是一个 promise
-export const qiankun = fetch('/config').then(() => ({
-  // 注册子应用信息
-  apps: [
-    // {
-    //   name: 'microApp', // 唯一 id
-    //   entry: '//localhost:8808', // 开发
-    // },
-    {
-      name: 'app1', // 唯一 id
-      entry: '//47.97.190.5:8804',  //测试
-    },
-    {
-      name: 'reviewMana', // 唯一 id
-      //entry: '//47.97.190.5:8807', //线上
-      entry: '//localhost:8804', // 开发
 
-    },
-    // {
-    //   name: 'budgetManaSystem', // 唯一 id
-    //   //entry: '//localhost:8001'
-    //   entry: '//112.124.59.133:5000/perform/', // 开发
-    // },
-    // {
-    //   name: 'PFMBackC', // 唯一 id
-    //   entry: '//112.124.59.133:5000/pfmManager/index.html'
-    //   //entry: '//112.124.59.133:5000/perform/', // 开发
-    // },
-  ],
-  // 完整生命周期钩子请看 https://qiankun.umijs.org/zh/api/#registermicroapps-apps-lifecycles
-  lifeCycles: {
-    afterMount: (props: any) => {},
-  },
-  // 支持更多的其他配置,详细看这里 https://qiankun.umijs.org/zh/api/#start-opts
-}));
+export const qiankun = async () => {
+  console.log('process.env', process.env);
+  const { NODE_ENV } = process.env;
+  //NODE_ENV == 'development'
+  if (NODE_ENV == 'development') {
+    return {
+      apps: [
+        // {
+        //   name: 'microApp', // 唯一 id
+        //   entry: '//localhost:8808', // 开发
+        // },
+        // {
+        //   name: 'app1', // 唯一 id
+        //   entry: '//120.27.235.181:8804',  //测试
+        // },
+        // {
+        //   name: 'reviewMana', // 唯一 id
+        //   entry: '//120.27.235.181:5000/pfmview/',
+        //   //entry: '//localhost:8804',  //本地调试
+        //   //entry: '//198.198.203.161:5000/pfmview/', //淮南
+        // },
+        {
+          name: 'budgetManaSystem', // 唯一 id
+          entry: '//localhost:8002',
+          //entry: '//120.27.235.181:5000/perform/',  //开发
+          //entry: '//47.96.149.190:5000/perform/', //演示
+          //entry: '//198.198.203.161:5000/perform/', //淮南
+        },
+        {
+          name: 'pfmBackMana', // 唯一 id
+          //entry: '//localhost:8001'
+          entry: '//120.27.235.181:5000/pfmManager/', // 开发
+        },
+        {
+          name: 'CostAccountingSys', // 唯一 id
+          entry: '//localhost:8001',
+          //entry: '//120.27.235.181:5000/costAccount/', // 开发
+        },
+        // {
+        //   name: 'personnelManaSystem', // 唯一 id
+        //   entry: '//192.168.0.118:8005'
+        //   //entry: '//120.27.235.181:5000/costAccount/', // 开发
+        // },
+        // {
+        //   name:'devServer',
+        //   entry: '//localhost:8005'
+        // }
+      ],
+    };
+  } else {
+    const resp = await getQiankunMicroApps();
+    if (resp) {
+      let apps = resp.list ? resp.list : resp;
+      return {
+        apps: [...apps],
+      };
+    }
+  }
+};
+
 
 //向子应用透传
 export function useQiankunStateForSlave() {
-
   const [masterState, setMasterState] = useState({});
 
   return {
@@ -276,37 +323,45 @@ export function useQiankunStateForSlave() {
   };
 }
 
+// //@/pages/platform/setting/reports/index
+export function patchRoutes({ routes }: { routes: any }) {
+  const treeLoop = (treeData: any) => {
+    if (treeData.path.indexOf('/platform') != -1) {
+      if (treeData.routes) {
+        const paths = [...new Array(100).keys()].map((a, index) => ({
+          path: `${treeData.path == '/' ? '' : treeData.path}/reports/${index}`,
+          exact: true,
+          component: require('@/pages/platform/setting/reports/index.tsx').default,
+        }));
+
+        const lanhuPagePaths = [...new Array(100).keys()].map((a, index) => ({
+          path: `${treeData.path == '/' ? '' : treeData.path}/static/${index}`,
+          exact: true,
+          component: require('@/pages/platform/setting/static/index.tsx').default,
+        }));
+
+        //console.log({paths});
+
+        paths.forEach((a: any) => {
+          treeData.routes.push(a);
+        });
+
+        lanhuPagePaths.forEach((a: any) => {
+          treeData.routes.push(a);
+        });
+      }
+    }
 
-
-//@/pages/platform/setting/reports/index
-export function patchRoutes({ routes }:{routes:any}) {
-  const paths = [...new Array(100).keys()].map((a,index)=>({
-    path: `/platform/setting/reports/${15+(index+1)}`,
-    exact: true,
-    component: require('@/pages/platform/setting/reports/index.tsx').default,
-  }));
-
-
-  const treeLoop = (treeData:any)=>{
-        //console.log({treeData})
-        if(treeData.path == '/platform'){
-          paths.forEach((a:any)=>{
-            treeData.routes.push(a); 
-          })
-          return;  
-        }else{
-            if(treeData.routes&&treeData.routes.length>0){
-              treeData.routes.forEach((a:any)=>{
-                  treeLoop(a);
-              })
-            }
-        }
-  }
+    if (treeData.routes && treeData.routes.length > 0) {
+      treeData.routes.forEach((a: any) => {
+        treeLoop(a);
+      });
+    }
+  };
 
   treeLoop(routes[0]);
 }
 
-
 export const layout = ({ initialState: { userData } }: { initialState: InitialStateType }): BasicLayoutProps => {
   return {
     headerRender: false,

+ 1 - 1
src/components/KCModal/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 15:26:43
- * @LastEditTime: 2022-08-01 10:57:12
+ * @LastEditTime: 2023-06-20 14:58:15
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/components/KCModal/index.tsx

+ 164 - 132
src/components/NavSelecter/index.tsx

@@ -2,158 +2,190 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-06-29 11:05:04
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2022-07-14 15:37:31
+ * @LastEditTime: 2024-01-16 16:37:52
  * @FilePath: /KC-MiddlePlatform/src/components/NavSelecter/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-import { Tabs, Checkbox, Button } from 'antd';
-import React, { useEffect, useState } from 'react';
+import { Tabs, Checkbox, Button, message } from 'antd';
+import React, { Key, useEffect, useState } from 'react';
 import './style.less';
+import { findNodesBySomes, getLeafNodes } from '@/utils';
 
 const { TabPane } = Tabs;
 
-
-
 export type NavSelecterItemType = {
-    name: string;
-    menuId: number | string;
-    path: string;
-    type: number;
-    systemId: string;
-}
-
+  name: string;
+  menuId: number | string;
+  path: string;
+  type: number;
+  contentType: number;
+  systemId: string;
+};
 
 export type NavSelecterData = {
-    name: string;
-    menuId: number | string;
-    path: string;
-    systemId: string;
-    type: number;
-    child?: NavSelecterData[]
-}
+  name: string;
+  menuId: number | string;
+  path: string;
+  systemId: string;
+  type: number;
+  contentType: number;
+  child?: NavSelecterData[];
+};
 
 export interface NavSelecter {
-    onVisibleChange?: (t: boolean) => void;
-    onChecked?: (t: NavSelecterItemType[]) => void;
-    value?: NavSelecterItemType[];
-    data?: NavSelecterData[];
+  onVisibleChange?: (t: boolean) => void;
+  onChecked?: (t: NavSelecterItemType[]) => void;
+  value?: Key[];
+  data?: NavSelecterData[];
+  title?: string;
+  type?: number; //1 默认 2 限制最多可选个数
 }
 
 const NavSelecter = (props: NavSelecter) => {
-
-    const { onVisibleChange, data, value = [], onChecked } = props;
-    const [checkedIds, set_checkedIds] = useState<(string | number)[]>([]);
-    const [checkedItems, set_checkedItems] = useState<NavSelecterItemType[]>([]);
-
-
-    const onChange = (tab: NavSelecterItemType) => {
-
-        let _checkedIds = checkedIds;
-        let _checkedItems = [...checkedItems];
-
-        if (_checkedIds.includes(tab.menuId)) {
-            _checkedIds.splice(checkedIds.indexOf(tab.menuId), 1);
-            _checkedItems.splice(_checkedItems.findIndex(t => t.menuId == tab.menuId), 1);
-            set_checkedIds([..._checkedIds]);
-            set_checkedItems([..._checkedItems]);
-        } else {
-
-            _checkedIds.push(tab.menuId);
-            _checkedItems.push(tab);
-            set_checkedItems([..._checkedItems]);
-            set_checkedIds([..._checkedIds]);
-        }
-    };
-
-    const onMaskClick = (e: React.MouseEvent) => {
-
-        onVisibleChange && onVisibleChange(false);
+  const { onVisibleChange, data, value = [], onChecked, title, type = 1 } = props;
+  const [checkedIds, set_checkedIds] = useState<(string | number)[]>([]);
+  const [checkedItems, set_checkedItems] = useState<NavSelecterItemType[]>([]);
+
+  const onChange = (tab: NavSelecterItemType) => {
+    let _checkedIds = [...checkedIds];
+    let _checkedItems = [...checkedItems];
+
+    if (_checkedIds.includes(tab.menuId)) {
+      _checkedIds.splice(checkedIds.indexOf(tab.menuId), 1);
+      _checkedItems.splice(
+        _checkedItems.findIndex((t) => t.menuId == tab.menuId),
+        1,
+      );
+      set_checkedIds([..._checkedIds]);
+      set_checkedItems([..._checkedItems]);
+    } else {
+      if (type == 2 && checkedIds.length + 1 > 6) {
+        message.warn('快速入口最多展示6项');
+        return;
+      }
+
+      _checkedIds.push(tab.menuId);
+      _checkedItems.push(tab);
+      set_checkedItems([..._checkedItems]);
+      set_checkedIds([..._checkedIds]);
     }
-
-    const onCommit = () => {
-        onChecked && onChecked(checkedItems);
-        onVisibleChange && onVisibleChange(false);
+  };
+
+  const onMaskClick = (e: React.MouseEvent) => {
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  const onCommit = () => {
+    onChecked && onChecked(checkedItems);
+    onVisibleChange && onVisibleChange(false);
+  };
+
+  const onReset = () => {
+    set_checkedItems([]);
+    set_checkedIds([]);
+  };
+
+  const checkAllHandle = (e: any) => {
+    let all: any[] = [];
+
+    if (e.target.checked) {
+      data?.forEach((item) => {
+        const _result = getLeafNodes({ child: item.child });
+        all = [...all, ..._result];
+      });
+      set_checkedItems([...all]);
+      set_checkedIds(all.map((a) => a.menuId));
+    } else {
+      set_checkedItems([]);
+      set_checkedIds([]);
     }
+  };
 
-    const onReset = () => {
-        set_checkedItems([]);
-        set_checkedIds([]);
-    }
+  useEffect(() => {
+    if (data) {
+      let result: any[] = [];
 
-    useEffect(() => {
-
-        set_checkedIds(value?.map(t => t.menuId));
-        set_checkedItems(value);
-
-    }, [value]);
-
-
-    return (
-        <div className="navSelecter" onClick={(e) => onMaskClick(e)}>
-            <div className='container'>
-                <div className='closeBtn' onClick={(e) => onMaskClick(e)}>
-                    <img src={require('./images/close.png')} />
-                </div>
-                <div className='content' onClick={(e) => e.stopPropagation()}>
-                    <div>
-                        <Tabs defaultActiveKey="1" >
-
-                            {
-                                data?.map((val) => (
-                                    
-                                        <TabPane tab={val.name} key={val.menuId}>
-                                            <div className='contentInner'>
-                                            {
-                                                val.child?.map((item) => (
-                                                    <div className='row' key={item.menuId}>
-                                                        <div className='rowName'>{item.name}</div>
-                                                        <div className='rowWrap'>
-                                                            {
-                                                                item.child?.map(a => {
-                                                                    if (a.type == 3) {
-                                                                        return (
-                                                                            <div className='tab' key={a.menuId}>
-                                                                                <Checkbox onChange={() => onChange({
-                                                                                    name: a.name,
-                                                                                    menuId: a.menuId,
-                                                                                    path: a.path,
-                                                                                    type: a.type,
-                                                                                    systemId: a.systemId
-                                                                                })} checked={checkedIds.includes(a.menuId)} ></Checkbox>
-                                                                                <span style={{ marginLeft: 8 }}>{a.name}</span>
-                                                                            </div>
-                                                                        )
-                                                                    }
-                                                                })
-                                                            }
-                                                        </div>
-                                                    </div>
-                                                ))
-                                            }
-                                            </div>
-                                        </TabPane>
-                                    
-                                ))
+      for (let tree of data) {
+        const node = findNodesBySomes(tree, new Set(checkedIds), 'menuId');
+        if (node) {
+          result = result.concat([...node]);
+        }
+      }
+      set_checkedItems(result);
+    }
+  }, [checkedIds]);
+
+  useEffect(() => {
+    set_checkedIds(value);
+  }, [value]);
+
+  return (
+    <div className="navSelecter" onClick={(e) => onMaskClick(e)}>
+      <div className="container">
+        <div className="selecterTitle">{title}</div>
+        <div className="closeBtn" onClick={(e) => onMaskClick(e)}>
+          <img src={require('./images/close.png')} />
+        </div>
+        <div className="content" onClick={(e) => e.stopPropagation()}>
+          <div>
+            <Tabs defaultActiveKey="1">
+              {data?.map((val) => (
+                <TabPane tab={`${val.name}(${getLeafNodes({ child: val.child }).length})`} key={val.menuId}>
+                  <div className="contentInner">
+                    {val.child?.map((item) => (
+                      <div className="row" key={item.menuId}>
+                        <div className="rowName">{item.name}</div>
+                        <div className="rowWrap">
+                          {item.child?.map((a) => {
+                            if (a.type == 3 || a.type == 1) {
+                              return (
+                                <div className="tab" key={a.menuId}>
+                                  <Checkbox
+                                    onChange={() =>
+                                      onChange({
+                                        name: a.name,
+                                        menuId: a.menuId,
+                                        path: a.path,
+                                        type: a.type,
+                                        contentType: a.contentType,
+                                        systemId: a.systemId,
+                                      })
+                                    }
+                                    checked={checkedIds.includes(a.menuId)}
+                                  ></Checkbox>
+                                  <span style={{ display: 'inline-block', width: '75%', marginLeft: 8, whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }}>{a.name}</span>
+                                </div>
+                              );
                             }
-
-                        </Tabs>
-                    </div>
-                </div>
-                <div className='footer' onClick={e => e.stopPropagation()}>
-                    <span className='count'>{`已选中${checkedIds.length}项`}</span>
-                    <div className='btnGroup'>
-                        <Button style={{ marginRight: 8 }} onClick={onReset}>重置</Button>
-                        <Button type="primary" onClick={onCommit}>确定</Button>
-                    </div>
-                </div>
-            </div>
+                          })}
+                        </div>
+                      </div>
+                    ))}
+                  </div>
+                </TabPane>
+              ))}
+            </Tabs>
+          </div>
         </div>
-    )
-}
-
+        <div className="footer" onClick={(e) => e.stopPropagation()}>
+          <span className="count">
+            {type == 1 && <Checkbox onChange={(e) => checkAllHandle(e)}>全部开启 </Checkbox>}
+            {type == 1 && <span className="count">{`已选中${checkedIds.length}项`}</span>}
+            {type == 2 && `当前快速入口已展示${checkedItems.length}/6项`}
+          </span>
+          <div className="btnGroup">
+            <Button className="resetBtn btn" style={{ marginRight: 8 }} onClick={onReset}>
+              重置
+            </Button>
+            <Button className="confirmBtn btn" type="primary" onClick={onCommit}>
+              确定
+            </Button>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
 
-export default NavSelecter;
+export default NavSelecter;

+ 53 - 15
src/components/NavSelecter/style.less

@@ -9,23 +9,40 @@
   left: 0;
   z-index: 999;
   background-color: rgba(41, 44, 51, 0.5);
+   
+  .kcmp-ant-tabs-tab {
+    padding-bottom: 6px !important;
+    padding-top:16px !important;
+  }
+  .kcmp-ant-tabs-top > .kcmp-ant-tabs-nav::before {
+      border-bottom: none !important;
+  }
 
   .container {
     position: relative;
-    width: 70%;
-    height: 60%;
+    width: 792px;
     padding-top: 12px;
     background: #FFFFFF;
-    border-radius: 4px;
-    border: 1px solid #CFD6E6;
+    border-radius: 8px;
+
+    .selecterTitle {
+      position: absolute;
+      top: 16px;
+      left: 16px;
+      height: 18px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #17181A;
+      line-height: 18px;
+    }
 
     .closeBtn {
       display: flex;
       justify-content: center;
       align-items: center;
       position: absolute;
-      right: 20px;
-      top: 10px;
+      right:8px;
+      top: 8px;
       width: 30px;
       height: 30px;
       cursor: pointer;
@@ -37,14 +54,13 @@
     }
 
     .content {
-      padding: 24px;
-      height: calc(100% - 56px);
-      overflow-y: hidden;
-
+      padding: 16px;
       .contentInner {
-          height:368px;
-          overflow-y: scroll;
+        min-height: 100px;
+        max-height: 440px;
+        overflow-y: scroll;
       }
+
       .row {
         margin-bottom: 16px;
 
@@ -111,11 +127,33 @@
       justify-content: space-between;
       align-items: center;
       height: 56px;
-      padding: 0 24px;
+      padding: 0 19px;
       background: #FFFFFF;
-      border-radius: 0px 0px 4px 4px;
-      border-top: 1px solid #CFD6E6;
+      border-radius: 0px 0px 8px 8px;
 
+      .btnGroup {
+           .btn {
+            width: 56px;
+            height: 24px;
+            font-size: 14px;
+            border-radius: 4px;
+            &>span {
+              position: relative;
+              top:-4px;
+              left:-2px;
+            }
+            
+            &.resetBtn {
+              color: #17181A;
+              background: #FAFCFF;
+              border: 1px solid #DAE2F2;
+            }
+            &.confirm {
+              color: #FFFFFF;
+              background: #3377FF;
+            }
+           }
+      }
     }
   }
 

+ 16 - 7
src/components/kcTable/style.less

@@ -22,14 +22,23 @@
   }
 
 
-  .kcmp-ant-table-tbody>tr>td {
-    border-bottom: 1px solid #DAE2F2;
-    padding: 9px 8px !important;
-    &:first-child {
-      padding-left: 16px !important;
-    }
-
+  .kcmp-ant-table-tbody {
+    tr {
+      &>td {
+        border-bottom: 1px solid #DAE2F2;
+        padding: 9px 8px !important;
+        &:first-child {
+          padding-left: 16px !important;
+        }
     
+        
+      }
+    }
+    .kcmp-ant-table-measure-row {
+        &>td {
+          padding: 0 !important;
+        }
+    }
   }
 
   .kcmp-ant-table-tbody > tr.kcmp-ant-table-row:hover > td, .kcmp-ant-table-tbody > tr > td.kcmp-ant-table-cell-row-hover {

+ 323 - 169
src/components/topBar/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-16 09:12:37
- * @LastEditTime: 2023-03-24 16:34:14
+ * @LastEditTime: 2024-04-09 14:27:27
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/index/components/topBar/index.tsx
@@ -11,17 +11,16 @@ import React, { useEffect, useState } from 'react';
 
 import './style.less';
 
-import { Tooltip } from 'antd';
+import { Input, Modal, Tooltip } from 'antd';
 import { LogoutOutlined, SettingOutlined } from '@ant-design/icons';
 
-import logo from '../../../public/images/kc-logo.png';
-import platFormMenuIcon from '../../../public/images/platformMenu.png';
+// import logo from '../../../public/images/kc-logo.png';
 import tabCloseIcon from '../../../public/images/tabCloseIcon.png';
 
-import { history, useModel } from 'umi';
+import { history, useLocation, useModel } from 'umi';
 import { Divider } from 'antd';
-import { addFastEntry, getUserPlatformNav } from '@/service/menu';
-import { NavSelecterData } from '../NavSelecter';
+import { updateTokenReq } from '@/service/user';
+import { logoutHandle } from '@/global';
 
 interface TopBarType {
   onTabChange?: (data: TopBar.Tab[]) => void; //当tab切换时回调
@@ -30,65 +29,69 @@ interface TopBarType {
   userPannelTabClick?: (tag: 'SETTING' | 'LOGOUT' | 'SETUSERINFO') => void;
   onCloseTab?: (data: TopBar.Tab) => void;
   onTabClick?: (data: TopBar.Tab) => void;
-  userData?: { name: string;[key: string]: any };
+  userData?: { name: string; [key: string]: any };
   navData: TopBar.PanelData[];
+  logo?: string;
+  topBarTitle?: string;
 }
 
-
 const TopBar: React.FC<TopBarType> = (props) => {
-  const { onTabChange, userPannelTabClick, onCloseTab, onTabClick, userData, navData,currentTab } = props;
+  const { onTabChange, userPannelTabClick, onCloseTab, onTabClick, userData, navData, currentTab, logo = undefined, topBarTitle = '欢迎进入医管平台' } = props;
   const [systemTabs, setSystemTabs] = useState<TopBar.Tab[]>([]); //已打开的tab
   const [currentSelectedTab, setCurrentSelectedTab] = useState<TopBar.Tab>();
   const [ifOpenPannel, setIfOpenPannel] = useState(false);
   const [arrowRotate, setArrowRotate] = useState(false);
-  const [pageTitle, set_pageTitle] = useState('欢迎进入医管平台');
+  const [pageTitle, set_pageTitle] = useState('');
   const [currentActivedBlockIndex, set_currentActivedBlockIndex] = useState(0);
   const [panelData, set_panelData] = useState<TopBar.PanelData[]>([]);
 
-  const [onTabSystemTabs,set_onTabSystemTabs] = useState<TopBar.Tab[]>([]); //tab导航可以放下的数量,剩余通过下拉获取
+  const [onTabSystemTabs, set_onTabSystemTabs] = useState<TopBar.Tab[]>([]); //tab导航可以放下的数量,剩余通过下拉获取
+  const [onTabSystemTabs_hide, set_onTabSystemTabs_hide] = useState<TopBar.Tab[]>([]); //下拉掩藏的导航
 
   const { initialState, setInitialState } = useModel('@@initialState');
+  const [tokenUpdateModalVisible, set_tokenUpdateModalVisible] = useState(false);
+  const location = useLocation();
 
+  const [showMoreTabPannel, set_showMoreTabPannel] = useState(false);
 
   const localSavedTab = localStorage.getItem('currentSelectedTab');
 
   const currentSelectedTabFromLocal = localSavedTab ? JSON.parse(localSavedTab) : {};
 
-  const _systemTabClickHandle = (item: TopBar.Tab) => {
+  let password: undefined | string = undefined;
 
+  const _systemTabClickHandle = (item: TopBar.Tab) => {
     //导航栏tab点击
     // console.log('_systemTabClickHandle',item);
     onTabClick && onTabClick(item);
     localStorage.setItem('currentSelectedTab', JSON.stringify(item));
     setCurrentSelectedTab(item);
-
   };
 
-
   const _systemListClickHandle = (data: TopBar.Tab, currentActivedBlockIndex: number, index: number, i: number) => {
     //导航栏系统菜单列表点击回调
     if (currentSelectedTab?.menuId == data.menuId) return;
 
-      //临时保存衣打开过的菜单
+    //临时保存衣打开过的菜单
     const t = localStorage.getItem('visitedTabs');
 
-    if(t){
+    if (t) {
       let visitedTabs = JSON.parse(t);
-      let index = visitedTabs.findIndex((t:TopBar.Tab)=>t.menuId == data.menuId);
-      if(index == -1){
+      let index = visitedTabs.findIndex((t: TopBar.Tab) => t.menuId == data.menuId);
+      if (index == -1) {
         visitedTabs.push(data);
-        localStorage.setItem('visitedTabs',JSON.stringify(visitedTabs));
+        localStorage.setItem('visitedTabs', JSON.stringify(visitedTabs));
       }
-    }else{
-      localStorage.setItem('visitedTabs',JSON.stringify([data]));
+    } else {
+      localStorage.setItem('visitedTabs', JSON.stringify([data]));
     }
 
     _systemTabClickHandle(data); //触发一次tab点击
 
-    set_pageTitle(panelData[currentActivedBlockIndex].child[index].name)
+    set_pageTitle(panelData[currentActivedBlockIndex].child[index].name);
 
     if (panelData[currentActivedBlockIndex].child[index].child) {
-      // console.log([...panelData[currentActivedBlockIndex].child[index].child])
+      //console.log([...panelData[currentActivedBlockIndex].child[index].child])
       setSystemTabs([...panelData[currentActivedBlockIndex].child[index].child]);
     }
     setIfOpenPannel(false);
@@ -104,7 +107,7 @@ const TopBar: React.FC<TopBarType> = (props) => {
     let _systemTabs = [...systemTabs];
     let delIndex = -1;
 
-    const filtered = _systemTabs.filter((t, index) => {
+    const filtered: any[] = _systemTabs.filter((t, index) => {
       if (t.menuId == item.menuId) {
         delIndex = index;
       }
@@ -123,68 +126,88 @@ const TopBar: React.FC<TopBarType> = (props) => {
 
   const UserPannel = () => {
     return (
-      <div className='userPannel'>
-        <div className='userPannelTab' onClick={() => _userPannelTabClick('SETTING')}>
+      <div className="userPannel">
+        <div className="userPannelTab" onClick={() => _userPannelTabClick('SETTING')}>
           <SettingOutlined />
-          设置
+          <span>设置</span>
         </div>
-        <div className='userPannelTab' onClick={() => _userPannelTabClick('LOGOUT')}>
+        <div className="userPannelTab" onClick={() => _userPannelTabClick('LOGOUT')}>
           <LogoutOutlined />
-          退出
+          <span>退出</span>
         </div>
       </div>
     );
   };
 
-  const goChannelIndex = (menuData:any) => {
+  const goChannelIndex = (menuData: any) => {
     setIfOpenPannel(false);
-    onTabClick&&onTabClick(menuData)
-  }
+    onTabClick && onTabClick(menuData);
+  };
 
   const goToHome = () => {
-    history.replace('/index');
-    setSystemTabs([]); //清空tab导航
-    onTabChange && onTabChange([]);
-    setCurrentSelectedTab(undefined);
-    set_pageTitle('欢迎进入医管平台');
-    setIfOpenPannel(false);
-    localStorage.removeItem('currentSelectedTab');
-    localStorage.removeItem('selectedKeys');
-    localStorage.removeItem('visitedTabs');
-    localStorage.removeItem('openKeys');
-  }
-
-  const goSystemIndex = (name:string)=>{
-       if(panelData[currentActivedBlockIndex]){
-            const result:TopBar.TypeBlock[] = panelData[currentActivedBlockIndex].child.filter(t=>(t.name == name));
-            if(result.length>0){
-              _systemTabClickHandle(Object.assign(result[0]))
-                // history.push(result[0].path)
-            }
-       }
-  }
+    const go = () => {
+      history.replace('/index');
+      setSystemTabs([]); //清空tab导航
+      onTabChange && onTabChange([]);
+      setCurrentSelectedTab(undefined);
+      set_pageTitle(topBarTitle);
+      setIfOpenPannel(false);
+      console.log('goHome');
+      localStorage.removeItem('currentSelectedTab');
+      localStorage.removeItem('selectedKeys');
+      // localStorage.removeItem('visitedTabs');
+      localStorage.removeItem('openKeys');
+    };
+
+    const currentSelectedSubHop_json = localStorage.getItem('currentSelectedSubHop');
+    if (currentSelectedSubHop_json) {
+      const currentSelectedSubHop = JSON.parse(currentSelectedSubHop_json);
+      if (currentSelectedSubHop.loadType) {
+        return false;
+      } else {
+        go();
+      }
+    } else {
+      go();
+    }
+  };
+
+  const goSystemIndex = (name: string) => {
+    if (panelData[currentActivedBlockIndex]) {
+      const result: TopBar.TypeBlock[] = panelData[currentActivedBlockIndex].child.filter((t) => t.name == name);
+      if (result.length > 0) {
+        _systemTabClickHandle(Object.assign(result[0]));
+        // history.push(result[0].path)
+      }
+    }
+  };
 
   const openNav = () => {
     setIfOpenPannel(!ifOpenPannel);
-  }
+  };
 
-  
+  const moreItemClickHandle = (systemData: TopBar.Tab) => {
+    //点击更多应用时
+    _systemTabClickHandle(systemData);
+    const temp = onTabSystemTabs[onTabSystemTabs.length - 1];
+    const _onTabSystemTabs = [...onTabSystemTabs];
+    const b = _onTabSystemTabs.filter((a) => a.systemId != temp.systemId);
+
+    set_onTabSystemTabs([...b, systemData]);
+    set_onTabSystemTabs_hide([...onTabSystemTabs_hide.filter((a) => a.systemId != systemData.systemId), temp]);
+  };
 
   const reSetNav = (_panelData: TopBar.PanelData[], cur: TopBar.Tab) => {
-    
-    if (!(_panelData.length > 0)) return
+    if (!(_panelData.length > 0)) return;
 
     if (JSON.stringify(cur) != '{}') {
-
       let blockIndex = 0;
       let channelIndex = 0;
 
-
       const _currentSelectedTabFromLocal = cur;
 
       one: for (let index = 0; index < _panelData.length; index++) {
         blockIndex = index;
-    
         if (_panelData[index] && _panelData[index].child) {
           two: for (let i = 0; i < _panelData[index].child.length; i++) {
             channelIndex = i;
@@ -194,8 +217,8 @@ const TopBar: React.FC<TopBarType> = (props) => {
                 for (let k = 0; k < _systems.length; k++) {
                   if (_systems[k].menuId == _currentSelectedTabFromLocal.menuId) {
                     set_currentActivedBlockIndex(blockIndex);
-                     set_pageTitle(_panelData[blockIndex].child[channelIndex].name); //设置体系标题
-                     
+                    set_pageTitle(_panelData[blockIndex].child[channelIndex].name); //设置体系标题
+
                     break one;
                   }
                 }
@@ -206,154 +229,285 @@ const TopBar: React.FC<TopBarType> = (props) => {
       }
 
       if (_panelData && _panelData.length > 0 && _panelData[blockIndex].child) {
-        setSystemTabs(_panelData[blockIndex].child[channelIndex].child);  //恢复体系列表
+        setSystemTabs(_panelData[blockIndex].child[channelIndex].child); //恢复体系列表
         setCurrentSelectedTab(_currentSelectedTabFromLocal);
         localStorage.setItem('currentSelectedTab', JSON.stringify(_currentSelectedTabFromLocal));
         setInitialState((s) => ({ ...s, currentSelectedSys: _currentSelectedTabFromLocal }));
       }
-      
+
+      // console.log({_currentSelectedTabFromLocal,location});
+      const { pathname } = location;
+      if (pathname.indexOf(_currentSelectedTabFromLocal.path) == -1) {
+        history.push(_currentSelectedTabFromLocal.path);
+      }
+
       //_systemTabClickHandle(_currentSelectedTabFromLocal);  //恢复选中的tab
-  
+    }
+  };
+
+  const [hideTimer, setHideTimer] = useState<null | any>(null);
+  const handleTabMoreMouseLeave = () => {
+    // 设置一个延时器,在一段时间后隐藏morePannel
+    const timer = setTimeout(() => {
+      set_showMoreTabPannel(false);
+    }, 300); // 例如延迟300毫秒
+    setHideTimer(timer);
+  };
 
+  const handleMorePannelMouseEnter = () => {
+    // 清除延时器,防止morePannel隐藏
+    if (hideTimer) {
+      clearTimeout(hideTimer);
+      setHideTimer(null);
     }
-  }
+  };
 
-  useEffect(() => { 
+  const handleMorePannelMouseLeave = () => {
+    set_showMoreTabPannel(false);
+  };
+
+  const updateToken = async () => {
+    const { account } = JSON.parse(localStorage.getItem('userInfo') as string);
+    const hospSign = localStorage.getItem('hospSign');
+    const data = {
+      account,
+      password: password,
+      hospSign,
+    };
+    const resp = await updateTokenReq(data);
+    if (resp) {
+      password = undefined;
+      set_tokenUpdateModalVisible(false);
+    }
+  };
+
+  useEffect(() => {
     if (currentSelectedTabFromLocal) {
       reSetNav(navData, currentSelectedTabFromLocal);
     }
-      
+
     set_panelData(navData);
-  }, [navData])
-
-  useEffect(()=>{
-
-    if(currentTab)reSetNav(panelData,currentTab);
-     
-  },[currentTab]);
-
- 
-
-
-  useEffect(()=>{
-      //  console.log('systemTabs.length',systemTabs.length);
-       if(systemTabs.length>6){
-        const tabs = systemTabs.filter((a:any,index:number)=>{
-                //暂时限制只展示最多5个
-                if(index<=5){
-                   return a
-                } 
-        });
-
-        set_onTabSystemTabs(tabs);
-       }else{
-        set_onTabSystemTabs(systemTabs);
-       }
-  },[systemTabs]);
-  
-  
+  }, [navData]);
+
   useEffect(() => {
+    if (currentTab) reSetNav(panelData, currentTab);
+  }, [currentTab]);
 
-    //_systemTabClickHandle(currentSelectedTabFromLocal);  //恢复选中的tab
+  useEffect(() => {
+    set_pageTitle(topBarTitle);
+  }, [topBarTitle]);
 
-    document.body.addEventListener('click', (e:any) => {
+  useEffect(() => {
+    if (systemTabs.length > 5) {
+      //set_onTabSystemTabs(tabs);
+      let _onTabSystemTabs: any[] = [];
+      let _set_onTabSystemTabs_hide: any[] = [];
+      systemTabs.forEach((a, index) => {
+        if (index <= 4) {
+          _onTabSystemTabs.push(a);
+        } else {
+          if (a.systemId == currentSelectedTabFromLocal.systemId) {
+            const _temp = _onTabSystemTabs[_onTabSystemTabs.length - 1];
+            _onTabSystemTabs.pop();
+            _onTabSystemTabs.push(a);
+            _set_onTabSystemTabs_hide.push(_temp);
+          } else {
+            _set_onTabSystemTabs_hide.push(a);
+          }
+        }
+      });
+      set_onTabSystemTabs(_onTabSystemTabs);
+      set_onTabSystemTabs_hide(_set_onTabSystemTabs_hide);
+    } else {
+      set_onTabSystemTabs(systemTabs);
+    }
+  }, [systemTabs]);
+
+  useEffect(() => {
+    //_systemTabClickHandle(currentSelectedTabFromLocal);  //恢复选中的tab
 
-      const classes = ['panel', 'left','typeBlockIcon', 'typeBlock', 'active', 'right', 'row', 'rowDetai', 'channelName', 'channelList', 'systemTab', 'channelIcon'];
+    document.body.addEventListener('click', (e: any) => {
+      const classes = [
+        'panel',
+        'typeBlockName',
+        'left',
+        'typeBlockIcon',
+        'typeBlock',
+        'typeBlock active',
+        'active',
+        'right',
+        'row',
+        'rowDetai',
+        'channelName',
+        'channelList',
+        'systemTab',
+        'channelIcon',
+        'rowDetail',
+        'typeBlockIcon typeBlockIcon1',
+        'typeBlockIcon typeBlockIcon2',
+        'typeBlockIcon typeBlockIcon3',
+        'typeBlockIcon typeBlockIcon4',
+        'typeBlockIcon typeBlockIcon5',
+        'typeBlockIcon typeBlockIcon6',
+        'typeBlockIcon typeBlockIcon7',
+        'typeBlockIcon typeBlockIcon8',
+        'typeBlockIcon typeBlockIcon9',
+      ];
       if (e.target) {
-        if (classes.includes(e.target.className)) {
-          return
+        let key = e.target.className ? e.target.className : '';
+        if (classes.includes(key) || (typeof key == 'string' && key.indexOf('typeBlockIcon') != -1)) {
+          return;
         }
       }
       setIfOpenPannel(false);
     });
 
+    // 事件监听器的函数定义
+    const handleStorageChange = (e: any) => {
+      if (e.key === 'tokenExpired') {
+        set_tokenUpdateModalVisible(true);
+      }
+    };
+
+    // 添加事件监听器
+    window.addEventListener('removeLocalItemEvent', handleStorageChange);
+
+    // 返回的函数用于在组件卸载时移除事件监听器
+    return () => {
+      window.removeEventListener('removeLocalItemEvent', handleStorageChange);
+    };
   }, []);
 
   return (
-    <div className='topBar' onClick={e => e.stopPropagation()}>
-      <div className='logoWrap'>
-        <img className='logo' src={logo} onClick={() => goToHome()} />
-        <Divider type="vertical" style={{ background: 'white', height: 16, opacity: 0.29, position: 'relative', top: 1, marginLeft: 24, marginRight: 8 }} />
-        <div className='menu' onClick={() => openNav()}>
+    <div className="topBar" onClick={(e) => e.stopPropagation()}>
+      <Modal className="TokenUpdateModal" open={tokenUpdateModalVisible} width={400} title={false} footer={false} closable={false}>
+        <div className="content">
+          <div className="title">登录超时锁定</div>
+          <div className="form">
+            <div className="avatar">
+              <img className="avatarImg" src={require('../../../public/images/initAvatar.png')} alt="" />
+              <img className="suoding" src={require('../../../public/images/suoding.png')} alt="" />
+            </div>
+            <div className="name">{userData?.name}</div>
+            <Input.Password onChange={(e) => (password = e.target.value)} className="input" />
+            <div className="updateBtn" onClick={() => updateToken()}>
+              解锁
+            </div>
+            <a onClick={() => logoutHandle()}>退出登录</a>
+          </div>
+        </div>
+      </Modal>
+      <div className="logoWrap">
+        {logo && <img className="logo" src={logo} onClick={() => goToHome()} />}
+        <Divider type="vertical" style={{ background: 'white', height: 16, opacity: 0.29, position: 'relative', top: 1, marginLeft: 16, marginRight: 8 }} />
+        <div className={ifOpenPannel ? 'menu active' : 'menu'} onClick={() => openNav()}>
           <img src={require('../../../public/images/menu.png')} alt="" />
         </div>
-        <span className='systemTitle' onClick={()=>goSystemIndex(pageTitle)}>{pageTitle}</span>
+        <span className="systemTitle" onClick={() => goSystemIndex(pageTitle)}>
+          {pageTitle}
+        </span>
       </div>
-      
-      <div className='userRelaInfoWrap'>
+
+      <div className="userRelaInfoWrap">
         <>
           {/**
            * 已打开的tab
            */}
-          <div className='tabWrap'>
-            {onTabSystemTabs&&(onTabSystemTabs).map((item, index) => (
-              <div key={index} className={currentSelectedTab?.menuId == item.menuId ? `tab on` : `tab`} onClick={() => _systemTabClickHandle(item)}>
-                <div className='tabText'>{item.name} </div>
-                <div className='closeIconWrap'>
-                  <img src={tabCloseIcon} onClick={(e) => closeTabHandle(item, e)}  />
+          <div className="tabWrap">
+            {onTabSystemTabs &&
+              onTabSystemTabs.map((item, index) => (
+                <div key={index} className={currentSelectedTab?.menuId == item.menuId ? `tab on` : `tab`} onClick={() => _systemTabClickHandle(item)}>
+                  <div className="tabText">{item.name} </div>
+                  <div className="closeIconWrap">
+                    <img src={tabCloseIcon} onClick={(e) => closeTabHandle(item, e)} />
+                  </div>
                 </div>
-              </div>
-            ))}
+              ))}
           </div>
+          {systemTabs.length > 5 && (
+            <div className={showMoreTabPannel ? 'tabMore active' : 'tabMore'} onMouseEnter={() => set_showMoreTabPannel(true)} onMouseLeave={handleTabMoreMouseLeave}>
+              {showMoreTabPannel && (
+                <div className="morePannel" onMouseEnter={handleMorePannelMouseEnter} onMouseLeave={handleMorePannelMouseLeave}>
+                  {onTabSystemTabs_hide.map((item, index) => {
+                    return (
+                      <div key={index} className="moreItem" onClick={() => moreItemClickHandle(item)}>
+                        {/* <Tooltip placement="right" title={item.name}> */}
+                        <span>{item.name}</span>
+                        {/* </Tooltip> */}
+                      </div>
+                    );
+                  })}
+                </div>
+              )}
+            </div>
+          )}
         </>
-        
-
-        {/* <div className='notification'>
-          <img className='notificationIcon' src={require('../../../public/images/notificationIcon.png')} />
-        </div> */}
-        <Tooltip title={<UserPannel />} color="#fff" onVisibleChange={(visible) => setArrowRotate(visible)}>
-          <div className='user'>
-            <img className='avator' src={require('../../../public/images/Mask.png')} />
-            <span className='name'>{userData?.name}</span>
-            <img className={arrowRotate ? `arrow on` : `arrow`} src={require('../../../public/images/arrow_white.png')} />
+
+        <div className="notification">
+          <img className="notificationIcon" src={require('../../../public/images/notificationIcon.png')} />
+        </div>
+        <Tooltip className="topBarTooltip" placement="bottomRight" title={<UserPannel />} color="#fff" onOpenChange={(visible) => setArrowRotate(visible)}>
+          <div className="user">
+            <div className="avator">
+              <img src={require('../../../public/images/avatar.png')} />
+            </div>
+            <div className="info">
+              <span className="hospName">{localStorage.getItem('hospAbbreviation')}</span>
+              <span className="name">{userData?.name}</span>
+            </div>
+            {/* <img className={arrowRotate ? `arrow on` : `arrow`} src={require('../../../public/images/arrow_white.png')} /> */}
           </div>
         </Tooltip>
       </div>
 
-      {
-        ifOpenPannel && (
-          <div className='panel' onClick={e => e.stopPropagation()}>
-            
-            <div className='left'>
-              {
-                panelData.map((item, index) => {
-                  return (
-                    <div className={currentActivedBlockIndex == index ? `typeBlock active` : `typeBlock`} key={index} onClick={() => set_currentActivedBlockIndex(index)}>
-                      {/* <img className='typeBlockIcon' src={item?.icon} alt="" /> */}
-                      <img className='typeBlockIcon' src={require('../../../public/images/blueBook.png')} alt="" />
-                      <span>{item.name}</span>
-                    </div>
-                  )
-                })
-              }
-            </div>
-            <div className='right'>
-              {
-                panelData.length > 0 && panelData[currentActivedBlockIndex] && panelData[currentActivedBlockIndex].child && panelData[currentActivedBlockIndex].child.map((item, index: number) => {
-                  return (
-                    <div className='row' key={index}>
-                      <img className='channelIcon' src={require('../../../public/images/zhilianganquan.png')} alt="" />
-                      <div className='rowDetail'>
-                        <div className='channelName' onClick={() => goChannelIndex(item)}>{item.name}</div>
-                        <div className='channelList'>
-                          {
-                            item.child && item.child.length > 0 && item.child.map((val, i: number) => {
-                              return (
-                                <div className={currentSelectedTab?.menuId == val.menuId ? 'systemTab on' : 'systemTab'} key={i} onClick={() => _systemListClickHandle(val, currentActivedBlockIndex, index, i)}>{val.name}</div>
-                              )
-                            })
-                          }
-                        </div>
+      {ifOpenPannel && (
+        <div className="panel" onClick={(e) => e.stopPropagation()}>
+          <div className="left">
+            {panelData.map((item, index) => {
+              return (
+                <div className={currentActivedBlockIndex == index ? `typeBlock active` : `typeBlock`} key={index} onClick={() => set_currentActivedBlockIndex(index)}>
+                  {/* <img className='typeBlockIcon' src={item?.icon} alt="" /> */}
+                  <div className={` typeBlockIcon typeBlockIcon${item.icon}`}></div>
+                  <span className="typeBlockName">{item.name}</span>
+                </div>
+              );
+            })}
+          </div>
+          <div className="right">
+            <div className="panelCloseBtn" onClick={() => setIfOpenPannel(false)}></div>
+            {panelData.length > 0 &&
+              panelData[currentActivedBlockIndex] &&
+              panelData[currentActivedBlockIndex].child &&
+              panelData[currentActivedBlockIndex].child.map((item, index: number) => {
+                return (
+                  <div className="row" key={index}>
+                    <img className="channelIcon" src={item.icon ? item.icon : require(`../../../public/images/tongyong_tixi.png`)} alt="" />
+                    <div className="rowDetail">
+                      <div className="channelName" onClick={() => goChannelIndex(item)}>
+                        {item.name}
+                      </div>
+                      <div className="channelList">
+                        {item.child &&
+                          item.child.length > 0 &&
+                          item.child.map((val, i: number) => {
+                            return (
+                              <div
+                                className={currentSelectedTab?.menuId == val.menuId ? 'systemTab on' : 'systemTab'}
+                                key={i}
+                                onClick={() => _systemListClickHandle(val, currentActivedBlockIndex, index, i)}
+                              >
+                                {val.name}
+                              </div>
+                            );
+                          })}
                       </div>
                     </div>
-                  )
-                })
-              }
-            </div>
+                  </div>
+                );
+              })}
           </div>
-        )
-      }
-
+        </div>
+      )}
     </div>
   );
 };

+ 481 - 53
src/components/topBar/style.less

@@ -1,3 +1,89 @@
+.kcmp-ant-tooltip {
+  .kcmp-ant-tooltip-content {
+    position: relative;
+    right: 8px;
+  }
+}
+
+.TokenUpdateModal {
+  .kcmp-ant-modal-content {
+    background: linear-gradient(180deg, #e8f1fc 0%, #ffffff 100%) !important;
+    .kcmp-ant-modal-body {
+      background-image: url('../../../public/images/tokenUpdateModalbg.png') !important;
+      background-size: 320px 180px !important;
+      background-repeat: no-repeat !important;
+      background-position: right top !important;
+
+      .content {
+        height: 300px;
+
+        .title {
+          font-weight: 500;
+          font-size: 16px;
+          color: #17181a;
+          margin-bottom: 14px;
+        }
+
+        .form {
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+          align-items: center;
+
+          .avatar {
+            position: relative;
+            width: 64px;
+            height: 64px;
+            margin-bottom: 8px;
+            .avatarImg {
+              width: 100%;
+              height: 100%;
+            }
+            .suoding {
+              position: absolute;
+              bottom: 0;
+              right: 0;
+              width: 24px;
+              height: 24px;
+            }
+          }
+
+          .name {
+            font-weight: 400;
+            font-size: 20px;
+            height: 20px;
+            line-height: 20px;
+            color: #17181a;
+            margin-bottom: 24px;
+          }
+
+          .input {
+            width: 240px;
+            height: 32px;
+            background: #ffffff;
+            border-radius: 4px;
+            margin-bottom: 24px;
+          }
+
+          .updateBtn {
+            cursor: pointer;
+            width: 240px;
+            height: 32px;
+            line-height: 32px;
+            background: #3377ff;
+            border-radius: 4px;
+            text-align: center;
+            font-weight: 400;
+            font-size: 14px;
+            color: #ffffff;
+            margin-bottom: 16px;
+          }
+        }
+      }
+    }
+  }
+}
+
 .userPannel {
   width: 100px;
   background-color: white;
@@ -5,18 +91,25 @@
   .userPannelTab {
     display: flex;
     flex-direction: row;
-    justify-content: space-evenly;
+    justify-content: flex-start;
     align-items: center;
     height: 30px;
     font-size: 14px;
     font-family: SourceHanSansCN-Normal, SourceHanSansCN;
     font-weight: 400;
-    color: rgb(131, 127, 127);
+    color: #17181a;
     cursor: pointer;
-    border-bottom: 1px solid #eee;
+    padding-left: 12px;
+    border-radius: 2px;
+
+    & > span {
+      &:last-child {
+        margin-left: 8px;
+      }
+    }
 
     &:hover {
-      background-color: #eee;
+      background-color: #f5f7fa;
     }
 
     &:last-child {
@@ -25,16 +118,32 @@
   }
 }
 
+.kcmp-ant-tooltip {
+  padding-top: 0 !important;
+
+  .kcmp-ant-tooltip-content {
+    .kcmp-ant-tooltip-arrow {
+      display: none;
+    }
+
+    .kcmp-ant-tooltip-inner {
+      border-radius: 4px;
+    }
+  }
+}
+
 .topBar {
   position: relative;
   z-index: 999;
   display: flex;
   flex-direction: row;
+  justify-content: space-between;
   align-items: center;
   width: 100%;
+  min-width: 1280px;
   height: 48px;
   padding-left: 16px;
-  background: #3071f2;
+  background: #3377ff;
 
   * {
     line-height: normal;
@@ -44,15 +153,22 @@
     display: flex;
     flex-direction: row;
     align-items: center;
-    width: 350px;
+    width: 400px;
 
     .logo {
-      width: 120px;
-      height: 24px;
+      // width: 120px;
+      height: 40px;
     }
 
     .systemTitle {
       cursor: pointer;
+      font-size: 16px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #ffffff;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
     }
 
     .menu {
@@ -67,46 +183,46 @@
       transition: all 0.3s ease-in;
       background: rgba(254, 255, 255, 0);
 
-
-      &>img {
+      & > img {
         width: 16px;
         height: 16px;
       }
 
+      &.active {
+        background: rgba(254, 255, 255, 0.1);
+      }
+
       &:hover {
         background: rgba(254, 255, 255, 0.1);
       }
     }
 
-    &>span {
+    & > span {
       font-size: 14px;
       font-family: SourceHanSansCN-Medium, SourceHanSansCN;
       font-weight: 500;
-      color: #FFFFFF;
+      color: #ffffff;
     }
   }
 
-
   .userRelaInfoWrap {
     display: flex;
     width: 55%;
     flex-direction: row;
     justify-content: flex-end;
     align-items: center;
-    position: fixed;
-    right: 0;
-    padding-right: 16px;
 
     .tabWrap {
       display: flex;
       width: 60%;
       flex-direction: row;
-      justify-content:flex-end;
+      justify-content: flex-end;
       align-items: center;
-      margin-right: 24px;
+      margin-right: 8px;
+
       .tab {
         display: flex;
-        max-width:180px;
+        max-width: 180px;
         height: 32px;
         line-height: 32px;
         text-align: center;
@@ -116,7 +232,7 @@
         padding: 0 2%;
         border-radius: 4px;
         opacity: 0.8;
-        margin-right:1%;
+        margin-right: 1%;
         cursor: pointer;
         box-sizing: border-box;
 
@@ -149,7 +265,7 @@
 
         &.on {
           opacity: 1;
-          background: #0b54e6;
+          background: #1963fa;
         }
 
         &:last-child {
@@ -158,18 +274,92 @@
       }
     }
 
+    .tabMore {
+      position: relative;
+      z-index: 999;
+      cursor: pointer;
+      width: 32px;
+      height: 32px;
+      border-radius: 4px;
+      margin-right: 8px;
+
+      .morePannel {
+        position: absolute;
+        z-index: 999;
+        top: 40px;
+        width: 130px;
+        background: #f5f7fa;
+        box-shadow: 0px 10px 20px 0px rgba(31, 71, 153, 0.2);
+        border-radius: 0px 0px 8px 8px;
+        opacity: 0.98;
+        padding: 8px;
+
+        .moreItem {
+          display: flex;
+          justify-content: flex-start;
+          align-items: center;
+          height: 32px;
+          background: #ffffff;
+          border-radius: 4px;
+          padding: 8px;
+
+          span {
+            font-size: 12px;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            color: #17181a;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+          }
+
+          &:hover {
+            background: #3376fe;
+
+            span {
+              color: #ffffff;
+            }
+          }
+        }
+      }
+
+      &::after {
+        position: relative;
+        // top: 3px;
+        // left: 6px;
+        display: inline-block;
+        content: '';
+        width: 32px;
+        height: 32px;
+        background: url('../../../public/images/threePoint_white_more.png');
+        background-size: 24px 24px;
+        background-position: center center;
+        background-repeat: no-repeat;
+      }
+
+      &.active {
+        background: rgba(249, 248, 248, 0.1);
+      }
+    }
+
     .notification {
       display: flex;
       flex-direction: row;
       justify-content: center;
       align-items: center;
-      width: 18px;
-      height: 18px;
-      margin-right: 16px;
+      margin-right: 8px;
       cursor: pointer;
+      width: 32px;
+      height: 32px;
+      border-radius: 4px;
 
       .notificationIcon {
-        width: 100%;
+        width: 16px;
+        height: 16px;
+      }
+
+      &:hover {
+        background: rgba(249, 248, 248, 0.1);
       }
     }
 
@@ -179,19 +369,58 @@
       flex-direction: row;
       justify-content: center;
       align-items: center;
+      //margin-left: 16px;
+      height: 48px;
+      padding-right: 16px;
+      padding-left: 8px;
+      background: linear-gradient(90deg, #66a6ff 0%, #3366ff 100%);
+      border-radius: 24px 0px 0px 24px;
 
       .avator {
-        width: 26px;
-        height: 26px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 32px;
+        height: 32px;
         margin-right: 8px;
+        border-radius: 50%;
+        background: #ffffff;
+        overflow: hidden;
+        border: 1px solid #ffffff;
+
+        img {
+          width: 101%;
+          height: 101%;
+        }
       }
 
-      .name {
-        font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-        font-weight: 400;
-        color: #ffffff;
-        margin-right: 10px;
+      .info {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+
+        .hospName {
+          height: 13px;
+          line-height: 13px;
+          font-size: 12px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #ffffff;
+          margin-bottom: 7px;
+          opacity: 0.9;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+
+        .name {
+          height: 13px;
+          line-height: 13px;
+          font-size: 12px;
+          font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+          font-weight: 500;
+          color: #ffffff;
+        }
       }
 
       .arrow {
@@ -209,17 +438,17 @@
   .panel {
     display: flex;
     flex-direction: row;
-    align-items:stretch;
+    align-items: stretch;
     position: absolute;
     top: 48px;
-    left: 165px;
+    left: 170px;
     min-height: 140px;
-    width: 80%;
-    border-radius: 0px 0px 0px 8px;
-    background: #F5F7FA;
+    width: 980px;
+    background: #f5f7fa;
     box-shadow: 0px 10px 20px 0px rgba(31, 71, 153, 0.2);
     border-radius: 0px 0px 8px 8px;
     opacity: 0.98;
+    overflow: hidden;
 
     .left {
       width: 140px;
@@ -238,59 +467,254 @@
         margin: 0 auto;
         border-radius: 4px;
 
-        &>img {
-          width: 32px;
-          height: 32px;
+        .typeBlockIcon {
+          width: 40px;
+          height: 40px;
           margin-bottom: 8px;
         }
 
-        &>span {
+        & > span {
           font-size: 12px;
           font-family: SourceHanSansCN-Normal, SourceHanSansCN;
           font-weight: 400;
           color: #515866;
         }
 
+        .typeBlockIcon1 {
+          background: url('../../../public/images/jingyiyiliao_gray.png');
+          background-size: contain;
+        }
+
+        .typeBlockIcon2 {
+          background: url('../../../public/images/HBI_gray.png');
+          background-size: contain;
+        }
+
+        .typeBlockIcon3 {
+          background: url('../../../public/images/zhongtaiguanli_gray.png');
+          background-size: contain;
+        }
+
+        .typeBlockIcon4 {
+          background: url('../../../public/images/guanlizhongxin_gray.png');
+          background-size: contain;
+        }
+
+        .typeBlockIcon5 {
+          background: url('../../../public/images/feiyi_gray.png');
+          background-size: contain;
+        }
+
         &.active {
-          background: #F5F7FA;
+          background: #f2f7ff;
+
+          .typeBlockIcon1 {
+            background: url('../../../public/images/jingyiyiliao.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon2 {
+            background: url('../../../public/images/HBI.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon3 {
+            background: url('../../../public/images/zhongtaiguanli.png');
+            background-size: contain;
+          }
 
-          &>span {
-            color: #3376FE;
+          .typeBlockIcon4 {
+            background: url('../../../public/images/guanlizhongxin.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon5 {
+            background: url('../../../public/images/feiyi.png');
+            background-size: contain;
+          }
+
+          & > span {
+            color: #3376fe;
           }
         }
+
+        &:hover {
+          // background: #F5F7FA;
+          .typeBlockIcon1 {
+            background: url('../../../public/images/jingyiyiliao.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon2 {
+            background: url('../../../public/images/HBI.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon3 {
+            background: url('../../../public/images/zhongtaiguanli.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon4 {
+            background: url('../../../public/images/guanlizhongxin.png');
+            background-size: contain;
+          }
+
+          .typeBlockIcon5 {
+            background: url('../../../public/images/feiyi.png');
+            background-size: contain;
+          }
+
+          & > span {
+            color: #3376fe;
+          }
+        }
+
+        // &:nth-child(2) {
+
+        //   .typeBlockIcon2 {
+        //     background: url('../../../public/images/HBI_gray.png');
+        //     background-size: contain;
+        //   }
+
+        //   &.active {
+        //     background: #F2F7FF;
+
+        //     .typeBlockIcon2 {
+        //       background: url('../../../public/images/HBI.png');
+        //       background-size: contain;
+        //     }
+
+        //     &>span {
+        //       color: #3376FE;
+        //     }
+        //   }
+
+        //   &:hover {
+        //     .typeBlockIcon2 {
+        //       background: url('../../../public/images/HBI.png');
+        //       background-size: contain;
+        //     }
+
+        //     &>span {
+        //       color: #3376FE;
+        //     }
+        //   }
+        // }
+
+        // &:nth-child(3) {
+
+        //   .typeBlockIcon3 {
+        //     background: url('../../../public/images/zhongtaiguanli_gray.png');
+        //     background-size: contain;
+        //   }
+
+        //   &.active {
+        //     background: #F2F7FF;
+
+        //     .typeBlockIcon3 {
+        //       background: url('../../../public/images/zhongtaiguanli.png');
+        //       background-size: contain;
+        //     }
+
+        //     &>span {
+        //       color: #3376FE;
+        //     }
+        //   }
+
+        //   &:hover {
+        //     .typeBlockIcon3 {
+        //       background: url('../../../public/images/zhongtaiguanli.png');
+        //       background-size: contain;
+        //     }
+
+        //     &>span {
+        //       color: #3376FE;
+        //     }
+        //   }
+        // }
+
+        // &:nth-child(4) {
+
+        //   .typeBlockIcon4 {
+        //     background: url('../../../public/images/guanlizhongxin_gray.png');
+        //     background-size: contain;
+        //   }
+
+        //   &.active {
+        //     background: #F2F7FF;
+
+        //     .typeBlockIcon4 {
+        //       background: url('../../../public/images/guanlizhongxin.png');
+        //       background-size: contain;
+        //     }
+
+        //     &>span {
+        //       color: #3376FE;
+        //     }
+        //   }
+
+        //   &:hover {
+        //     .typeBlockIcon4 {
+        //       background: url('../../../public/images/guanlizhongxin.png');
+        //       background-size: contain;
+        //     }
+
+        //     &>span {
+        //       color: #3376FE;
+        //     }
+        //   }
+        // }
       }
     }
 
     .right {
+      position: relative;
       width: calc(100% - 140px);
       height: 100%;
+      max-height: 572px;
       padding: 2% 2.5%;
+      overflow: scroll;
+
+      .panelCloseBtn {
+        position: absolute;
+        width: 12px;
+        height: 12px;
+        cursor: pointer;
+        top: 16px;
+        right: 16px;
+        background: url('../../../public/images/close.png');
+        background-size: contain;
+      }
 
       .row {
         display: flex;
         flex-direction: row;
         justify-content: flex-start;
         align-items: flex-start;
+        margin-bottom: 16px;
 
         .channelIcon {
           width: 24px;
           height: 24px;
-          margin-right: 24px;
+          margin-right: 17px;
         }
 
         .rowDetail {
           width: 100%;
+
           .channelName {
             display: inline-block;
             font-size: 14px;
             font-family: SourceHanSansCN-Normal, SourceHanSansCN;
             font-weight: 400;
-            color: #7A8599;
+            color: #7a8599;
             margin-bottom: 8px;
             cursor: pointer;
             transition: all 0.3s ease-in;
+
             &:hover {
-              color: #3376FE;
+              color: #3376fe;
             }
           }
 
@@ -303,15 +727,15 @@
             align-items: center;
 
             .systemTab {
-              width: 24%;
+              width: 180px;
               height: 32px;
               line-height: 32px;
-              background: #FFFFFF;
+              background: #ffffff;
               border-radius: 4px;
               font-size: 12px;
               font-family: SourceHanSansCN-Normal, SourceHanSansCN;
               font-weight: 400;
-              color: #17181A;
+              color: #17181a;
               padding-left: 8px;
               margin-right: 1%;
               cursor: pointer;
@@ -323,16 +747,20 @@
 
               &.on {
                 color: white;
-                background: linear-gradient(90deg, #3376FE 0%, #66A6FF 100%);
+                background: linear-gradient(90deg, #3376fe 0%, #66a6ff 100%);
               }
 
               &:hover {
                 color: white;
-                background: linear-gradient(90deg, #3376FE 0%, #66A6FF 100%);
+                background: linear-gradient(90deg, #3376fe 0%, #66a6ff 100%);
               }
             }
           }
         }
+
+        &:last-child {
+          margin-bottom: 0;
+        }
       }
     }
   }

+ 2 - 2
src/components/topBar/typings.d.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-10 13:56:19
- * @LastEditTime: 2022-07-11 18:12:01
+ * @LastEditTime: 2023-09-07 17:37:27
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/components/topBar/typings.d.ts
@@ -16,7 +16,7 @@ declare namespace TopBar {
     url?: string;
     path: string;
     type:number;
-    contentType:string;
+    contentType:number;
     isSetupMenu?:number;
   };
 

+ 3 - 1
src/constant.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-14 16:09:09
- * @LastEditTime: 2022-07-26 09:45:51
+ * @LastEditTime: 2023-12-26 19:48:10
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/constant.ts
@@ -56,3 +56,5 @@ export const Platforms = [
     logo: pfmIcon,
   },
 ];
+
+export const KcimCenterSysId = '1547394914533380096';

+ 83 - 71
src/global.less

@@ -3,6 +3,11 @@
   padding: 0;
 }
 
+body {
+  margin: 0;
+  height: 100%;
+  zoom: unset !important;
+}
 
 input {
   outline: none !important;
@@ -23,7 +28,7 @@ input {
 }
 
 .kcmp-ant-layout {
-  background: #F5F7FA;
+  background: #f5f7fa;
 }
 
 .kcmp-ant-pro-table-search {
@@ -35,26 +40,24 @@ input {
   margin-bottom: 16px;
 }
 
-
 /**
       input 
 **/
 .kcmp-ant-input-affix-wrapper {
   padding: 0px 8px;
   border-radius: 4px;
-  border: 1px solid #CFD7E6;
+  border: 1px solid #cfd7e6;
 
-  &>input {
+  & > input {
     &::placeholder {
       font-size: 14px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #99A6BF;
+      color: #99a6bf;
     }
   }
 }
 
-
 /**
     Form
 **/
@@ -74,26 +77,23 @@ input {
   }
 
   .kcmp-ant-form-item-control-input {
-
     .kcmp-ant-form-item-control-input-content {
       textarea {
         padding: 4px 8px;
         border-radius: 4px !important;
-        border: 1px solid #CFD7E6;
+        border: 1px solid #cfd7e6;
       }
 
       .kcmp-ant-input {
-
         //padding-left: 8px;
         &::placeholder {
-          color: #99A6BF;
+          color: #99a6bf;
         }
       }
     }
   }
 }
 
-
 /**
     input-number
 **/
@@ -101,39 +101,37 @@ input {
 .kcmp-ant-input-number {
   height: 24px;
   border-radius: 4px;
-  border: 1px solid #CFD7E6;
+  border: 1px solid #cfd7e6;
 
   .kcmp-ant-input-number-handler-wrap {
     .kcmp-ant-input-number-handler {
-      border-left: 1px solid #CFD7E6;
+      border-left: 1px solid #cfd7e6;
     }
 
     .kcmp-ant-input-number-handler-down {
-      border-top: 1px solid #CFD7E6;
+      border-top: 1px solid #cfd7e6;
     }
 
     .kcmp-ant-input-number-handler-up-inner,
     .kcmp-ant-input-number-handler-down-inner {
-      color: #99A6BF;
+      color: #99a6bf;
     }
   }
 
   .kcmp-ant-input-number-input-wrap {
-
     .kcmp-ant-input-number-input {
       height: 22px;
       line-height: 24px;
       padding: 0 8px;
 
       &::placeholder {
-        color: #99A6BF;
+        color: #99a6bf;
       }
     }
   }
 }
 
-
-.kcmp-ant-table-thead>tr>th {
+.kcmp-ant-table-thead > tr > th {
   border-bottom: none;
 
   &::before {
@@ -141,7 +139,6 @@ input {
   }
 }
 
-
 /**
     Select
 **/
@@ -150,7 +147,7 @@ input {
     height: 24px !important;
     padding: 0 8px !important;
     border-radius: 4px !important;
-    border: 1px solid #CFD7E6 !important;
+    border: 1px solid #cfd7e6 !important;
 
     .kcmp-ant-select-selection-item {
       line-height: 24px;
@@ -165,25 +162,25 @@ input {
       font-size: 14px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #99A6BF;
+      color: #99a6bf;
     }
   }
 
   .kcmp-ant-select-arrow {
-    color: #CFD7E6;
+    color: #cfd7e6;
   }
 
   &.kcmp-ant-select-disabled {
     .kcmp-ant-select-selector {
-      border: 1px solid #DADEE6 !important;
+      border: 1px solid #dadee6 !important;
 
       .kcmp-ant-select-selection-placeholder {
-        color: #7A8599;
+        color: #7a8599;
       }
     }
 
     .kcmp-ant-select-arrow {
-      color: #7A8599;
+      color: #7a8599;
     }
   }
 }
@@ -197,28 +194,25 @@ input {
 
   .kcmp-ant-transfer {
     .kcmp-ant-transfer-list {
-      border: 1px solid #DAE2F2;
+      border: 1px solid #dae2f2;
       border-radius: 4px;
 
       .kcmp-ant-transfer-list-header {
-        border-bottom: 1px solid #DAE2F2;
+        border-bottom: 1px solid #dae2f2;
       }
     }
   }
 }
 
-
-
-
 .kcmp-ant-modal {
   padding-bottom: 0;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 8px;
   overflow: hidden;
 
   .kcmp-ant-modal-content {
     .kcmp-ant-modal-close-x {
-      color: #17181A;
+      color: #17181a;
     }
 
     .kcmp-ant-modal-header {
@@ -226,8 +220,9 @@ input {
       font-size: 16px;
       font-family: SourceHanSansCN-Medium, SourceHanSansCN;
       font-weight: 500;
-      color: #17181A;
+      color: #17181a;
       border-bottom: none;
+      padding-bottom: 0;
     }
 
     .kcmp-ant-modal-body {
@@ -270,44 +265,47 @@ input {
   }
 }
 
-
-
-
-div::-webkit-scrollbar {
-  width: 2px;
-  height: 2px;
+*::-webkit-scrollbar {
+  width: 4px !important;
+  height: 10px !important;
   /**/
 }
 
-div::-webkit-scrollbar-track {
+*::-webkit-scrollbar-track {
   background: transparent;
   border-radius: 2px;
 }
 
-div::-webkit-scrollbar-thumb {
-  background: #bfbfbf;
+*::-webkit-scrollbar-thumb {
+  background: rgba(228, 231, 235, 0.7) !important;
   border-radius: 10px;
 }
 
-div::-webkit-scrollbar-thumb:hover {
+*::-webkit-scrollbar-thumb:hover {
   width: 4px;
   height: 4px;
-  background: rgb(136, 135, 135);
+  background: rgba(228, 231, 235, 0.7);
 }
 
-div::-webkit-scrollbar-corner {
-  background: rgb(136, 135, 135);
-
+*::-webkit-scrollbar-corner {
+  background: rgba(228, 231, 235, 0.7);
 }
 
+//-----------  Menu左侧菜单
 
+.kcmp-ant-layout-sider {
+  &.kcmp-ant-layout-sider-collapsed {
+    width: 60px !important;
+    flex: 0 0 60px !important;
+    max-width: 60px !important;
+    min-width: 60px !important;
+  }
+}
 
 //--------------------
 
-
 //Transfer
 
-
 .kcmp-ant-modal-body {
   .TableTransfer {
     .kcmp-ant-transfer-operation {
@@ -320,13 +318,13 @@ div::-webkit-scrollbar-corner {
         height: 40px !important;
         // background: #FAFCFF;
         border-radius: 4px;
-        border: 1px solid #DAE2F2;
+        border: 1px solid #dae2f2;
       }
     }
 
     .kcmp-ant-transfer-list-header {
       .anticon {
-        color: #99A6BF;
+        color: #99a6bf;
       }
 
       .kcmp-ant-transfer-list-header-selected {
@@ -340,7 +338,7 @@ div::-webkit-scrollbar-corner {
 
         .kcmp-ant-input-prefix {
           .anticon-search {
-            color: #99A6BF;
+            color: #99a6bf;
           }
         }
       }
@@ -350,13 +348,12 @@ div::-webkit-scrollbar-corner {
       .kcmp-ant-table-container {
         .kcmp-ant-table-content {
           .kcmp-ant-table-thead {
-
-            &>tr>th {
+            & > tr > th {
               font-size: 14px;
               font-family: SourceHanSansCN-Medium, SourceHanSansCN;
               font-weight: 500;
-              color: #17181A;
-              background: #EEF3FA;
+              color: #17181a;
+              background: #eef3fa;
               padding: 4px 8px !important;
             }
           }
@@ -364,47 +361,62 @@ div::-webkit-scrollbar-corner {
       }
     }
   }
-
 }
 
-
 //checkbox
 
 .kcmp-ant-checkbox {
   .kcmp-ant-checkbox-inner {
-    border: 1px solid #DAE2F2;
+    border: 1px solid #dae2f2;
     border-radius: 4px;
   }
 }
 
-.kcmp-ant-checkbox+span {
+.kcmp-ant-checkbox + span {
   padding-left: 4px;
   padding-right: 4px;
 }
 
-
 //drawer
 
-
 .kcmp-ant-drawer-body {
   padding: 16px;
 }
 
-
 //Picker
 
 .kcmp-ant-picker {
   padding: 0px 11px !important;
   border-radius: 4px;
-  border: 1px solid #CFD7E6;
+  border: 1px solid #cfd7e6;
   .kcmp-ant-picker-input {
-         input {
-             &::placeholder {
-              color: #99A6BF;
-             }
-         }
+    input {
+      &::placeholder {
+        color: #99a6bf;
+      }
+    }
   }
   .kcmp-ant-picker-suffix {
-    color: #99A6BF;
+    color: #99a6bf;
   }
 }
+
+/**
+   Layout
+**/
+
+.kcmp-ant-pro-sider {
+  .bms-ant-layout-sider-children {
+    padding-inline: 8px;
+  }
+  .kcmp-ant-pro-sider-collapsed-button {
+    border-top: 1px solid transparent;
+  }
+}
+.kcmp-ant-pro-sider-collapsed-button .anticon {
+  display: inline-block;
+  font-size: 24px !important;
+}
+.kcmp-ant-layout-header {
+  z-index: 200 !important;
+}

+ 4 - 2
src/global.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-12-21 11:05:37
- * @LastEditTime: 2023-03-23 16:49:49
+ * @LastEditTime: 2024-03-28 18:04:34
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/global.tsx
@@ -18,10 +18,12 @@ const loginPath = '/login';
 
 export const logoutHandle = async () => {
   // await logout();
+  console.log('logoutHandle');
   localStorage.removeItem('userData');
   localStorage.removeItem('initialState');
-  localStorage.removeItem('currentSelectedTab');
+  // localStorage.removeItem('currentSelectedTab');
   //localStorage.removeItem('isChildShowMenu');
+
   localStorage.removeItem('selectedKeys');
   localStorage.removeItem('openKeys');
   // localStorage.removeItem('visitedTabs');

+ 123 - 72
src/layouts/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 13:56:33
- * @LastEditTime: 2023-02-27 10:38:07
+ * @LastEditTime: 2024-01-18 15:45:55
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/layouts/index.tsx
@@ -12,42 +12,62 @@ import ProLayout from '@ant-design/pro-layout';
 
 import TopBar from '@/components/topBar';
 import { Key, useEffect, useState } from 'react';
-import { getPlatformMenu, getSpecifyMenuDetail, getUserPlatformNav } from '@/service/menu';
-import { NavSelecterData } from '@/components/NavSelecter';
-
-
-
-const TopHoc = ({ currentSelectedSys, openedSysLists, navData,set_emptyPageContent }: {set_emptyPageContent:any; currentSelectedSys: TopBar.Tab | undefined, openedSysLists: TopBar.Tab[], navData: TopBar.PanelData[] }) => {
+import { getSpecifyMenuDetail, getUserPlatformNav } from '@/service/menu';
+import { getAppAccess, getSysParamsByCode } from '@/service';
+import { Modal } from 'antd';
+import { KcimCenterSysId } from '@/constant';
+
+const TopHoc = ({
+  currentSelectedSys,
+  openedSysLists,
+  navData,
+  set_emptyPageContent,
+  logo,
+  topBarTitle,
+}: {
+  set_emptyPageContent: any;
+  currentSelectedSys: TopBar.Tab | undefined;
+  openedSysLists: TopBar.Tab[];
+  navData: TopBar.PanelData[];
+  logo: string;
+  topBarTitle: string;
+}) => {
   const { initialState, setInitialState } = useModel('@@initialState');
 
-
-  const onTabChangeHandle = async (data: TopBar.Tab[]) => {
-
-  };
+  const onTabChangeHandle = async (data: TopBar.Tab[]) => {};
 
   const onTabClickHandle = async (data: TopBar.Tab) => {
-
-    if(JSON.stringify(data) != '{}'){
-      await setInitialState((s) => ({ ...s, currentSelectedSys: data }));
-  
-      if(data.contentType == '4'){
+    const { systemId = '', menuId = '' } = data;
+    const resp = await getAppAccess(systemId.length > 0 ? systemId : menuId);
+    if (!resp) {
+      if (JSON.stringify(data) != '{}') {
+        await setInitialState((s) => ({ ...s, currentSelectedSys: data }));
+        // localStorage.removeItem('currentSelectedTab');
+        localStorage.removeItem('selectedKeys');
+        // localStorage.removeItem('visitedTabs');
+        localStorage.removeItem('openKeys');
+
+        if (data.contentType == 4) {
           //空白页面
-          if(data.isSetupMenu){
+          if (data.isSetupMenu) {
             //体系菜单掩藏子应用的menu
-            localStorage.setItem('isChildShowMenu','false');
+            localStorage.setItem('isChildShowMenu', 'false');
           }
-          
           history.push(`${data.path}?isEmpty=true&menuId=${data.menuId}`);
-      }else{
-        if(data.isSetupMenu){
-          //体系菜单掩藏子应用的menu
-          localStorage.setItem('isChildShowMenu','false');
-        }else{
-          localStorage.setItem('isChildShowMenu','true');
+        } else {
+          if (data.isSetupMenu) {
+            //体系菜单掩藏子应用的menu
+            localStorage.setItem('isChildShowMenu', 'false');
+          } else {
+            localStorage.setItem('isChildShowMenu', 'true');
+          }
+          history.push(data.path);
         }
-     
-        history.push(data.path);
       }
+    } else {
+      Modal.error({
+        title: '当前系统未注册,请联系管理员处理!',
+      });
     }
   };
 
@@ -60,29 +80,29 @@ const TopHoc = ({ currentSelectedSys, openedSysLists, navData,set_emptyPageConte
     }
     if (tag == 'SETTING') {
       if (initialState) {
-        setInitialState((s) => ({
-          ...s,
-          currentSelectedSys: {
-            menuId: -1,
-            name: '个人中心',
-            icon: '',
-            url: '',
-            systemId: '-1',
-            type:1,
-            contentType:'0',
-            path: '/personalCenter',
-          },
-        }));
+        // setInitialState((s) => ({
+        //   ...s,
+        //   currentSelectedSys: {
+        //     menuId: -1,
+        //     name: '个人中心',
+        //     icon: '',
+        //     url: '',
+        //     systemId: '-1',
+        //     type:1,
+        //     contentType:'0',
+        //     path: '/personalCenter',
+        //   },
+        // }));
       }
+      history.push('/personalCenter');
     }
   };
 
-  
- 
-
   return (
     <TopBar
       navData={navData}
+      logo={logo}
+      topBarTitle={topBarTitle}
       userData={initialState?.userData}
       openedTabs={openedSysLists}
       onTabChange={onTabChangeHandle}
@@ -90,7 +110,6 @@ const TopHoc = ({ currentSelectedSys, openedSysLists, navData,set_emptyPageConte
       currentTab={currentSelectedSys}
       userPannelTabClick={userPannelTabClickhandle}
     />
-    
   );
 };
 
@@ -98,46 +117,79 @@ export default function Layout({ children, location, route, history, match }: IR
   const { initialState, setInitialState } = useModel('@@initialState');
   const [navData, set_navData] = useState<TopBar.PanelData[]>([]);
   const [emptyPageContent, set_emptyPageContent] = useState('');
-  const [isEmpty,set_isEmpty] = useState(false);
+  const [isEmpty, set_isEmpty] = useState(false);
+  const [topBarLogoUrl, set_topBarLogoUrl] = useState<string>('');
+  const [topBarTitle, set_topBarTitle] = useState('');
+  const [iframeUrl, set_iframeUrl] = useState<string | undefined>(undefined);
 
   const getNavData = async () => {
     const nav = await getUserPlatformNav();
     if (nav) {
-      set_navData(nav);
-
+      set_navData(nav as any);
     }
-  }
+  };
 
+  const getAllParamsHanle = async () => {
+    const resp = await getSysParamsByCode(KcimCenterSysId);
+    if (resp) {
+      resp.forEach((item: any) => {
+        if (item.code == '1739122834787143680') {
+          set_topBarLogoUrl(item.value);
+        }
+        if (item.code == '1739123252502073344') {
+          set_topBarTitle(item.value);
+        }
+      });
+    }
+  };
 
-  const getEmptyPageContent = async (menuId:Key) => {
+  const getEmptyPageContent = async (menuId: Key) => {
     const menuItem = await getSpecifyMenuDetail(menuId);
     set_emptyPageContent(menuItem.description);
-  }
-
+  };
 
   useEffect(() => {
     if (location.pathname != '/login') {
       getNavData();
     }
-    if(location.query.isEmpty == 'true'&&location.query.menuId){
-      getEmptyPageContent(location.query.menuId as string)
+    if (location.pathname == '/index') {
+      //localStorage.removeItem('currentSelectedTab');
+      //localStorage.removeItem('isChildShowMenu');
+
+      localStorage.removeItem('selectedKeys');
+      localStorage.removeItem('openKeys');
+    }
+    if (location.query.isEmpty == 'true' && location.query.menuId) {
+      getEmptyPageContent(location.query.menuId as string);
     }
-  }, [])
+  }, []);
 
-  useEffect(()=>{
-  
-    if(location.pathname != '/platform'){
+  useEffect(() => {
+    if (location.pathname != '/platform') {
       //排除已有系统的空白页面
       set_isEmpty(location.query.isEmpty == 'true');
     }
-  })
+  });
 
   if (location.pathname == '/login') {
     return <div>{children}</div>;
   }
 
+  useEffect(() => {
+    getAllParamsHanle();
+  }, []);
+
+  // if (initialState?.currentSelectedSys) {
+  //   const { type, url, contentType } = initialState.currentSelectedSys;
+  //   if (type == 1 && contentType == 6) {
+  //     const userData = localStorage.getItem('userData');
+  //     const { token } = JSON.parse(userData as string);
+  //     return (
+  //       <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={addTokenToUrl(url as string, token)} onLoad={() => adjustIframe()} ></iframe>
+  //     )
+  //   }
+  // }
 
- 
   return (
     <ProLayout
       layout="top"
@@ -153,17 +205,16 @@ export default function Layout({ children, location, route, history, match }: IR
           >
             {dom}
           </a>
-        )
+        );
       }}
       menu={{
-
         request: async () => {
           return [
             {
               path: '/index',
-              name: '欢迎进入医管平台'
-            }
-          ]
+              name: topBarTitle,
+            },
+          ];
         },
       }}
       pageTitleRender={false}
@@ -171,6 +222,8 @@ export default function Layout({ children, location, route, history, match }: IR
         initialState && (
           <TopHoc
             navData={navData}
+            topBarTitle={topBarTitle}
+            logo={topBarLogoUrl as string}
             set_emptyPageContent={set_emptyPageContent}
             currentSelectedSys={initialState.currentSelectedSys}
             openedSysLists={initialState.openedSysLists ? initialState.openedSysLists : []}
@@ -178,14 +231,12 @@ export default function Layout({ children, location, route, history, match }: IR
         )
       }
     >
-      {
-        isEmpty&& (
-          <div style={{ textAlign: 'center', paddingTop: 100,height:'93vh' }}>
-            <h1>{emptyPageContent}</h1>
-          </div>
-        )
-      }
-      {!isEmpty&&(<div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll' }}>{children}</div>)}
+      {isEmpty && (
+        <div style={{ textAlign: 'center', paddingTop: 100, height: '93vh' }}>
+          <h1>{emptyPageContent}</h1>
+        </div>
+      )}
+      {!isEmpty && <div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll', minWidth: 1280 }}>{children}</div>}
     </ProLayout>
   );
 }

+ 167 - 166
src/pages/index/components/FastEntry/index.tsx

@@ -2,190 +2,191 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-05-27 14:17:59
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-07 15:56:31
+ * @LastEditTime: 2024-01-16 16:50:20
  * @FilePath: /KC-MiddlePlatform/src/pages/index/components/FastEntry/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
 //快速入口模块
 import { history, useModel } from 'umi';
 import { useEffect, useState } from 'react';
 import './style.less';
-import { Empty } from 'antd';
+import { Empty, Modal } from 'antd';
 import NavSelecter, { NavSelecterData, NavSelecterItemType } from '@/components/NavSelecter';
 import { addFastEntry, AddFastEntryDataType, getUserPlatformNav } from '@/service/menu';
-
-
-
+import { getAppAccess } from '@/service';
+import { createFromIconfontCN } from '@ant-design/icons';
 
 export type FastEntryTabType = {
-    name: string;
-    path: string;
-    systemId:string;
-    type:number;
-    menuId:number|string;
-}
+  name: string;
+  path: string;
+  systemId: string;
+  type: number;
+  contentType: number;
+  menuId: number | string;
+};
 export interface FastEntryType {
-    data: FastEntryTabType[];
+  data: FastEntryTabType[];
 }
 
-export const FastEntry = (props: FastEntryType) => {
-
-    const { initialState, setInitialState } = useModel('@@initialState');
-
-    const [tabs, set_tabs] = useState<FastEntryTabType[]>([]);
-    const [open,set_open] = useState(false);
-    const [navSelecterData,set_navSelecterData] = useState<NavSelecterData[]>([]);
-  
-
-    const tabClickHandle = async (tab: FastEntryTabType) => {
-        await setInitialState((s) => ({ ...s, currentSelectedSys:tab as any,currentTab:tab})); 
-        history.push(tab.path)
-    }
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
 
-    
-
-    const getNavData =async () => {
-          
-        const navData = await getUserPlatformNav();
-        
-        set_navSelecterData(navData)
+export const FastEntry = (props: FastEntryType) => {
+  const { initialState, setInitialState } = useModel('@@initialState');
+
+  const [tabs, set_tabs] = useState<FastEntryTabType[]>([]);
+  const [open, set_open] = useState(false);
+  const [navSelecterData, set_navSelecterData] = useState<NavSelecterData[]>([]);
+
+  const tabClickHandle = async (tab: FastEntryTabType) => {
+    const { systemId = '', menuId = '', contentType, type } = tab;
+    const resp = await getAppAccess(systemId.length > 0 ? systemId : menuId);
+
+    if (!resp) {
+      await setInitialState((s) => ({ ...s, currentSelectedSys: tab as any, currentTab: tab }));
+      if (type == 1 && contentType == 6) {
+        //体系或第三方iframe
+        history.push('/platform');
+      } else {
+        history.push(tab.path);
+      }
+    } else {
+      Modal.error({
+        title: '当前系统未注册,请联系管理员处理!',
+      });
     }
+  };
 
-    const onCheckedHandle = async (data:NavSelecterItemType[])=>{
-        const resp = await addFastEntry(data as AddFastEntryDataType[]);
-        if(resp){
-            set_tabs(data);   
-        }
-        
-    }
+  const getNavData = async () => {
+    const navData = await getUserPlatformNav();
+    set_navSelecterData(navData);
+  };
 
-    const addHandle = ()=>{
-        getNavData();
-        set_open(true);
+  const onCheckedHandle = async (data: NavSelecterItemType[]) => {
+    const resp = await addFastEntry(data as AddFastEntryDataType[]);
+    if (resp) {
+      set_tabs(data);
     }
-
-
-    useEffect(() => {
-        const { data } = props;
-        set_tabs(data);
-    }, [props]);
-
-
-
-    useEffect(()=>{
-        
-        // set_navSelecterData([
-        //       {
-        //         name:'精益医疗管理',
-        //         key:0,
-        //         children:[
-        //             {
-        //                 name:'质量安全管理',
-        //                 key:1,
-        //                 children:[
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:2
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:3
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:4
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:20
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:21
-        //                     }
-        //                 ]
-        //             },
-        //             {
-        //                 name:'质量安全管理2',
-        //                 key:30,
-        //                 children:[
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:31
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:32
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:33
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:34
-        //                     },
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:35
-        //                     }
-        //                 ]
-        //             }
-        //         ]
-        //       },
-        //       {
-        //         name:'HBI',
-        //         key:5,
-        //         children:[
-        //             {
-        //                 name:'质量安全管理',
-        //                 key:6,
-        //                 children:[
-        //                     {
-        //                         name:'质量管理及十大安全目标',
-        //                         key:7
-        //                     }
-        //                 ]
-        //             }
-        //         ]
-        //       }
-        // ])      
-    },[])
-
-    return (
-        <div className='fastEntry'>
-            
-            <div className='topTitle'>
-                <span className='name'>快速入口</span>
-                <span className='addBtn' onClick={()=>addHandle()}>添加</span>
-            </div>
-            
-            {
-                open&&(
-                     <NavSelecter data={navSelecterData} onVisibleChange={(bool)=>set_open(bool)} value={tabs} onChecked={onCheckedHandle} />
-                )
-            }
-
-            <div className='wrap'>
-                {
-                    tabs.map((item, index) => {
-                        return (
-                            <div className='tab' onClick={() => tabClickHandle(item)} key={index}>{item.name}</div>
-                        )
-                    })
-                }
-                {
-                    tabs.length == 0 && (
-                        <div className='empty'>
-                            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                        </div>
-                    )
-                }
+  };
+
+  const addHandle = () => {
+    getNavData();
+    set_open(true);
+  };
+
+  useEffect(() => {
+    const { data } = props;
+    set_tabs(data);
+  }, [props]);
+
+  useEffect(() => {
+    // set_navSelecterData([
+    //       {
+    //         name:'精益医疗管理',
+    //         key:0,
+    //         children:[
+    //             {
+    //                 name:'质量安全管理',
+    //                 key:1,
+    //                 children:[
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:2
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:3
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:4
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:20
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:21
+    //                     }
+    //                 ]
+    //             },
+    //             {
+    //                 name:'质量安全管理2',
+    //                 key:30,
+    //                 children:[
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:31
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:32
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:33
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:34
+    //                     },
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:35
+    //                     }
+    //                 ]
+    //             }
+    //         ]
+    //       },
+    //       {
+    //         name:'HBI',
+    //         key:5,
+    //         children:[
+    //             {
+    //                 name:'质量安全管理',
+    //                 key:6,
+    //                 children:[
+    //                     {
+    //                         name:'质量管理及十大安全目标',
+    //                         key:7
+    //                     }
+    //                 ]
+    //             }
+    //         ]
+    //       }
+    // ])
+  }, []);
+
+  return (
+    <div className="fastEntry">
+      <div className="topTitle">
+        <span className="name">快速入口</span>
+        <span className="addBtn" onClick={() => addHandle()}>
+          管理
+        </span>
+      </div>
+
+      {open && <NavSelecter type={2} title="选择应用" data={navSelecterData} onVisibleChange={(bool) => set_open(bool)} value={tabs.map((a) => a.menuId)} onChecked={onCheckedHandle} />}
+
+      <div className="wrap">
+        {tabs.slice(0, 6).map((item, index) => {
+          return (
+            <div className="tab" onClick={() => tabClickHandle(item)} key={index}>
+              <IconFont type="icontubiao1" style={{ marginRight: 8 }} />
+              {item.name}
             </div>
-        </div>
-    )
-}
+          );
+        })}
+        {tabs.length == 0 && (
+          <div className="empty">
+            {/* <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> */}
+            添加系统快速入口,方便再次进入
+          </div>
+        )}
+      </div>
+    </div>
+  );
+};

+ 28 - 14
src/pages/index/components/FastEntry/style.less

@@ -1,9 +1,8 @@
 .fastEntry {
   flex-grow: 1;
-  min-height: 153px;
-  background: #FFFFFF;
+  height: 176px;
+  background: #ffffff;
   border-radius: 4px;
-  margin-right: 16px;
   .topTitle {
     display: flex;
     flex-direction: row;
@@ -11,20 +10,20 @@
     align-items: center;
     height: 48px;
     padding: 0 16px;
-    border-bottom: 1px solid #E6EAF2;
+    // border-bottom: 1px solid #E6EAF2;
 
     .name {
       font-size: 16px;
       font-family: SourceHanSansCN-Medium, SourceHanSansCN;
       font-weight: 500;
-      color: #17181A;
+      color: #17181a;
     }
 
     .addBtn {
       font-size: 14px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #3376FE;
+      color: #3376fe;
       cursor: pointer;
     }
   }
@@ -33,6 +32,7 @@
     display: flex;
     flex-direction: row;
     padding: 16px;
+    padding-top: 0;
     padding-bottom: 0;
     flex-wrap: wrap;
     .empty {
@@ -40,11 +40,13 @@
       justify-content: center;
       align-items: center;
       width: 100%;
-      
+      margin-top: 45px;
+      font-size: 14px;
+      color: #7a8599;
     }
     .tab {
-      width: 19.2%;
-      margin-right:1%;
+      width: 48.7%;
+      margin-right: 2.5%;
       font-size: 14px;
       text-align: left;
       line-height: 32px;
@@ -52,19 +54,31 @@
       font-weight: 400;
       color: #525866;
       height: 32px;
-      padding-left: 1%;
-      background: #F5F7FA;
+      padding-left: 2%;
+      background: #f5f7fa;
       margin-bottom: 8px;
       border-radius: 4px;
       cursor: pointer;
 
       &:hover {
-        color: #3376FE;
+        color: #3376fe;
       }
 
-      &:nth-child(5n){
-          margin-right: 0;
+      &:nth-child(2n) {
+        margin-right: 0;
       }
+
+      // &::before {
+      //    position: relative;
+      //    top:3px;
+      //    display: inline-block;
+      //    content: '';
+      //    width: 16px;
+      //    height: 16px;
+      //    margin-right: 8px;
+      //    background: url('../../../../../public/images/icon-box.png');
+      //    background-size: contain;
+      // }
     }
   }
 }

+ 51 - 50
src/pages/index/components/RecentlyVisited/index.tsx

@@ -2,75 +2,76 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-05-30 09:50:41
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-07 16:00:57
+ * @LastEditTime: 2023-11-10 17:20:09
  * @FilePath: /KC-MiddlePlatform/src/pages/index/components/RecentlyVisited/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
 //最近访问模块
 
 import { useEffect, useState } from 'react';
 import './style.less';
-import {history, useModel} from 'umi';
-import { Empty } from 'antd';
+import { history, useModel } from 'umi';
+import { Empty, Modal } from 'antd';
 import { NavSelecterItemType } from '@/components/NavSelecter';
-
-
+import { getAppAccess } from '@/service';
 
 export type RecentlyVisitedItemsType = {
-        name:string;
-        path:string;
-        menuId:string;
-        type:number;
-        systemId:string;
-}
+  name: string;
+  path: string;
+  menuId: string;
+  type: number;
+  systemId: string;
+};
 export interface RecentlyVisitedPropsType {
-       data:RecentlyVisitedItemsType[]
+  data: RecentlyVisitedItemsType[];
 }
 
-export const RecentlyVisited = (props:RecentlyVisitedPropsType) => {
+export const RecentlyVisited = (props: RecentlyVisitedPropsType) => {
+  const { data } = props;
 
-    const {data} = props;
+  const { initialState, setInitialState } = useModel('@@initialState');
 
-    const { initialState, setInitialState } = useModel('@@initialState');
+  const [tabs, set_tabs] = useState<RecentlyVisitedItemsType[]>([]);
 
-    const [tabs, set_tabs] = useState<RecentlyVisitedItemsType[]>([]);
+  const clickHandle = async (val: NavSelecterItemType) => {
+    //更新currentSelectedSys/currentTab触发导航跳转
+    const { systemId = '', menuId = '' } = val;
+    const resp = await getAppAccess(systemId.length > 0 ? systemId : menuId);
 
-    const clickHandle = async (val:NavSelecterItemType)=>{
-        //更新currentSelectedSys/currentTab触发导航跳转
-        await setInitialState((s) => ({ ...s, currentSelectedSys:val as any,currentTab:val})); 
-        history.push(val.path)
+    if (!resp) {
+      await setInitialState((s) => ({ ...s, currentSelectedSys: val as any, currentTab: val }));
+      history.push(val.path);
+    } else {
+      Modal.error({
+        title: '当前系统未注册,请联系管理员处理!',
+      });
     }
+  };
 
-    useEffect(()=>{
-        set_tabs(data);
-    },[data])
-    
+  useEffect(() => {
+    set_tabs(data);
+  }, [data]);
 
-    return (
-        <div className='RecentlyVisited'>
-            <div className='topTitle'>
-                <span className='name'>最近访问</span>
-            </div>
-            <div className='wrap'>
-                {
-                    tabs.map((item, index) => {
-                        return (
-                            <div className='tab' onClick={()=>clickHandle(item)} key={index}>{item.name}</div>
-                        )
-                    })
-                }
-                {
-                    tabs.length == 0 && (
-                        <div className='empty'>
-                            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                        </div>
-                    )
-                }
+  return (
+    <div className="RecentlyVisited">
+      <div className="topTitle">
+        <span className="name">最近访问</span>
+      </div>
+      <div className="wrap">
+        {tabs.map((item, index) => {
+          return (
+            <div className="tab" onClick={() => clickHandle(item)} key={index}>
+              {item.name}
             </div>
-        </div>
-    )
-}
+          );
+        })}
+        {tabs.length == 0 && (
+          <div className="empty">
+            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+          </div>
+        )}
+      </div>
+    </div>
+  );
+};

+ 52 - 53
src/pages/index/components/TodoList/index.tsx

@@ -2,75 +2,74 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-05-30 10:49:32
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2022-07-07 17:53:44
+ * @LastEditTime: 2023-12-27 14:51:13
  * @FilePath: /KC-MiddlePlatform/src/pages/index/components/TodoList/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
 //待办事项模块
 
 import { useEffect, useState } from 'react';
 import './style.less';
 
-
-
 export type todoItem = {
-    id:number;
-    status:number;
-    taskLevel:number;
-    createDate:number;
-    content:string;
-}
+  recordTitle: string;
+  id: number;
+  status: number;
+  taskLevel: number;
+  createDate: number;
+  content: string;
+};
 
 export interface TodoList {
-       todoList:todoItem[];
-       todoListClickHandle?:(id:number)=>void;
+  todoList: todoItem[];
+  todoListClickHandle?: (id: number) => void;
 }
 
-export const TodoList = (props:TodoList) => {
-    
-    const {todoList,todoListClickHandle} = props;
-    const [todoLists, set_todoLists] = useState<todoItem[]>([]);
+export const TodoList = (props: TodoList) => {
+  const { todoList, todoListClickHandle } = props;
+  const [todoLists, set_todoLists] = useState<todoItem[]>([]);
 
-    const setTodoClass = (val:todoItem)=>{
-        if(val.taskLevel == 3)return 'todoStatus green';
-        if(val.taskLevel == 2)return 'todoStatus orange';
-        if(val.taskLevel == 1)return 'todoStatus red';
-    }
+  const setTodoClass = (val: todoItem) => {
+    if (val.taskLevel == 3) return 'todoStatus green';
+    if (val.taskLevel == 2) return 'todoStatus orange';
+    if (val.taskLevel == 1) return 'todoStatus red';
+  };
 
-    const checkBtnHandle = (item:todoItem)=>{
-        todoListClickHandle&&todoListClickHandle(item.id)
-    }
+  const checkBtnHandle = (item: todoItem) => {
+    todoListClickHandle && todoListClickHandle(item.id);
+  };
 
-    useEffect(()=>{
-        set_todoLists(todoList)
-    },[todoList])
+  useEffect(() => {
+    set_todoLists(todoList.splice(0, 4));
+  }, [todoList]);
 
-    return (
-        <div className='TodoList'>
-            <div className='topTitle'>
-                <span className='name'>待办事项</span>
-                {/* <span className='actBtn'>全部处理</span> */}
-            </div>
-            <div className='wrap'>
-                {
-                    todoLists.map((item, index) => {
-                        return (
-                            <div className='todoList'  key={index}>
-                                   <div className='checkBtn' onClick={()=>checkBtnHandle(item)}></div>
-                                   <div className='status'>
-                                         <div className={setTodoClass(item)}>医务管理系统 / 医资授予</div>
-                                         <span className='date'>{item.createDate}</span>
-                                   </div>
-                                   <div className='detail' dangerouslySetInnerHTML={{__html:item.content}}></div>
-                            </div>
-                        )
-                    })
-                }
+  return (
+    <div className="TodoList">
+      <div className="topTitle">
+        <span className="name">待办事项</span>
+        {/* <span className='actBtn'>全部处理</span> */}
+      </div>
+      <div className="wrap">
+        {todoLists.map((item, index) => {
+          return (
+            <div className="todoList" key={index}>
+              <div className="checkBtn" onClick={() => checkBtnHandle(item)}></div>
+              <div className="status">
+                <div className={setTodoClass(item)}>{item.recordTitle}</div>
+                <span className="date">{item.createDate ? `${item.createDate}`.replace(/:\d{2}$/, '') : ''}</span>
+              </div>
+              <div className="detail" dangerouslySetInnerHTML={{ __html: item.content }}></div>
             </div>
-        </div>
-    )
-}
+          );
+        })}
+        {todoLists.length == 0 && (
+          <div className="empty">
+            <img src={require('../../../../../public/images/empty.png')} alt="" />
+            <span>待办事项已全部处理</span>
+          </div>
+        )}
+      </div>
+    </div>
+  );
+};

+ 93 - 71
src/pages/index/components/TodoList/style.less

@@ -1,9 +1,8 @@
 .TodoList {
   flex-grow: 1;
-  min-height: 300px;
-  background: #FFFFFF;
+  min-height: 348px;
+  background: #ffffff;
   border-radius: 4px;
-  margin-right: 16px;
   padding-bottom: 24px;
   .topTitle {
     display: flex;
@@ -12,20 +11,20 @@
     align-items: center;
     height: 48px;
     padding: 0 16px;
-    border-bottom: 1px solid #E6EAF2;
+    // border-bottom: 1px solid #E6EAF2;
 
     .name {
       font-size: 16px;
       font-family: SourceHanSansCN-Medium, SourceHanSansCN;
       font-weight: 500;
-      color: #17181A;
+      color: #17181a;
     }
 
     .actBtn {
       font-size: 14px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #3376FE;
+      color: #3376fe;
       cursor: pointer;
     }
   }
@@ -34,21 +33,24 @@
     display: flex;
     flex-direction: column;
     padding: 16px;
+    padding-top: 0;
     padding-bottom: 0;
+    height: calc(100% - 48px);
+    overflow-y: scroll;
 
     .todoList {
       position: relative;
       margin-bottom: 24px;
       .checkBtn {
         position: absolute;
-        right: 24px;
-        top:50%;
+        right: 0px;
+        top: 50%;
         cursor: pointer;
         margin-top: -16px;
         width: 32px;
         height: 32px;
         border-radius: 50%;
-        background: #F5F7FA;
+        background: #f5f7fa;
         background-image: url('./images/gou.png');
         background-position: center center;
         background-size: 15px 15px;
@@ -64,98 +66,118 @@
         .todoStatus {
           height: 24px;
           line-height: 24px;
-          background: #E5F9F9;
+          background: #e5f9f9;
           border-radius: 6px;
           font-size: 12px;
           font-family: SourceHanSansCN-Medium, SourceHanSansCN;
           font-weight: 500;
-          color: #2FC0C0;
+          color: #2fc0c0;
           margin-right: 16px;
           padding-left: 4px;
           padding-right: 10px;
 
           &.green {
-            &::before {
-              position: relative;
-              top:3px;
-              display: inline-block;
-              content: '';
-              width: 16px;
-              height: 16px;
-              margin-right: 6px;
-              background: #2FC0C0;
-              border-radius: 4px;
-              background-image: url('./images/exclamationMark.png');
-              background-size: 10px 10px;
-              background-position: center center;
-              background-repeat: no-repeat;
-          
-            }
+            // &::before {
+            //   position: relative;
+            //   top:3px;
+            //   display: inline-block;
+            //   content: '';
+            //   width: 16px;
+            //   height: 16px;
+            //   margin-right: 6px;
+            //   background: #2FC0C0;
+            //   border-radius: 4px;
+            //   background-image: url('./images/exclamationMark.png');
+            //   background-size: 10px 10px;
+            //   background-position: center center;
+            //   background-repeat: no-repeat;
+
+            // }
           }
           &.orange {
-            color: #FFAA33;
-            background-color: #FCF7F0;
-            &::before {
-              position: relative;
-              top:3px;
-              display: inline-block;
-              content: '';
-              width: 16px;
-              height: 16px;
-              margin-right: 6px;
-              background: #FFAA33;
-              border-radius: 4px;
-              background-image: url('./images/exclamationMark.png');
-              background-size: 10px 10px;
-              background-position: center center;
-              background-repeat: no-repeat;
-          
-            }
+            color: #ffaa33;
+            background-color: #fcf7f0;
+            // &::before {
+            //   position: relative;
+            //   top:3px;
+            //   display: inline-block;
+            //   content: '';
+            //   width: 16px;
+            //   height: 16px;
+            //   margin-right: 6px;
+            //   background: #FFAA33;
+            //   border-radius: 4px;
+            //   background-image: url('./images/exclamationMark.png');
+            //   background-size: 10px 10px;
+            //   background-position: center center;
+            //   background-repeat: no-repeat;
+
+            // }
           }
           &.red {
-            color: #FF6666;
-            background-color: #FCF0F0;
-            &::before {
-              position: relative;
-              top:3px;
-              display: inline-block;
-              content: '';
-              width: 16px;
-              height: 16px;
-              margin-right: 6px;
-              background:#FF6666;
-              border-radius: 4px;
-              background-image: url('./images/exclamationMark.png');
-              background-size: 10px 10px;
-              background-position: center center;
-              background-repeat: no-repeat;
-          
-            }
-          }
-
+            color: #ff6666;
+            background-color: #fcf0f0;
+            // &::before {
+            //   position: relative;
+            //   top:3px;
+            //   display: inline-block;
+            //   content: '';
+            //   width: 16px;
+            //   height: 16px;
+            //   margin-right: 6px;
+            //   background:#FF6666;
+            //   border-radius: 4px;
+            //   background-image: url('./images/exclamationMark.png');
+            //   background-size: 10px 10px;
+            //   background-position: center center;
+            //   background-repeat: no-repeat;
 
+            // }
+          }
         }
 
         .date {
           font-size: 12px;
           font-family: SourceHanSansCN-Normal, SourceHanSansCN;
           font-weight: 400;
-          color: #7A8599;
+          color: #7a8599;
         }
       }
       .detail {
+        width: 323px;
         font-size: 14px;
         font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
-        color: #666F80;
-        &>span {
-            font-weight: bold;
-            color: #17181A;
+        color: #666f80;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        & > span {
+          font-weight: 500;
+          color: #17181a;
         }
       }
 
       &:last-child {
-          margin-bottom: 0;
+        margin-bottom: 0;
+      }
+    }
+
+    .empty {
+      display: flex;
+      margin-top: 70px;
+      justify-content: center;
+      flex-direction: column;
+      align-items: center;
+      & > img {
+        width: 100px;
+        height: 88px;
+        margin-bottom: 16px;
+      }
+      & > span {
+        font-size: 14px;
+        font-weight: 400;
+        color: #7a8599;
       }
     }
   }

+ 432 - 221
src/pages/index/index.less

@@ -1,245 +1,456 @@
 .indexPage {
-  height:100%;
-  background: #F5F7FA;
+  height: 100%;
+  min-width: 1180px;
+  background: #f5f7fa;
+
   .pageContainer {
+    display: flex;
+    width: calc(100%);
+    flex-direction: row;
+    align-items: flex-start;
+    justify-content: space-between;
     padding: 16px;
-    .profileCard {
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      padding: 32px;
-      background: #FFFFFF;
+    // .profileCard {
+    //   display: flex;
+    //   flex-direction: column;
+    //   justify-content: flex-start;
+    //   padding: 32px;
+    //   background: #FFFFFF;
+    //   border-radius: 4px;
+
+    //   .wraper {
+    //     display: flex;
+    //     flex: 1;
+
+    //     .avatar {
+    //       width: 80px;
+    //       height: 80px;
+    //       margin-right: 24px;
+
+    //       img {
+    //         width: 100%;
+    //       }
+    //     }
+
+    //     .description {
+    //       width: calc(100% - 104px);
+
+    //       .rowOne {
+    //         display: flex;
+    //         flex: 1;
+    //         flex-direction: row;
+    //         justify-content: space-between;
+    //         align-items: flex-start;
+    //         padding-top: 16px;
+
+    //         .info {
+    //           .name {
+    //             height: 20px;
+    //             font-size: 20px;
+    //             font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+    //             font-weight: bold;
+    //             color: #17181A;
+    //             line-height: 30px;
+    //             margin-bottom: 16px;
+    //           }
+
+    //           .baseInfo {
+    //             height: 14px;
+    //             font-size: 14px;
+    //             font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    //             font-weight: 400;
+    //             color: #666E80;
+    //             line-height: 21px;
+    //           }
+    //         }
+
+    //         .staffBaseInfo {
+    //           display: flex;
+    //           flex: 1;
+    //           flex-direction: row;
+    //           justify-content: flex-end;
+    //           align-items: flex-start;
+
+    //           .staffBaseInfoSpan {
+    //             display: flex;
+    //             flex-direction: column;
+    //             justify-content: center;
+    //             align-items: center;
+
+    //             .spanName {
+    //               height: 14px;
+    //               font-size: 14px;
+    //               font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    //               font-weight: 400;
+    //               color: #666E80;
+    //               line-height: 14px;
+    //               margin-bottom: 16px;
+    //             }
+
+    //             .spanValue {
+    //               height: 20px;
+    //               font-size: 20px;
+    //               font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+    //               font-weight: bold;
+    //               color: #17181A;
+    //               line-height: 20px;
+
+    //               &.status {
+    //                 color: #FFB54D;
+    //               }
+    //             }
+    //           }
+
+    //           .Divider {
+    //             height: 24px;
+    //             margin-left: 5%;
+    //             margin-right: 5%;
+    //             margin-top: 10px;
+    //           }
+    //         }
+    //       }
+
+    //       .rowTwo {
+    //         display: flex;
+    //         flex: 1;
+    //         margin-top: 45px;
+    //         flex-direction: row;
+    //         justify-content: flex-start;
+    //         align-items: center;
+
+    //         .medicalInfoSpan {
+    //           display: flex;
+    //           width: 20%;
+    //           height: 45px;
+    //           flex-direction: column;
+    //           align-items: flex-start;
+    //           margin-right: 10%;
+
+    //           .span {
+    //             height: 14px;
+    //             font-size: 14px;
+    //             font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    //             font-weight: 400;
+    //             color: #666E80;
+    //             line-height: 14px;
+    //             margin-bottom: 16px;
+
+    //             span {
+    //               color: #17181A;
+    //             }
+
+    //             &:last-child {
+    //               margin-bottom: 0;
+    //             }
+    //           }
+
+    //           &:first-child {
+    //              width: 40%;
+    //           }
+
+    //           &:last-child {
+    //             margin-right: 0;
+    //           }
+    //         }
+    //       }
+    //     }
+    //   }
+
+    //   .profileFooter {
+    //     display: flex;
+    //     flex-direction: row;
+    //     justify-content: space-between;
+    //     padding-top: 25px;
+    //     margin-top: 32px;
+    //     border-top: 1px solid #DFE3EB;
+
+    //     .flowInstruction {
+    //       height: 14px;
+    //       font-size: 14px;
+    //       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    //       font-weight: 400;
+    //       color: #17181A;
+    //       line-height: 14px;
+    //       cursor: pointer;
+
+    //       &::before {
+    //         position: relative;
+    //         display: inline-block;
+    //         content: '';
+    //         top: 2px;
+    //         width: 16px;
+    //         height: 16px;
+    //         margin-right: 8px;
+    //         // background-image: url('../../../../public/images/alert.png');
+    //         // background-size: cover;
+    //       }
+    //     }
+
+    //     .action {
+    //       display: flex;
+    //       flex-direction: row;
+
+    //       .editProfile {
+    //         height: 14px;
+    //         font-size: 14px;
+    //         font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    //         font-weight: 400;
+    //         color: #26334D;
+    //         line-height: 14px;
+    //         margin-right: 32px;
+    //         cursor: pointer;
+
+    //         &::before {
+    //           position: relative;
+    //           display: inline-block;
+    //           content: '';
+    //           top: 3px;
+    //           width: 16px;
+    //           height: 16px;
+    //           margin-right: 8px;
+    //           // background-image: url('../../../../public/images/box.png');
+    //           // background-size: cover;
+    //         }
+    //       }
+
+    //       .qualificationApply {
+    //         height: 14px;
+    //         font-size: 14px;
+    //         font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    //         font-weight: 400;
+    //         color: #26334D;
+    //         line-height: 14px;
+    //         cursor: pointer;
+
+    //         &::before {
+    //           position: relative;
+    //           display: inline-block;
+    //           content: '';
+    //           top: 3px;
+    //           width: 16px;
+    //           height: 16px;
+    //           margin-right: 8px;
+    //           // background-image: url('../../../../public/images/blueFile.png');
+    //           // background-size: cover;
+    //         }
+    //       }
+    //     }
+    //   }
+    // }
+    // .cardTwo {
+    //   display: flex;
+    //   flex-direction: row;
+    //   padding-top: 16px;
+    //   margin-bottom: 16px;
+    // }
+    // .cardThree {
+    //   display: flex;
+    //   flex-direction: row;
+    //   margin-bottom: 16px;
+    // }
+
+    .left {
+      width: calc(100% - 454px);
+      height: calc(100vh - 80px);
+      min-height: 686px;
+      padding: 16px;
       border-radius: 4px;
-  
-      .wraper {
+      background: #fff;
+
+      .leftTitle {
+        height: 24px;
+        line-height: 24px;
+        font-size: 24px;
+        font-weight: bold;
+        color: #17181a;
+        margin-bottom: 12px;
+      }
+
+      .leftTitleSub {
+        font-size: 14px;
+        font-weight: 400;
+        color: #525866;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        -webkit-box-orient: vertical;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+
+      .leftContent {
         display: flex;
-        flex: 1;
-  
-        .avatar {
-          width: 80px;
-          height: 80px;
-          margin-right: 24px;
-  
-          img {
-            width: 100%;
+        width: 100%;
+        height: calc(100% - 112px);
+        justify-content: center;
+        align-items: center;
+        margin-top: 16px;
+        overflow: hidden;
+
+        .imgWrap {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          width: 100%;
+          height: 100%;
+          background-size: cover !important;
+          background-repeat: no-repeat !important;
+
+          & > img {
+            width: 810px;
+            transition: all 0.3s linear;
           }
         }
-  
-        .description {
-          width: calc(100% - 104px);
-  
-          .rowOne {
-            display: flex;
-            flex: 1;
-            flex-direction: row;
-            justify-content: space-between;
-            align-items: flex-start;
-            padding-top: 16px;
-  
-            .info {
-              .name {
-                height: 20px;
-                font-size: 20px;
-                font-family: SourceHanSansCN-Bold, SourceHanSansCN;
-                font-weight: bold;
-                color: #17181A;
-                line-height: 30px;
-                margin-bottom: 16px;
-              }
-  
-              .baseInfo {
-                height: 14px;
-                font-size: 14px;
-                font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-                font-weight: 400;
-                color: #666E80;
-                line-height: 21px;
-              }
-            }
-  
-            .staffBaseInfo {
-              display: flex;
-              flex: 1;
-              flex-direction: row;
-              justify-content: flex-end;
-              align-items: flex-start;
-  
-              .staffBaseInfoSpan {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: center;
-  
-                .spanName {
-                  height: 14px;
-                  font-size: 14px;
-                  font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-                  font-weight: 400;
-                  color: #666E80;
-                  line-height: 14px;
-                  margin-bottom: 16px;
-                }
-  
-                .spanValue {
-                  height: 20px;
-                  font-size: 20px;
-                  font-family: SourceHanSansCN-Bold, SourceHanSansCN;
-                  font-weight: bold;
-                  color: #17181A;
-                  line-height: 20px;
-  
-                  &.status {
-                    color: #FFB54D;
-                  }
-                }
-              }
-  
-              .Divider {
-                height: 24px;
-                margin-left: 5%;
-                margin-right: 5%;
-                margin-top: 10px;
-              }
-            }
+
+        /* 当屏幕宽度小于或等于 600px */
+        @media screen and (max-width: 1250px) {
+          .imgWrap > img {
+            width: 600px;
           }
-  
-          .rowTwo {
-            display: flex;
-            flex: 1;
-            margin-top: 45px;
-            flex-direction: row;
-            justify-content: flex-start;
-            align-items: center;
-  
-            .medicalInfoSpan {
+        }
+
+        /* 当屏幕宽度小于或等于 600px */
+        @media screen and (min-width: 1250px) and (max-width: 1360px) {
+          .imgWrap > img {
+            width: 700px;
+          }
+        }
+
+        /* 当屏幕宽度在 601px 到 900px */
+        @media screen and (min-width: 1360px) and (max-width: 1500px) {
+          .imgWrap > img {
+            width: 800px;
+          }
+        }
+
+        /* 当屏幕宽度大于 900px */
+        @media screen and (min-width: 1500px) and (max-width: 1760px) {
+          .imgWrap > img {
+            width: 900px;
+          }
+        }
+        /* 当屏幕宽度大于 900px */
+        @media screen and (min-width: 1760px) and (max-width: 1920px) {
+          .imgWrap > img {
+            width: 1000px;
+          }
+        }
+        /* 当屏幕宽度大于 900px */
+        @media screen and (min-width: 1960px) and (max-width: 2000px) {
+          .imgWrap > img {
+            width: 1200px;
+          }
+        }
+        /* 当屏幕宽度大于 900px */
+        @media screen and (min-width: 2000px) {
+          .imgWrap > img {
+            width: 1400px;
+          }
+        }
+      }
+    }
+
+    .right {
+      width: 434px;
+      min-height: 686px;
+      height: calc(100vh - 80px);
+
+      .cardOne {
+        position: relative;
+        width: 100%;
+        height: 132px;
+        padding: 16px;
+        background: linear-gradient(180deg, #ebf2fc 0%, #fcfeff 100%);
+        box-shadow: 0px 10px 16px 0px rgba(0, 0, 0, 0.02);
+        border-radius: 4px;
+        border: 1px solid #f7fbff;
+
+        .welcomBg {
+          position: absolute;
+          z-index: 1;
+          top: 0;
+          left: 0;
+          width: 100%;
+          height: 100%;
+        }
+
+        .inner {
+          position: relative;
+          z-index: 9;
+          width: 100%;
+          height: 100%;
+
+          .userId {
+            position: absolute;
+            top: -7px;
+            right: -15.5px;
+            font-size: 14px;
+            color: #5c7599;
+            height: 24px;
+            padding-left: 16px;
+            padding-right: 8px;
+            font-weight: 500;
+            background: linear-gradient(180deg, #e8f1fc 0%, #fcfeff 100%);
+            border-radius: 100px 0px 0px 100px;
+            opacity: 0.8;
+            border: 1px solid #f7fbff;
+          }
+
+          .cardOneTitle {
+            height: 24px;
+            font-size: 24px;
+            font-weight: bold;
+            color: #17181a;
+            margin-bottom: 25px;
+          }
+
+          .content {
+            .row {
               display: flex;
-              width: 20%;
-              height: 45px;
-              flex-direction: column;
-              align-items: flex-start;
-              margin-right: 10%;
-  
-              .span {
-                height: 14px;
+              height: 16px;
+              flex-direction: row;
+              align-items: center;
+              overflow: hidden;
+              text-overflow: ellipsis;
+              white-space: nowrap;
+
+              .label {
+                width: 50%;
                 font-size: 14px;
-                font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-                font-weight: 400;
-                color: #666E80;
-                line-height: 14px;
-                margin-bottom: 16px;
-  
-                span {
-                  color: #17181A;
+                color: #17181a;
+                text-align: left;
+
+                & > img {
+                  position: relative;
+                  top: -1px;
+                  width: 16px;
+                  height: 16px;
+                  margin-right: 4px;
                 }
-  
-                &:last-child {
-                  margin-bottom: 0;
+
+                & > span {
+                  color: #7a8599;
+                  padding-right: 16px;
                 }
               }
 
-              &:first-child {
-                 width: 40%;
-              }
-  
               &:last-child {
-                margin-right: 0;
+                margin-top: 14px;
               }
             }
           }
         }
       }
-  
-      .profileFooter {
-        display: flex;
-        flex-direction: row;
-        justify-content: space-between;
-        padding-top: 25px;
-        margin-top: 32px;
-        border-top: 1px solid #DFE3EB;
-  
-        .flowInstruction {
-          height: 14px;
-          font-size: 14px;
-          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-          font-weight: 400;
-          color: #17181A;
-          line-height: 14px;
-          cursor: pointer;
-  
-          &::before {
-            position: relative;
-            display: inline-block;
-            content: '';
-            top: 2px;
-            width: 16px;
-            height: 16px;
-            margin-right: 8px;
-            // background-image: url('../../../../public/images/alert.png');
-            // background-size: cover;
-          }
-        }
-  
-        .action {
-          display: flex;
-          flex-direction: row;
-  
-          .editProfile {
-            height: 14px;
-            font-size: 14px;
-            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-            font-weight: 400;
-            color: #26334D;
-            line-height: 14px;
-            margin-right: 32px;
-            cursor: pointer;
-  
-            &::before {
-              position: relative;
-              display: inline-block;
-              content: '';
-              top: 3px;
-              width: 16px;
-              height: 16px;
-              margin-right: 8px;
-              // background-image: url('../../../../public/images/box.png');
-              // background-size: cover;
-            }
-          }
-  
-          .qualificationApply {
-            height: 14px;
-            font-size: 14px;
-            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-            font-weight: 400;
-            color: #26334D;
-            line-height: 14px;
-            cursor: pointer;
-  
-            &::before {
-              position: relative;
-              display: inline-block;
-              content: '';
-              top: 3px;
-              width: 16px;
-              height: 16px;
-              margin-right: 8px;
-              // background-image: url('../../../../public/images/blueFile.png');
-              // background-size: cover;
-            }
-          }
-        }
+
+      .cardTwo {
+        margin-top: 16px;
+      }
+
+      .cardThree {
+        // height: calc(100% - 340px);
+        margin-top: 16px;
+        border-radius: 4px;
+        background-color: #fff;
       }
-    }
-    .cardTwo {
-      display: flex;
-      flex-direction: row;
-      padding-top: 16px;
-      margin-bottom: 16px;
-    }
-    .cardThree {
-      display: flex;
-      flex-direction: row;
-      margin-bottom: 16px;
     }
   }
 }

+ 172 - 121
src/pages/index/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-10 09:33:30
- * @LastEditTime: 2022-09-08 09:06:07
+ * @LastEditTime: 2024-03-28 17:26:40
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/index.tsx
@@ -9,16 +9,17 @@
 
 import { useModel, history, Location, Helmet } from 'umi';
 import './index.less';
-import { Skeleton, Divider } from 'antd';
-import { useState,useEffect } from 'react';
+import { Skeleton, Divider, Modal } from 'antd';
+import { useState, useEffect } from 'react';
 import avatar from '../../../public/images/avatar.png';
 import TopBar from '@/components/topBar';
 import { FastEntry, FastEntryTabType } from './components/FastEntry';
 import { RecentlyVisited, RecentlyVisitedItemsType } from './components/RecentlyVisited';
 import { todoItem, TodoList } from './components/TodoList';
-import { getUserIndexData, todoListAct, UserInfo } from '@/service';
+import { getSysParamsByCode, getUserIndexData, todoListAct, UserInfo } from '@/service';
 import { MsgRecord } from './components/MsgRecord';
-
+import { getParamsManaTableData } from '../platform/setting/paramsMana/service';
+import { KcimCenterSysId } from '@/constant';
 
 export interface IndexPageType {
   location: Location;
@@ -28,7 +29,7 @@ const IndexPage: React.FC<IndexPageType> = ({ location }) => {
   const {
     systemLists, //当前医院可选子系统列表
     setInitialState,
-    userData
+    userData,
   } = useModel('@@initialState', (model) => {
     return {
       systemLists: model.initialState?.systemLists,
@@ -37,145 +38,195 @@ const IndexPage: React.FC<IndexPageType> = ({ location }) => {
     };
   });
 
-  const [loading, setLoading] = useState(false);
-  const [userInfo,set_userInfo]  = useState<UserInfo>();
-
-  const [fastEntry,set_fastEntry] = useState<FastEntryTabType[]>([]);
-  const [recentlyVisitedList,set_recentlyVisitedList] = useState<RecentlyVisitedItemsType[]>([]);
-  const [todoList,set_todoList] = useState<todoItem[]>([]);
-  const [msgRecord,set_msgRecord] = useState([]);
-  
-
-
-
-
-  const getIndexPageDataFunc =async () => {
-        const resp = await getUserIndexData();
-        if(resp){
-          
-          set_userInfo(resp.userInfo);
-
-          const fastEntryList = resp.fastEntrance.map((item:any)=>({
-            name:item.name,
-            path:item.path,
-            menuId:item.menuId,
-            systemId:item.systemId
-          }));
-
-          set_fastEntry(fastEntryList);
-
-          set_todoList(resp.todoList.map((t:any)=>({
-            id:t.id,
-            status:1,
-            content:t.content,
-            createDate:t.createDate,
-            taskLevel:t.taskLevel,
-            
-          })));
-
-          set_msgRecord(resp.messageRecords.map((t:any)=>({
-                title:t.recordTitle,
-                date:t.createDate,
-                resolveTime:t.resolveTime,
-                isProcess:t.isProcess,
-                content:t.content
-          })));
-        }
-  }
+  const [userInfo, set_userInfo] = useState<UserInfo>();
+
+  const [fastEntry, set_fastEntry] = useState<FastEntryTabType[]>([]);
+  const [recentlyVisitedList, set_recentlyVisitedList] = useState<RecentlyVisitedItemsType[]>([]);
+  const [todoList, set_todoList] = useState<todoItem[]>([]);
+  const [msgRecord, set_msgRecord] = useState([]);
+
+  const [specialPageUrl, setspecialPageUrl] = useState<string | undefined>(undefined);
+
+  const [leftImgUrl, set_leftImgUrl] = useState<string | undefined>(undefined);
+  const [leftBgImgUrl, set_leftBgImgUrl] = useState<string | undefined>(undefined);
+
+  const [iframeLoading, set_iframeLoading] = useState(false);
+
+  const [allParams, set_allParams] = useState<any[]>([]);
+  const [title, set_title] = useState<string | undefined>(undefined);
+  const [welcomTitle, set_welcomTitle] = useState('欢迎进入医管平台');
+
+  const onLoadhandle = () => {
+    set_iframeLoading(false);
+  };
+
+  const getIndexPageDataFunc = async () => {
+    const resp = await getUserIndexData();
+    if (resp) {
+      set_userInfo(resp.userInfo);
+      set_leftImgUrl(resp.indexUrl ? resp.indexUrl.split('|')[0] : undefined);
+      set_leftBgImgUrl(resp.indexUrl ? resp.indexUrl.split('|')[1] : undefined);
+      localStorage.setItem('userInfo', JSON.stringify(resp.userInfo));
+
+      const fastEntryList = resp.fastEntrance.map((item: any) => ({
+        name: item.name,
+        path: item.path,
+        menuId: item.menuId,
+        systemId: item.systemId,
+        type: item.type,
+        contentType: item.contentType,
+        url: item.url,
+      }));
+
+      set_fastEntry(fastEntryList);
+
+      set_todoList(
+        resp.todoList.map((t: any) => ({
+          id: t.id,
+          status: 1,
+          content: t.content,
+          createDate: t.createDate,
+          taskLevel: t.taskLevel,
+          recordTitle: t.recordTitle,
+        })),
+      );
+
+      set_msgRecord(
+        resp.messageRecords.map((t: any) => ({
+          title: t.recordTitle,
+          date: t.createDate,
+          resolveTime: t.resolveTime,
+          isProcess: t.isProcess,
+          content: t.content,
+        })),
+      );
+    }
+  };
+
+  const todoListClickHandle = async (id: number) => {
+    const resp = await todoListAct([id]);
+    if (resp) {
+      getIndexPageDataFunc();
+    }
+  };
+
+  const setIframeUrl = async (allParams: any[]) => {
+    const needItem = allParams.filter((a: any) => a.code == '1644270043527254016');
+    const userData = localStorage.getItem('userData');
+    let token = '';
 
-  const todoListClickHandle = async (id:number)=>{
-        const resp = await todoListAct([id]);
-        if(resp){
-          getIndexPageDataFunc();
+    if (userData) {
+      const { youshuToken } = JSON.parse(userData);
+      token = youshuToken;
+    }
+
+    if (needItem.length > 0) {
+      setspecialPageUrl(`http://eastern1.kcim-bi.163yun.com/dash/integration/56?rid=${needItem[0].value}&toolbar=[]&hideTitle=true&hideScaleBar=false&&scale=screen&hidePageBar=false&token=${token}`);
+    }
+  };
+
+  const getAllParamsHanle = async () => {
+    const resp = await getSysParamsByCode(KcimCenterSysId);
+    if (resp) {
+      set_allParams(resp);
+    }
+  };
+
+  useEffect(() => {
+    if (allParams) {
+      setIframeUrl(allParams);
+      allParams.forEach((item) => {
+        if (item.code == '1739124039835848704') {
+          set_title(item.value);
+        }
+        if (item.code == '1739123252502073344') {
+          set_welcomTitle(item.value);
         }
-  }
+      });
+    }
+  }, [allParams]);
 
-  
-  useEffect(()=>{
+  useEffect(() => {
     getIndexPageDataFunc();
     const t = localStorage.getItem('visitedTabs');
-    if(t){
+    if (t) {
       const visitedPaths = JSON.parse(t);
       set_recentlyVisitedList(visitedPaths);
     }
-  },[])
 
+    getAllParamsHanle();
+
+    // const url = `${spacialPage[0].url}&token=${youshuToken}`;
+  }, []);
 
   return (
     <div className="indexPage">
       <Helmet>
-        <title>欢迎进入医管平台</title>
+        <title>{welcomTitle}</title>
       </Helmet>
-      <div className='pageContainer'>
-        <div className="profileCard">
-          <Skeleton loading={loading} active avatar>
-            <div className='wraper'>
-              <div className="avatar">
-                <img src={avatar} alt="头像" />
+      <div className="pageContainer">
+        <div className="left">
+          <div style={{ padding: 8 }}>
+            <div className="leftTitle">{title ? title.split('|')[0] : '默认标题'}</div>
+            <div className="leftTitleSub">{title ? title.split('|')[1] : '默认标题'}</div>
+          </div>
+
+          <div className="leftContent">
+            {specialPageUrl && (
+              <div className="iframe" style={{ width: '100%' }}>
+                <Skeleton loading={iframeLoading} paragraph={{ rows: 50 }} active />
+                <iframe onLoad={() => onLoadhandle()} style={{ width: '100%', height: 'calc(100vh - 180px)', border: 'none' }} src={specialPageUrl}></iframe>
+              </div>
+            )}
+            {!specialPageUrl && (
+              <div className="imgWrap" style={{ width: '100%', background: `url(${leftBgImgUrl})` }}>
+                <img src={leftImgUrl} alt="" />
               </div>
-              <div className="description">
-                <div className="rowOne">
-                  <div className="info">
-                    <div className="name">{userInfo?.name}</div>
-                    <div className="baseInfo">
-                      {`${userInfo?.gender} | ${userInfo?.title?userInfo?.title:'-'} | ${userInfo?.major?userInfo?.major:'-'}`}
-                    </div>
+            )}
+          </div>
+        </div>
+        <div className="right">
+          <div className="cardOne">
+            <img className="welcomBg" src={require('../../../public/images/welcom_bg.png')} alt="" />
+            <div className="inner">
+              <span className="userId">{userInfo?.account}</span>
+              <div className="cardOneTitle">{`欢迎回来,${userInfo?.name}`}</div>
+              <div className="content">
+                <div className="row">
+                  <div className="label">
+                    <img src={require('../../../public/images/icon-keshi.png')} alt="" />
+                    <span>科室</span>
+                    {userInfo?.departmentName ? userInfo?.departmentName : '-'}
                   </div>
-                  <div className='staffBaseInfo'>
-                    <div className='staffBaseInfoSpan'>
-                      <span className='spanName'>人员工号</span>
-                      <span className='spanValue'>{userInfo?.account?userInfo?.account:'-'}</span>
-                    </div>
-                    <Divider type="vertical" className='Divider' />
-                    <div className='staffBaseInfoSpan'>
-                      <span className='spanName'>人员类别</span>
-                      <span className='spanValue'>{userInfo?.jobTitle?userInfo?.jobTitle:'-'}</span>
-                    </div>
-                    <Divider type="vertical" className='Divider' />
-                    <div className='staffBaseInfoSpan'>
-                      <span className='spanName'>所属科室</span>
-                      <span className='spanValue'>{userInfo?.departmentName?userInfo?.departmentName:'-'}</span>
-                    </div>
-                    <Divider type="vertical" className='Divider' />
-                    <div className='staffBaseInfoSpan'>
-                      <span className='spanName'>进院日期</span>
-                      <span className='spanValue'>{userInfo?.entryTime?`${new Date(userInfo?.entryTime).getFullYear()}-${(new Date(userInfo?.entryTime).getMonth()+1)>10?(new Date(userInfo?.entryTime).getMonth()+1):'0'+(new Date(userInfo?.entryTime).getMonth()+1)}-${(new Date(userInfo?.entryTime).getDate())>10?(new Date(userInfo?.entryTime).getDate()):'0'+(new Date(userInfo?.entryTime).getDate())}`:'-'}</span>
-                    </div>
+                  <div className="label">
+                    <img src={require('../../../public/images/icon-zhicheng.png')} alt="" />
+                    <span>职称</span>
+                    {userInfo?.title ? userInfo?.title : '-'}
                   </div>
                 </div>
-                <div className="rowTwo">
-
-                  <div className='medicalInfoSpan'>
-                    <div className='span'>资格证号:<span>{userInfo?.qualificationCertificateNo?userInfo?.qualificationCertificateNo:'-'}</span></div>
-                    <div className='span'>执业证号:<span>{userInfo?.practiceCertificateNo?userInfo?.practiceCertificateNo:'-'}</span></div>
-                  </div>
-                  <div className='medicalInfoSpan'>
-                    <div className='span'>医师级别:<span>{userInfo?.doctorLevel?userInfo?.doctorLevel:'-'}</span></div>
-                    <div className='span'>执业状态:<span>{userInfo?.practiceStatus?userInfo?.practiceStatus:'-'}</span></div>
+                <div className="row">
+                  <div className="label">
+                    <img src={require('../../../public/images/icon-leibie.png')} alt="" />
+                    <span>类别</span>
+                    {userInfo?.userCate ? userInfo?.userCate : '-'}
                   </div>
-                  <div className='medicalInfoSpan'>
-                    <div className='span'>执业科目:<span>{userInfo?.practiceCate?userInfo?.practiceCate:'-'}</span></div>
-                    <div className='span'>备注:<span>{userInfo?.remark?userInfo?.remark:'-'}</span></div>
+                  <div className="label">
+                    <img src={require('../../../public/images/icon-gangwei.png')} alt="" />
+                    <span>岗位</span>
+                    {userInfo?.position ? userInfo?.position : '-'}
                   </div>
-                  <div className='medicalInfoSpan'>
-                    <div className='span'>执业类别:<span>{userInfo?.userCate?userInfo?.userCate:'-'}</span></div>
-                  </div>
-
                 </div>
               </div>
-            </div>  
-          </Skeleton>
-        </div>
-        <div className='cardTwo '>
-          <FastEntry data={fastEntry}  />
-          <RecentlyVisited data={recentlyVisitedList} />
-        </div>
-        <div className='cardThree'>
-           <TodoList todoList={todoList} todoListClickHandle={todoListClickHandle} />
-           <MsgRecord list={msgRecord}/>
+            </div>
+          </div>
+          <div className="cardTwo">
+            <FastEntry data={fastEntry} />
+          </div>
+          <div className="cardThree">
+            <TodoList todoList={todoList} todoListClickHandle={todoListClickHandle} />
+          </div>
         </div>
       </div>
-
     </div>
   );
 };

+ 131 - 59
src/pages/login/index.tsx

@@ -1,14 +1,14 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 14:58:08
- * @LastEditTime: 2023-02-13 11:35:50
+ * @LastEditTime: 2024-03-28 17:50:54
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/login/index.tsx
  */
 
 import React, { useRef, useEffect, useState, Children, ReactEventHandler } from 'react';
-import { Select, message, Row, Col } from 'antd';
+import { Select, message, Row, Col, Modal } from 'antd';
 import './style.less';
 
 import { useModel, history, Location, Helmet } from 'umi';
@@ -19,8 +19,10 @@ import logo from '../../../public/images/kclogo_colorful.png';
 
 import KCSelect from '@/components/kc-select';
 
-import { getHospConfigBySign, login } from '@/service/login';
+import { getHospConfigBySign, getLastLoginSys, getLoginTipType, login } from '@/service/login';
 import Divider from '@ant-design/pro-card/lib/components/Divider';
+import { getSysParamsByCode } from '@/service';
+import { KcimCenterSysId } from '@/constant';
 
 const { Option } = Select;
 
@@ -30,40 +32,71 @@ export interface LoginPageType {
 }
 
 const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
-
   const loginPageRef = useRef<HTMLDivElement>(null);
-  const [subHospList, setSubHospList] = useState<{ name: string; value: string | number }[]>([]); //分院列表
+  const [subHospList, setSubHospList] = useState<
+    {
+      loadType: number;
+      id: string;
+      hospAbbreviation: any;
+      name: string;
+      value: string | number;
+    }[]
+  >([]); //分院列表
   const [ifLoading, setIfLoading] = useState(false);
   // const [systemList, setSystemList] = useState<userRelationInfo.OwnAppsItem[]>([]); //可选平台列表
   const [currentHospName, setCurrentHospName] = useState('欢迎进入医务管理系统');
   const { initialState, setInitialState } = useModel('@@initialState');
   const [windowWidth, set_windowWidth] = useState(0);
   const [ifShowLeftBlock, set_ifShowLeftBlock] = useState(true);
+  const [currentSelectedSubHop, set_currentSelectedSubHop] = useState<any | undefined>({
+    id: undefined,
+    loginTips: '',
+    loginPic: '',
+  }); //当前选中的院区
+
+  const [hospSign, set_hospSign] = useState<undefined | string>(undefined); //登陆用的hospSign
 
-  
+  const initLoginPageInfo = async () => {
+    const resp = await getSysParamsByCode(KcimCenterSysId);
+    if (resp) {
+      return [];
+    }
+  };
 
   //获取当前账号分院列表
   const getSubHospFunc = async () => {
-    const hospSign = history.location.query?.hospSign as string;
     if (hospSign) {
       const data = await getHospConfigBySign(hospSign);
-   
-      if(data as any instanceof Array){
+
+      if ((data as any) instanceof Array) {
         setSubHospList(
-          data.map((t) => ({
-            name: t.name,
-            value: t.hospSign,
-          })),
+          data.map((t) => {
+            const temp = {
+              name: t.name,
+              value: t.hospSign,
+              id: t.id,
+              hospAbbreviation: t.hospAbbreviation,
+              loadType: t.loadType,
+              loginPic: t.loginPic ? t.loginPic : '',
+              loginTips: t.loginTips ? t.loginTips : '',
+              systemName: t.systemName,
+            };
+            if (t.hospSign == hospSign) {
+              setCurrentHospName(temp.systemName);
+              set_currentSelectedSubHop(temp);
+              localStorage.setItem('currentSelectedSubHop', JSON.stringify(temp));
+              localStorage.setItem('hospAbbreviation', temp.hospAbbreviation);
+              localStorage.setItem('currentHospName', temp.systemName);
+            }
+            return temp;
+          }),
         );
-        setCurrentHospName(data[0].systemName);
       }
-      
     }
   };
 
   const onFinish = async (values: LoginPageTypes.LoginInfo) => {
     setIfLoading(true);
-    const hospSign = localStorage.getItem('hospSign');
     if (!hospSign) {
       notification.error({
         message: '网址标记缺失,请检查网址!',
@@ -79,11 +112,54 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
     });
 
     setIfLoading(false);
-    
+
     if (resp) {
       localStorage.setItem('userData', JSON.stringify(resp));
+      localStorage.setItem('tokenExpired', 'false');
       setInitialState((s) => ({ ...s, userData: resp }));
-      history.replace('/index');
+      if (currentSelectedSubHop.loadType) {
+        const lastLoginSysData = await getLastLoginSys({ hospId: currentSelectedSubHop.id, userId: resp.userId });
+        if (lastLoginSysData) {
+          history.replace(lastLoginSysData.path);
+          localStorage.setItem('currentSelectedTab', JSON.stringify({ ...lastLoginSysData, menuId: lastLoginSysData.systemId }));
+        }
+      } else {
+        history.replace('/index');
+      }
+
+      // if(values.password == '123456'){
+      //       //如果密码为默认密码时
+      //       const loginTipeType = await getSysParamsByCode('','1688483840064098304');
+      //       if(loginTipeType){
+
+      //            const needItem = loginTipeType.filter((a:any)=>a.code == '1688483840064098304');
+
+      //            if(needItem.length>0){
+      //                 if(needItem[0].value == 2){
+      //                   Modal.confirm({
+      //                     title:'提醒',
+      //                     content:'您的账号存在密码泄露风险,请尽快修改密码!',
+      //                     okText:'去更改',
+      //                     cancelText:'稍后',
+      //                     onOk(...args) {
+      //                       history.replace('/personalCenter');
+      //                     },
+      //                   })
+      //                 }
+      //                 if(needItem[0].value == 3){
+      //                   Modal.warn({
+      //                     title:'提醒',
+      //                     content:'您的账号存在密码泄露风险,请先修改密码!',
+      //                     okText:'去更改',
+      //                     onOk(...args) {
+      //                       history.replace('/personalCenter');
+      //                     },
+      //                   })
+      //                 }
+      //            }
+      //       }
+
+      // }
 
       setIfLoading(false);
     }
@@ -92,88 +168,86 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
   const handleResize = (e: Event) => {
     // console.log('innerWidth',(e.target as Window).innerWidth);
     set_windowWidth((e.target as Window).innerWidth);
-
-  }
-
+  };
 
   useEffect(() => {
     setCurrentHospName(title);
   }, [title]);
 
   useEffect(() => {
-    if (windowWidth <= 1000&&windowWidth != 0) {
+    if (windowWidth <= 1000 && windowWidth != 0) {
       set_ifShowLeftBlock(false);
     } else {
       set_ifShowLeftBlock(true);
     }
   }, [windowWidth]);
 
+  useEffect(() => {
+    if (hospSign) {
+      location.pathname == '/login' && getSubHospFunc();
+    }
+  }, [hospSign]);
 
   useEffect(() => {
     //根据hospSign获取分院信息
-    location.pathname == '/login' && getSubHospFunc();
     setInitialState((s) => ({ ...s, currentSelectedSys: undefined, openedSysLists: [] }));
 
     window.addEventListener('resize', (e) => handleResize(e)); //监听窗口大小改变
 
     const hospSign = history.location.query?.hospSign as string;
     localStorage.setItem('hospSign', hospSign);
+    set_hospSign(hospSign);
 
-    return ()=>{
-      window.removeEventListener('resize',handleResize);
-    }
-
+    return () => {
+      window.removeEventListener('resize', handleResize);
+    };
   }, []);
-  
-  
 
   return (
-    <div className="loginPage" >
+    <div className="loginPage">
       <Helmet>
         <title>{currentHospName}</title>
       </Helmet>
 
       {location.pathname == '/login' ? (
         <Row style={{ height: '100%' }}>
-          {
-            ifShowLeftBlock && (
-              <Col flex="500px">
-                <div className='left'>
-                  <div className='topLogo'>
-                    <img className='logo' src={logo} alt="康程智医" />
-                    <div className='logoDesc'>助力医疗机构高质量发展</div>
-                  </div>
-                  <img className='loginbanner' src={require('../../../public/images/loginBannner.png')} alt="" />
+          {ifShowLeftBlock && (
+            <Col flex="500px">
+              <div className="left">
+                <div className="topLogo">
+                  <img className="logo" src={currentSelectedSubHop?.loginPic} alt="康程智医" />
+                  <div className="logoDesc">{(currentSelectedSubHop?.loginTips.split('|'))[0]}</div>
                 </div>
-              </Col>
-            )
-          }
+                <img className="loginbanner" src={require('../../../public/images/loginBannner.png')} alt="" />
+              </div>
+            </Col>
+          )}
           <Col flex="auto">
             <div className="rightLoginArea">
-              {
-                !ifShowLeftBlock && (
-                  <div className='topLogo'>
-                    <img className='logo' src={logo} alt="康程智医" />
-                    <div className='logoDesc'>助力医疗机构高质量发展</div>
-                  </div>
-                )
-              }
+              {!ifShowLeftBlock && (
+                <div className="topLogo">
+                  <img className="logo" src={currentSelectedSubHop?.loginPic} alt="康程智医" />
+                  <div className="logoDesc">{(currentSelectedSubHop?.loginTips.split('|'))[0]}</div>
+                </div>
+              )}
 
               <div className="subHospSelector">
                 {subHospList.length > 0 && (
                   <KCSelect
                     allowClear={false}
                     style={{ width: 180 }}
-                    defaultValue={subHospList[0].value}
-                    onSelect={(val:any)=>{
-                      localStorage.removeItem('hospSign');
-                      localStorage.setItem('hospSign', val);
+                    defaultValue={hospSign}
+                    onSelect={(val: any, option) => {
+                      set_hospSign(val);
+                      localStorage.setItem('hospAbbreviation', option.item.hospAbbreviation);
+                      localStorage.setItem('currentSelectedSubHop', JSON.stringify(option.item));
+                      set_currentSelectedSubHop(option.item);
                     }}
                     suffixIcon={<img style={{ width: '10px', height: '6px' }} src={require('../../../public/images/arrow.png')} />}
                   >
                     {subHospList.map((item) => {
                       return (
-                        <Option value={item.value} key={item.value}>
+                        <Option value={item.value} item={item} key={item.value}>
                           {item.name}
                         </Option>
                       );
@@ -183,7 +257,6 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
               </div>
               <div className="systemName">{currentHospName}</div>
               <Form onFinish={onFinish}>
-
                 <Form.Item name="account" rules={[{ required: true, message: '请输入用户名!' }]}>
                   <Input className="input" placeholder="请输入用户名" />
                 </Form.Item>
@@ -202,12 +275,11 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
                     <Checkbox className="checkBtn">记住密码</Checkbox>
                   </Form.Item> */}
               </Form>
-              <div className='bottomCopyright'>© 2022 康程智医(成都)技术部出品</div>
-              <div className='versionInfo'>精益管理决策平台 V1.0</div>
+              <div className="bottomCopyright">{(currentSelectedSubHop?.loginTips.split('|'))[1]}</div>
+              <div className="versionInfo">{(currentSelectedSubHop?.loginTips.split('|'))[2]}</div>
             </div>
           </Col>
         </Row>
-
       ) : (
         children
       )}

+ 2 - 1
src/pages/personalCenter/components/security.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-03-03 17:42:10
- * @LastEditTime: 2022-07-21 16:13:32
+ * @LastEditTime: 2023-06-12 16:14:59
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/personalCenter/components/security.tsx
@@ -104,6 +104,7 @@ const SecurityView: React.FC = () => {
         Modal.confirm({
           title: '密码修改成功,前往重新登录?',
           closable: false,
+          okText:'确定',
           onOk: () => {
             if (initialState?.logout) {
               initialState.logout();

+ 10 - 0
src/pages/personalCenter/index.tsx

@@ -1,6 +1,7 @@
 import React, { useState, useRef, useLayoutEffect } from 'react';
 import { GridContent } from '@ant-design/pro-layout';
 import { Menu } from 'antd';
+import { history } from 'umi';
 import BaseView from './components/base';
 import BindingView from './components/binding';
 import NotificationView from './components/notification';
@@ -101,6 +102,15 @@ const PAGE_NAME_UPPER_CAMEL_CASE: React.FC = () => {
           </Menu>
         </div>
         <div className={styles.right}>
+          <div className={styles.gobacktoindex} onClick={()=>{
+                const lastLoginSysData =  localStorage.getItem('currentSelectedTab');
+                if(lastLoginSysData){
+                    const {path} = JSON.parse(lastLoginSysData);
+                    history.replace(path);
+                }else{
+                  history.replace('/index');
+                }
+          }}>返回</div>
           <div className={styles.title}>{menuMap[initConfig.selectKey]}</div>
           {renderChildren()}
         </div>

+ 15 - 0
src/pages/personalCenter/style.less

@@ -21,6 +21,7 @@
     }
   }
   .right {
+    position: relative;
     flex: 1;
     padding: 8px 40px;
     .title {
@@ -30,6 +31,20 @@
       font-size: 20px;
       line-height: 28px;
     }
+    .gobacktoindex {
+        position: absolute;
+        top:16px;
+        right: 16px;
+        height: 24px;
+        padding: 0 8px;
+        cursor: pointer;
+        font-size: 14px;
+        color: #17181A;
+        border-radius: 4px;
+        background: #FAFCFF;
+        border: 1px solid #DAE2F2;
+
+    }
 
     .rightListItem {
       background-color: #eee;

+ 220 - 80
src/pages/platform/_layout.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-06 15:25:39
- * @LastEditTime: 2023-03-23 16:41:41
+ * @LastEditTime: 2024-01-16 16:49:31
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/_layout.tsx
@@ -13,10 +13,17 @@ import ProLayout, { PageContainer } from '@ant-design/pro-layout';
 import { getPlatformMenu, getSpecifyMenuDetail } from '@/service/menu';
 import './index.less';
 import { TreeItemType } from '@/utils';
-import { Iframe, SpacicalPageParamsType } from '@/typings';
+import { SpacicalPageParamsType } from '@/typings';
 import { Key, useEffect, useState } from 'react';
-import IconFont from '@ant-design/icons/lib/components/IconFont';
-import { FileOutlined, FolderOutlined, SmileOutlined } from '@ant-design/icons';
+
+import Icon, { FileOutlined, FolderOutlined, createFromIconfontCN } from '@ant-design/icons';
+import { getAllParams } from '@/service';
+
+import '../../../public/zhongtaiC';
+
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
 
 export default function Layout({ children, location, route, history, match, ...rest }: IRouteComponentProps) {
   const { initialState, setInitialState } = useModel('@@initialState');
@@ -26,8 +33,9 @@ export default function Layout({ children, location, route, history, match, ...r
   const [isShowPageMenu, set_isShowPageMenu] = useState(true);
   const [isEmpty, set_isEmpty] = useState(false);
 
-  //const isShowMenu = localStorage.getItem('isChildShowMenu');
-  // console.log({ children, location, route, history, match});
+  const [collapsed, set_collapsed] = useState(false);
+
+  const [pageUrl, set_pageUrl] = useState<string | undefined>(undefined);
 
   const { pathname } = location;
 
@@ -37,23 +45,41 @@ export default function Layout({ children, location, route, history, match, ...r
       set_isShowPageMenu(false);
     }
     set_emptyPageContent(menuItem.description);
-  }
+  };
 
   useEffect(() => {
-
     const isShowMenu = localStorage.getItem('isChildShowMenu');
-    set_isShowPageMenu(isShowMenu == 'true')
+    set_isShowPageMenu(isShowMenu == 'true');
   });
 
   useEffect(() => {
-
     if (location.query.menuId) {
       setEmptyPageContent(location.query.menuId as string);
     }
-
     set_isEmpty(location.query.isEmpty == 'true');
   }, [location]);
 
+  useEffect(() => {
+    const handleResize = () => {
+      if (window.innerWidth <= 1280) {
+        // 自定义触发宽度为 800px
+        set_collapsed(true);
+      } else {
+        set_collapsed(false);
+      }
+    };
+
+    // 初始化
+    handleResize();
+
+    // 监听窗口大小变化
+    window.addEventListener('resize', handleResize);
+
+    // 清除监听器
+    return () => {
+      window.removeEventListener('resize', handleResize);
+    };
+  }, []);
 
   const adjustIframe = () => {
     // var ifm:any = document.getElementById("bi_iframe");
@@ -61,35 +87,127 @@ export default function Layout({ children, location, route, history, match, ...r
     //   ifm.height=document.documentElement.clientHeight;
     //   ifm.width=document.documentElement.clientWidth;
     // }
+  };
+
+  const addTokenToUrl = (url: string, token = '') => {
+    // 检查 URL 中是否有查询字符串
+    url = url.trim();
+    if (url.includes('?')) {
+      // 检查是否已经有 token 参数
+      if (!url.includes('token=')) {
+        // 添加 &token=,因为 URL 中已经有其他查询参数
+        url += `&token=${token}`;
+      }
+    } else {
+      // URL 中没有查询参数,所以添加 ?token=
+      url += `?token=${token}`;
+    }
+    return url;
+  };
+
+  if (initialState?.currentSelectedSys) {
+    const { type, url, contentType } = initialState.currentSelectedSys;
+    if (type == 1 && contentType == 6) {
+      const userData = localStorage.getItem('userData');
+      const { token } = JSON.parse(userData as string);
+      return <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={addTokenToUrl(url as string, token)} onLoad={() => adjustIframe()}></iframe>;
+    }
   }
 
   //临时演示处理
 
   if (location.pathname == '/platform/costMana') {
-    return <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src="http://112.124.59.133:4000/platformMana/roleManage?hospSign=dOBHdoPmJgPGnMSH" onLoad={() => adjustIframe()} ></iframe>;
+    //临时解决未嵌入成本核算,而实现访问的效果
+    const getToken = async () => {
+      const resp = await getAllParams();
+
+      if (resp) {
+        const needItem = resp.filter((a: any) => a.code == '1647777324889935872');
+
+        if (needItem.length > 0) {
+          set_pageUrl(`http://47.96.149.190:8000/platformMana/roleManage?hospSign=dOBHdoPmJgPGnMSH&token=${needItem[0].value}`);
+        }
+      }
+    };
+
+    getToken();
+
+    return <>{pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()}></iframe>};</>;
+  }
+
+  if (location.pathname == '/platform/costMana2') {
+    //临时解决未嵌入成本核算,而实现访问的效果
+    const getToken = async () => {
+      const resp = await getAllParams();
+      if (resp) {
+        const needItem = resp.filter((a: any) => a.code == '1733034722981974016');
+
+        if (needItem.length > 0) {
+          set_pageUrl(`http://47.96.149.190:8000/platformMana/roleManage?hospSign=QgqzJxUR5reLh5ER&token=${needItem[0].value}`);
+        }
+      }
+    };
+
+    getToken();
+
+    return <>{pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()}></iframe>};</>;
+  }
+
+  if (location.pathname == '/platform/Budget') {
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=budget/index`;
+
+    return <>{pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()}></iframe>};</>;
   }
 
+  if (location.pathname == '/platform/DRG') {
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=drgs/index`;
 
+    return <>{pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()}></iframe>};</>;
+  }
+
+  if (location.pathname == '/platform/DIP') {
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=dips/index`;
+
+    return <>{pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()}></iframe>};</>;
+  }
+
+  if (location.pathname == '/platform/baokangCostApp') {
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=cost/index `;
+
+    return <>{pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()}></iframe>};</>;
+  }
 
   return (
     <ProLayout
       style={{
         height: 'calc(100vh - 50px)',
       }}
-      iconfontUrl="//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js"
+      //iconfontUrl="//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js"
       logoStyle={{
         display: 'none',
       }}
-      location={{
-
-      }}
+      location={{}}
       headerContentRender={false}
       headerRender={false}
-      siderWidth={isShowPageMenu ? 220 : 0}
+      siderWidth={isShowPageMenu ? 200 : 0}
+      breakpoint={false}
       pageTitleRender={false}
       disableContentMargin
+      collapsed={collapsed}
+      onCollapse={(collapsed) => set_collapsed(collapsed)}
+      collapsedButtonRender={() => {
+        return (
+          <div
+            className="collapsedBtn"
+            onClick={() => {
+              set_collapsed(collapsed ? false : true);
+            }}
+          >
+            <IconFont style={{ display: 'inline-block' }} className="menuCollapseIcon" type={collapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'} />
+          </div>
+        );
+      }}
       menuItemRender={(item, dom) => {
-
         return (
           <a
             onClick={() => {
@@ -98,7 +216,7 @@ export default function Layout({ children, location, route, history, match, ...r
           >
             {dom}
           </a>
-        )
+        );
       }}
       menuProps={{
         openKeys: [...openKeys],
@@ -115,11 +233,9 @@ export default function Layout({ children, location, route, history, match, ...r
       menu={{
         autoClose: false,
         params: {
-          initialState
+          initialState,
         },
         request: async () => {
-
-
           if (initialState && initialState.currentSelectedSys) {
             const { systemId, menuId, path } = initialState.currentSelectedSys;
             if (systemId || menuId) {
@@ -134,8 +250,8 @@ export default function Layout({ children, location, route, history, match, ...r
                     if (t.isHomepage) {
                       homePage = t;
                     }
-                    if (t[key] && t[key] == 1) {
-                      //非一般页面
+                    if (t[key] == 1 || t[key] == 2 || t[key] == 3) {
+                      //网易有数页面
                       result.push({
                         contentType: t[key],
                         path: t['path'],
@@ -143,6 +259,15 @@ export default function Layout({ children, location, route, history, match, ...r
                         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);
                     }
@@ -152,7 +277,6 @@ export default function Layout({ children, location, route, history, match, ...r
                 return result;
               };
 
-
               const _menu = getVFromTree(menuData, 'contentType');
               setInitialState((t) => ({ ...t, spacicalPageParamsType: _menu }));
 
@@ -161,96 +285,112 @@ export default function Layout({ children, location, route, history, match, ...r
                 set_openKeys([homePage.key]);
                 set_selectedKeys([homePage.key]);
                 history.push(homePage.path);
-
               } else {
-
                 if (path == '/platform') {
-
                   const selectedKeys = localStorage.getItem('selectedKeys');
                   const openKeys = localStorage.getItem('openKeys');
 
-                  if (selectedKeys&&openKeys) {
+                  if (selectedKeys && openKeys) {
                     const _selectedKeys = JSON.parse(selectedKeys);
                     const _openKeys = JSON.parse(openKeys);
                     set_openKeys(_openKeys);
                     set_selectedKeys(_selectedKeys);
                   } else {
                     if (menuData[0].children && menuData[0].children.length > 0) {
-
                       const childs = menuData[0].children;
                       set_openKeys([menuData[0].key]);
                       set_selectedKeys([childs[0].key]);
-                      localStorage.setItem('openKeys',JSON.stringify([menuData[0].key]));
-                      localStorage.setItem('selectedKeys',JSON.stringify([childs[0].key]));
+                      localStorage.setItem('openKeys', JSON.stringify([menuData[0].key]));
+                      localStorage.setItem('selectedKeys', JSON.stringify([childs[0].key]));
                       history.push(`${childs[0].path}`);
-
+                    } else {
+                      if (menuData[0]) {
+                        set_openKeys([menuData[0].key]);
+                        set_selectedKeys([menuData[0].key]);
+                        localStorage.setItem('openKeys', JSON.stringify([menuData[0].key]));
+                        localStorage.setItem('selectedKeys', JSON.stringify([menuData[0].key]));
+                        history.push(`${menuData[0].path}`);
+                      }
                     }
                   }
                 }
-
               }
 
-              // console.log({homePage})
-              // return [...menuData, {
-              //   name: 'SQL编辑器',
-              //   path: '/platform/sqlEditer'
-              // }];
-
-              const addIcon = (arr: any) => arr.map((item: any) => (item.children ? {
-                ...item,
-                icon: <FolderOutlined />,
-                children: addIcon(item.children)
-              } : {
-                ...item,
-                icon: <FileOutlined />,
-              }))
-
-              const result = addIcon(menuData);
+              const addIcon = (arr: any) =>
+                arr.map((item: any) =>
+                  item.children
+                    ? {
+                        ...item,
+                        icon: <FolderOutlined />,
+                        children: addIcon(item.children),
+                      }
+                    : {
+                        ...item,
+                        icon: <FileOutlined />,
+                      },
+                );
+
+              const imgNode = (props: any) => {
+                return <IconFont type="icon-pingtaiguanli" />;
+              };
 
+              const systemSet = (props: any) => {
+                return <IconFont type="icon-xitongshezhi" />;
+              };
 
-              return [...result];
+              function addIconToPath(node: any) {
+                if (node.name == '超管设置') {
+                  node.icon = <Icon component={imgNode} />;
+                }
+                if (node.name == '系统设置') {
+                  node.icon = <Icon component={systemSet} />;
+                }
+                if (node.children) {
+                  node.children.forEach((child: any) => addIconToPath(child));
+                }
+              }
 
+              const result = addIcon(menuData);
 
+              result.forEach((item: any) => {
+                addIconToPath(item);
+              });
 
+              return [...result];
             }
             return [];
           }
           return [];
         },
       }}
-      onPageChange={(location) => { }}
+      onPageChange={(location) => {}}
       layout="side"
       navTheme="light"
     >
-      {
-        isEmpty && (
-          <div className='emptyContainer' style={{ textAlign: 'center', paddingTop: 100 }}>
-            <h1>{emptyPageContent}</h1>
+      {isEmpty && (
+        <div className="emptyContainer" style={{ textAlign: 'center', paddingTop: 100 }}>
+          <h1>{emptyPageContent}</h1>
+        </div>
+      )}
+      {!isEmpty && (
+        <PageContainer
+          className="kcmpPageContainer"
+          header={{
+            title: false,
+          }}
+          style={{
+            margin: 0,
+          }}
+        >
+          <Helmet>
+            <title>精益管理中台</title>
+          </Helmet>
+
+          <div className="page" style={{ height: 'calc(100vh - 80px)', overflowY: 'scroll' }}>
+            {children}
           </div>
-        )
-      }
-      {
-        !isEmpty && (
-          <PageContainer
-            className="kcmpPageContainer"
-            header={{
-              title: false,
-            }}
-            style={{
-              margin: 0,
-            }}
-          >
-
-            <Helmet>
-              <title>精益管理中台</title>
-            </Helmet>
-
-            <div className="page" style={{ height: 'calc(100vh - 80px)', overflowY: 'scroll' }}>
-              {children}
-            </div>
-          </PageContainer>
-        )
-      }
+        </PageContainer>
+      )}
     </ProLayout>
   );
 }

+ 113 - 141
src/pages/platform/components/TreeEditer/index.tsx

@@ -2,168 +2,140 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-07-06 09:31:32
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-01-05 09:19:27
+ * @LastEditTime: 2023-08-10 15:21:18
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/components/TreeEditer/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
-import React, { Key, useEffect, useState } from 'react'
-import { Tree, Radio,Divider } from 'antd';
+import React, { Key, useEffect, useState } from 'react';
+import { Tree, Radio, Divider } from 'antd';
 import type { DataNode } from 'antd/lib/tree';
 import { getMenuDirectory, MenuItemDataType } from '@/service/menu';
 import { TagsOutlined } from '@ant-design/icons';
 
-
-
 const { TreeNode } = Tree;
 
-
-
-
 const getTreeNode = (data: MenuItemDataType[]) => {
-    if (data && data.length > 0) {
-        return data.map((item) => {
-            if (item.children) {
-                return (
-                    <TreeNode key={item.menuId} title={item.name}>
-                        {getTreeNode(item.children)}
-                    </TreeNode>
-                );
-            }
-            return (
-                <TreeNode
-                    key={item.menuId}
-                    title={item.name}
-                    switcherIcon={<TagsOutlined />} // TreeNode这个Tree的子组件居然存在SwitcherIcon属性.
-                />
-            );
-        });
-    }
-    return [];
+  if (data && data.length > 0) {
+    return data.map((item) => {
+      if (item.children) {
+        return (
+          <TreeNode key={item.menuId} title={item.name}>
+            {getTreeNode(item.children)}
+          </TreeNode>
+        );
+      }
+      return (
+        <TreeNode
+          key={item.menuId}
+          title={item.name}
+          switcherIcon={<TagsOutlined />} // TreeNode这个Tree的子组件居然存在SwitcherIcon属性.
+        />
+      );
+    });
+  }
+  return [];
 };
 
-
-
-export type  TreeEditerValueType = {actType:'COPY'|'MOVE';selectedKeysValue: Key[]}
+export type TreeEditerValueType = { actType: 'COPY' | 'MOVE'; selectedKeysValue: Key[] };
 
 export interface TreeEditerPropsType {
-    onChange?: (data:TreeEditerValueType) => void;
+  onChange?: (data: TreeEditerValueType) => void;
 }
 
-
 function TreeEditer(props: TreeEditerPropsType) {
-
-    const { onChange } = props;
-
-    const [treeData, set_treeData] = useState<MenuItemDataType[]>([]);
-    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
-    const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
-    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-    const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
-    const [actType,set_actType] = useState<'COPY'|'MOVE'>('COPY');
-
-    // const onExpand = (expandedKeysValue: React.Key[]) => {
-    //     console.log('onExpand', expandedKeysValue);
-    //     // if not set autoExpandParent to false, if children expanded, parent can not collapse.
-    //     // or, you can remove all expanded children keys.
-    //     setExpandedKeys(expandedKeysValue);
-    //     setAutoExpandParent(false);
-    // };
-
-    // const onCheck = (checkedKeysValue:any) => {
-    //     console.log('onCheck', checkedKeysValue);
-    //     setCheckedKeys(checkedKeysValue);
-    // };
-
-    const onSelect = (selectedKeysValue: React.Key[], info: any) => {
-      
-        setSelectedKeys(selectedKeysValue);
-        onChange && onChange({actType,selectedKeysValue});
-        
+  const { onChange } = props;
+
+  const [treeData, set_treeData] = useState<MenuItemDataType[]>([]);
+  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+  const [actType, set_actType] = useState<'COPY' | 'MOVE'>('COPY');
+
+  // const onExpand = (expandedKeysValue: React.Key[]) => {
+  //     console.log('onExpand', expandedKeysValue);
+  //     // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+  //     // or, you can remove all expanded children keys.
+  //     setExpandedKeys(expandedKeysValue);
+  //     setAutoExpandParent(false);
+  // };
+
+  // const onCheck = (checkedKeysValue:any) => {
+  //     console.log('onCheck', checkedKeysValue);
+  //     setCheckedKeys(checkedKeysValue);
+  // };
+
+  const onSelect = (selectedKeysValue: React.Key[], info: any) => {
+    setSelectedKeys(selectedKeysValue);
+    onChange && onChange({ actType, selectedKeysValue });
+  };
+
+  const radioOnchange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    if (e.target.value == 'COPY') set_actType('COPY');
+    if (e.target.value == 'MOVE') set_actType('MOVE');
+  };
+
+  const getTreeData = async () => {
+    let expandedKeys: (number | string)[] = [];
+
+    const convertData = (data: Array<any>) => {
+      data.forEach((item) => {
+        item.title = item.name;
+        item.key = item.menuId;
+        if (!item.children || item.children.length == 0) {
+          expandedKeys.push(item.menuId);
+        }
+        if (item.children) {
+          convertData(item.children);
+        }
+      });
     };
 
-    const radioOnchange = (e:React.ChangeEvent<HTMLInputElement>)=>{
-
-        if(e.target.value == 'COPY')set_actType('COPY');
-        if(e.target.value == 'MOVE')set_actType('MOVE');
-        
-    }
-
-    const getTreeData = async () => {
-
-        let expandedKeys: (number | string)[] = [];
-
-        const convertData = (data: Array<any>) => {
-            data.forEach((item) => {
-                item.title = item.name;
-                item.key = item.menuId;
-                if (!item.children || item.children.length == 0) {
-                    expandedKeys.push(item.menuId);
-                }
-                if (item.children) {
-                    convertData(item.children);
-                }
-            });
-        };
-
-
-        const resp = await getMenuDirectory();
-
-        if (resp) {
-            let data = resp.list;
-            convertData(data)
-            setExpandedKeys(Array.from(new Set(expandedKeys)));
-            set_treeData(data);
-        }
+    const resp = await getMenuDirectory();
 
+    if (resp) {
+      let data = resp.list;
+      convertData(data);
+      setExpandedKeys(Array.from(new Set(expandedKeys)));
+      set_treeData(data);
+      console.log({ resp });
     }
-
-    useEffect(() => {
-        getTreeData();
-    }, [])
-
-
-
-    return (
-        <div>
-            <Radio.Group defaultValue={actType} buttonStyle="solid" onChange={(e)=>radioOnchange(e as unknown as React.ChangeEvent<HTMLInputElement>)}>
-                <Radio.Button value="COPY">复制</Radio.Button>
-                <Radio.Button value="MOVE">移动</Radio.Button>
-            </Radio.Group>
-
-            <Divider plain>请选择</Divider>
-
-            {
-                expandedKeys.length > 0 && treeData.length > 0 && (
-                    <Tree
-                        // checkable
-                        showLine
-                        blockNode
-                        autoExpandParent={true}
-                        // onCheck={onCheck}
-                        defaultExpandAll
-                        // onExpand={onExpand}
-                        expandedKeys={expandedKeys}
-                        // autoExpandParent={autoExpandParent}
-                        // // onCheck={onCheck}
-                        // checkedKeys={checkedKeys}
-                        onSelect={onSelect}
-                        // selectedKeys={selectedKeys}
-                        treeData={treeData as any}
-                    >
-                        {/* {getTreeNode(treeData)} */}
-                    </Tree>
-                )
-            }
-        </div>
-    )
+  };
+
+  useEffect(() => {
+    getTreeData();
+  }, []);
+
+  return (
+    <div>
+      <Radio.Group defaultValue={actType} buttonStyle="solid" onChange={(e) => radioOnchange(e as unknown as React.ChangeEvent<HTMLInputElement>)}>
+        <Radio.Button value="COPY">复制</Radio.Button>
+        <Radio.Button value="MOVE">移动</Radio.Button>
+      </Radio.Group>
+
+      <Divider plain>请选择</Divider>
+
+      {expandedKeys.length > 0 && treeData.length > 0 && (
+        <Tree
+          // checkable
+          showLine
+          blockNode
+          autoExpandParent={true}
+          // onCheck={onCheck}
+          defaultExpandAll
+          // onExpand={onExpand}
+          expandedKeys={expandedKeys}
+          // autoExpandParent={autoExpandParent}
+          // // onCheck={onCheck}
+          // checkedKeys={checkedKeys}
+          onSelect={onSelect}
+          // selectedKeys={selectedKeys}
+          treeData={treeData as any}
+        >
+          {/* {getTreeNode(treeData)} */}
+        </Tree>
+      )}
+    </div>
+  );
 }
 
-export default TreeEditer
-
-
-
+export default TreeEditer;

+ 64 - 87
src/pages/platform/components/menuEditer/menu.tsx

@@ -10,7 +10,7 @@
 import React, { Key, useEffect, useState } from 'react';
 import KCTable from '@/components/kcTable';
 import { Popconfirm } from 'antd';
-import { Input,Transfer, Tree  } from 'antd';
+import { Input, Transfer, Tree } from 'antd';
 import { getAllMenus, getAllMenusDataType, getHospAllMenus } from '@/service/menu';
 import { ProColumns } from '@ant-design/pro-table';
 import type { MenuItemDataType } from '@/service/menu';
@@ -29,128 +29,109 @@ export interface MenuEditerType {
   value?: React.Key[] | React.Key[];
   onChange?: (selectedRowKeys: React.Key[], selectedRows?: any[]) => {};
   noAction?: boolean;
-  hospId?:number|string;
+  hospId?: number | string;
 }
 
-const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction = false,hospId }) => {
- 
-
+const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction = false, hospId }) => {
   const getData = async () => {
-  
-    if(hospId){
+    if (hospId) {
       const resp = await getHospAllMenus(hospId);
-      if(resp){
+      if (resp) {
         const data = resp.allMenuVO;
-      
+
         const convertData = (data: Array<any>) => {
           data.forEach((item) => {
-              item.children = item.child;
-              if (item.child) {
-                  convertData(item.child);
-              }
+            item.children = item.child;
+            if (item.child) {
+              convertData(item.child);
+            }
           });
         };
         convertData(data);
         setDataSource(data);
       }
-     
-    }else{
+    } else {
       const resp = await getAllMenus();
       const data = resp.list ? resp.list : [];
       setDataSource(data);
     }
   };
 
-  
-
-
   const [dataSource, setDataSource] = useState<any[]>([]);
 
   const [targetKeys, setTargetKeys] = useState<string[]>([]);
 
-  const [_selectedKeys,set__selectedKeys] = useState<string[]>([]);
+  const [_selectedKeys, set__selectedKeys] = useState<string[]>([]);
 
-  const [sourceSelectedKeys,set_sourceSelectedKeys] = useState<string[]>([]);
+  const [sourceSelectedKeys, set_sourceSelectedKeys] = useState<string[]>([]);
 
   const onTransFerChange = (keys: string[]) => {
     let _keys = Array.from(new Set(keys));
     setTargetKeys(_keys);
-    onChange&&onChange(_keys)
+    onChange && onChange(_keys);
   };
-  
+
   interface TreeTransferProps {
     dataSource: MenuItemDataType[];
     targetKeys: string[];
     onChange: (targetKeys: string[], direction: TransferDirection, moveKeys: string[]) => void;
   }
-  
-
-  const isChecked = (selectedKeys:(string|number)[], eventKeys: (string|number)[]) => {
 
+  const isChecked = (selectedKeys: (string | number)[], eventKeys: (string | number)[]) => {
     // console.log({selectedKeys,eventKeys});
 
-    const isIncludesFunc = (arr1:(string|number)[],arr2:(string|number)[])=>{
-
-          if(arr2.length == 0){
-            return true;
-          }
-          return arr2.every((item)=>arr1.includes(item))
-    }
-
-
-    return isIncludesFunc(selectedKeys,eventKeys)
-  }
-
+    const isIncludesFunc = (arr1: (string | number)[], arr2: (string | number)[]) => {
+      if (arr2.length == 0) {
+        return true;
+      }
+      return arr2.every((item) => arr1.includes(item));
+    };
 
+    return isIncludesFunc(selectedKeys, eventKeys);
+  };
 
   const generateTree = (treeNodes: MenuItemDataType[] = [], checkedKeys: string[] = []): any[] => {
+    return treeNodes.map(({ children, menuId, name, ...props }) => ({
+      key: menuId,
+      title: name,
+      disabled: checkedKeys.includes(menuId as string),
+      children: generateTree(children, checkedKeys),
+      ...props,
+    }));
+  };
 
-      return treeNodes.map(({ children,menuId,name, ...props }) => ({
-        key:menuId,
-        title:name,
-        disabled: checkedKeys.includes(menuId as string),
-        children: generateTree(children, checkedKeys),
-        ...props
-      }));
-  
-
-  }
-
-  const onSelectChangeHandle = (_sourceSelectedKeys:Key[], targetSelectedKeys:Key[])=>{
-        set_sourceSelectedKeys(_sourceSelectedKeys as string[]);
-        // set_selectedKeysVal(sourceSelectedKeys as string[]);
-        // setTargetKeys(targetSelectedKeys as string[]);
-  }
-    
-
+  const onSelectChangeHandle = (_sourceSelectedKeys: Key[], targetSelectedKeys: Key[]) => {
+    set_sourceSelectedKeys(_sourceSelectedKeys as string[]);
+    // set_selectedKeysVal(sourceSelectedKeys as string[]);
+    // setTargetKeys(targetSelectedKeys as string[]);
+  };
 
   const TreeTransfer = ({ dataSource, targetKeys, ...restProps }: TreeTransferProps) => {
-
     const transferDataSource: MenuItemDataType[] = [];
 
     function flatten(list: MenuItemDataType[] = []) {
-      list.forEach(item => {
+      list.forEach((item) => {
         transferDataSource.push(item as MenuItemDataType);
         flatten(item.children);
       });
     }
-    
+
     flatten(dataSource);
-  
+
     return (
       <Transfer
         {...restProps}
-        listStyle={{width:100,height:500}}
+        listStyle={{ width: 100, height: 500 }}
         targetKeys={targetKeys}
-        rowKey={record => record.menuId}
+        rowKey={(record) => record.menuId}
         dataSource={transferDataSource}
         className="tree-transfer"
         // onSelectChange={onSelectChangeHandle}
         // selectedKeys={_selectedKeys}
-        render={item => item.name!}
+        render={(item) => item.name!}
         showSelectAll={true}
       >
-        {({ direction, onItemSelect, selectedKeys,onItemSelectAll }) => {
+        {({ direction, onItemSelect, selectedKeys, onItemSelectAll }) => {
           if (direction === 'left') {
             const checkedKeys = [...selectedKeys, ...targetKeys];
             return (
@@ -162,30 +143,26 @@ const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction =
                 height={460}
                 checkedKeys={checkedKeys}
                 treeData={generateTree(dataSource, targetKeys)}
-                onCheck={(keys,{node,halfCheckedKeys,...rest}) => {
-
+                onCheck={(keys, { node, halfCheckedKeys, ...rest }) => {
                   // console.log({keys,node,rest});
-                 
                   // 差集
-                  let difference = (keys as Key[]).filter(v => !targetKeys.includes(v as string) );
-                  const map = (list:any, cb:any) => {
-                    return list.reduce((res:any, v:any) => {
-                        res.push(cb(v));
-                        if(Array.isArray(v.child)) res = res.concat(map(v.child, cb))
-                        return res;
+                  let difference = (keys as Key[]).filter((v) => !targetKeys.includes(v as string));
+                  const map = (list: any, cb: any) => {
+                    return list.reduce((res: any, v: any) => {
+                      res.push(cb(v));
+                      if (Array.isArray(v.child)) res = res.concat(map(v.child, cb));
+                      return res;
                     }, []);
+                  };
+
+                  if (!node.checked) {
+                    //选中
+                    onItemSelectAll(difference as string[], true);
+                  } else {
+                    //取消勾选
+                    const cancelKeys = map(node.children, (v: any) => v.key);
+                    onItemSelectAll([node.key, ...cancelKeys, ...(halfCheckedKeys as Key[])] as string[], false);
                   }
-                  
-
-                  if(!node.checked){
-                         //选中
-                         onItemSelectAll(difference as string[],true);
-                  }else{
-                         //取消勾选
-                         const cancelKeys = map(node.children,(v:any)=>v.key);
-                         onItemSelectAll([node.key,...cancelKeys,...halfCheckedKeys as Key[]] as string[],false)
-                  }
-                  
                 }}
                 onSelect={(keys, { node: { key } }) => {}}
               />
@@ -195,10 +172,10 @@ const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction =
       </Transfer>
     );
   };
-   
-  useEffect(()=>{
+
+  useEffect(() => {
     setTargetKeys(value as string[]);
-  },[value])
+  }, [value]);
 
   useEffect(() => {
     getData();
@@ -206,7 +183,7 @@ const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction =
 
   return (
     <div className="MenuEditer">
-    <TreeTransfer dataSource={dataSource}  targetKeys={targetKeys} onChange={onTransFerChange} />
+      <TreeTransfer dataSource={dataSource} targetKeys={targetKeys} onChange={onTransFerChange} />
     </div>
   );
 };

+ 24 - 57
src/pages/platform/components/usersEditer/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-19 14:53:37
- * @LastEditTime: 2022-07-07 09:20:34
+ * @LastEditTime: 2024-01-19 14:45:27
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/components/usersEditer/index.tsx
@@ -9,7 +9,7 @@
 
 import React, { useEffect, useState } from 'react';
 import KCTable from '@/components/kcTable';
-import { Input,Transfer } from 'antd';
+import { Input, Transfer } from 'antd';
 import { getUsers } from '@/service/user';
 import type { EditUsersDataType } from '@/service/user';
 import { ProColumns } from '@ant-design/pro-table';
@@ -22,19 +22,10 @@ export interface UserEditerType {
   value?: React.Key[] | React.Key[];
   onChange?: (selectedRowKeys: React.Key[]) => {};
   noAction?: boolean;
-  total?:[]
+  total?: [];
 }
 
-
-const UserEditer: React.FC<UserEditerType> = ({
-  value = [],
-  onChange,
-  noAction = false,
-  total = []
-}) => {
-
-
-  
+const UserEditer: React.FC<UserEditerType> = ({ value = [], onChange, noAction = false, total = [] }) => {
   const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
   const [keyword, setKeyword] = useState('');
 
@@ -42,12 +33,7 @@ const UserEditer: React.FC<UserEditerType> = ({
   const [targetKeys, setTargetKeys] = useState<React.Key[]>([]);
 
   //record: T, selected: boolean, selectedRows: T[], nativeEvent: Event
-  const onSelectHandle = (
-    record: EditUsersDataType,
-    selected: boolean,
-    selectedRows: EditUsersDataType[],
-    nativeEvent: Event,
-  ) => {
+  const onSelectHandle = (record: EditUsersDataType, selected: boolean, selectedRows: EditUsersDataType[], nativeEvent: Event) => {
     // console.log({record,selected,selectedRows,nativeEvent});
     if (selected) {
       //保证每次选择能够保留之前选中的
@@ -58,68 +44,49 @@ const UserEditer: React.FC<UserEditerType> = ({
     }
   };
 
-
-  const onChangeHandle = (
-    selectedRowKeys: React.Key[],
-    selectedRows: any[],
-  ) => {
+  const onChangeHandle = (selectedRowKeys: React.Key[], selectedRows: any[]) => {
     if (selectedRows.length == 0) {
       //取消选择时
       setSelectedKeys([]);
     }
   };
 
-  const onSearchHandle = (
-    e: React.ChangeEvent & { target: { value: string } },
-  ) => {
+  const onSearchHandle = (e: React.ChangeEvent & { target: { value: string } }) => {
     setKeyword(e.target.value);
   };
 
-
-
-  const filterOption = (inputValue: string, option: EditUsersDataType) =>
-  option.name&&option.name.indexOf(inputValue) > -1;
+  const filterOption = (inputValue: string, option: EditUsersDataType) => option.name && option.name.indexOf(inputValue) > -1;
 
   const handleChange = (newTargetKeys: string[]) => {
     setTargetKeys(newTargetKeys);
-    onChange&&onChange(newTargetKeys);
-  };
-
-  const handleSearch = (dir: TransferDirection, value: string) => {
-   
+    onChange && onChange(newTargetKeys);
   };
 
-
-
+  const handleSearch = (dir: TransferDirection, value: string) => {};
 
   useEffect(() => {
     onChange && onChange(selectedKeys);
   }, [selectedKeys]);
 
   useEffect(() => {
-   setTargetKeys(value);
-   setData(total)
-
+    setTargetKeys(value);
+    setData(total);
   }, []);
 
   return (
     <div className="UserEditer">
-
-      
-    <Transfer
-      dataSource={data}
-      showSearch
-      pagination={{pageSize:20}}
-      rowKey={record => `${record.id}`}
-      showSelectAll={true}
-      // filterOption={filterOption}
-      targetKeys={targetKeys as string[]}
-      onChange={handleChange}
-      onSearch={handleSearch}
-      render={item => item.name?item.name:''}
-    />
-
-
+      <Transfer
+        dataSource={data}
+        showSearch
+        pagination={{ pageSize: 20 }}
+        rowKey={(record) => `${record.id}`}
+        showSelectAll={true}
+        // filterOption={filterOption}
+        targetKeys={targetKeys as string[]}
+        onChange={handleChange}
+        onSearch={handleSearch}
+        render={(item) => (item.name ? `${item.name}(${item.account})` : '')}
+      />
 
       {/* <div className="search">
         <span className="label">搜索人员:</span>

+ 98 - 3
src/pages/platform/index.less

@@ -8,8 +8,103 @@
 
 
 
-.kcmp-ant-pro-sider-light .kcmp-ant-menu-light {
+.kcmp-ant-pro-sider-light {
   border-right-color: rgba(54, 61, 77, 0.1);
+
+  .kcmp-ant-menu-light {
+    padding: 8px;
+
+    .kcmp-ant-menu-submenu-inline {
+      .kcmp-ant-menu-submenu-title {
+        // padding-left: 8px !important;
+        margin-top: 0 !important;
+        margin-bottom: 0 !important;
+      }
+
+      &.kcmp-ant-menu-submenu-selected {
+        .kcmp-ant-menu-submenu-arrow {
+          color: #3376FE !important;
+        }
+      }
+    }
+
+    .kcmp-ant-menu-inline {
+
+      .kcmp-ant-menu-item {
+        border-radius: 4px;
+
+        a:hover {
+          color: rgba(0, 0, 0, 0.88);
+        }
+        
+        &.kcmp-ant-menu-item-selected {
+          background-color: #F2F6FF !important;
+          a:hover {
+            color: #3376FE;
+          }
+        }
+
+
+        &::after {
+          display: none !important;
+        }
+
+        &:hover {
+          color: rgba(0, 0, 0, 0.88) !important;
+          background-color:#f0f2f5;
+        }
+      }
+
+    }
+
+
+    
+    &.kcmp-ant-pro-sider-link-menu {
+         .kcmp-ant-menu-item {
+             //height: 24px !important;
+             .collapsedBtn {
+                  display: flex;
+                  justify-content: center;
+                  align-items: center;
+                  cursor: pointer;
+                  position: absolute;
+                  right:8px;
+                  bottom:0px;
+                  z-index: 10;
+                  width: 23px;
+                  height: 23px;
+             }
+         }
+    }
+
+    &.kcmp-ant-menu-inline-collapsed {
+      width: 60px !important;
+      .kcmp-ant-menu-item {
+        //height: 24px !important;
+        .collapsedBtn {
+             display: flex;
+             justify-content: center;
+             align-items: center;
+             cursor: pointer;
+            //  position: absolute;
+            //  right:0px;
+            //  bottom: 0px;
+             z-index: 10;
+             width: 24px;
+             height: 24px;
+        }
+    }
+    }
+
+
+  }
+
+  &.kcmp-ant-layout-sider-collapsed {
+         .kcmp-ant-menu-submenu-selected {
+             background-color:#F2F6FF;
+             border-radius: 8px;
+         }
+  }
 }
 
 .kcmp-ant-page-header {
@@ -20,8 +115,8 @@
   .kcmp-ant-pro-page-container-children-content {
     margin: 0;
     margin-top: 16px;
-    margin-left:16px;
-    margin-right:12px;
+    margin-left: 16px;
+    margin-right: 12px;
     border-radius: 4px;
     overflow: hidden;
   }

+ 1 - 1
src/pages/platform/setting/departmentMana/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-31 17:22:38
+ * @LastEditTime: 2023-06-09 10:57:54
  * @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
  */

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 473 - 467
src/pages/platform/setting/hospManage/index.tsx


+ 77 - 62
src/pages/platform/setting/hospManage/modals/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-03-23 17:50:10
+ * @LastEditTime: 2024-01-19 10:35:31
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/modal.tsx
@@ -33,7 +33,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
   const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
   const [dataSource, setDataSource] = useState<DataSourceType[]>([]);
 
-  const [dirData,set_dirData] = useState<PlatformPubDirDataType[]>([]);
+  const [dirData, set_dirData] = useState<PlatformPubDirDataType[]>([]);
 
   const columns: ProColumns<DataSourceType>[] = [
     {
@@ -95,7 +95,6 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
   };
 
   const onFinishHandle = (data: any & AddUsersDataType) => {
-
     if (tableAct == TableActType.ADD) {
       dispatch &&
         dispatch({
@@ -104,15 +103,20 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
         });
     }
 
-    if (
-      tableAct == TableActType.EDIT ||
-      tableAct == TableActType.EDITMENU ||
-      tableAct == TableActType.BINDACCOUNT
-    ) {
+    if (tableAct == TableActType.EDIT || tableAct == TableActType.BINDACCOUNT) {
+      console.log({ data });
+
       dispatch &&
         dispatch({
           type: 'hospManageModel/postEditData',
-          payload: data,
+          payload:
+            tableAct == TableActType.EDIT
+              ? {
+                  ...data,
+                  parentId: data.isHospital ? data.parentId.value : undefined,
+                  parentName: data.isHospital ? data.parentId.label : '-',
+                }
+              : data,
         });
     }
     return true;
@@ -125,34 +129,29 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     if (tableAct == TableActType.ADD) {
       return '新增院区';
     }
-    if (tableAct == TableActType.EDITMENU) {
-      return '绑定菜单';
-    }
     if (tableAct == TableActType.BINDACCOUNT) {
       return '院区报告设置';
     }
   };
 
-  const setInitialValues = () => {
+  const setInitialValues: any = () => {
     if (tableAct == TableActType.EDIT) {
       return {
         ...currentEdit,
+        parentId: currentEdit?.parentId,
+        parentName: currentEdit?.parentName,
         isDataShare: currentEdit?.dataShare == '是' ? 1 : 0,
       };
     }
     if (tableAct == TableActType.ADD) {
-      return { 
+      return {
         hospSign: randomString(16),
         isDataShare: 0,
-        hospitalLevel:setSelectorData('HOSPITAL_LEVEL').defaultvalue,
-        hospitalType:setSelectorData('HOSPITAL_TYPE').defaultvalue,
-        hospitalNature:setSelectorData('HOSPITAL_NATURE').defaultvalue
+        hospitalLevel: setSelectorData('HOSPITAL_LEVEL').defaultvalue,
+        hospitalType: setSelectorData('HOSPITAL_TYPE').defaultvalue,
+        hospitalNature: setSelectorData('HOSPITAL_NATURE').defaultvalue,
       };
     }
-    if (tableAct == TableActType.EDITMENU) {
-      return { ...currentEdit };
-    }
-
     if (tableAct == TableActType.BINDACCOUNT) {
       if (currentEdit?.reportId) {
         return { ...currentEdit, reportId: parseInt(currentEdit.reportId) };
@@ -161,78 +160,65 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
   };
 
   const getDirecData = async (key?: string) => {
-
     const data = await getPlatformDictionary();
     if (data) {
       set_dirData(data);
     }
-  }
+  };
 
   const setSelectorData = (key: string) => {
-    let result = dirData.filter((t: any) => (t.code == key));
+    let result = dirData.filter((t: any) => t.code == key);
 
     if (result.length > 0) {
-      
       let dataArr = result[0].dataVoList;
 
-      let defaultValue = dataArr.filter(t=>t.defaultValue == 1);
+      let defaultValue = dataArr.filter((t) => t.defaultValue == 1);
 
-      dataArr.sort((prev:any,next:any)=>{
+      dataArr.sort((prev: any, next: any) => {
         return prev.sort - next.sort;
       });
 
       return {
-           defaultvalue:defaultValue[0]?defaultValue[0].value:'',
-           list:dataArr.map(t=>({label:t.code,value:t.value,defaultValue:t.defaultValue}))
-      }
+        defaultvalue: defaultValue[0] ? defaultValue[0].value : '',
+        list: dataArr.map((t) => ({ label: t.name, value: t.code, defaultValue: t.defaultValue })),
+      };
     }
     return {
-      defaultvalue:'',
-      list:[]
+      defaultvalue: '',
+      list: [],
     };
-  }
-
+  };
 
   useEffect(() => {
     //加装key字段
     const fixedDataSource = currentEdit?.youshuUsers
       ? currentEdit.youshuUsers.map((t) => ({
-        ...t,
-        key: Number((Math.random() * 1000000).toFixed(0)),
-      }))
+          ...t,
+          key: Number((Math.random() * 1000000).toFixed(0)),
+        }))
       : [];
     setDataSource(fixedDataSource);
   }, [currentEdit]);
 
-
-
-  useEffect(()=>{
+  useEffect(() => {
     getDirecData();
-  },[])
+  }, []);
 
   return (
     <KCModal
       visible={isShowModal}
       onVisibleChange={onVisibleChangeHandle}
       layout="horizontal"
-      width={tableAct == TableActType.EDITMENU?800:800}
+      width={480}
       initialValues={setInitialValues()}
       title={setModalTitle()}
-      labelCol={{ 
-        span: 7,
+      labelCol={{
+        span: 5,
       }}
       wrapperCol={{ span: 12 }}
-      onFinish={async (data) =>
-        onFinishHandle(tableAct == TableActType.BINDACCOUNT ? { ...data, dataSource } : data)
-      }
+      onFinish={async (data) => onFinishHandle(tableAct == TableActType.BINDACCOUNT ? { ...data, dataSource } : data)}
     >
-      {tableAct == TableActType.EDITMENU && (
-        <Form.Item name="bindMenuIds">
-          <MenuEditer />
-        </Form.Item>
-      )}
-
-      {tableAct != TableActType.EDITMENU && tableAct != TableActType.BINDACCOUNT && (
+      {tableAct != TableActType.BINDACCOUNT && (
         <>
           <ProFormText
             width="md"
@@ -274,11 +260,14 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
                   <KCProSelect
                     label="选择主院"
                     width="md"
-                    name="mainHospId"
+                    name="parentId"
+                    fieldProps={{
+                      labelInValue: true,
+                    }}
                     request={async () => {
-                      const hospList = await getHospList();
+                      const hospList: any[] = await getHospList();
                       if (hospList) {
-                        return hospList.map((t) => ({
+                        return hospList.map((t: any) => ({
                           label: t.name,
                           value: t.id,
                         }));
@@ -301,8 +290,9 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             width="md"
             name="hospitalLevel"
             request={async () => {
-              return setSelectorData('HOSPITAL_LEVEL').list;    
+              return setSelectorData('HOSPITAL_LEVEL').list;
             }}
+            fieldProps={{ showSearch: true }}
             rules={[
               {
                 required: true,
@@ -317,6 +307,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             request={async () => {
               return setSelectorData('HOSPITAL_TYPE').list;
             }}
+            fieldProps={{ showSearch: true }}
             rules={[
               {
                 required: true,
@@ -331,6 +322,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             request={async () => {
               return setSelectorData('HOSPITAL_NATURE').list;
             }}
+            fieldProps={{ showSearch: true }}
             rules={[
               {
                 required: true,
@@ -340,14 +332,23 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
           />
 
           <ProFormText width="md" name="hospSign" label="医院标识" disabled />
-          <ProFormText width="md" name="hospAbbreviation" label="简称" placeholder="请输入"
+          <ProFormText
+            width="md"
+            name="hospAbbreviation"
+            label="简称"
+            placeholder="请输入"
             rules={[
               {
                 required: true,
               },
-            ]} />
-          
-          <ProFormText width="md" name="systemName" label="系统名称" placeholder="请输入"
+            ]}
+          />
+
+          <ProFormText
+            width="md"
+            name="systemName"
+            label="系统名称"
+            placeholder="请输入"
             rules={[
               {
                 required: true,
@@ -369,6 +370,20 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
               },
             ]}
           />
+          <ProFormRadio.Group
+            name="loadType"
+            label="登陆模式"
+            options={[
+              {
+                label: '简易',
+                value: 1,
+              },
+              {
+                label: '普通',
+                value: 0,
+              },
+            ]}
+          />
         </>
       )}
       {tableAct == TableActType.BINDACCOUNT && (

+ 3 - 6
src/pages/platform/setting/hospManage/model.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2022-03-03 09:05:55
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2023-08-18 21:37:40
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/model.ts
  */
@@ -31,7 +31,7 @@ enum TableActType {
   BINDACCOUNT, //绑定有数账号
 }
 
-type CurrentSelectedData = TableListItem & GetHospYoushuAccountsType;
+type CurrentSelectedData = TableListItem & GetHospYoushuAccountsType&{[key:string]:any};
 export interface hospManageModelState {
   name: string;
   tableAct: TableActType;
@@ -73,9 +73,6 @@ const hospManageModel: hospManageModelType = {
 
   effects: {
     *query({ payload }, { call, put }) {},
-
-  
-
     *postAddData({ payload }, { call, put }) {
       yield addHosp({ mainHospId: 0, ...payload });
       yield put({

+ 22 - 7
src/pages/platform/setting/hospManage/style.less

@@ -9,13 +9,34 @@
     .title {
       height: 16px;
       font-size: 16px;
-      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
       font-weight: 500;
       color: #17181A;
       line-height:16px;
     }
 
     .btnGroup {
+
+      .clearBtn {
+        cursor: pointer;
+        display: inline-block;
+        text-align: center;
+        width: 112px;
+        height: 24px;
+        line-height: 23px;
+        background: #FAFCFF;
+        border-radius: 4px;
+        border: 1px solid #DAE2F2;
+        font-size: 14px;
+        font-weight: 400;
+        color: #17181A;
+        margin-right: 8px;
+
+        &.disabled {
+          cursor: not-allowed;
+          color: #65676a;
+          background-color: #f5f5f5;
+        }
+      }
       .cancel {
         cursor: pointer;
         display: inline-block;
@@ -27,7 +48,6 @@
         border-radius: 4px;
         border: 1px solid #DAE2F2;
         font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
         color: #17181A;
         margin-right: 8px;
@@ -44,7 +64,6 @@
         border-radius: 4px;
         border: 1px solid #DAE2F2;
         font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
         color: #fff;
       }
@@ -101,7 +120,6 @@
         border-radius: 4px;
         text-align: center;
         font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
         color: #FFF;
       }
@@ -116,7 +134,6 @@
         background: #F0FCFC;
         font-size: 12px;
         color: #515866;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
         margin-top: 12px;
         margin-bottom: 15px;
@@ -124,7 +141,6 @@
         &>span {
           cursor: pointer;
           font-size: 12px;
-          font-family: SourceHanSansCN-Medium, SourceHanSansCN;
           font-weight: 500;
           color: #00B3B3;
           padding-right: 4px;
@@ -212,7 +228,6 @@
         cursor: pointer;
         display: inline-block;
         font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
         font-weight: 400;
         color: #FFFFFF;
         line-height: 24px;

+ 4 - 2
src/pages/platform/setting/hospManage/typings.d.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 11:10:58
- * @LastEditTime: 2022-01-13 17:38:05
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2023-08-18 21:36:41
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/typings.d.ts
  */
@@ -17,6 +17,8 @@ export type TableListItem = {
   updateTime: string;
   systemName: string;
   dataShare: number;
+  parentId:string;
+  parentName:string;
 };
 
 // export enum TableActType {

+ 494 - 0
src/pages/platform/setting/hospParamsMana/index.tsx

@@ -0,0 +1,494 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-28 11:17:13
+ * @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 { KCInput } from '@/components/KCInput';
+import KCTable from '@/components/kcTable';
+
+import { ModalForm, ProFormDependency, ProFormInstance, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Modal, Popconfirm, Switch, TreeProps } from 'antd';
+import React, { Key, useEffect, useRef, useState } from 'react'
+import { addData, delData, dicOpenStatHandle, editData, getData, getTreeData } from './service';
+
+import './style.less';
+
+import { createFromIconfontCN } from '@ant-design/icons';
+import { DataNode } from 'antd/lib/tree';
+
+import expandedIcon from '../../../../../public/images/treenode_open.png';
+import closeIcon from '../../../../../public/images/treenode_collapse.png';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { getDeepestTreeData } from '@/utils';
+import { getPubDicData } from '@/service/public';
+import { getCurrentHospAllDepartments, getCurrentHospAllEmps } from '@/service/hospList';
+
+
+const SearchIcon = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
+
+
+export default function PubDicTypeMana() {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const [reload, set_reload] = useState(false);
+    const [currentEdit, set_currentEdit] = useState<any>(undefined);
+
+    const [treeData, set_treeData] = useState<any[]>([]);
+    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+    const [searchValue, setSearchValue] = useState('');
+    const [autoExpandParent, setAutoExpandParent] = useState(true);
+    const [defaultSelectedKeys,set_defaultSelectedKeys] = useState<Key[]>([]);
+
+
+
+
+    const columns: ProColumns[] = [
+        {
+            title: '参数等级',
+            dataIndex: 'levelName',
+
+        },
+        {
+            title: '作用对象',
+            dataIndex: 'targetName',
+        },
+        {
+            title: '参数值',
+            dataIndex: 'value',
+        },
+        {
+            title: '启用',
+            dataIndex: 'status',
+            hideInTable:currentSelectedTreeNode?.status != 1,
+            renderText(val, record, index, action) {
+                return <Switch size='small' checked={val? true : false} onChange={(bool) => chnageDicOpenStatHandle(bool, record)} />
+            },
+        },
+        {
+            title: '操作',
+            key: 'option',
+            width: 120,
+            hideInTable:currentSelectedTreeNode?.status != 1,
+            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 chnageDicOpenStatHandle = async (bool: boolean, record: any) => {
+        const resp = await dicOpenStatHandle({ id: record.id, status: bool ? '1' : '0' });
+        if (resp) {
+            set_reload(true);
+        }
+    }
+
+
+    const getTableData = async (params: any) => {
+        const resp = await getData({ ...params, parameterCode: currentSelectedTreeNode.code });
+        set_reload(false);
+        if (resp) {
+            return {
+                data: resp.list,
+                success: true,
+                total: resp.totalCount,
+            }
+        }
+        return []
+    }
+
+    const delTableData = async (record: any) => {
+        const resp = await delData(record.id);
+        if (resp) {
+            set_reload(true);
+            // message.success('操作成功!');
+        }
+    }
+
+
+
+
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
+
+        if (type == 'ADD') {
+            const resp = await addData({
+                code:currentSelectedTreeNode.code,
+                level:formVal.level,
+                systemId:currentSelectedTreeNode.systemId,
+                targetCode:formVal.target.value,
+                targetName:formVal.target.label,
+                value:formVal.value
+            });
+            if (resp) {
+                set_reload(true);
+            }
+        }
+        if (type == 'EDIT') {
+            const { id,status } = currentEdit;
+            const resp = await editData({
+                id:id,
+                value:formVal.value,
+                level:formVal.level,
+                status:status,
+                systemId:currentSelectedTreeNode.systemId,
+                targetCode:formVal.target.value,
+                targetName:formVal.target.label,
+                
+            });
+            if (resp) {
+                set_reload(true);
+            }
+        }
+
+
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+        const formRef = useRef<ProFormInstance>();
+        return (
+            <ModalForm
+                title={`${type == 'EDIT' ? '编辑' : '新增'}参数(${currentSelectedTreeNode&&currentSelectedTreeNode.name})`}
+                width={352}
+                formRef={formRef}
+                initialValues={type == 'EDIT' ? { ...record,level:`${record.level}`,target:{label:record.targetName,value:record.targetCode} } : {}}
+                trigger={
+                    type == 'EDIT' ? <a key="edit" onClick={(e) =>{e.stopPropagation();set_currentEdit(record)} }>编辑</a> : <span className='add'>新增</span>
+                }
+                onFinish={(val) => {
+                    return updateTable(val, type);
+                }}
+            >
+                <ProFormSelect
+                    name="level"
+                    label="参数等级:"
+                    placeholder="请选择院区"
+                    request={async () => {
+                        const resp = await getPubDicData('PARAMS_LEVEL');
+                        if (resp) {
+                            const data: any = resp.dataVoList?.map((a: any) => ({
+                                label: a.name,
+                                value: a.code
+                            }));
+
+                            return data;
+                        }
+                        return []
+
+                    }}
+
+                    fieldProps={{
+                        onChange(value, option) {
+                            formRef.current?.setFieldValue('target',undefined);
+                        },
+                    }}
+                    rules={[{ required: true, message: '参数等级不能为空!' }]}
+                />
+
+                <ProFormDependency name={['level']}>
+                    {
+                        ({ level }) => {
+                           
+                            return (
+                                <ProFormSelect
+                                    name="target"
+                                    label="作用对象:"
+                                    placeholder="请选择"
+                                    params={level}
+                                    rules={[{ required: true, message: '作用对象不能为空!' }]}
+                                    request={ async () => {
+                                        if (level == '1') {
+                                            const currentSelectedHop = localStorage.getItem('currentSelectedSubHop');
+                                            if (currentSelectedHop) {
+                                                const { id, name } = JSON.parse(currentSelectedHop);
+                                                return [{
+                                                    value: id,
+                                                    label: name
+                                                }]
+                                            }
+
+                                        }
+                                        if (level == '2') {
+                                            const resp = await getCurrentHospAllDepartments();
+                                            if (resp) {
+                                                const data: any = resp.map((a: any) => ({
+                                                    label: a.name,
+                                                    value: a.id
+                                                }));
+
+                                                return data;
+                                            }
+                                        }
+                                        if (level == '3') {
+                                            const resp = await getCurrentHospAllEmps();
+                                            if (resp) {
+                                                const data: any = resp.map((a: any) => ({
+                                                    label: a.name,
+                                                    value: a.id
+                                                }));
+
+                                                return data;
+                                            }
+                                        }
+                                        return []
+
+                                    }}
+
+                                    fieldProps={{
+                                          labelInValue:true
+                                    }}
+                                />
+                            )
+                        }
+                    }
+                </ProFormDependency>
+
+                <ProFormTextArea
+                    name="value"
+                    label="参数值:"
+                    placeholder="请输入"
+                    rules={[{ required: true, message: '参数值不能为空!' }]}
+
+                />
+            </ModalForm>
+        )
+    }
+
+
+
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+    }
+
+    const getTreeReqFunc = async (name?: string) => {
+        const resp = await getTreeData();
+        if (resp) {
+            const treeData = resp.map((a: any) => ({
+                ...a,
+                name: a.systemName,
+                id:Math.random(),
+                children: a.parameters
+            }));
+            set_treeData(treeData);
+        }
+    }
+
+
+    const dataList: any[] = [];
+
+    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+        let parentKey: React.Key;
+        for (let i = 0; i < tree.length; i++) {
+            const node = tree[i];
+            if (node.children) {
+                if (node.children.some((item: { id: React.Key; }) => item.id === key)) {
+                    parentKey = node.id;
+                } else if (getParentKey(key, node.children)) {
+                    parentKey = getParentKey(key, node.children);
+                }
+            }
+        }
+        return parentKey!;
+    };
+
+    const generateList = (data: any[]) => {
+        for (let i = 0; i < data.length; i++) {
+            const node = data[i];
+            const { id, name } = node;
+            dataList.push({ id, name: name });
+            if (node.children) {
+                generateList(node.children);
+            }
+        }
+    };
+    generateList(treeData as any);
+
+    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+
+        const { value } = e.target;
+        const newExpandedKeys = dataList
+            .map((item) => {
+                if (item.name.indexOf(value) > -1) {
+                    return getParentKey(item.id, treeData);
+                }
+                return null;
+            });
+
+        const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+        setExpandedKeys(newExpandedKeys as React.Key[]);
+        setSearchValue(value);
+        setAutoExpandParent(true);
+    }
+
+    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+        //console.log('selected', selectedKeys, info);
+        const { node } = info;
+        if (!node.children) {
+            set_currentSelectedTreeNode(node);
+        }
+    };
+
+    const onExpand = (newExpandedKeys: React.Key[]) => {
+        setExpandedKeys(newExpandedKeys);
+        setAutoExpandParent(false);
+    };
+
+    useEffect(() => {
+        if (currentSelectedTreeNode) {
+            set_tableDataFilterParams({ ...tableDataFilterParams, systemId: currentSelectedTreeNode.code });
+        }
+
+    }, [currentSelectedTreeNode]);
+
+    useEffect(() => {
+        //初始化左侧树结构数据后
+        if (treeData?.length > 0) {
+
+            if (treeData[0].children && treeData[0].children.length > 0) {
+                const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
+
+                set_currentSelectedTreeNode(node);
+                setExpandedKeys([nodeParent.id]);
+                set_defaultSelectedKeys(node.id);
+                console.log({node,treeData});
+            }
+        }
+    }, [treeData]);
+
+
+    useEffect(() => {
+        getTreeReqFunc();
+    }, []);
+
+
+    return (
+        <div className='PubDicTypeMana'>
+            <div className='left'>
+                <div className='search'>
+                    <Input
+                        className='searchInput'
+                        placeholder="请输入"
+                        size='small'
+                        allowClear
+
+                        style={{ marginBottom: 16 }}
+                        onChange={onTreeSearchKeyChange}
+                        suffix={
+                            <SearchIcon type='iconsousuo' />
+                        }
+                    />
+                </div>
+                {
+                    treeData && treeData.length > 0 && (
+                        <DirectoryTree
+                            fieldNames={{ title: 'name', key: 'id' }}
+                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+                            onSelect={onSelect}
+                            onExpand={onExpand}
+                            expandedKeys={expandedKeys}
+                            autoExpandParent={autoExpandParent}
+                            selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.id] : []}
+                            blockNode={true}
+                            icon={() => null}
+                            titleRender={
+                                (nodeData: any) => {
+                                    const strTitle = nodeData.name as string;
+                                    const index = strTitle.indexOf(searchValue);
+                                    const beforeStr = strTitle.substring(0, index);
+                                    const afterStr = strTitle.slice(index + searchValue.length);
+
+                                    const title =
+                                        index > -1 ? (
+                                            <span>
+                                                {beforeStr}
+                                                <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
+                                                {afterStr}
+                                            </span>
+                                        ) : (
+                                            <span className='strTitle'>{strTitle}</span>
+                                        );
+                                    return <div style={{
+                                        display: 'flex', flexDirection: 'row',
+                                        width: '100%',
+                                        justifyContent: 'flex-start', alignItems: 'center', height: 32,
+                                        borderRadius: '4px',
+                                        overflow: 'hidden',
+                                        color: '#17181A',
+                                        textOverflow: 'ellipsis',
+                                        whiteSpace: 'nowrap'
+
+                                    }}>{title}</div>
+                                }
+                            }
+                            defaultSelectedKeys={defaultSelectedKeys}
+                            treeData={treeData as unknown as DataNode[]}
+                            // treeData={treeDataNew}
+                            switcherIcon={(props: any) => {
+                                const { expanded } = props;
+                                //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
+                                return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+                            }}
+                        />
+                    )
+                }
+            </div>
+            <div className='right'>
+                <div className='rightTitle'>{currentSelectedTreeNode&&currentSelectedTreeNode.name}</div>
+                <div className='descr'>{`默认值:${currentSelectedTreeNode?currentSelectedTreeNode.value:''}  丨  参数描述:${currentSelectedTreeNode?currentSelectedTreeNode.description:''}`}</div>
+                <div className='toolBar'>
+                    <div className='filter'>
+                        <div className='filterItem'>
+                            <span className='label'>检索:</span>
+                            <KCInput placeholder={'请输入名称'} style={{ width: 160 }} search allowClear
+                                onChange={(e) => {
+                                    set_tableDataSearchKeywords(e.target.value);
+                                    if (e.target.value.length == 0) {
+                                        set_tableDataFilterParams({
+                                            ...tableDataFilterParams,
+                                            targetName: ''
+                                        });
+                                    }
+                                }}
+                                onSearch={() => tableDataSearchHandle('targetName')}
+
+                            />
+                        </div>
+                    </div>
+                    <div className='btnGroup'>
+                        {currentSelectedTreeNode?.status == 1&&<UpDataActBtn record type='ADD' />}
+                    </div>
+                </div>
+                <div style={{ marginTop: 16 }}>
+                    {currentSelectedTreeNode && <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='id' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />}
+                </div>
+            </div>
+        </div>
+    )
+}

+ 107 - 0
src/pages/platform/setting/hospParamsMana/service.ts

@@ -0,0 +1,107 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-09-14 17:41:10
+ * @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 HospParamsItemType = {
+  dictId:string;
+  dictName:string;
+  dictType:string;
+  hospId:string;
+  hospName:string;
+  remark:string;
+  status:string
+}
+
+
+export const getData = (params?:any) => {
+  return request<{list:HospParamsItemType[],totalCount:number}>('/centerSys/parameter/getHospParameterList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+
+
+//新增表格数据
+export type AddTableDataType = {
+  code:string,
+  level:string,
+  targetCode:string,
+  targetName:string,
+  value:string,
+  systemId:string;
+}
+export const addData = (data:AddTableDataType) => {
+  return request('/centerSys/parameter/addHospParameter', {
+    method: 'POST',
+    data
+  });
+}; 
+
+//获取左侧系统数据
+export const  getTreeData = () => {
+  return request('/centerSys/parameter/getSystemParameterList', {
+    method: 'GET',
+  });
+};
+
+
+
+
+//编辑表格数据
+export type EditTableDataType = {
+  id:number,
+  level:string,
+  targetCode:string,
+  targetName:string,
+  value:string,
+  status:string,
+  systemId:string;
+}
+
+export const editData = (data:EditTableDataType) => {
+  return request('/centerSys/parameter/editHospParameter', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+export const delData = (id:string) => {
+  return request('/centerSys/parameter/deleteHospParameter', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+//字典类型开放操作
+export const dicOpenStatHandle = (data:{id:string;status:string}) => {
+  return request('/centerSys/parameter/editStatus', {
+    method: 'POST',
+    params:{...data}
+  });
+};
+
+
+
+
+
+
+
+
+
+
+

+ 138 - 0
src/pages/platform/setting/hospParamsMana/style.less

@@ -0,0 +1,138 @@
+.PubDicTypeMana {
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+  height: 100%;
+  border-radius: 4px;
+
+  .left {
+
+    border-radius: 4px;
+    width: 220px;
+    height: calc(100vh - 80px);
+    overflow: scroll;
+    margin-right: 16px;
+    padding: 16px;
+    background: #FFFFFF;
+
+    .searchInput {
+      border: 1px solid #CFD7E6;
+    }
+
+    .wrap {
+      height: calc(100% - 55px);
+      overflow: scroll;
+    }
+
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode {
+
+      //style={{display:'inline-flex',justifyContent:'center',alignItems:'center',width:16,height:16,background:'#fff',borderRadius:4,border:'1px solid #DAE2F2',marginLeft:4,position:'relative',top:2}}
+      .copy {
+        display: none;
+      }
+
+      &:hover {
+        border-radius: 4px;
+        background: #F0F2F5;
+
+        .copy {
+          display: inline-flex;
+          justify-content: center;
+          align-items: center;
+          width: 16px;
+          height: 16px;
+          background: #FFFFFF;
+          border-radius: 4px;
+          border-radius: 4px;
+          border: 1px solid #DAE2F2;
+          margin-left: 4px;
+          position: relative;
+          top: 2px;
+
+        }
+
+        &::before {
+          border-radius: 4px;
+          background: #F0F2F5;
+        }
+      }
+    }
+
+
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode-selected {
+      &::before {
+        border-radius: 4px;
+        background: #F0F2F5;
+
+      }
+    }
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode .kcmp-ant-tree-node-content-wrapper.kcmp-ant-tree-node-selected {
+      font-weight: bold;
+    }
+  }
+
+  .right {
+
+    width: calc(100% - 236px);
+    padding: 16px;
+    border-radius: 4px;
+    background: #FFFFFF;
+
+    .rightTitle {
+      height: 16px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #17181A;
+      line-height: 16px;
+      margin-bottom: 12px;
+    }
+
+    .descr {
+      font-size: 12px;
+      color: #515866;
+      line-height: 18px;
+      margin-bottom: 16px;
+    }
+
+    .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;
+        }
+      }
+
+    }
+  }
+
+}

+ 219 - 0
src/pages/platform/setting/kcClassification/index.tsx

@@ -0,0 +1,219 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-12-04 19:41:52
+ * @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 { KCInput } from '@/components/KCInput';
+import KCTable from '@/components/kcTable';
+import { getAllHosp } from '@/service/hospList';
+import { getUserRelaSeletData } from '@/service/user';
+import { ModalForm, ProFormCascader, ProFormDigit, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+import { ProColumns } from '@ant-design/pro-table';
+import { Popconfirm } from 'antd';
+import { useEffect, useState } from 'react';
+import { getSysLists } from '../paramsMana/service';
+import { addData, delData, editData, getData } from './service';
+
+import './style.less';
+import { findParents, renameChildListToChildren, searchTreeAndKeepStructure } from '@/utils';
+
+export default function KcClassification() {
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+  const [reload, set_reload] = useState(false);
+  const [currentEdit, set_currentEdit] = useState<any>(undefined);
+  const [tableData, set_tableData] = useState<any[]>([]);
+  const [dataSource, set_dataSource] = useState<any[]>([]);
+
+  const columns = [
+    {
+      title: '分类名称',
+      dataIndex: 'name',
+    },
+    {
+      title: '分类代码',
+      dataIndex: 'code',
+    },
+    {
+      title: '序号',
+      dataIndex: 'sort',
+    },
+    {
+      title: '说明',
+      dataIndex: 'description',
+    },
+    {
+      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>,
+          <UpDataActBtn key={'act2'} record={record} type="ADDCHILD" />,
+        ];
+      },
+    },
+  ];
+
+  const getTableData = async () => {
+    const resp = await getData();
+    set_reload(false);
+    if (resp) {
+      const data = renameChildListToChildren(resp, 'childList');
+      set_tableData(data);
+      set_dataSource(data);
+    }
+    set_reload(false);
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData(record.id);
+    if (resp) {
+      set_reload(true);
+      // message.success('操作成功!');
+    }
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD' | 'ADDCHILD') => {
+    // const parents = findParents(tableData, 'id', formVal.id);
+    // console.log({formVal});
+    const result = {
+      code: formVal.code,
+      name: formVal.name,
+      value: '',
+      sort: formVal.sort,
+      description: formVal.description,
+    };
+    if (type == 'ADD') {
+      const resp = await addData({
+        ...result,
+        parentCode: undefined,
+        codePath: formVal.code,
+        levelName: formVal.name,
+      });
+      if (resp) {
+        set_reload(true);
+      }
+    }
+    if (type == 'ADDCHILD') {
+      const resp = await addData({
+        ...result,
+        parentCode: formVal.parentCode,
+        codePath: `${formVal.codePath},${formVal.code}`,
+        levelName: `${formVal.levelName}/${formVal.name}`,
+      });
+      if (resp) {
+        set_reload(true);
+      }
+    }
+    if (type == 'EDIT') {
+      // const parents = findParents(tableData,'id',formVal.id);
+      // console.log({parents});
+
+      const resp = await editData({
+        ...result,
+        id: formVal.id,
+      });
+      if (resp) {
+        set_reload(true);
+      }
+    }
+  };
+
+  const UpDataActBtn = ({ record, type }: { record: any; type: 'EDIT' | 'ADD' | 'ADDCHILD' }) => {
+    return (
+      <ModalForm
+        title={`${type == 'EDIT' ? '编辑' : type == 'ADDCHILD' ? '添加' : '新增'}康程分类`}
+        width={350}
+        initialValues={
+          type == 'EDIT'
+            ? {
+                ...record,
+              }
+            : {}
+        }
+        trigger={type == 'EDIT' ? <a key="edit">编辑</a> : <a className="add">{type == 'ADDCHILD' ? '添加' : '新增'}</a>}
+        onFinish={(val) => {
+          return updateTable(type == 'EDIT' ? { ...val, id: record.id } : type == 'ADDCHILD' ? { ...record, ...val, parentCode: record.code } : { ...val }, type);
+        }}
+        colProps={{ span: 24 }}
+        grid
+      >
+        <ProFormText name="name" label="分类名称:" placeholder="请输入" rules={[{ required: true, message: '名称不能为空!' }]} />
+        <ProFormText name="code" label="分类代码:" placeholder="请输入" rules={[{ required: true, message: '代码不能为空!' }]} />
+        <ProFormDigit name="sort" label="序号:" placeholder="请输入" rules={[{ required: true, message: '序号不能为空!' }]} />
+        <ProFormTextArea colProps={{ span: 24 }} name="description" label="说明:" placeholder="请输入" />
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  useEffect(() => {
+    if (reload) {
+      getTableData();
+    }
+  }, [reload]);
+
+  useEffect(() => {
+    if (tableDataFilterParams) {
+      const { name } = tableDataFilterParams;
+      const result = searchTreeAndKeepStructure(dataSource, 'name', name);
+      set_tableData([...result]);
+    } else {
+      set_tableData(dataSource);
+    }
+  }, [tableDataFilterParams]);
+
+  useEffect(() => {
+    getTableData();
+  }, []);
+
+  return (
+    <div className="KcClassification">
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem">
+            <span className="label">分类名称:</span>
+            <KCInput
+              placeholder={'请输入'}
+              style={{ width: 160 }}
+              search
+              allowClear
+              onChange={(e) => {
+                set_tableDataSearchKeywords(e.target.value);
+                if (e.target.value.length == 0) {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    name: '',
+                  });
+                }
+              }}
+              onSearch={() => tableDataSearchHandle('name')}
+            />
+          </div>
+        </div>
+        <div className="btnGroup">
+          <UpDataActBtn record type="ADD" />
+        </div>
+      </div>
+      <div style={{ marginTop: 16 }}>
+        <KCTable scroll={{ y: `calc(100vh - 250px)` }} pagination={false} columns={columns as ProColumns[]} rowKey="id" newVer dataSource={tableData} />
+      </div>
+    </div>
+  );
+}

+ 75 - 0
src/pages/platform/setting/kcClassification/service.ts

@@ -0,0 +1,75 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-11-07 20:59: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';
+
+//获取table列表数据
+
+export type TableDataType = {
+  id: number;
+  hospId: string;
+  code: string;
+  name: string;
+  value: string;
+  sort: number;
+  parentCode: string;
+  codePath: string;
+  levelName: string;
+  description: string;
+  childList: TableDataType[];
+};
+
+export const getData = (params?: any) => {
+  return request<TableDataType[]>('/centerSys/kcClass/list', {
+    method: 'GET',
+    params: { ...params },
+  });
+};
+
+//新增表格数据
+export type AddTableDataType = {
+  code: string;
+  name: string;
+  value: string;
+  sort: number;
+  parentCode?: string;
+  codePath: string;
+  levelName: string;
+  description: string;
+};
+export const addData = (data: AddTableDataType) => {
+  return request('/centerSys/kcClass/add', {
+    method: 'POST',
+    data,
+  });
+};
+
+//编辑表格数据
+export type EditableDataType = {
+  id: number;
+  code: string;
+  name: string;
+  value: string;
+  sort: number;
+  description: string;
+};
+export const editData = (data: EditableDataType) => {
+  return request('/centerSys/kcClass/edit', {
+    method: 'POST',
+    data,
+  });
+};
+
+//删除表格操作
+export const delData = (id: string) => {
+  return request('/centerSys/kcClass/delete', {
+    method: 'POST',
+    params: { id },
+  });
+};

+ 42 - 0
src/pages/platform/setting/kcClassification/style.less

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

+ 205 - 226
src/pages/platform/setting/menuManage/modals/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2022-07-21 16:56:55
+ * @LastEditTime: 2023-08-31 10:57:48
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/modal.tsx
@@ -12,7 +12,7 @@ import KCModal from '@/components/KCModal';
 import KCProSelect from '@/components/KCProSelect';
 import { menuManageModelState, Dispatch } from 'umi';
 
-import { Form } from 'antd'
+import { Form } from 'antd';
 
 import { ProFormText, ProFormDependency, ProFormDigit, ProFormRadio, ProFormTextArea } from '@ant-design/pro-form';
 import type { AddUsersDataType } from '@/service/user';
@@ -28,21 +28,14 @@ export enum TableActType { //表格操作类型枚举
   DEL,
   EDIT,
   SET,
-  MOVEANDCOPY
+  MOVEANDCOPY,
 }
 
 interface ActModalProps extends menuManageModelState {
   dispatch: Dispatch | undefined;
 }
 
-const ActModal: React.FC<ActModalProps> = ({
-  dispatch,
-  isShowModal,
-  tableAct,
-  currentEdit,
-  parentId,
-  record,
-}) => {
+const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, currentEdit, parentId, record }) => {
   const onVisibleChangeHandle = (bool: boolean) => {
     // console.log({bool});
     if (!bool) {
@@ -90,8 +83,6 @@ const ActModal: React.FC<ActModalProps> = ({
   };
 
   const menuTypeOptionFiler = () => {
-
-
     if (parentId == '0') {
       //顶级目录
       return MenuTypes.filter((t) => t.label == '中心层');
@@ -104,7 +95,7 @@ const ActModal: React.FC<ActModalProps> = ({
 
     if (record?.type == 5) {
       //体系
-      return MenuTypes.filter((t) => (t.label == '系统' || t.label == '菜单'));
+      return MenuTypes.filter((t) => t.label == '系统' || t.label == '菜单');
     }
 
     if (record?.type == 3) {
@@ -127,7 +118,7 @@ const ActModal: React.FC<ActModalProps> = ({
     if (key == TableActType.EDIT) return '编辑菜单';
     if (key == TableActType.SET) return '设置首页';
     if (key == TableActType.MOVEANDCOPY) return '复制/移动';
-  }
+  };
 
   return (
     <KCModal
@@ -139,8 +130,10 @@ const ActModal: React.FC<ActModalProps> = ({
         tableAct == TableActType.EDIT
           ? { ...currentEdit }
           : {
-            hospSign: randomString(16), isDataShare: 0, isHomepage: 0,
-          }
+              hospSign: randomString(16),
+              isDataShare: 0,
+              isHomepage: 0,
+            }
       }
       // title={tableAct == TableActType.EDIT ? '编辑菜单' : tableAct == TableActType.SET ? '设为首页' : '新增菜单'}
       title={setModalFormTitle(tableAct)}
@@ -150,219 +143,205 @@ const ActModal: React.FC<ActModalProps> = ({
       wrapperCol={{ span: 12 }}
       onFinish={async (data) => onFinishHandle(data)}
     >
-      {
-        tableAct == TableActType.SET && (
-          <>
-            <ProFormText
-              width="md"
-              name="menuName"
-              label="首页名称"
-              placeholder="请输入"
-              rules={[
-                {
-                  required: false,
-                  message: '请输入名称(可选)',
-                },
-              ]}
-            />
-          </>
-        )
-      }
-      {
-        tableAct == TableActType.MOVEANDCOPY && (
-          <Form.Item name='treeEditer'>
-            <TreeEditer />
-          </Form.Item>
-        )
-      }
-      {
-        (tableAct == TableActType.ADD || tableAct == TableActType.EDIT) && (
-          <>
-            <ProFormText
-              width="md"
-              name="name"
-              label="名称"
-              placeholder="请输入"
-              rules={[
-                {
-                  required: true,
-                  message: '请输入名称!',
-                },
-              ]}
-            />
-            <KCProSelect
-              label="类型"
-              width="md"
-              name="type"
-              options={menuTypeOptionFiler()}
-              rules={[
-                {
-                  required: true,
-                  message: '请选择!',
-                },
-              ]}
-            />
-            <ProFormText
-              width="md"
-              name="url"
-              label="URL"
-              placeholder="请输入"
-              rules={[
-                {
-                  required: false,
-                  message: '请输入!',
-                },
-              ]}
-            />
-
-            <ProFormDependency name={['type', 'contentType']}>
+      {tableAct == TableActType.SET && (
+        <>
+          <ProFormText
+            width="md"
+            name="menuName"
+            label="首页名称"
+            placeholder="请输入"
+            rules={[
               {
-                ({ type, contentType }) => {
-                  if (type == 1 && contentType != 4) {
-                    return (
-                      <ProFormText
-                        width="md"
-                        name="path"
-                        label="PATH"
-                        placeholder="请输入"
-                        rules={[
-                          {
-                            required: true,
-                            message: '请输入!',
-                          },
-                        ]}
-                      />
-                    )
-                  } else {
-                    return (
-                      <ProFormText
-                        width="md"
-                        name="path"
-                        label="PATH"
-                        initialValue={tableAct == TableActType.ADD ? '/platform' : ''}
-                        placeholder="请输入"
-                        rules={[
-                          {
-                            required: false,
-                            message: '请输入!',
-                          },
-                        ]}
-                      />
-                    )
-                  }
-                }
-              }
-            </ProFormDependency>
-            <ProFormDigit
-              label="排序号"
-              name="orderNum"
-              min={0}
-              width="md"
-              max={1000}
-              fieldProps={{ precision: 0 }}
-            />
-            <ProFormText width="md" name="icon" label="icon" placeholder="请输入" />
-            <ProFormDependency name={['type']}>
-              {({ type }) => {
-                return (
-                  type == 1 && (
-                    //类型时菜单时
-                    <>
-                      <KCProSelect
-                        label="内容类型"
-                        width="md"
-                        name="contentType"
-                        initialValue={0}
-                        options={[
-                          {
-                            label: '一般',
-                            value: 0, //普通页面,默认值
-                          },
-                          {
-                            label: '报告',
-                            value: 1,
-                          },
-                          {
-                            label: '大屏',
-                            value: 2,
-                          },
-                          {
-                            label: '填报',
-                            value: 3,
-                          },
-                          {
-                            label: '空白',
-                            value: 4,
-                          },
-                        ]}
-                        rules={[
-                          {
-                            required: true,
-                            message: '请选择!',
-                          },
-                        ]}
-                      />
-                      <ProFormRadio.Group
-                        name="isHomepage"
-                        label="是否为首页"
-                        options={[
-                          {
-                            label: '是',
-                            value: 1,
-                          },
-                          {
-                            label: '否',
-                            value: 0,
-                          },
-                        ]}
-                      />
+                required: false,
+                message: '请输入名称(可选)',
+              },
+            ]}
+          />
+        </>
+      )}
+      {tableAct == TableActType.MOVEANDCOPY && (
+        <Form.Item name="treeEditer">
+          <TreeEditer />
+        </Form.Item>
+      )}
+      {(tableAct == TableActType.ADD || tableAct == TableActType.EDIT) && (
+        <>
+          <ProFormText
+            width="md"
+            name="name"
+            label="名称"
+            placeholder="请输入"
+            rules={[
+              {
+                required: true,
+                message: '请输入名称!',
+              },
+            ]}
+          />
+          <KCProSelect
+            label="类型"
+            width="md"
+            name="type"
+            options={menuTypeOptionFiler()}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+          <ProFormText
+            width="md"
+            name="url"
+            label="URL"
+            placeholder="请输入"
+            rules={[
+              {
+                required: false,
+                message: '请输入!',
+              },
+            ]}
+          />
 
-                      <ProFormDependency name={['contentType']}>
-                        {({ contentType }) => {
-                          return (
-                            contentType &&
-                            contentType != 0 && contentType != 4 && (
-                              //页面内容为非一般时,填写对应有数Id
-                              <ProFormDigit
-                                label="报告Id"
-                                name="reportId"
-                                min={1}
-                                fieldProps={{ precision: 0 }}
-                                rules={[
-                                  {
-                                    required: true,
-                                    message: '请填写id!',
-                                  },
-                                ]}
-                              />
-                            )
-                          );
-                        }}
-                      </ProFormDependency>
-                    </>
-                  )
+          <ProFormDependency name={['type', 'contentType']}>
+            {({ type, contentType }) => {
+              if (type == 1 && contentType != 4) {
+                return (
+                  <ProFormText
+                    width="md"
+                    name="path"
+                    label="PATH"
+                    placeholder="请输入"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入!',
+                      },
+                    ]}
+                  />
+                );
+              } else {
+                return (
+                  <ProFormText
+                    width="md"
+                    name="path"
+                    label="PATH"
+                    initialValue={tableAct == TableActType.ADD ? '/platform' : ''}
+                    placeholder="请输入"
+                    rules={[
+                      {
+                        required: false,
+                        message: '请输入!',
+                      },
+                    ]}
+                  />
                 );
-              }}
-            </ProFormDependency>
-            <ProFormDependency name={['contentType']}>
-              {
-                ({ contentType }) => {
-                  if (contentType == 4) {
-                    return (
-                      <ProFormTextArea
-                        name="description"
-                        label="空白页描述"
-                        placeholder="请输入"
-                        fieldProps={{}}
-                      />
-                    )
-                  }
-                }
               }
-            </ProFormDependency>
-          </>
-        )
-      }
+            }}
+          </ProFormDependency>
+          <ProFormDigit label="排序号" name="orderNum" min={0} width="md" max={1000} fieldProps={{ precision: 0 }} />
+          <ProFormText width="md" name="icon" label="icon" placeholder="请输入" />
+          <ProFormDependency name={['type']}>
+            {({ type }) => {
+              return (
+                type == 1 && (
+                  //类型时菜单时
+                  <>
+                    <KCProSelect
+                      label="内容类型"
+                      width="md"
+                      name="contentType"
+                      initialValue={0}
+                      options={[
+                        {
+                          label: '一般',
+                          value: 0, //普通页面,默认值
+                        },
+                        {
+                          label: '报告',
+                          value: 1,
+                        },
+                        {
+                          label: '大屏',
+                          value: 2,
+                        },
+                        {
+                          label: '填报',
+                          value: 3,
+                        },
+                        {
+                          label: '空白',
+                          value: 4,
+                        },
+                        {
+                          label: '静态',
+                          value: 5,
+                        },
+                        {
+                          label: '外部系统嵌入',
+                          value: 6,
+                        },
+                      ]}
+                      rules={[
+                        {
+                          required: true,
+                          message: '请选择!',
+                        },
+                      ]}
+                    />
+                    <ProFormRadio.Group
+                      name="isHomepage"
+                      label="是否为首页"
+                      options={[
+                        {
+                          label: '是',
+                          value: 1,
+                        },
+                        {
+                          label: '否',
+                          value: 0,
+                        },
+                      ]}
+                    />
+
+                    <ProFormDependency name={['contentType']}>
+                      {({ contentType }) => {
+                        return (
+                          contentType &&
+                          contentType != 0 &&
+                          contentType != 4 &&
+                          contentType != 6 && (
+                            //页面内容为非一般时,填写对应有数Id
+                            <ProFormDigit
+                              label="报告Id"
+                              name="reportId"
+                              min={1}
+                              fieldProps={{ precision: 0 }}
+                              rules={[
+                                {
+                                  required: true,
+                                  message: '请填写id!',
+                                },
+                              ]}
+                            />
+                          )
+                        );
+                      }}
+                    </ProFormDependency>
+                  </>
+                )
+              );
+            }}
+          </ProFormDependency>
+          <ProFormDependency name={['contentType']}>
+            {({ contentType }) => {
+              if (contentType == 4) {
+                return <ProFormTextArea name="description" label="空白页描述" placeholder="请输入" fieldProps={{}} />;
+              }
+            }}
+          </ProFormDependency>
+        </>
+      )}
     </KCModal>
   );
 };

+ 5 - 5
src/pages/platform/setting/notificationTemplate/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-23 17:54:17
+ * @LastEditTime: 2023-09-28 11:20:09
  * @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
  */
@@ -143,7 +143,7 @@ export default function PubDicTypeMana() {
 
             return {
                 defaultvalue: defaultValue[0] ? defaultValue[0].value : '',
-                list: dataArr.map((t: any) => ({ label: t.value, value: t.code }))
+                list: dataArr.map((t: any) => ({ label: t.name, value: t.code }))
             }
         }
 
@@ -183,7 +183,7 @@ export default function PubDicTypeMana() {
         return (
             <ModalForm
                 title={`${type == 'EDIT' ? '编辑' : '新增'}消息模板`}
-                width={700}
+                width={730}
                 initialValues={type == 'EDIT' ? { 
                     ...record,
                     systemId:record.systemPath?record.systemPath.split(','):[]
@@ -307,7 +307,7 @@ export default function PubDicTypeMana() {
     },[])
 
     return (
-        <div className='PubDicTypeMana'>
+        <div className='NotificationTemplate'>
             <div className='toolBar'>
                 <div className='filter'>
                     <div className='filterItem'>
@@ -389,7 +389,7 @@ export default function PubDicTypeMana() {
                 </div>
             </div>
             <div style={{ marginTop: 16 }}>
-                <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='id' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />
+                <KCTable  scroll={{y:`calc(100vh - 250px)`}} columns={columns as ProColumns[]} reload={reload} rowKey='id' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />
             </div>
         </div>
     )

+ 1 - 1
src/pages/platform/setting/notificationTemplate/style.less

@@ -1,4 +1,4 @@
-.PubDicTypeMana {
+.NotificationTemplate {
   padding: 16px;
   background: #FFFFFF;
   border-radius: 4px;

+ 253 - 168
src/pages/platform/setting/paramsMana/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-09 17:15:03
+ * @LastEditTime: 2023-09-15 17:49:44
  * @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
  */
@@ -14,13 +14,22 @@ import KCTable from '@/components/kcTable';
 import { getAllHosp } from '@/service/hospList';
 import { ModalForm, ProFormCascader, ProFormDigit, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea, ProFormTreeSelect } from '@ant-design/pro-form'
 import { ProColumns } from '@ant-design/pro-table';
-import { message, Popconfirm } from 'antd';
-import React, { useState } from 'react'
-import { addData, delData, editData, getData, getSysLists } from './service';
+import { Input, message, Popconfirm, Switch, TreeProps } from 'antd';
+import React, { Key, useEffect, useState } from 'react'
+import { addData, delData, editData, getParamsManaTableData, getSysLists } from './service';
 
 import './style.less';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { DataNode } from 'antd/es/tree';
 
+import expandedIcon from '../../../../../public/images/treenode_open.png';
+import closeIcon from '../../../../../public/images/treenode_collapse.png';
+import { getDeepestTreeData } from '@/utils';
 
+const SearchIcon = createFromIconfontCN({
+    scriptUrl: '',
+});
 
 export default function ParamsMana() {
 
@@ -30,9 +39,22 @@ export default function ParamsMana() {
     const [currentEdit, set_currentEdit] = useState<any>(undefined);
 
 
+    const [treeData, set_treeData] = useState<any[]>([]);
+    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+    const [searchValue, setSearchValue] = useState('');
+    const [autoExpandParent, setAutoExpandParent] = useState(true);
 
+    const [defaultSelectedKeys, set_defaultSelectedKeys] = useState<Key[]>([]);  //默认选中的左侧系统
 
-    const columns = [
+
+
+    const columns: ProColumns[] = [
+        {
+            title: '参数代码',
+            dataIndex: 'code',
+
+        },
         {
             title: '参数名称',
             dataIndex: 'name',
@@ -41,28 +63,29 @@ export default function ParamsMana() {
         {
             title: '参数说明',
             dataIndex: 'description',
+            ellipsis: true
         },
         {
             title: '参数值',
             dataIndex: 'value',
+            ellipsis: true
         },
-        {
-            title: '院区',
-            dataIndex: 'hospName',
+        // {
+        //     title: '院区',
+        //     dataIndex: 'hospName',
 
-        },
-        {
-            title: '系统',
-            dataIndex: 'systemName',
+        // },
+        // {
+        //     title: '系统',
+        //     dataIndex: 'systemName',
 
-        },
+        // },
         {
-            title: '启用',
+            title: '开放',
             dataIndex: 'status',
-            render: (_: any, record: any) => {
-                console.log({record});
-                return <span style={{ color: record.status == 1?'#00BF8F':'red' }}>{record.status == 1 ? '启用' : '禁用'}</span>
-            }
+            renderText(val, record, index, action) {
+                return <Switch size='small' checked={val ? true : false} onChange={(bool) => changeOpenStatHandle(bool, record)} />
+            },
         },
         {
             title: '操作',
@@ -84,11 +107,18 @@ export default function ParamsMana() {
             },
         },
 
-    ]
+    ];
+
+    const changeOpenStatHandle = async (bool: boolean, record: any) => {
+        const resp = await editData({ ...record, status: bool ? '1' : '0' })
+        if (resp) {
+            set_reload(true);
+        }
+    }
 
 
     const getTableData = async (params: any) => {
-        const resp = await getData(params);
+        const resp = await getParamsManaTableData(params);
         set_reload(false);
         if (resp) {
             return {
@@ -111,15 +141,15 @@ export default function ParamsMana() {
     }
 
     const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-        const {systemId} = formVal;
+        const { systemId } = formVal;
         if (type == 'ADD') {
-            const resp = await addData({...formVal,systemId:systemId[systemId.length -1],systemPath:systemId.join(',')});
+            const resp = await addData({ ...formVal, systemId:currentSelectedTreeNode.code });
             if (resp) {
                 set_reload(true);
             }
         }
         if (type == 'EDIT') {
-            const resp = await editData({ ...formVal,systemId:systemId[systemId.length -1],systemPath:systemId.join(',')});
+            const resp = await editData({ ...formVal, systemId:currentSelectedTreeNode.code});
             if (resp) {
                 set_reload(true);
             }
@@ -134,12 +164,12 @@ export default function ParamsMana() {
             <ModalForm
                 title={`${type == 'EDIT' ? '编辑' : '新增'}参数`}
                 width={352}
-                initialValues={type == 'EDIT' ? { ...record,systemId:record.systemPath?record.systemPath.split(','):[] } : {}}
+                initialValues={type == 'EDIT' ? { ...record } : {}}
                 trigger={
                     type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
                 }
                 onFinish={(val) => {
-                    return updateTable(type == 'ADD'?val:{...record,...val}, type);  //编辑时将id返回去
+                    return updateTable(type == 'ADD' ? val : { ...record, ...val }, type);  //编辑时将id返回去
                 }}
             >
                 <ProFormText
@@ -160,71 +190,6 @@ export default function ParamsMana() {
                     placeholder="请输入"
                     rules={[{ required: true, message: '参数值不能为空!' }]}
                 />
-                {/* <ProFormDigit label="参数值" name="value" rules={[{ required: true, message: '参数值不能为空!' }]} /> */}
-                <ProFormSelect
-                    name="hospId"
-                    label="院区:"
-                    placeholder="请选择院区"
-                    rules={[{ required: true, message: '院区不能为空!' }]} 
-                    request={async () => {
-                        const resp = await getAllHosp({ pageSize: 200, current: 1 });
-                        if (resp) {
-                            const data: any = resp.list?.map((a) => ({
-                                label: a.hospName,
-                                value: a.id
-                            }));
-
-                            return [
-                                {
-                                    label:'所有院区',
-                                    value:'0'
-                                },...data
-                            ];
-                        }
-                        return []
-
-                    }}
-
-                />
-                <ProFormCascader
-                    name='systemId'
-                    label="系统:"
-                    rules={[{ required: true, message: '系统不能为空!' }]} 
-                    placeholder="请选择"
-                    request={async () => {
-                        const resp = await getSysLists();
-                        if (resp) {
-                            return resp
-                        }
-                        return []
-
-                    }}
-                    fieldProps={{
-                        fieldNames: {
-                            label: 'name',
-                            value: 'code'
-                        },
-                    }}
-                />
-                <ProFormRadio.Group
-                    name="status"
-                    label="启用:"
-                    fieldProps={{
-                        buttonStyle: 'solid'
-                    }}
-                    options={[
-                        {
-                            label: '是',
-                            value: 1,
-                        },
-                        {
-                            label: '否',
-                            value: 0,
-                        },
-                    ]}
-                    rules={[{ required: true, message: '启用不能为空!' }]}
-                />
-
             </ModalForm>
         )
     }
@@ -239,91 +204,211 @@ export default function ParamsMana() {
         })
     }
 
+
+    const getTreeReqFunc = async () => {
+        const resp = await getSysLists();
+        if (resp) {
+            set_treeData(resp);
+        }
+    }
+
+
+    const dataList: any[] = [];
+
+    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+        let parentKey: React.Key;
+        for (let i = 0; i < tree.length; i++) {
+            const node = tree[i];
+            if (node.children) {
+                if (node.children.some((item: { code: React.Key; }) => item.code === key)) {
+                    parentKey = node.code;
+                } else if (getParentKey(key, node.children)) {
+                    parentKey = getParentKey(key, node.children);
+                }
+            }
+        }
+        return parentKey!;
+    };
+
+    const generateList = (data: any[]) => {
+        for (let i = 0; i < data.length; i++) {
+            const node = data[i];
+            const { code, name } = node;
+            dataList.push({ code, name: name });
+            if (node.children) {
+                generateList(node.children);
+            }
+        }
+    };
+    generateList(treeData as any);
+
+    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+
+        const { value } = e.target;
+        const newExpandedKeys = dataList
+            .map((item) => {
+                if (item.name.indexOf(value) > -1) {
+                    return getParentKey(item.code, treeData);
+                }
+                return null;
+            });
+
+        const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+        setExpandedKeys(newExpandedKeys as React.Key[]);
+        setSearchValue(value);
+        setAutoExpandParent(true);
+    }
+
+    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+        //console.log('selected', selectedKeys, info);
+        const { node } = info;
+        if (!node.children) {
+            set_currentSelectedTreeNode(node);
+        }
+    };
+
+    const onExpand = (newExpandedKeys: React.Key[]) => {
+        setExpandedKeys(newExpandedKeys);
+        setAutoExpandParent(false);
+    };
+
+    useEffect(() => {
+        if (currentSelectedTreeNode) {
+            set_tableDataFilterParams({ ...tableDataFilterParams, systemId: currentSelectedTreeNode.code })
+        }
+
+    }, [currentSelectedTreeNode]);
+
+    useEffect(() => {
+        //初始化左侧树结构数据后
+
+        if (treeData?.length > 0) {
+
+            if (treeData[0].children && treeData[0].children.length > 0) {
+                const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
+
+                set_currentSelectedTreeNode(node);
+                setExpandedKeys([nodeParent.code]);
+                set_defaultSelectedKeys([node.code])
+            } else if (treeData[0]) {
+                set_currentSelectedTreeNode(treeData[0]);
+                set_defaultSelectedKeys([treeData[0].code])
+            }
+        }
+    }, [treeData]);
+
+    useEffect(() => {
+        getTreeReqFunc();
+    }, [])
+
+
     return (
-        <div className='PubDicTypeMana'>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label'>适用院区:</span>
-                        <ProFormSelect
-                            noStyle
-                            allowClear
-                            placeholder="请选择"
-                            style={{ width: 160, marginRight: 16 }}
-                            request={async () => {
-                                const resp = await getAllHosp({ pageSize: 200, current: 1 });
-                                if (resp) {
-                                    const data: any = resp.list?.map((a) => ({
-                                        label: a.hospName,
-                                        value: a.id
-                                    }));
-
-                                    return [
-                                        {
-                                            label: '所有院区', value: '0'
-                                        }, ...data
-                                    ];
-                                }
-                                return []
-
-                            }}
-                            fieldProps={{
-                                onChange(value, option) {
-                                    set_tableDataFilterParams({ ...tableDataFilterParams, hospId: value })
-                                },
-                            }}
-                        />
-                    </div>
-                    <div className='filterItem' style={{ marginRight: 16 }}>
-                        <span className='label'>系统名称:</span>
-                        <ProFormCascader
-                            noStyle
-                            allowClear
-                            width={160}
-                            placeholder="请选择"
-                            request={async () => {
-                                const resp = await getSysLists();
-                                if (resp) {
-                                    return resp
+        <div className='paramsMana'>
+            <div className='left'>
+                <div className='search'>
+                    <Input
+                        className='searchInput'
+                        placeholder="请输入"
+                        size='small'
+                        allowClear
+                        onChange={onTreeSearchKeyChange}
+                        suffix={
+                            <SearchIcon type='iconsousuo' />
+                        }
+                    />
+                </div>
+                <div className='wrap'>
+                    {
+                        treeData && treeData.length > 0 && (
+                            <DirectoryTree
+                                fieldNames={{ title: 'name', key: 'code' }}
+                                rootStyle={{ height: '100%',overflowX: 'hidden',padding:16}}
+                                onSelect={onSelect}
+                                onExpand={onExpand}
+                                expandedKeys={expandedKeys}
+                                autoExpandParent={autoExpandParent}
+                                selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.code] : []}
+                                blockNode={true}
+                                icon={() => null}
+                                titleRender={
+                                    (nodeData: any) => {
+                                        const strTitle = nodeData.name as string;
+                                        const index = strTitle.indexOf(searchValue);
+                                        const beforeStr = strTitle.substring(0, index);
+                                        const afterStr = strTitle.slice(index + searchValue.length);
+
+                                        const copyFunc = async () => {
+                                            try {
+                                                await navigator.clipboard.writeText(nodeData.systemId);
+                                                message.success('复制成功!');
+                                            } catch (err) {
+                                                console.error('Failed to copy text: ', err);
+                                            }
+                                        }
+                                        const title =
+                                            index > -1 ? (
+                                                <span>
+                                                    {beforeStr}
+                                                    <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
+                                                    {afterStr}
+                                                </span>
+                                            ) : (
+                                                <span className='strTitle'>{strTitle}</span>
+                                            );
+                                        return <div style={{
+                                            display: 'flex', flexDirection: 'row',
+                                            width: '100%',
+                                            justifyContent: 'flex-start', alignItems: 'center', height: 32,
+                                            borderRadius: '4px',
+                                            overflow: 'hidden',
+                                            color: '#17181A',
+                                            textOverflow: 'ellipsis',
+                                            whiteSpace: 'nowrap'
+
+                                        }}>{title}</div>
+                                    }
                                 }
-                                return []
-
-                            }}
-                            fieldProps={{
-                                fieldNames: {
-                                    label: 'name',
-                                    value: 'code'
-                                },
-                                onChange(value: any, option: any) {
-                                    set_tableDataFilterParams({ ...tableDataFilterParams, systemId: value ? value[value.length - 1] : '' })
-                                },
-                            }}
-                        />
+                                defaultSelectedKeys={defaultSelectedKeys}
+                                treeData={treeData as unknown as DataNode[]}
+                                switcherIcon={(props: any) => {
+                                    const { expanded } = props;
+                                    //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
+                                    return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+                                }}
+                            />
+                        )
+                    }
+                </div>
+            </div>
+            <div className='right'>
+                <div className='toolBar'>
+                    <div className='filter'>
+                        <div className='filterItem'>
+                            <span className='label'>检索:</span>
+                            <KCInput placeholder={'请输入参数名称'} style={{ width: 160 }} search allowClear
+                                onChange={(e) => {
+                                    set_tableDataSearchKeywords(e.target.value);
+                                    if (e.target.value.length == 0) {
+                                        set_tableDataFilterParams({
+                                            ...tableDataFilterParams,
+                                            parameterName: ''
+                                        });
+                                    }
+                                }}
+                                onSearch={() => tableDataSearchHandle('parameterName')}
+
+                            />
+                        </div>
                     </div>
-                    <div className='filterItem'>
-                        <span className='label'>检索:</span>
-                        <KCInput placeholder={'请输入参数名称'} style={{ width: 160 }} search allowClear
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        parameterName: ''
-                                    });
-                                }
-                            }}
-                            onSearch={() => tableDataSearchHandle('parameterName')}
-
-                        />
+                    <div className='btnGroup'>
+                        <UpDataActBtn record type='ADD' />
                     </div>
                 </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
+                <div style={{ marginTop: 16 }}>
+                    {currentSelectedTreeNode && <KCTable columns={columns} scroll={{ y: `calc(100vh - 250px)` }} reload={reload} rowKey='id' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />}
                 </div>
             </div>
-            <div style={{ marginTop: 16 }}>
-                <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='id' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
+
         </div>
     )
 }

+ 13 - 5
src/pages/platform/setting/paramsMana/service.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 16:31:27
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-08 16:58:00
+ * @LastEditTime: 2023-09-14 18:15:35
  * @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
  */
@@ -28,10 +28,12 @@ export type PubDicTypeData = {
 }
 
 
-export const getData = (params:{
+export const getParamsManaTableData = (params:{
   systemId?:number;
   hospId?:number;
   parameterName?:string;
+  current?:number,
+  pageSize?:number
 
 }) => {
   return request<{
@@ -49,9 +51,14 @@ export const getData = (params:{
 
 //获取所有系统列表
 export const getSysLists = () => {
-  return request('/centerSys/menu/getSystemList', {
-    method: 'GET',
-  });
+  const currentHosp = localStorage.getItem('currentSelectedSubHop');
+  if(currentHosp){
+    const { id } = JSON.parse(currentHosp);
+    return request('/centerSys/hospital/getSystemList', {
+      method: 'GET',
+      params:{hospId:id}
+    });
+  }
 };
 
 
@@ -111,3 +118,4 @@ export const delData = (id:number) => {
 
 
 
+

+ 123 - 0
src/pages/platform/setting/paramsMana/style.less

@@ -0,0 +1,123 @@
+.paramsMana {
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+  height: 100%;
+  border-radius: 4px;
+
+  .left {
+
+    border-radius: 4px;
+    width: 220px;
+    height: calc(100vh - 80px);
+    margin-right: 16px;
+    background: #FFFFFF;
+    
+    .search {
+       padding: 16px;
+       padding-bottom: 0;
+       .searchInput {
+        border: 1px solid #CFD7E6;
+      }
+    }
+
+    .wrap {
+      height: calc(100% - 55px);
+      overflow: scroll;
+    }
+
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode {
+
+      //style={{display:'inline-flex',justifyContent:'center',alignItems:'center',width:16,height:16,background:'#fff',borderRadius:4,border:'1px solid #DAE2F2',marginLeft:4,position:'relative',top:2}}
+      .copy {
+        display: none;
+      }
+
+      &:hover {
+        border-radius: 4px;
+        background: #F0F2F5;
+
+        .copy {
+          display: inline-flex;
+          justify-content: center;
+          align-items: center;
+          width: 16px;
+          height: 16px;
+          background: #FFFFFF;
+          border-radius: 4px;
+          border-radius: 4px;
+          border: 1px solid #DAE2F2;
+          margin-left: 4px;
+          position: relative;
+          top: 2px;
+
+        }
+
+        &::before {
+          border-radius: 4px;
+          background: #F0F2F5;
+        }
+      }
+    }
+
+
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode-selected {
+      &::before {
+        border-radius: 4px;
+        background: #F0F2F5;
+
+      }
+    }
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode .kcmp-ant-tree-node-content-wrapper.kcmp-ant-tree-node-selected {
+      font-weight: bold;
+    }
+  }
+
+  .right {
+    width: calc(100% - 236px);
+    padding: 16px;
+    border-radius: 4px;
+    background: #FFFFFF;
+  }
+
+  .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;
+      }
+    }
+
+  }
+
+}

+ 429 - 302
src/pages/platform/setting/pubDicMana/index.tsx

@@ -2,339 +2,466 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-10 17:36:08
+ * @LastEditTime: 2024-03-01 16:15: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 { KCInput } from '@/components/KCInput';
 import KCTable from '@/components/kcTable';
 import { getAllHosp } from '@/service/hospList';
 import { ModalForm, ProFormDigit, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
-import { message, Popconfirm } from 'antd';
+import { Input, message, Modal, Popconfirm, TreeProps } from 'antd';
 import { useEffect, useState } from 'react';
 import { getData, PubDicTypeData } from '../pubDicTypeMana/service';
-import { addPubDicRelaTbaleData, delData, editPubDicRelaTbaleData, getPubDicRelaTbaleData } from './service';
-
+import { addPubDicRelaTbaleData, delData, editPubDicRelaTbaleData, getLeftData, getPubDicRelaTbaleData, initReq } from './service';
 
+import { useLocation } from 'umi';
 import './style.less';
-
-
+import { getDeepestTreeData } from '@/utils';
+
+import expandedIcon from '../../../../../public/images/treenode_open.png';
+import closeIcon from '../../../../../public/images/treenode_collapse.png';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { DataNode } from 'antd/lib/tree';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+
+const SearchIcon = createFromIconfontCN({
+  scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
+
+let systemId = '';
+const currentSelectedTab = localStorage.getItem('currentSelectedTab');
+if (currentSelectedTab) {
+  const { systemId: id } = JSON.parse(currentSelectedTab as string);
+  systemId = id;
+}
 
 const PubDicMana = () => {
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+  const [reload, set_reload] = useState(false);
+
+  const [treeData, set_treeData] = useState<any[]>([]);
+  const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+  const [searchValue, setSearchValue] = useState('');
+  const [autoExpandParent, setAutoExpandParent] = useState(true);
+  const [pageType, set_pageType] = useState<undefined | number>(undefined); // 1 公用字典 2 院区公用字典
+  const location = useLocation();
+
+  const defaultColumns = [
+    {
+      title: '项目名称',
+      dataIndex: 'name',
+    },
+    {
+      title: '项目代码',
+      dataIndex: 'code',
+    },
+    {
+      title: '项目值',
+      dataIndex: 'value',
+    },
+    {
+      title: '默认',
+      dataIndex: 'data.0.dictDefault',
+      render: (_: any, record: any) => {
+        return record.dictDefault == 1 ? '是' : '否';
+      },
+    },
+    {
+      title: '序号',
+      dataIndex: pageType == 1 ? 'dictSort' : 'sort',
+    },
+    {
+      title: '扩展1',
+      dataIndex: 'expandOne',
+    },
+    {
+      title: '扩展2',
+      dataIndex: 'expandTwo',
+    },
+  ];
+
+  const options = [
+    {
+      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 [columns, set_columns] = useState<any[]>([]);
+
+  const getTableData = async (params: any) => {
+    const { dictType, systemId } = currentSelectedTreeNode;
+
+    if (dictType && pageType) {
+      const resp = await getPubDicRelaTbaleData({ ...params, dictType: params.dictType ? params.dictType : currentSelectedTreeNode.dictType, systemId }, pageType);
+      set_reload(false);
+      if (resp) {
+        return {
+          data: resp.list,
+          success: true,
+          total: resp.totalCount,
+        };
+      }
+    }
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    if (pageType) {
+      const resp = await delData(pageType == 1 ? record.dictDataId : record.id, pageType);
+      if (resp) {
+        set_reload(true);
+      }
+    }
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    const currentSelectedHop = localStorage.getItem('currentSelectedSubHop');
+    const { systemId: parentId } = currentSelectedTreeNode;
+    let hospId = '0';
+    // if (currentSelectedHop) {
+    //     const { id } = JSON.parse(currentSelectedHop);
+    //     hospId = id
+    // }
+    if (type == 'EDIT' && pageType) {
+      const resp = await editPubDicRelaTbaleData(
+        pageType == 1 ? { ...formVal, systemId: parentId, hospId, dictType: currentSelectedTreeNode?.dictType } : { ...formVal, systemId: parentId, hospId, type: currentSelectedTreeNode?.dictType },
+        pageType,
+      );
+      if (resp) {
+        set_reload(true);
+      }
+    }
+    if (type == 'ADD' && pageType) {
+      const resp = await addPubDicRelaTbaleData(
+        pageType == 1 ? { ...formVal, systemId: parentId, hospId, dictType: currentSelectedTreeNode?.dictType } : { ...formVal, systemId: parentId, hospId, type: currentSelectedTreeNode?.dictType },
+        pageType,
+      );
+      if (resp) {
+        set_reload(true);
+      }
+    }
+  };
 
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const [reload, set_reload] = useState(false);
-    const [typeList, set_typeList] = useState<PubDicTypeData[]>([]);
-    const [showTypeListArr, set_showTypeListArr] = useState<PubDicTypeData[]>([]);
-    const [currentSelectedType, set_currentSelectedType] = useState<PubDicTypeData | undefined>(undefined);
-    const [currentEdit,set_currentEdit] = useState<any>(undefined);
-
-
-
-
-    const columns = [
-        {
-            title: '项目名称',
-            dataIndex: 'name',
-
-        },
-        {
-            title: '项目代码',
-            dataIndex: 'code',
-        },
-        {
-            title: '项目值',
-            dataIndex: 'value',
-        },
-        {
-            title: '默认',
-            dataIndex: 'data.0.dictDefault',
-            render: (_: any, record:any) => {
-                return record.dictDefault == 1 ? '是' : '否'
+  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>}
+        onFinish={(val) => {
+          return updateTable(type == 'EDIT' ? (pageType == 1 ? { ...val, dictDataId: record.dictDataId } : { ...val, id: record.id }) : val, type);
+        }}
+      >
+        <ProFormText name="name" label="项目名称:" placeholder="请输入" rules={[{ required: true, message: '项目名称不能为空!' }]} />
+        <ProFormText name="code" label="项目代码:" placeholder="请输入" rules={[{ required: true, message: '项目代码不能为空!' }]} />
+        <ProFormText name="value" label="项目值:" placeholder="请输入" />
+        <ProFormDigit label="顺序号:" name={pageType == 1 ? 'dictSort' : 'sort'} rules={[{ required: true, message: '顺序号不能为空!' }]} />
+
+        <ProFormRadio.Group
+          name={pageType == 1 ? 'dictDefault' : 'defaultFlag'}
+          label="默认:"
+          fieldProps={{
+            buttonStyle: 'solid',
+          }}
+          options={[
+            {
+              label: '是',
+              value: 1,
             },
-
-        },
-        {
-            title: '序号',
-            dataIndex: 'dictSort',
-
-        },
-        {
-            title: '适用院区',
-            dataIndex: 'hospName',
-
-        },
-        {
-            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>
-                ]
+            {
+              label: '否',
+              value: 0,
             },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const { dictType } = params;
-        if (dictType) {
-            const resp = await getPubDicRelaTbaleData(params);
-            set_reload(false);
-            if (resp) {
-                return {
-                    data: resp.list,
-                    success: true,
-                    total: resp.totalCount,
-                    pageSize: resp.pageSize,
-                    totalPage: resp.totalPage,
-                }
-            }
+          ]}
+          rules={[{ required: true, message: '默认不能为空!' }]}
+        />
+        {true && (
+          <>
+            <ProFormText name="expandOne" label="扩展一:" placeholder="请输入" />
+            <ProFormText name="expandTwo" label="扩展二:" placeholder="请输入" />
+          </>
+        )}
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const getTreeReqFunc = async (type: number) => {
+    const resp = await getLeftData(type);
+    const transformResp = resp.map((a: any, index: number) => {
+      return {
+        code: Math.random(),
+        name: a.systemName,
+        systemId: a.systemId,
+        children: a.dictTypeList.map((b: any, num: number) => ({ ...b, name: b.dictName, code: Math.random() })),
+      };
+    });
+    set_treeData(transformResp);
+  };
+
+  const dataList: any[] = [];
+
+  const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+    let parentKey: React.Key;
+    for (let i = 0; i < tree.length; i++) {
+      const node = tree[i];
+      if (node.children) {
+        if (node.children.some((item: { code: React.Key }) => item.code === key)) {
+          parentKey = node.code;
+        } else if (getParentKey(key, node.children)) {
+          parentKey = getParentKey(key, node.children);
         }
-        return []
+      }
     }
-
-    const getTypeList = async () => {
-        const resp = await getData({ pageSize: 1000, current: 1 });
-        if (resp) {
-            set_typeList(resp.list);
-            set_showTypeListArr(resp.list);
-        }
+    return parentKey!;
+  };
+
+  const generateList = (data: any[]) => {
+    if (!data) return;
+    for (let i = 0; i < data.length; i++) {
+      const node = data[i];
+      const { code, name } = node;
+      dataList.push({ code, name: name });
+      if (node.children) {
+        generateList(node.children);
+      }
     }
-
-    const delTableData = async (record: any) => {
-          const resp = await delData(record.dictDataId);
-          if(resp){
+  };
+  generateList(treeData as any);
+
+  const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    const { value } = e.target;
+    const newExpandedKeys = dataList.map((item) => {
+      if (item.name.indexOf(value) > -1) {
+        return getParentKey(item.code, treeData);
+      }
+      return null;
+    });
+
+    const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+    setExpandedKeys(newExpandedKeys as React.Key[]);
+    setSearchValue(value);
+    setAutoExpandParent(true);
+  };
+
+  const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+    //console.log('selected', selectedKeys, info);
+    const { node } = info;
+    if (!node.children) {
+      set_currentSelectedTreeNode(node);
+    }
+  };
+
+  const onExpand = (newExpandedKeys: React.Key[]) => {
+    setExpandedKeys(newExpandedKeys);
+    setAutoExpandParent(false);
+  };
+
+  const initFunction = () => {
+    Modal.confirm({
+      title: '注意',
+      content: '初始化操作会覆盖已有的字典数据并根据默认数据生成字典数据,确定继续操作?',
+      onOk: async (...args) => {
+        if (currentSelectedTreeNode) {
+          const { systemId, dictType } = currentSelectedTreeNode;
+          const resp = await initReq(systemId, dictType);
+          if (resp) {
             set_reload(true);
+            message.success('初始化成功!');
           }
-    }
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-        if (type == 'EDIT') {
-            const resp = await editPubDicRelaTbaleData({...formVal});
-            if (resp) {
-                set_reload(true);
-            }
         }
-        if (type == 'ADD') {
-            const resp = await addPubDicRelaTbaleData({...formVal,dictType:currentSelectedType?.dictType});
-            if (resp) {
-                set_reload(true);
-            }
-        }
-
-
+      },
+    });
+  };
+
+  useEffect(() => {
+    if (currentSelectedTreeNode) {
+      const { topic = '' } = currentSelectedTreeNode;
+      const titles = topic.split('|');
+      if (topic && titles.length == 7) {
+        const newColumns = defaultColumns.map((a, index) => ({
+          ...a,
+          title: titles[index],
+        }));
+        set_columns([...newColumns, ...options]);
+      } else {
+        set_columns([...defaultColumns, ...options]);
+      }
+      set_reload(true);
     }
+  }, [currentSelectedTreeNode]);
 
-    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>
-                }
-                onFinish={(val) => {
-                    return updateTable(type == 'EDIT'?{...val,dictDataId:record.dictDataId}:val, type);
-                }}
-            >
-                <ProFormText
-                    name="name"
-                    label="项目名称:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '项目名称不能为空!' }]}
-                />
-                <ProFormText
-                    name="code"
-                    label="项目代码:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '项目代码不能为空!' }]}
-                />
-                <ProFormText
-                    name="value"
-                    label="项目值:"
-                    placeholder="请输入"
-
-                />
-                <ProFormDigit label="顺序号:" name="dictSort" rules={[{ required: true, message: '顺序号不能为空!' }]} />
-
-                <ProFormRadio.Group
-                    name="dictDefault"
-                    label="默认:"
-                    fieldProps={{
-                        buttonStyle: 'solid'
-                    }}
-                    options={[
-                        {
-                            label: '是',
-                            value: 1,
-                        },
-                        {
-                            label: '否',
-                            value: 0,
-                        },
-                    ]}
-                    rules={[{ required: true, message: '默认不能为空!' }]}
-                />
-                <ProFormSelect
-                    name="hospId"
-                    label="适用院区:"
-                    placeholder="请选择院区"
-                    request={async () => {
-                        const resp = await getAllHosp({ pageSize: 200, current: 1 });
-                        if (resp) {
-                            const data: any = resp.list?.map((a) => ({
-                                label: a.hospName,
-                                value: a.id
-                            }));
-
-                            return [
-                                {
-                                    label:'所有院区',value:'0'
-                                },...data
-                            ];
-                        }
-                        return []
+  useEffect(() => {
+    //初始化左侧树结构数据后
 
-                    }}
-                    rules={[{ required: true, message: '院区不能为空!' }]}
-                />
-
-            </ModalForm>
-        )
-    }
-
-    const editHandle = (record: any) => {
+    if (treeData?.length > 0) {
+      if (treeData[0].children && treeData[0].children.length > 0) {
+        const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
 
+        set_currentSelectedTreeNode(node);
+        setExpandedKeys([nodeParent.code]);
+      }
     }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-    }
-
-    useEffect(()=>{
-        if(currentSelectedType){
-            set_tableDataFilterParams({...tableDataFilterParams,dictType:currentSelectedType.dictType})
-        }
-    },[currentSelectedType])
-
-    useEffect(() => {
-        if (showTypeListArr.length > 0) {
-            set_currentSelectedType(showTypeListArr[0]);
-            set_tableDataFilterParams({ ...tableDataFilterParams, dictType: showTypeListArr[0].dictType });
-        }
-    }, [showTypeListArr])
-
-    useEffect(() => {
-        getTypeList();
-    }, [])
-
-    return (
-        <div className='PubDicMana'>
-            <div className='left'>
-                <KCInput placeholder={'请输入类目名称'} search allowClear
-                    onChange={(e) => {
-                           const result = typeList.filter(item=>item.dictName.indexOf(e.target.value) != -1);
-                           set_showTypeListArr(result);
+  }, [treeData]);
+
+  useEffect(() => {
+    const { pathname } = location;
+    if (pathname == '/platform/setting/pubDicMana/1') set_pageType(1);
+    if (pathname == '/platform/setting/pubDicMana/2') set_pageType(2);
+  }, [location]);
+
+  useEffect(() => {
+    if (pageType) getTreeReqFunc(pageType);
+  }, [pageType]);
+
+  return (
+    <div className="PubDicMana">
+      <div className="left">
+        <div className="search">
+          <Input className="searchInput" placeholder="请输入" size="small" allowClear style={{ marginBottom: 16 }} onChange={onTreeSearchKeyChange} suffix={<SearchIcon type="iconsousuo" />} />
+        </div>
+        <div className="wrap">
+          {treeData && treeData.length > 0 && (
+            <DirectoryTree
+              fieldNames={{ title: 'name', key: 'code' }}
+              rootStyle={{ height: '100%', paddingBottom: 50 }}
+              onSelect={onSelect}
+              onExpand={onExpand}
+              expandedKeys={expandedKeys}
+              autoExpandParent={autoExpandParent}
+              selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.code] : []}
+              blockNode={true}
+              icon={() => null}
+              titleRender={(nodeData: any) => {
+                const strTitle = nodeData.name as string;
+                const index = strTitle.indexOf(searchValue);
+                const beforeStr = strTitle.substring(0, index);
+                const afterStr = strTitle.slice(index + searchValue.length);
+
+                const title =
+                  index > -1 ? (
+                    <span>
+                      {beforeStr}
+                      <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
+                        {searchValue}
+                      </span>
+                      {afterStr}
+                    </span>
+                  ) : (
+                    <span className="strTitle">{strTitle}</span>
+                  );
+                return (
+                  <div
+                    style={{
+                      display: 'flex',
+                      flexDirection: 'row',
+                      width: '100%',
+                      justifyContent: 'flex-start',
+                      alignItems: 'center',
+                      height: 32,
+                      borderRadius: '4px',
+                      overflow: 'hidden',
+                      color: '#17181A',
+                      textOverflow: 'ellipsis',
+                      whiteSpace: 'nowrap',
                     }}
-                
-                />
-                <div className='wrap'>
-                    {
-                        showTypeListArr.map((item, index) => {
-                            return (
-                                <div className={currentSelectedType ? currentSelectedType.dictId == item.dictId ? 'type on' : 'type' : 'type'}
-                                    key={index}
-                                    onClick={() => set_currentSelectedType(item)}
-                                >{item.dictName}</div>
-                            )
-                        })
-                    }
-                </div>
-            </div>
-            <div className='right'>
-                <div className='toolBar'>
-                    <div className='filter'>
-                        <div className='filterItem'>
-                            <span className='label'>适用院区:</span>
-                            <ProFormSelect
-                                noStyle
-                                allowClear
-                                placeholder="请选择"
-                                style={{ width: 160,marginRight:16}}
-                                request={async () => {
-                                    const resp = await getAllHosp({ pageSize: 200, current: 1 });
-                                    if (resp) {
-                                        const data: any = resp.list?.map((a) => ({
-                                            label: a.hospName,
-                                            value: a.id
-                                        }));
-
-                                        return [
-                                            {
-                                                label:'所有院区',value:'0'
-                                            },...data
-                                        ];
-                                    }
-                                    return []
-
-                                }}
-                                fieldProps={{
-                                    onChange(value, option) {
-                                        set_tableDataFilterParams({...tableDataFilterParams,hospId:value})
-                                    },
-                                }}
-                            />
-                        </div>
-                        <div className='filterItem'>
-                            <span className='label'>检索:</span>
-                            <KCInput placeholder={'请输入项目名称'} style={{ width: 160 }} search allowClear
-                                onChange={(e) => {
-                                    set_tableDataSearchKeywords(e.target.value);
-                                    if (e.target.value.length == 0) {
-                                        set_tableDataFilterParams({
-                                            ...tableDataFilterParams,
-                                            typeName: ''
-                                        });
-                                    }
-                                }}
-                                onSearch={() => tableDataSearchHandle('typeName')}
-                            />
-                        </div>
-                    </div>
-                    <div className='btnGroup'>
-                        <UpDataActBtn record type='ADD' />
-                    </div>
-                </div>
-                <div style={{ marginTop: 16 }}>
-                    {currentSelectedType && <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='dictDataId' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />}
-                </div>
+                  >
+                    {title}
+                  </div>
+                );
+              }}
+              defaultSelectedKeys={[treeData[0].children[0].code]}
+              treeData={treeData as unknown as DataNode[]}
+              // treeData={treeDataNew}
+
+              switcherIcon={(props: any) => {
+                const { expanded } = props;
+                //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
+                return !expanded ? (
+                  <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} />
+                ) : (
+                  <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+                );
+              }}
+            />
+          )}
+        </div>
+      </div>
+      <div className="right">
+        <div className="toolBar">
+          <div className="filter">
+            <div className="filterItem">
+              <span className="label">检索:</span>
+              <KCInput
+                placeholder={'请输入项目名称'}
+                style={{ width: 160 }}
+                search
+                allowClear
+                onChange={(e) => {
+                  set_tableDataSearchKeywords(e.target.value);
+                  if (e.target.value.length == 0) {
+                    set_tableDataFilterParams(
+                      pageType == 1
+                        ? {
+                            ...tableDataFilterParams,
+                            typeName: '',
+                          }
+                        : { ...tableDataFilterParams, dictName: '' },
+                    );
+                  }
+                }}
+                onSearch={() => tableDataSearchHandle(pageType == 1 ? 'typeName' : 'dictName')}
+              />
             </div>
+          </div>
+          <div className="btnGroup">
+            {pageType == 2 && (
+              <span className="initBtn" onClick={() => initFunction()}>
+                初始化
+              </span>
+            )}
+            <UpDataActBtn record type="ADD" />
+          </div>
         </div>
-    )
-}
-
+        <div style={{ marginTop: 16 }}>
+          {currentSelectedTreeNode && (
+            <KCTable
+              scroll={{ y: `calc(100vh - 250px)` }}
+              columns={columns as ProColumns[]}
+              reload={reload}
+              rowKey={pageType == 1 ? 'dictDataId' : 'id'}
+              newVer
+              params={tableDataFilterParams}
+              request={(params) => getTableData(params)}
+            />
+          )}
+        </div>
+      </div>
+    </div>
+  );
+};
 
 export default PubDicMana;

+ 30 - 11
src/pages/platform/setting/pubDicMana/service.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-07 11:12:10
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-08 17:04:57
+ * @LastEditTime: 2023-09-08 11:23:11
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicMana/service.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -24,14 +24,24 @@ export type PubDicRelaTbaleDataType = {
     hospId?:string;
 }
 
-export const getPubDicRelaTbaleData = (params:PubDicRelaTbaleDataType) => {
-    return request('/centerSys/sysdictdata/getDictDataList', {
+export const getPubDicRelaTbaleData = (params:PubDicRelaTbaleDataType,pageType:number) => {
+    return request(pageType == 1?'/centerSys/sysdictdata/getDictDataList':'/centerSys/sysdictdata/getHospDict', {
       method: 'GET',
       params:{...params}
     });
 };
 
 
+//获取左侧列表数据
+
+export const getLeftData = (pageType:number) => {
+  return request(pageType == 1?'/centerSys/sysdictdata/getSystemDictTypeList':'/centerSys/sysdictdata/getHospSystemDictTypeList', {
+    method: 'GET',
+  });
+};
+
+
+
 //新增表格数据
 
 export type AddPubDicRelaTbaleDataType = {
@@ -44,8 +54,8 @@ export type AddPubDicRelaTbaleDataType = {
     hospId:number;
 }
 
-export const addPubDicRelaTbaleData = (data:AddPubDicRelaTbaleDataType) => {
-    return request('/centerSys/sysdictdata/addData', {
+export const addPubDicRelaTbaleData = (data:AddPubDicRelaTbaleDataType,pageType:number) => {
+    return request(pageType == 1?'/centerSys/sysdictdata/addData':'/centerSys/sysdictdata/addHospDict', {
       method: 'POST',
       data
     });
@@ -64,8 +74,8 @@ export type EditPubDicRelaTbaleDataType = {
     hospId:number;
 }
 
-export const editPubDicRelaTbaleData = (data:EditPubDicRelaTbaleDataType) => {
-    return request('/centerSys/sysdictdata/editData', {
+export const editPubDicRelaTbaleData = (data:EditPubDicRelaTbaleDataType,pageType:number) => {
+    return request(pageType == 1?'/centerSys/sysdictdata/editData':'/centerSys/sysdictdata/editHospDict', {
       method: 'POST',
       data
     });
@@ -73,9 +83,18 @@ export const editPubDicRelaTbaleData = (data:EditPubDicRelaTbaleDataType) => {
 
 
 //删除表格操作
-export const delData = (dictDataId:string) => {
-    return request('/centerSys/sysdictdata/deleteData', {
+export const delData = (dictDataId:string,pageType:number) => {
+    return request(pageType == 1?'/centerSys/sysdictdata/deleteData':'/centerSys/sysdictdata/deleteHospDict', {
       method: 'POST',
-      params:{dictDataId}
+      params:pageType == 1?{dictDataId}:{id:dictDataId}
     });
-  };
+};
+
+//初始化
+export const initReq = (systemId:string,dictType:string) => {
+  return request('/centerSys/sysdictdata/initHospDict', {
+    method: 'POST',
+    params:{systemId,dictType}
+  });
+};
+

+ 60 - 22
src/pages/platform/setting/pubDicMana/style.less

@@ -6,39 +6,63 @@
     float: left;
     border-radius: 4px;
     width: 220px;
-    height:calc(100vh - 80px);
-    overflow: scroll;
+    height: calc(100vh - 80px);
     margin-right: 16px;
     padding: 16px;
     background: #FFFFFF;
 
     .wrap {
-      margin-top: 16px;
-
-      .type {
-        cursor: pointer;
-        height: 32px;
-        line-height: 32px;
-        padding-left: 8px;
-        background: #FFFFFF;
+      height: calc(100vh - 152px);
+      overflow: scroll;
+    }
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode {
+
+      //style={{display:'inline-flex',justifyContent:'center',alignItems:'center',width:16,height:16,background:'#fff',borderRadius:4,border:'1px solid #DAE2F2',marginLeft:4,position:'relative',top:2}}
+      .copy {
+        display: none;
+      }
+
+      &:hover {
         border-radius: 4px;
-        font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-        font-weight: 400;
-        color: #17181A;
-        margin-bottom: 4px;
-
-        &.on {
-          font-weight: 500;
-          color: #17181A;
-          background: #F0F2F5;
+        background: #F0F2F5;
+
+        .copy {
+          display: inline-flex;
+          justify-content: center;
+          align-items: center;
+          width: 16px;
+          height: 16px;
+          background: #FFFFFF;
+          border-radius: 4px;
+          border-radius: 4px;
+          border: 1px solid #DAE2F2;
+          margin-left: 4px;
+          position: relative;
+          top: 2px;
+
         }
 
-        &:last-child {
-            margin-bottom: 0;
+        &::before {
+          border-radius: 4px;
+          background: #F0F2F5;
         }
       }
     }
+
+
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode-selected {
+      &::before {
+        border-radius: 4px;
+        background: #F0F2F5;
+
+      }
+    }
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode .kcmp-ant-tree-node-content-wrapper.kcmp-ant-tree-node-selected {
+      font-weight: bold;
+    }
   }
 
   .right {
@@ -69,6 +93,20 @@
       }
 
       .btnGroup {
+        .initBtn {
+          display: inline-flex;
+          justify-content: center;
+          align-items: center;
+          width: 72px;
+          height: 24px;
+          cursor: pointer;
+          font-size: 14px;
+          background: #FAFCFF;
+          border-radius: 4px;
+          border: 1px solid #DAE2F2;
+          margin-right: 8px;
+        }
+
         .add {
           cursor: pointer;
           display: inline-block;

+ 348 - 167
src/pages/platform/setting/pubDicTypeMana/index.tsx

@@ -2,137 +2,164 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-24 12:10:56
+ * @LastEditTime: 2024-03-01 15:54:23
  * @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 { KCInput } from '@/components/KCInput';
 import KCTable from '@/components/kcTable';
-import { getAllHosp } from '@/service/hospList';
-import { ModalForm, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+
+import { ModalForm, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
 import { ProColumns } from '@ant-design/pro-table';
-import { message, Modal, Popconfirm } from 'antd';
-import React, { useState } from 'react'
-import { addData, delData, editData, getData } from './service';
+import { Input, message, Modal, Popconfirm, Switch, TreeProps } from 'antd';
+import React, { useEffect, useState } from 'react';
+import { addData, delData, dicOpenStatHandle, editData, getData, getTreeData } from './service';
 
 import './style.less';
 
+import { createFromIconfontCN } from '@ant-design/icons';
+import { DataNode } from 'antd/lib/tree';
 
+import expandedIcon from '../../../../../public/images/treenode_open.png';
+import closeIcon from '../../../../../public/images/treenode_collapse.png';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { getDeepestTreeData } from '@/utils';
 
-export default function PubDicTypeMana() {
+const SearchIcon = createFromIconfontCN({
+  scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
 
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-    const [reload, set_reload] = useState(false);
-    const [currentEdit,set_currentEdit] = useState<any>(undefined);
-
-
-
-
-    const columns = [
-        {
-            title: '类型名称',
-            dataIndex: 'dictName',
-
-        },
-        {
-            title: '类型代码',
-            dataIndex: 'dictType',
-        },
-        {
-            title: '说明',
-            dataIndex: 'remark',
-        },
-        // {
-        //     title: '院区',
-        //     dataIndex: 'hospName',
-
-        // },
-        {
-            title: '操作',
-            key: 'option',
-            width: 120,
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return [
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={()=>delTableData(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ]
-            },
-        },
-
-    ]
-
-
-    const getTableData = async (params: any) => {
-        const resp = await getData(params);
-        set_reload(false);
-        if (resp) {
-            return {
-                data: resp.list,
-                success: true,
-                total: resp.totalCount,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
-            }
-        }
-        return []
+export default function PubDicTypeMana() {
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+  const [reload, set_reload] = useState(false);
+  const [currentEdit, set_currentEdit] = useState<any>(undefined);
+
+  const [treeData, set_treeData] = useState<any[]>([]);
+  const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+  const [searchValue, setSearchValue] = useState('');
+  const [autoExpandParent, setAutoExpandParent] = useState(true);
+
+  const columns: ProColumns[] = [
+    {
+      title: '类型名称',
+      dataIndex: 'dictName',
+    },
+    {
+      title: '类型代码',
+      dataIndex: 'dictType',
+    },
+    {
+      title: '标题',
+      dataIndex: 'topic',
+    },
+    {
+      title: '说明',
+      dataIndex: 'remark',
+    },
+    {
+      title: '开放',
+      dataIndex: 'status',
+      renderText(val, record, index, action) {
+        return <Switch size="small" checked={val == '0' ? true : false} onChange={(bool) => chnageDicOpenStatHandle(bool, record)} />;
+      },
+    },
+    {
+      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 chnageDicOpenStatHandle = async (bool: boolean, record: any) => {
+    const resp = await dicOpenStatHandle({ dictId: record.dictId, status: bool ? '0' : '1' });
+    if (resp) {
+      message.success('开放成功!');
+      set_reload(true);
     }
-
-    const delTableData = async (record:any)=>{
-          const resp = await delData(record.dictId);
-          if(resp){
-            set_reload(true);
-            // message.success('操作成功!');
-          }
+  };
+
+  const getTableData = async (params: any) => {
+    const resp = await getData({ ...params, systemId: params.systemId ? params.systemId : currentSelectedTreeNode.code });
+    set_reload(false);
+    if (resp) {
+      return {
+        data: resp.list,
+        success: true,
+        total: resp.totalCount,
+      };
     }
-
-
-    
-
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
-       
-        if (type == 'ADD') {
-            const resp = await addData({...formVal,hospId:0});
-            if (resp) {
-                set_reload(true);
-            }
-        }
-        if (type == 'EDIT') {
-            const {dictId} = currentEdit;
-            const resp = await editData({...formVal,dictId,hospId:0});
-            if (resp) {
-                set_reload(true);
-            }
-        }
-
-
+    return [];
+  };
+
+  const delTableData = async (record: any) => {
+    const resp = await delData(record.dictId);
+    if (resp) {
+      set_reload(true);
+      // message.success('操作成功!');
     }
+  };
+
+  const updateTable = async (formVal: any, type: 'EDIT' | 'ADD') => {
+    if (type == 'ADD') {
+      const resp = await addData({
+        dictName: formVal.dictName,
+        dictType: formVal.dictType,
+        remark: formVal.remark,
+        topic: formVal.topic ? formVal.topic : null,
+        systemId: currentSelectedTreeNode.code,
+      });
+      if (resp) {
+        set_reload(true);
+      }
+    }
+    if (type == 'EDIT') {
+      const { dictId } = currentEdit;
+      const resp = await editData({
+        dictId,
+        dictName: formVal.dictName,
+        dictType: formVal.dictType,
+        remark: formVal.remark,
+        topic: formVal.topic ? formVal.topic : null,
+        systemId: currentSelectedTreeNode.code,
+      });
+      if (resp) {
+        set_reload(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" onClick={() => set_currentEdit(record)}>编辑</a> : <span className='add'>新增</span>
-                }
-                onFinish={(val) => {
-                    return updateTable(val, type);
-                }}
-            >
-                {/* <ProFormSelect
+  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" onClick={() => set_currentEdit(record)}>
+              编辑
+            </a>
+          ) : (
+            <span className="add">新增</span>
+          )
+        }
+        onFinish={(val) => {
+          return updateTable(val, type);
+        }}
+      >
+        {/* <ProFormSelect
                     name="hospId"
                     label="院区:"
                     disabled={type == 'EDIT'}
@@ -155,69 +182,223 @@ export default function PubDicTypeMana() {
 
                     }}
                 /> */}
-                <ProFormText
-                    name="dictName"
-                    label="类型名称:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '类型名称不能为空!' }]}
-                />
-                <ProFormText
-                    name="dictType"
-                    label="类型代码:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '类型代码不能为空!' }]}
-                />
-                <ProFormTextArea
-                    name="remark"
-                    label="说明:"
-                    placeholder="请输入"
-
-                />
-            </ModalForm>
-        )
+        <ProFormText name="dictName" label="类型名称:" placeholder="请输入" rules={[{ required: true, message: '类型名称不能为空!' }]} />
+        <ProFormText name="dictType" label="类型代码:" placeholder="请输入" rules={[{ required: true, message: '类型代码不能为空!' }]} />
+        <ProFormTextArea name="topic" label="标题(|线分割):" placeholder="请输入" />
+        <ProFormTextArea name="remark" label="说明:" placeholder="请输入" />
+      </ModalForm>
+    );
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const getTreeReqFunc = async (name?: string) => {
+    const resp = await getTreeData();
+    set_treeData(resp);
+  };
+
+  const dataList: any[] = [];
+
+  const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+    let parentKey: React.Key;
+    for (let i = 0; i < tree.length; i++) {
+      const node = tree[i];
+      if (node.children) {
+        if (node.children.some((item: { code: React.Key }) => item.code === key)) {
+          parentKey = node.code;
+        } else if (getParentKey(key, node.children)) {
+          parentKey = getParentKey(key, node.children);
+        }
+      }
+    }
+    return parentKey!;
+  };
+
+  const generateList = (data: any[]) => {
+    for (let i = 0; i < data.length; i++) {
+      const node = data[i];
+      const { code, name } = node;
+      dataList.push({ code, name: name });
+      if (node.children) {
+        generateList(node.children);
+      }
+    }
+  };
+  generateList(treeData as any);
+
+  const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    const { value } = e.target;
+    const newExpandedKeys = dataList.map((item) => {
+      if (item.name.indexOf(value) > -1) {
+        return getParentKey(item.code, treeData);
+      }
+      return null;
+    });
+
+    const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+    setExpandedKeys(newExpandedKeys as React.Key[]);
+    setSearchValue(value);
+    setAutoExpandParent(true);
+  };
+
+  const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+    //console.log('selected', selectedKeys, info);
+    const { node } = info;
+    if (!node.children) {
+      set_currentSelectedTreeNode(node);
     }
+  };
 
-    const editHandle = (record: any) => {
+  const onExpand = (newExpandedKeys: React.Key[]) => {
+    setExpandedKeys(newExpandedKeys);
+    setAutoExpandParent(false);
+  };
 
+  useEffect(() => {
+    if (currentSelectedTreeNode) {
+      set_tableDataFilterParams({ ...tableDataFilterParams, systemId: currentSelectedTreeNode.code });
     }
+  }, [currentSelectedTreeNode]);
 
-    const tableDataSearchHandle = (paramName: string) => {
+  useEffect(() => {
+    //初始化左侧树结构数据后
 
+    if (treeData?.length > 0) {
+      if (treeData[0].children && treeData[0].children.length > 0) {
+        const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
 
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
+        set_currentSelectedTreeNode(node);
+        setExpandedKeys([nodeParent.code]);
+      }
     }
+  }, [treeData]);
 
-    return (
-        <div className='PubDicTypeMana'>
-            <div className='toolBar'>
-                <div className='filter'>
-                    <div className='filterItem'>
-                        <span className='label'>检索:</span>
-                        <KCInput placeholder={'请输入类型名称'} style={{ width: 160 }} search allowClear
-                            onChange={(e) => {
-                                set_tableDataSearchKeywords(e.target.value);
-                                if (e.target.value.length == 0) {
-                                    set_tableDataFilterParams({
-                                        ...tableDataFilterParams,
-                                        typeName: ''
-                                    });
-                                }
-                            }}
-                            onSearch={() => tableDataSearchHandle('typeName')}
-
-                        />
-                    </div>
-                </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
+  useEffect(() => {
+    getTreeReqFunc();
+  }, []);
+
+  return (
+    <div className="PubDicTypeMana">
+      <div className="left">
+        <div className="search">
+          <Input className="searchInput" placeholder="请输入" size="small" allowClear style={{ marginBottom: 16 }} onChange={onTreeSearchKeyChange} suffix={<SearchIcon type="iconsousuo" />} />
+        </div>
+        {treeData && treeData.length > 0 && (
+          <DirectoryTree
+            fieldNames={{ title: 'name', key: 'code' }}
+            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+            onSelect={onSelect}
+            onExpand={onExpand}
+            expandedKeys={expandedKeys}
+            autoExpandParent={autoExpandParent}
+            selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.code] : []}
+            blockNode={true}
+            icon={() => null}
+            titleRender={(nodeData: any) => {
+              const strTitle = nodeData.name as string;
+              const index = strTitle.indexOf(searchValue);
+              const beforeStr = strTitle.substring(0, index);
+              const afterStr = strTitle.slice(index + searchValue.length);
+
+              const copyFunc = async () => {
+                try {
+                  await navigator.clipboard.writeText(nodeData.systemId);
+                  message.success('复制成功!');
+                } catch (err) {
+                  console.error('Failed to copy text: ', err);
+                }
+              };
+              const title =
+                index > -1 ? (
+                  <span>
+                    {beforeStr}
+                    <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
+                      {searchValue}
+                    </span>
+                    {afterStr}
+                    <a className="copy" onClick={() => copyFunc()}>
+                      <img style={{ width: 14, height: 14 }} src={require('../../../../../public/images/copy.png')} alt="" />
+                    </a>
+                  </span>
+                ) : (
+                  <span className="strTitle">
+                    {strTitle}
+                    <a className="copy" onClick={() => copyFunc()}>
+                      <img style={{ width: 14, height: 14 }} src={require('../../../../../public/images/copy.png')} alt="" />
+                    </a>
+                  </span>
+                );
+              return (
+                <div
+                  style={{
+                    display: 'flex',
+                    flexDirection: 'row',
+                    width: '100%',
+                    justifyContent: 'flex-start',
+                    alignItems: 'center',
+                    height: 32,
+                    borderRadius: '4px',
+                    overflow: 'hidden',
+                    color: '#17181A',
+                    textOverflow: 'ellipsis',
+                    whiteSpace: 'nowrap',
+                  }}
+                >
+                  {title}
                 </div>
+              );
+            }}
+            defaultSelectedKeys={[treeData[0].children[0].code]}
+            treeData={treeData as unknown as DataNode[]}
+            // treeData={treeDataNew}
+            switcherIcon={(props: any) => {
+              const { expanded } = props;
+              //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
+              return !expanded ? (
+                <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} />
+              ) : (
+                <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+              );
+            }}
+          />
+        )}
+      </div>
+      <div className="right">
+        <div className="toolBar">
+          <div className="filter">
+            <div className="filterItem">
+              <span className="label">检索:</span>
+              <KCInput
+                placeholder={'请输入类型名称'}
+                style={{ width: 160 }}
+                search
+                allowClear
+                onChange={(e) => {
+                  set_tableDataSearchKeywords(e.target.value);
+                  if (e.target.value.length == 0) {
+                    set_tableDataFilterParams({
+                      ...tableDataFilterParams,
+                      typeName: '',
+                    });
+                  }
+                }}
+                onSearch={() => tableDataSearchHandle('typeName')}
+              />
             </div>
-            <div style={{ marginTop: 16 }}>
-                <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='dictId' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
+          </div>
+          <div className="btnGroup">
+            <UpDataActBtn record type="ADD" />
+          </div>
+        </div>
+        <div style={{ marginTop: 16 }}>
+          {currentSelectedTreeNode && <KCTable columns={columns as ProColumns[]} reload={reload} rowKey="dictId" newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />}
         </div>
-    )
+      </div>
+    </div>
+  );
 }

+ 52 - 50
src/pages/platform/setting/pubDicTypeMana/service.ts

@@ -2,86 +2,88 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 16:31:27
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-07 10:28:57
+ * @LastEditTime: 2024-03-01 15:47:56
  * @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 PubDicTypeData = {
-  dictId:string;
-  dictName:string;
-  dictType:string;
-  hospId:string;
-  hospName:string;
-  remark:string;
-  status:string
-}
-
+  dictId: string;
+  dictName: string;
+  dictType: string;
+  hospId: string;
+  hospName: string;
+  remark: string;
+  status: string;
+};
 
-export const getData = (params?:any) => {
-  return request<{
-       current:number;
-       list:PubDicTypeData[];
-       pageSize:number;
-       totalCount:number;
-       totalPage:number;
-  }>('/centerSys/sysdictdata/getDictType', {
+export const getData = (params?: any) => {
+  return request('/centerSys/sysdictdata/getSystemDict', {
     method: 'GET',
-    params:{...params}
+    params: { ...params },
   });
 };
 
-
 //新增表格数据
 export type AddTableDataType = {
-  hospId:number;
-  dictName:string;
-  dictType:string;
-  remark:string
-}
-export const addData = (data:AddTableDataType) => {
-  return request('/centerSys/sysdictdata/addDictType', {
+  dictName: string;
+  dictType: string;
+  remark: string;
+  systemId: string;
+  topic: string;
+};
+export const addData = (data: AddTableDataType) => {
+  return request('/centerSys/sysdictdata/addSystemDict', {
     method: 'POST',
-    data
+    data,
   });
 };
 
-
+//获取左侧系统数据
+export const getTreeData = () => {
+  const currentHosp = localStorage.getItem('currentSelectedSubHop');
+  if (currentHosp) {
+    const { id } = JSON.parse(currentHosp);
+    return request('/centerSys/hospital/getSystemList', {
+      method: 'GET',
+      params: { hospId: id },
+    });
+  }
+};
 
 //编辑表格数据
 export type EditTableDataType = {
-  dictId:number;
-  hospId:number;
-  dictName:string;
-  dictType:string;
-  remark:string
-}
+  dictId: number;
+  systemId: string;
+  dictName: string;
+  dictType: string;
+  remark: string;
+  topic: string;
+};
 
-export const editData = (data:EditTableDataType) => {
-  return request('/centerSys/sysdictdata/editDictType', {
+export const editData = (data: EditTableDataType) => {
+  return request('/centerSys/sysdictdata/editSystemDict', {
     method: 'POST',
-    data
+    data,
   });
 };
 
 //删除表格操作
-export const delData = (dictId:string) => {
-  return request('/centerSys/sysdictdata/deleteDictType', {
+export const delData = (dictId: string) => {
+  return request('/centerSys/sysdictdata/deleteSystemDict', {
     method: 'POST',
-    params:{dictId}
+    params: { dictId },
   });
 };
 
-
-
-
-
-
-
-
+//字典类型开放操作
+export const dicOpenStatHandle = (data: { dictId: string; status: string }) => {
+  return request('/centerSys/sysdictdata/editSystemDictStatus', {
+    method: 'POST',
+    params: { ...data },
+  });
+};

+ 99 - 25
src/pages/platform/setting/pubDicTypeMana/style.less

@@ -1,42 +1,116 @@
 .PubDicTypeMana {
-  padding: 16px;
-  background: #FFFFFF;
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+  height: 100%;
   border-radius: 4px;
 
-  .toolBar {
-    display: flex;
-    flex-direction: row;
-    justify-content: space-between;
-    align-items: center;
+  .left {
 
-    .filter {
+    border-radius: 4px;
+    width: 220px;
+    height: calc(100vh - 80px);
+    overflow: scroll;
+    margin-right: 16px;
+    padding: 16px;
+    background: #FFFFFF;
+
+    .searchInput {
+      border: 1px solid #CFD7E6;
+    }
+
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode {
+
+      //style={{display:'inline-flex',justifyContent:'center',alignItems:'center',width:16,height:16,background:'#fff',borderRadius:4,border:'1px solid #DAE2F2',marginLeft:4,position:'relative',top:2}}
+      .copy {
+        display:none;
+      }
+      &:hover {
+        border-radius: 4px;
+        background: #F0F2F5;
+  
+        .copy {
+          display: inline-flex;
+          justify-content: center;
+          align-items: center;
+          width:16px;
+          height:16px;
+          background: #FFFFFF;
+          border-radius: 4px;
+          border-radius:4px;
+          border:1px solid #DAE2F2;
+          margin-left:4px;
+          position:relative;
+          top:2px;
+
+        }
+  
+        &::before {
+          border-radius: 4px;
+          background: #F0F2F5;
+        }
+      }
+    }
+    
+    
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode-selected {
+      &::before {
+        border-radius: 4px;
+        background: #F0F2F5;
+
+      }
+    }
+
+    .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode .kcmp-ant-tree-node-content-wrapper.kcmp-ant-tree-node-selected {
+      font-weight: bold;
+    }
+  }
+
+  .right {
+
+    width: calc(100% - 236px);
+    padding: 16px;
+    border-radius: 4px;
+    background: #FFFFFF;
+
+    .toolBar {
       display: flex;
       flex-direction: row;
-      justify-content: flex-start;
+      justify-content: space-between;
       align-items: center;
 
-      .filterItem {
+      .filter {
         display: flex;
         flex-direction: row;
-        justify-content: center;
+        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;
+      .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;
+        }
       }
-    }
 
+    }
   }
+
 }

+ 8 - 6
src/pages/platform/setting/reports/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-03-03 18:04:40
- * @LastEditTime: 2023-02-27 14:16:42
+ * @LastEditTime: 2023-05-30 15:46:46
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/reports/index.tsx
@@ -15,8 +15,8 @@ export default () => {
   const { initialState, setInitialState } = useModel('@@initialState');
   const [specialPageUrl, setspecialPageUrl] = useState<string | undefined>(undefined);
   const [loading, setloading] = useState(false);
+  const { pathname } = location;
 
-  console.log('reports');
 
   const onLoadhandle = () => {
     setloading(false);
@@ -24,6 +24,11 @@ export default () => {
 
   useEffect(() => {
     setloading(true);
+
+  }, [initialState]);
+
+  useEffect(()=>{
+    console.log({pathname});
     if (initialState && initialState.spacicalPageParamsType && initialState.userData) {
       const {
         spacicalPageParamsType,
@@ -42,10 +47,7 @@ export default () => {
         setspecialPageUrl(url);
       }
     }
-
-    console.log({specialPageUrl});
-
-  }, [initialState]);
+  },[pathname])
 
   return (
     <>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 460 - 438
src/pages/platform/setting/roleManage/index.tsx


+ 4 - 4
src/pages/platform/setting/roleManage/modals/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-03-17 16:33:16
+ * @LastEditTime: 2024-01-10 16:50:30
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/modal.tsx
@@ -13,7 +13,7 @@ import KCProSelect from '@/components/KCProSelect';
 import { roleManageModelState, Dispatch } from 'umi';
 
 import { ProFormText, ProFormTextArea } from '@ant-design/pro-form';
-import { getHospList } from '@/service/hospList';
+import { getHospList, getShareHospList } from '@/service/hospList';
 import { AddUsersDataType, getYoushuUsers } from '@/service/user';
 
 import { TableActType } from '..';
@@ -104,7 +104,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
 
       {tableAct == TableActType.EDITRELAUSER && (
         <Form.Item name="bindUserIds">
-          <UserEditer total={currentEdit?currentEdit.allUsers:[]} noAction={true} />
+          <UserEditer total={currentEdit ? currentEdit.allUsers : []} noAction={true} />
         </Form.Item>
       )}
 
@@ -116,7 +116,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             name="hospId"
             disabled
             request={async () => {
-              const hospList = await getHospList();
+              const hospList = await getShareHospList();
               if (hospList) {
                 return hospList.map((t) => ({
                   label: t.name,

+ 11 - 7
src/pages/platform/setting/roleManage/model.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2022-01-19 17:28:09
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2023-09-18 17:59:16
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/model.ts
  */
@@ -141,11 +141,15 @@ const roleManageModel: roleManageModelType = {
       return id;
     },
     *addEffect({ payload }, { put }) {
-      const { id } = yield getMainHosp();
-      yield put({
-        type: 'add',
-        payload: { hospId: id },
-      });
+      // const { id } = yield getMainHosp();
+      const currentHosp = localStorage.getItem('currentSelectedSubHop');
+      if(currentHosp){
+           const {id} = JSON.parse(currentHosp);
+           yield put({
+            type: 'add',
+            payload: { hospId: id },
+          });
+      }
     },
   },
   reducers: {

+ 212 - 0
src/pages/platform/setting/roleManage/style.less

@@ -1,3 +1,214 @@
+.setApiPermDrawer_roleMana {
+  .topbar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 16px;
+
+    .title {
+      height: 16px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #17181A;
+      line-height:16px;
+    }
+
+    .btnGroup {
+
+      .clearBtn {
+        cursor: pointer;
+        display: inline-block;
+        text-align: center;
+        width: 112px;
+        height: 24px;
+        line-height: 23px;
+        background: #FAFCFF;
+        border-radius: 4px;
+        border: 1px solid #DAE2F2;
+        font-size: 14px;
+        font-weight: 400;
+        color: #17181A;
+        margin-right: 8px;
+
+        &.disabled {
+          cursor: not-allowed;
+          color: #65676a;
+          background-color: #f5f5f5;
+        }
+      }
+      .cancel {
+        cursor: pointer;
+        display: inline-block;
+        text-align: center;
+        width: 56px;
+        height: 24px;
+        line-height: 23px;
+        background: #FAFCFF;
+        border-radius: 4px;
+        border: 1px solid #DAE2F2;
+        font-size: 14px;
+        font-weight: 400;
+        color: #17181A;
+        margin-right: 8px;
+      }
+
+      .save {
+        cursor: pointer;
+        display: inline-block;
+        width: 56px;
+        text-align: center;
+        height: 24px;
+        line-height: 23px;
+        background: #3377FF;
+        border-radius: 4px;
+        border: 1px solid #DAE2F2;
+        font-size: 14px;
+        font-weight: 400;
+        color: #fff;
+      }
+    }
+  }
+
+  .content {
+    overflow: hidden;
+    .leftTree {
+      width: 220px;
+      height:calc(100vh - 72px);
+      float: left;
+      background: #FFF;
+      border-radius: 4px;
+      overflow: hidden;
+      margin-right: 16px;
+      padding: 16px;
+      border: 1px solid #DAE2F2;
+   
+      .searchInput {
+        border: 1px solid #CFD7E6;
+      }
+
+
+      .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode-selected:hover::before,
+      .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode-selected::before {
+        border-radius: 4px;
+        background: #F0F2F5;
+      }
+
+      .kcmp-ant-tree.kcmp-ant-tree-directory .kcmp-ant-tree-treenode .kcmp-ant-tree-node-content-wrapper.kcmp-ant-tree-node-selected {
+        font-weight: bold;
+      }
+
+    }
+
+    .rightContent {
+      position: relative;
+      border-radius: 4px;
+      width: calc(100% - 236px);
+      // padding: 16px;
+      margin-left: 236px;
+      background: #FFF;
+
+      .checkBtn {
+        position: absolute;
+        cursor: pointer;
+        top: 0;
+        right: 0;
+        padding: 0 14px;
+        height: 24px;
+        line-height: 24px;
+        background: #3376FE;
+        border-radius: 4px;
+        text-align: center;
+        font-size: 14px;
+        font-weight: 400;
+        color: #FFF;
+      }
+
+      .midLine {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+        height: 24px;
+        line-height: 24px;
+        background: #F0FCFC;
+        font-size: 12px;
+        color: #515866;
+        font-weight: 400;
+        margin-top: 12px;
+        margin-bottom: 15px;
+
+        &>span {
+          cursor: pointer;
+          font-size: 12px;
+          font-weight: 500;
+          color: #00B3B3;
+          padding-right: 4px;
+        }
+
+      }
+
+      .kcmp-ant-tabs-nav {
+        &::before {
+          border-bottom: none !important;
+        }
+      }
+
+      .tableToolbar {
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 16px;
+
+        .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 {
+          &>span {
+            display: inline-block;
+            text-align: center;
+            width: 56px;
+            height: 24px;
+            line-height: 24px;
+            background: #3377FF;
+            color: #FFF;
+            border-radius: 4px;
+            cursor: pointer;
+          }
+        }
+      }
+      .tixiMenuSet {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
+        width: 100%;
+        height:calc(100vh - 72px);
+        .despcrip {
+          height: 14px;
+          line-height: 14px;
+          font-size: 14px;
+          color: #7A8599;
+          margin-top: 16px;
+          margin-bottom: 15px;
+        }
+      }
+    }
+  }
+}
+
 .RoleManage {
   height: auto;
   padding: 16px;
@@ -40,4 +251,5 @@
     }
 
   }
+ 
 }

+ 52 - 0
src/pages/platform/setting/static/index.tsx

@@ -0,0 +1,52 @@
+/*
+ * @Author: your name
+ * @Date: 2022-03-03 18:04:40
+ * @LastEditTime: 2023-08-08 14:45:58
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/reports/index.tsx
+ */
+
+import { useEffect, useState } from 'react';
+
+import { Skeleton } from 'antd';
+import { useModel } from 'umi';
+
+export default () => {
+  const { initialState, setInitialState } = useModel('@@initialState');
+  const [specialPageUrl, setspecialPageUrl] = useState<string | undefined>(undefined);
+  const [loading, setloading] = useState(false);
+
+  const onLoadhandle = () => {
+    setloading(false);
+  };
+
+  useEffect(() => {
+    setloading(true);
+    if (initialState && initialState.spacicalPageParamsType && initialState.userData) {
+      const {
+        spacicalPageParamsType,
+        userData: { youshuToken },
+      } = initialState;
+
+      console.log({ spacicalPageParamsType });
+
+      const { pathname } = location;
+      const spacialPage = spacicalPageParamsType.filter((t) => t.path == pathname);
+
+      if (spacialPage.length > 0) {
+        //当前页面属于有数数据展示页面
+        console.log(`${spacialPage[0].url}`);
+        const url = `${spacialPage[0].url}`;
+        setspecialPageUrl(url);
+      }
+    }
+  }, [initialState]);
+
+  return (
+    <>
+      <Skeleton loading={loading} paragraph={{ rows: 50 }} active />
+      <iframe onLoad={() => onLoadhandle()} style={{ width: '100%', height: '90vh', border: 'none' }} src={specialPageUrl}></iframe>
+    </>
+  );
+};

+ 663 - 716
src/pages/platform/setting/systemNavMana/index.tsx

@@ -1,18 +1,12 @@
-
-
 /*
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-16 09:42:52
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-23 17:33:53
+ * @LastEditTime: 2023-11-10 10:25:38
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
-
 import { useEffect, useImperativeHandle, useRef, useState } from 'react';
 import './style.less';
 
@@ -24,7 +18,7 @@ import closeIcon from '../../../../../public/images/treenode_collapse.png';
 import type { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
 
 import { createFromIconfontCN } from '@ant-design/icons';
-import { addData, delData, editData, getMenuRelaActDic, getTableDataRequest, getTreeData, getTreeDataRespType, updateFuncDic } from './service';
+import { addData, delData, editData, getMenuContentType, getMenuRelaActDic, getTableDataRequest, getTreeData, getTreeDataRespType, updateFuncDic } from './service';
 import { TransferDirection, TransferItem } from 'antd/es/transfer';
 
 import difference from 'lodash/difference';
@@ -37,759 +31,712 @@ import DirectoryTree from 'antd/es/tree/DirectoryTree';
 import { ActionType, ProColumns } from '@ant-design/pro-table';
 import KCTable from '@/components/kcTable';
 import { getDeepestTreeData } from '@/utils';
-import ProForm, { ModalForm, ProFormDependency, ProFormDigit, ProFormItem, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+import ProForm, { ModalForm, ProFormDependency, ProFormDigit, ProFormInstance, ProFormItem, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
 import { KCInput } from '@/components/KCInput';
 import { UserRelaSeletDataListType } from '@/service/user';
 
-
-
 const IconFont = createFromIconfontCN({
-    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+  scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
 });
 
 const SearchIcon = createFromIconfontCN({
-    scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+  scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
 });
 
-
-
-
-
 export type TableListItem = {
-    key: number;
-    name: string;
+  key: number;
+  name: string;
 };
 
-
 const MonthlyInfoCheck: React.FC = () => {
-
-    const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
-    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
-
-    const [reload, set_reload] = useState(false);
-
-    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
-
-    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
-    const [searchValue, setSearchValue] = useState('');
-    const [autoExpandParent, setAutoExpandParent] = useState(true);
-    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
-
-    const [currentOperateRow, set_currentOperateRow] = useState<any | undefined>(undefined);  //当前操作的表格行数据
-
-
-    const tableRef = useRef<ActionType>();
-
-
-    const transferTableColumn = [
-        {
-            title: '功能名称',
-            dataIndex: 'name',
-            key: 'name',
-
-        },
-        {
-            title: '功能代码',
-            dataIndex: 'code',
-            key: 'code',
-
-        },
-    ];
-
-
-    const columns = [
-        {
-            title: '名称',
-            dataIndex: 'name',
-            key: 'name',
-
-        },
-        {
-            title: '类型',
-            dataIndex: 'contentType',
-            key: 'contentType',
-            render: (_: any, record: any) => {
-                //console.log({ record });
-                switch (record.type) {
-                    case 0:
-                        return '目录'
-                    case 1:
-                        return '菜单'
-                    case 2:
-                        return 'api'
-                    case 3:
-                        return '系统'
-                    case 4:
-                        return '有数bi'
-                    case 5:
-                        return '体系'
-                    case 6:
-                        return '中心层'
-                    case 7:
-                        return '平台层'
-                    default:
-                        break;
-                }
-            },
-        },
-        {
-            title: 'Path',
-            dataIndex: 'path',
-            key: 'path',
-
-        },
-        {
-            title: '内容',
-            dataIndex: 'contentType',
-            key: 'contentType',
-            valueEnum: {
-                0: '一般',
-                1: '报告',
-                2: '大屏',
-                3: '填报',
-                4: '空白'
-            }
-
-        },
-        {
-            title: '功能',
-            dataIndex: 'deptName',
-            key: 'deptName',
-            render: (_: any, record: any) => {
-                if (record.functionList) {
-                    return record.functionList.reduce((prev: any, cur: any) => {
-                        return `${prev ? prev + ' | ' : prev}${cur.name}`
-                    }, '')
-                }
-                return '-'
-            }
-
-        },
-        {
-            title: '操作',
-            key: 'option',
-            width: 120,
-            fixed: 'right',
-            valueType: 'option',
-            render: (_: any, record: any) => {
-                return record.type != 1 && record.type != 2 && record.type != 4 ? [
-                    <UpDataActBtn key={'add'} record={record} type='ADD' />,
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delMenuHandle(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ] : [
-                    <a key={'fuc'} onClick={() => addFuncHandle(record)}>功能</a>,
-                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
-                    <Popconfirm
-                        title="是否确认删除?"
-                        key="del"
-                        onConfirm={() => delMenuHandle(record)}
-                    >
-                        <a>删除</a>
-                    </Popconfirm>
-                ]
-            },
-        },
-    ]
-
-
-    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
-        //console.log('selected', selectedKeys, info);
-        const { node } = info;
-        set_currentSelectedTreeNode(node);
-    };
-
-
-    const getTableData = async (params: any, sort: any, filter: any) => {
-        set_reload(false);
-        if (currentSelectedTreeNode) {
-            const resp = await getTableDataRequest(params);
-            if (resp) {
-                return {
-                    data: resp,
-                    success: true,
-                }
-            }
-            return {
-                data: [],
-                success: true
-            }
+  const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
+  const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+
+  const [reload, set_reload] = useState(false);
+
+  const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+
+  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+  const [searchValue, setSearchValue] = useState('');
+  const [autoExpandParent, setAutoExpandParent] = useState(true);
+  const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+
+  const [currentOperateRow, set_currentOperateRow] = useState<any | undefined>(undefined); //当前操作的表格行数据
+
+  const [contentType, set_contentType] = useState<any[]>([]); //菜单内容类型列表
+
+  const tableRef = useRef<ActionType>();
+
+  const formRef = useRef<ProFormInstance>();
+
+  const transferTableColumn = [
+    {
+      title: '功能名称',
+      dataIndex: 'name',
+      key: 'name',
+    },
+    {
+      title: '功能代码',
+      dataIndex: 'code',
+      key: 'code',
+    },
+  ];
+
+  const columns: ProColumns[] = [
+    {
+      title: '名称',
+      dataIndex: 'name',
+      key: 'name',
+      ellipsis: true,
+    },
+    {
+      title: '类型',
+      dataIndex: 'contentType',
+      key: 'contentType',
+      width: 100,
+      render: (_: any, record: any) => {
+        //console.log({ record });
+        switch (record.type) {
+          case 0:
+            return '目录';
+          case 1:
+            return '菜单';
+          case 2:
+            return 'api';
+          case 3:
+            return '系统';
+          case 4:
+            return '有数bi';
+          case 5:
+            return '体系';
+          case 6:
+            return '中心层';
+          case 7:
+            return '平台层';
+          default:
+            break;
         }
-
-        return []
-    }
-
-    const addFuncHandle = (record: any) => {
-        set_currentOperateRow(record);
-        const ref = React.createRef<{ save: any; }>();
-
-        Modal.confirm({
-            title: '菜单功能设置(核算单元管理)',
-            icon: '',
-            width: 672,
-            content: <TableTransfer
-                ref={ref}
-                record={record}
-                leftColumns={transferTableColumn}
-                rightColumns={transferTableColumn} dataSource={[]}
-            ></TableTransfer>,
-            onOk: () => {
-                return ref.current && ref.current.save();
-            }
-        })
-    }
-
-
-    const delMenuHandle = async (record: any) => {
-        const resp = await delData(record.menuId);
-        resp && set_reload(true);
-    }
-
-    interface DataType {
-        key: string;
-        title: string;
-        description: string;
-        disabled: boolean;
-        tag: string;
-    }
-
-    interface TableTransferProps extends TransferProps<TransferItem> {
-        dataSource: DataType[];
-        leftColumns: ColumnsType<DataType>;
-        rightColumns: ColumnsType<DataType>;
-        record: any
-    }
-
-    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record, ...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 getMenuRelaActDic();
-            if (resp) {
-
-                set_datasource(resp);
-
-                if (record && record.functionList) {
-
-                    const defaultSelctedkeys = record.functionList.map((item: any) => item.code);
-
-                    setTargetKeys(defaultSelctedkeys);
-                }
-
-            }
+      },
+    },
+    {
+      title: 'Path',
+      width: 300,
+      dataIndex: 'path',
+      key: 'path',
+      ellipsis: true,
+    },
+    {
+      title: '内容',
+      dataIndex: 'contentType',
+      key: 'contentType',
+      width: 100,
+      valueEnum: {
+        0: '一般',
+        1: '报告',
+        2: '大屏',
+        3: '填报',
+        4: '空白',
+        5: '静态',
+        6: '外部系统嵌入',
+      },
+    },
+    {
+      title: '功能',
+      dataIndex: 'deptName',
+      key: 'deptName',
+      render: (_: any, record: any) => {
+        if (record.functionList) {
+          return record.functionList.reduce((prev: any, cur: any) => {
+            return `${prev ? prev + ' | ' : prev}${cur.name}`;
+          }, '');
         }
-
-        const onChange = (nextTargetKeys: string[]) => {
-            setTargetKeys(nextTargetKeys);
-        };
-
-        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
-            //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
-            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        return '-';
+      },
+    },
+    {
+      title: '操作',
+      key: 'option',
+      width: 120,
+      fixed: 'right',
+      valueType: 'option',
+      render: (_: any, record: any) => {
+        return record.type != 1 && record.type != 2 && record.type != 4
+          ? [
+              <UpDataActBtn key={'add'} record={record} type="ADD" />,
+              <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+              <Popconfirm title="是否确认删除?" key="del" onConfirm={() => delMenuHandle(record)}>
+                <a>删除</a>
+              </Popconfirm>,
+            ]
+          : [
+              <a key={'fuc'} onClick={() => addFuncHandle(record)}>
+                功能
+              </a>,
+              <UpDataActBtn key={'act'} record={record} type="EDIT" />,
+              <Popconfirm title="是否确认删除?" key="del" onConfirm={() => delMenuHandle(record)}>
+                <a>删除</a>
+              </Popconfirm>,
+            ];
+      },
+    },
+  ];
+
+  const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+    //console.log('selected', selectedKeys, info);
+    const { node } = info;
+    set_currentSelectedTreeNode(node);
+  };
+
+  const getContentType = async () => {
+    const currentSelectedTab = localStorage.getItem('currentSelectedTab');
+    const { systemId } = JSON.parse(currentSelectedTab as string);
+    const resp = await getMenuContentType(systemId);
+    if (resp) {
+      set_contentType(resp.list);
+    }
+  };
+
+  const getTableData = async (params: any, sort: any, filter: any) => {
+    set_reload(false);
+    if (currentSelectedTreeNode) {
+      const resp = await getTableDataRequest(params);
+      if (resp) {
+        return {
+          data: resp,
+          success: true,
         };
+      }
+      return {
+        data: [],
+        success: true,
+      };
+    }
 
-        useImperativeHandle(ref, () => ({
-            save: async () => {
-
-                const data = datasource.filter(item => targetKeys.includes(item.code));
-
-                const resp = await updateFuncDic({
-                    menuId: record.menuId,
-                    function: data
-                });
-                if (resp) {
-                    set_reload(true);
-                }
-            }
-        }));
-
-        useEffect(() => {
-            getFuncList();
-        }, [])
-
-        return (
-            <Transfer className='TableTransfer' showSearch
-                titles={['待选项目', '已选项目']}
-                locale={{
-                    itemUnit: '项',
-                    itemsUnit: '项',
-                    searchPlaceholder: '请输入'
-                }}
-                onChange={onChange}
-                onSelectChange={onSelectChange}
-                dataSource={datasource}
-                rowKey={record => record.code}
-                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(({ code }) => code);
-                            const diffKeys = selected
-                                ? difference(treeSelectedKeys, listSelectedKeys)
-                                : difference(listSelectedKeys, treeSelectedKeys);
-                            onItemSelectAll(diffKeys as string[], selected);
-                        },
-                        onSelect({ code }, selected) {
-                            onItemSelect(code as string, selected);
-                        },
-                        selectedRowKeys: listSelectedKeys,
-                    };
-
-                    return (
-                        <Table
-                            rowSelection={rowSelection}
-                            columns={columns as TransferItem[]}
-                            dataSource={filteredItems}
-                            size="small"
-                            rowKey={'code'}
-                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
-                            onRow={({ code, disabled: itemDisabled }) => ({
-                                onClick: () => {
-                                    if (itemDisabled || listDisabled) return;
-                                    onItemSelect(code as string, !listSelectedKeys.includes(code as string));
-                                },
-                            })}
-                        />
-                    );
-                }}
-            </Transfer>
-        )
-    })
-
-
-
-
-    const dataList: any[] = [];
-
-    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
-        let parentKey: React.Key;
-        for (let i = 0; i < tree.length; i++) {
-            const node = tree[i];
-            if (node.children) {
-                if (node.children.some((item: { code: React.Key; }) => item.code === key)) {
-                    parentKey = node.code;
-                } else if (getParentKey(key, node.children)) {
-                    parentKey = getParentKey(key, node.children);
-                }
-            }
+    return [];
+  };
+
+  const addFuncHandle = (record: any) => {
+    set_currentOperateRow(record);
+    const ref = React.createRef<{ save: any }>();
+
+    Modal.confirm({
+      title: '菜单功能设置(核算单元管理)',
+      icon: '',
+      width: 672,
+      okText: '确定',
+      cancelText: '取消',
+      content: <TableTransfer ref={ref} record={record} leftColumns={transferTableColumn} rightColumns={transferTableColumn} dataSource={[]}></TableTransfer>,
+      onOk: () => {
+        return ref.current && ref.current.save();
+      },
+    });
+  };
+
+  const delMenuHandle = async (record: any) => {
+    const resp = await delData(record.menuId);
+    resp && set_reload(true);
+  };
+
+  interface DataType {
+    key: string;
+    title: string;
+    description: string;
+    disabled: boolean;
+    tag: string;
+  }
+
+  interface TableTransferProps extends TransferProps<TransferItem> {
+    dataSource: DataType[];
+    leftColumns: ColumnsType<DataType>;
+    rightColumns: ColumnsType<DataType>;
+    record: any;
+  }
+
+  const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record, ...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 getMenuRelaActDic();
+      if (resp) {
+        set_datasource(resp);
+
+        if (record && record.functionList) {
+          const defaultSelctedkeys = record.functionList.map((item: any) => item.code);
+
+          setTargetKeys(defaultSelctedkeys);
         }
-        return parentKey!;
+      }
     };
 
-
-    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-
-        const { value } = e.target;
-        const newExpandedKeys = dataList
-            .map((item) => {
-                if (item.name.indexOf(value) > -1) {
-                    return getParentKey(item.code, treeData);
-                }
-                return null;
-            });
-
-        const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
-
-        setExpandedKeys(newExpandedKeys as React.Key[]);
-        setSearchValue(value);
-        setAutoExpandParent(true);
-    }
-
-
-    const onExpand = (newExpandedKeys: React.Key[]) => {
-        setExpandedKeys(newExpandedKeys);
-        setAutoExpandParent(false);
+    const onChange = (nextTargetKeys: string[]) => {
+      setTargetKeys(nextTargetKeys);
     };
 
-    const generateList = (data: getTreeDataRespType[]) => {
-        for (let i = 0; i < data.length; i++) {
-            const node = data[i];
-            const { code, name } = node;
-            dataList.push({ code, name: name });
-            if (node.children) {
-                generateList(node.children);
-            }
-        }
+    const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+      //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+      setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
     };
-    generateList(treeData as any);
-
-
-    const getTreeReqFunc = async (name?: string) => {
-        const resp = await getTreeData();
-        set_treeData(resp);
-    }
-
-    const tableDataSearchHandle = (paramName: string) => {
-
-
-        set_tableDataFilterParams({
-            ...tableDataFilterParams,
-            [`${paramName}`]: tableDataSearchKeywords
-        })
-    }
-
-
-    const updateTable = async (type: 'EDIT' | "ADD", formVal: any, record: any) => {
-
 
+    useImperativeHandle(ref, () => ({
+      save: async () => {
+        const data = datasource.filter((item) => targetKeys.includes(item.code));
 
-        if (type == 'ADD') {
-            let data = undefined;
-            if (record) {
-                //添加操作
-                data = { ...formVal, parentId: record.menuId, systemId: record.systemId }
-            } else {
-                //新增
-                data = { ...formVal, parentId: currentSelectedTreeNode.code, systemId: currentSelectedTreeNode.code }
-            }
-
-            const resp = await addData({ ...data });
-
-            if (resp) {
-                set_reload(true);
-            }
+        const resp = await updateFuncDic({
+          menuId: record.menuId,
+          function: data,
+        });
+        if (resp) {
+          set_reload(true);
         }
-        if (type == 'EDIT') {
+      },
+    }));
 
-            const resp = await editData({ ...record, ...formVal });
-            if (resp) {
-                set_reload(true);
-            }
-        }
-
-        set_currentOperateRow(undefined);
+    useEffect(() => {
+      getFuncList();
+    }, []);
 
-        return true
+    return (
+      <Transfer
+        className="TableTransfer"
+        showSearch
+        titles={['待选项目', '已选项目']}
+        locale={{
+          itemUnit: '项',
+          itemsUnit: '项',
+          searchPlaceholder: '请输入',
+        }}
+        onChange={onChange}
+        onSelectChange={onSelectChange}
+        dataSource={datasource}
+        rowKey={(record) => record.code}
+        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(({ code }) => code);
+              const diffKeys = selected ? difference(treeSelectedKeys, listSelectedKeys) : difference(listSelectedKeys, treeSelectedKeys);
+              onItemSelectAll(diffKeys as string[], selected);
+            },
+            onSelect({ code }, selected) {
+              onItemSelect(code as string, selected);
+            },
+            selectedRowKeys: listSelectedKeys,
+          };
+
+          return (
+            <Table
+              rowSelection={rowSelection}
+              columns={columns as TransferItem[]}
+              dataSource={filteredItems}
+              size="small"
+              rowKey={'code'}
+              style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+              onRow={({ code, disabled: itemDisabled }) => ({
+                onClick: () => {
+                  if (itemDisabled || listDisabled) return;
+                  onItemSelect(code as string, !listSelectedKeys.includes(code as string));
+                },
+              })}
+            />
+          );
+        }}
+      </Transfer>
+    );
+  });
+
+  const dataList: any[] = [];
+
+  const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+    let parentKey: React.Key;
+    for (let i = 0; i < tree.length; i++) {
+      const node = tree[i];
+      if (node.children) {
+        if (node.children.some((item: { code: React.Key }) => item.code === key)) {
+          parentKey = node.code;
+        } else if (getParentKey(key, node.children)) {
+          parentKey = getParentKey(key, node.children);
+        }
+      }
+    }
+    return parentKey!;
+  };
+
+  const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    const { value } = e.target;
+    const newExpandedKeys = dataList.map((item) => {
+      if (item.name.indexOf(value) > -1) {
+        return getParentKey(item.code, treeData);
+      }
+      return null;
+    });
+
+    const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+
+    setExpandedKeys(newExpandedKeys as React.Key[]);
+    setSearchValue(value);
+    setAutoExpandParent(true);
+  };
+
+  const onExpand = (newExpandedKeys: React.Key[]) => {
+    setExpandedKeys(newExpandedKeys);
+    setAutoExpandParent(false);
+  };
+
+  const generateList = (data: getTreeDataRespType[]) => {
+    for (let i = 0; i < data.length; i++) {
+      const node = data[i];
+      const { code, name } = node;
+      dataList.push({ code, name: name });
+      if (node.children) {
+        generateList(node.children);
+      }
+    }
+  };
+  generateList(treeData as any);
+
+  const getTreeReqFunc = async (name?: string) => {
+    const resp = await getTreeData();
+    set_treeData(resp);
+  };
+
+  const tableDataSearchHandle = (paramName: string) => {
+    set_tableDataFilterParams({
+      ...tableDataFilterParams,
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
+
+  const updateTable = async (type: 'EDIT' | 'ADD', formVal: any, record: any) => {
+    if (type == 'ADD') {
+      let data = undefined;
+      if (record) {
+        //添加操作
+        data = { ...formVal, parentId: record.menuId, systemId: record.systemId };
+      } else {
+        //新增
+        data = { ...formVal, parentId: currentSelectedTreeNode.code, systemId: currentSelectedTreeNode.code };
+      }
+
+      const resp = await addData({ ...data });
+
+      if (resp) {
+        set_reload(true);
+      }
+    }
+    if (type == 'EDIT') {
+      const resp = await editData({ ...record, ...formVal });
+      if (resp) {
+        set_reload(true);
+      }
     }
 
+    set_currentOperateRow(undefined);
 
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-
-        return (
-
-            <ModalForm
-                className='systemNavManaForm'
-                title={`${type == 'EDIT' ? '编辑' : '新增'}菜单`}
-                width={688}
-                initialValues={type == 'EDIT' ? { ...record } : { isHomepage: 0 }}
-                trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : record ? <a className='add'>添加</a> : <span>新增</span>
-                }
-                grid={true}
-
-                onFinish={(val) => {
-                    set_currentOperateRow(record);
-
-                    return updateTable(type, val, record)
+    return true;
+  };
 
-                }}
-            >
-                <ProFormText
-                    name="name"
-                    label="名称:"
-                    placeholder="请输入"
-                    colProps={{ span: 12 }}
-                    rules={[{ required: true, message: '名称不能为空!' }]}
-                />
-                <ProFormSelect
-                    name="type"
-                    label="类型:"
-                    placeholder="请输入"
-                    colProps={{ span: 12 }}
-                    options={[
-                        {
-                            label: '目录',
-                            value: 0
-                        },
-                        {
-                            label: '菜单',
-                            value: 2
-                        }
-                    ]}
-                    rules={[{ required: true, message: '类型不能为空!' }]}
-                />
-                <ProFormText
-                    name="path"
-                    label="Path:"
-                    placeholder="请输入"
-                    colProps={{ span: 12 }}
-                    rules={[{ required: true, message: 'Path不能为空!' }]}
-                />
-                <ProFormText
-                    name="icon"
-                    label="icon:"
-                    placeholder="请输入"
-                    colProps={{ span: 12 }}
-                //rules={[{ required: true, message: '类型代码不能为空!' }]}
-                />
-                <ProFormDigit
-                    name="orderNum"
-                    label="顺序号:"
-                    width={'xs'}
-                    placeholder="请输入"
-                    colProps={{ span: 12 }}
+  const UpDataActBtn = ({ record, type }: { record: any; type: 'EDIT' | 'ADD' }) => {
+    return (
+      <ModalForm
+        className="systemNavManaForm"
+        title={`${type == 'EDIT' ? '编辑' : '新增'}菜单`}
+        width={688}
+        initialValues={type == 'EDIT' ? { ...record } : { isHomepage: 0 }}
+        trigger={type == 'EDIT' ? <a key="edit">编辑</a> : record ? <a className="add">添加</a> : <span>新增</span>}
+        formRef={formRef}
+        grid={true}
+        onFinish={(val) => {
+          set_currentOperateRow(record);
+          return updateTable(type, val, record);
+        }}
+      >
+        <ProFormText name="name" label="名称:" placeholder="请输入" colProps={{ span: 12 }} rules={[{ required: true, message: '名称不能为空!' }]} />
+        <ProFormSelect
+          name="type"
+          label="类型:"
+          placeholder="请输入"
+          colProps={{ span: 12 }}
+          options={[
+            {
+              label: '目录',
+              value: 0,
+            },
+            {
+              label: '菜单',
+              value: 1,
+            },
+          ]}
+          rules={[{ required: true, message: '类型不能为空!' }]}
+        />
+        <ProFormText name="path" label="Path:" placeholder="请输入" colProps={{ span: 12 }} rules={[{ required: true, message: 'Path不能为空!' }]} />
+        <ProFormText
+          name="icon"
+          label="icon:"
+          placeholder="请输入"
+          colProps={{ span: 12 }}
+          //rules={[{ required: true, message: '类型代码不能为空!' }]}
+        />
+        <ProFormDigit
+          name="orderNum"
+          label="顺序号:"
+          width={'xs'}
+          placeholder="请输入"
+          colProps={{ span: 12 }}
+          //rules={[{ required: true, message: '类型代码不能为空!' }]}
+        />
+        <ProFormDependency name={['type']}>
+          {({ type }) =>
+            type == 1 && (
+              <ProFormRadio.Group
+                name="isHomepage"
+                label="是否首页:"
+                width={'xs'}
+                placeholder="请选择"
+                colProps={{ span: 12 }}
+                rules={[{ required: true, message: '是否为首页不能为空!' }]}
+                options={[
+                  {
+                    label: '是',
+                    value: 1,
+                  },
+                  {
+                    label: '否',
+                    value: 0,
+                  },
+                ]}
                 //rules={[{ required: true, message: '类型代码不能为空!' }]}
-                />
-                <ProFormDependency name={['type']}>
-                    {
-                        ({ type }) => type == 2 && (
-                            <ProFormRadio.Group
-                                name="isHomepage"
-                                label="是否首页:"
-                                width={'xs'}
-                                placeholder="请选择"
-                                colProps={{ span: 12 }}
-                                rules={[{ required: true, message: '是否为首页不能为空!' }]}
-                                options={[
-                                    {
-                                        label: '是',
-                                        value: 1,
-                                    },
-                                    {
-                                        label: '否',
-                                        value: 0,
-                                    },
-                                ]}
-                            //rules={[{ required: true, message: '类型代码不能为空!' }]}
-                            />
-                        )
-                    }
-                </ProFormDependency>
-
-                <ProFormDependency name={['type']}>
-                    {
-                        ({ type }) => type == 2 && (
-                            <ProForm.Group colProps={{ span: 12 }} align='start'>
-                                <ProFormSelect
-                                    name="contentType"
-                                    label="内容类型:"
-                                    placeholder="请输入"
-                                    width={100}
-                                    colProps={{ span: 8 }}
-                                    options={[
-                                        { label: '一般', value: 0 },
-                                        { label: '报告', value: 1 },
-                                        { label: '大屏', value: 2 },
-                                        { label: '填报', value: 3 },
-                                        { label: '空白', value: 4 },
-                                    ]}
-                                    rules={[{ required: true, message: '类型不能为空!' }]}
-                                />
-                                <ProFormDependency name={['contentType']}>
-                                    {
-                                        ({ contentType }) => {
-                                            return contentType == 1 && (
-                                                <div style={{ position: 'relative', top: 24 }}>
-                                                    <ProFormText
-                                                        noStyle
-                                                        width={210}
-                                                        className='reportId'
-                                                        name="reportId"
-                                                        placeholder="请输入报告Id"
-                                                        colProps={{ span: 16 }}
-                                                    //rules={[{ required: true, message: '类型代码不能为空!' }]}
-                                                    />
-                                                </div>
-                                            )
-                                        }
-                                    }
-                                </ProFormDependency>
-                            </ProForm.Group>
-                        )
+              />
+            )
+          }
+        </ProFormDependency>
+
+        <ProFormDependency name={['type']}>
+          {({ type }) =>
+            type == 1 && (
+              <ProForm.Group colProps={{ span: 12 }} align="start">
+                <ProFormSelect
+                  name="contentType"
+                  label="内容类型:"
+                  placeholder="请输入"
+                  width={100}
+                  colProps={{ span: 8 }}
+                  request={async () => {
+                    if (contentType) {
+                      return contentType.map((a: any) => ({ label: a.name, value: Number(a.code) }));
                     }
-                </ProFormDependency>
-
-                <ProFormDependency name={['type']}>
-                    {
-                        ({ type }) => type == 2 && (
-                            <ProFormText
-                                name="url"
-                                label="URL:"
-                                placeholder="请输入"
-                                colProps={{ span: 12 }}
+                    return [];
+                  }}
+                  fieldProps={{
+                    onChange(value, option) {
+                      if (value == 1) {
+                        //报告页面
+                        const need = contentType.filter((item: any) => item.code == `${value}`);
+                        if (need.length > 0) formRef.current?.setFieldValue('url', need[0].value);
+                      }
+                    },
+                  }}
+                  // options={[
+                  //     { label: '一般', value: 0 },
+                  //     { label: '报告', value: 1 },
+                  //     { label: '大屏', value: 2 },
+                  //     { label: '填报', value: 3 },
+                  //     { label: '空白', value: 4 },
+                  //     { label: '静态', value: 5 },
+                  // ]}
+                  rules={[{ required: true, message: '类型不能为空!' }]}
+                />
+                <ProFormDependency name={['contentType']}>
+                  {({ contentType }) => {
+                    return (
+                      contentType == 1 && (
+                        <div style={{ position: 'relative', top: 24 }}>
+                          <ProFormText
+                            noStyle
+                            width={210}
+                            className="reportId"
+                            name="reportId"
+                            placeholder="请输入报告Id"
+                            colProps={{ span: 16 }}
                             //rules={[{ required: true, message: '类型代码不能为空!' }]}
-                            />
-                        )
-                    }
+                          />
+                        </div>
+                      )
+                    );
+                  }}
                 </ProFormDependency>
+              </ProForm.Group>
+            )
+          }
+        </ProFormDependency>
+
+        <ProFormDependency name={['type']}>
+          {({ type }) =>
+            type == 1 && (
+              <ProFormText
+                name="url"
+                label="URL:"
+                placeholder="请输入"
+                colProps={{ span: 12 }}
+                //rules={[{ required: true, message: '类型代码不能为空!' }]}
+              />
+            )
+          }
+        </ProFormDependency>
 
+        <ProFormTextArea name="description" label="描述:" placeholder="请输入" colProps={{ span: 24 }} />
+      </ModalForm>
+    );
+  };
 
-                <ProFormTextArea
-                    name="description"
-                    label="描述:"
-                    placeholder="请输入"
-                    colProps={{ span: 24 }}
-
-                />
-
-            </ModalForm>
-        )
+  useEffect(() => {
+    if (currentSelectedTreeNode) {
+      set_tableDataFilterParams({ ...tableDataFilterParams, systemId: currentSelectedTreeNode.code });
     }
+  }, [currentSelectedTreeNode]);
 
+  useEffect(() => {
+    //初始化左侧树结构数据后
 
+    if (treeData?.length > 0) {
+      if (treeData[0].children && treeData[0].children.length > 0) {
+        const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
 
-    useEffect(() => {
-        if (currentSelectedTreeNode) {
-            set_tableDataFilterParams({ ...tableDataFilterParams, systemId: currentSelectedTreeNode.code })
-        }
-
-    }, [currentSelectedTreeNode]);
-
-
-    useEffect(() => {
-        //初始化左侧树结构数据后
-
-        if (treeData?.length > 0) {
-
-            if (treeData[0].children && treeData[0].children.length > 0) {
-                const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
-
-                set_currentSelectedTreeNode(node);
-                setExpandedKeys([nodeParent.code]);
-            }
-        }
-    }, [treeData]);
-
-
-
-
-    useEffect(() => {
-        getTreeReqFunc();
-    }, []);
-
-
-    return (
-        <div className='SystemNavMana'>
-            <div className='leftTree'>
-                <div className='search'>
-                    <Input
-                        className='searchInput'
-                        placeholder="请输入"
-                        size='small'
-                        allowClear
-
-                        style={{ marginBottom: 16 }}
-                        onChange={onTreeSearchKeyChange}
-                        suffix={
-                            <SearchIcon type='iconsousuo' />
-                        }
-                    />
+        set_currentSelectedTreeNode(node);
+        setExpandedKeys([nodeParent.code]);
+      }
+    }
+  }, [treeData]);
+
+  useEffect(() => {
+    getTreeReqFunc();
+    getContentType();
+  }, []);
+
+  return (
+    <div className="SystemNavMana">
+      <div className="leftTree">
+        <div className="search">
+          <Input className="searchInput" placeholder="请输入" size="small" allowClear style={{ marginBottom: 16 }} onChange={onTreeSearchKeyChange} suffix={<SearchIcon type="iconsousuo" />} />
+        </div>
+        {treeData && treeData.length > 0 && (
+          <DirectoryTree
+            fieldNames={{ title: 'name', key: 'code' }}
+            rootStyle={{ overflowY: 'scroll', overflowX: 'hidden' }}
+            onSelect={onSelect}
+            onExpand={onExpand}
+            expandedKeys={expandedKeys}
+            autoExpandParent={autoExpandParent}
+            selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.code] : []}
+            blockNode={true}
+            icon={() => null}
+            titleRender={(nodeData: any) => {
+              const strTitle = nodeData.name as string;
+              const index = strTitle.indexOf(searchValue);
+              const beforeStr = strTitle.substring(0, index);
+              const afterStr = strTitle.slice(index + searchValue.length);
+              const title =
+                index > -1 ? (
+                  <span>
+                    {beforeStr}
+                    <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
+                      {searchValue}
+                    </span>
+                    {afterStr}
+                  </span>
+                ) : (
+                  <span className="strTitle">{strTitle}</span>
+                );
+              return (
+                <div
+                  style={{
+                    display: 'flex',
+                    flexDirection: 'row',
+                    width: '100%',
+                    justifyContent: 'flex-start',
+                    alignItems: 'center',
+                    height: 32,
+                    borderRadius: '4px',
+                    overflow: 'hidden',
+                    color: '#17181A',
+                    textOverflow: 'ellipsis',
+                    whiteSpace: 'nowrap',
+                  }}
+                >
+                  {title}
                 </div>
-                {
-                    treeData && treeData.length > 0 && (
-                        <DirectoryTree
-                            fieldNames={{ title: 'name', key: 'code' }}
-                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
-                            onSelect={onSelect}
-                            onExpand={onExpand}
-                            expandedKeys={expandedKeys}
-                            autoExpandParent={autoExpandParent}
-                            selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.code] : []}
-                            blockNode={true}
-                            icon={() => null}
-                            titleRender={
-                                (nodeData: any) => {
-
-                                    const strTitle = nodeData.name as string;
-                                    const index = strTitle.indexOf(searchValue);
-                                    const beforeStr = strTitle.substring(0, index);
-                                    const afterStr = strTitle.slice(index + searchValue.length);
-                                    const title =
-                                        index > -1 ? (
-                                            <span>
-                                                {beforeStr}
-                                                <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
-                                                {afterStr}
-                                            </span>
-                                        ) : (
-                                            <span className='strTitle'>{strTitle}</span>
-                                        );
-                                    return <div style={{
-                                        display: 'flex', flexDirection: 'row',
-                                        width: '100%',
-                                        justifyContent: 'flex-start', alignItems: 'center', height: 32,
-                                        borderRadius: '4px',
-                                        overflow: 'hidden',
-                                        color: '#17181A',
-                                        textOverflow: 'ellipsis',
-                                        whiteSpace: 'nowrap'
-
-                                    }}>{title}</div>
-                                }
-                            }
-                            defaultSelectedKeys={[treeData[0].children[0].code]}
-                            treeData={treeData as unknown as DataNode[]}
-                            // treeData={treeDataNew}
-                            switcherIcon={(props: any) => {
-                                const { expanded } = props;
-                                //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
-                                return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
-                            }}
-                        />
-                    )
-                }
+              );
+            }}
+            defaultSelectedKeys={[treeData[0].children[0].code]}
+            treeData={treeData as unknown as DataNode[]}
+            // treeData={treeDataNew}
+            switcherIcon={(props: any) => {
+              const { expanded } = props;
+              //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
+              return !expanded ? (
+                <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} />
+              ) : (
+                <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+              );
+            }}
+          />
+        )}
+      </div>
+      {/* <div style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
+      <div className="rightContent">
+        <div className="tableToolbar">
+          <div className="filter">
+            <div className="filterItem">
+              <span className="label">检索:</span>
+              <KCInput
+                placeholder={'请输入菜单名称'}
+                style={{ width: 160 }}
+                search
+                allowClear
+                onChange={(e) => {
+                  set_tableDataSearchKeywords(e.target.value);
+                  if (e.target.value.length == 0) {
+                    set_tableDataFilterParams({
+                      ...tableDataFilterParams,
+                      name: '',
+                    });
+                  }
+                }}
+                onSearch={() => tableDataSearchHandle('name')}
+              />
             </div>
-            {/* <div style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
-            <div className='rightContent'>
-                <div className='tableToolbar'>
-                    <div className='filter'>
-                        <div className='filterItem'>
-                            <span className='label'>检索:</span>
-                            <KCInput placeholder={'请输入菜单名称'} style={{ width: 160 }} search allowClear
-                                onChange={(e) => {
-                                    set_tableDataSearchKeywords(e.target.value);
-                                    if (e.target.value.length == 0) {
-                                        set_tableDataFilterParams({
-                                            ...tableDataFilterParams,
-                                            name: ''
-                                        });
-                                    }
-                                }}
-                                onSearch={() => tableDataSearchHandle('name')}
-
-                            />
-                        </div>
-                    </div>
+          </div>
 
-                    <div className={'btnGroup'}>
-                        <UpDataActBtn key={'act'} record={undefined} type='ADD' />
-                    </div>
-
-                </div>
-                {currentSelectedTreeNode && <KCTable pagination={false} reload={reload} newVer params={tableDataFilterParams} rowKey='menuId' columns={columns as ProColumns[]} request={(params: any, sort: any, filter: any) => getTableData(params, sort, filter)} />}
-
-            </div>
+          <div className={'btnGroup'}>
+            <UpDataActBtn key={'act'} record={undefined} type="ADD" />
+          </div>
         </div>
-    );
-
+        {currentSelectedTreeNode && (
+          <KCTable
+            pagination={false}
+            reload={reload}
+            newVer
+            params={tableDataFilterParams}
+            rowKey="menuId"
+            columns={columns as ProColumns[]}
+            request={(params: any, sort: any, filter: any) => getTableData(params, sort, filter)}
+          />
+        )}
+      </div>
+    </div>
+  );
 };
 
-export default MonthlyInfoCheck;
+export default MonthlyInfoCheck;

+ 107 - 137
src/pages/platform/setting/systemNavMana/service.ts

@@ -2,171 +2,141 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-21 11:13:51
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-15 16:40:17
+ * @LastEditTime: 2023-11-10 10:26:29
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlyInfoCheck/service.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-
-
-
 import { request } from 'umi';
 
-
-
-
 //获取树结构数据
 
 export type getTreeDataRespType = {
-    code: number;
-    name: string;
-    children: getTreeDataRespType[]
-}
-
-export const getTreeData = (name?:string) => {
-
-    return request<getTreeDataRespType[]>('/centerSys/navigation/getSystemList', {
-        method: 'GET',
-        params: { name }
-    })
-}
-
-
-
+  code: number;
+  name: string;
+  children: getTreeDataRespType[];
+};
+
+export const getTreeData = (name?: string) => {
+  return request<getTreeDataRespType[]>('/centerSys/navigation/getSystemList', {
+    method: 'GET',
+    params: { name },
+  });
+};
+
+//获取菜单内容类型列表
+
+export const getMenuContentType = (systemId: string) => {
+  return request('/centerSys/sysdictdata/getDictDataList?current=1&pageSize=1000&dictType=MENU_CONTENT_TYPE', {
+    method: 'GET',
+    params: { systemId },
+  });
+};
 
 //获取表格数据
 
 export type SystemRelaMenuDataType = {
-    menuId:string;
-    parentId:string;
-    name:string;
-    path:string;
-    url:string;
-    softUrl:string;
-    perms:string;
-    type:number;
-    icon:string;
-    orderNum:number;
-    reportId:string;
-    contentType:number;
-    isHomepage:number;
-    children:SystemRelaMenuDataType[]
-}
-
-export const getTableDataRequest = (params:{systemId:string;name?:string}) => {
-
-    return request<SystemRelaMenuDataType[]>('/centerSys/navigation/getMenuList', {
-        method: 'GET',
-        params: { ...params }
-    })
-
-}
-
+  menuId: string;
+  parentId: string;
+  name: string;
+  path: string;
+  url: string;
+  softUrl: string;
+  perms: string;
+  type: number;
+  icon: string;
+  orderNum: number;
+  reportId: string;
+  contentType: number;
+  isHomepage: number;
+  children: SystemRelaMenuDataType[];
+};
+
+export const getTableDataRequest = (params: { systemId: string; name?: string }) => {
+  return request<SystemRelaMenuDataType[]>('/centerSys/navigation/getMenuList', {
+    method: 'GET',
+    params: { ...params },
+  });
+};
 
 //新增菜单
 
 export type AddMenuDataType = {
-    parentId:number;
-    name:string;
-    path:string;
-    url:string;
-    softUrl:string;
-    perms:string;
-    type:string;
-    icon:string;
-    orderNum:number;
-    reportId:string;
-    contentType:string;
-    isHomepage:number;
-    systemId:number;
-}
-
-export const addData = (data:AddMenuDataType) => {
-
-    return request('/centerSys/navigation/addMenu', {
-        method: 'POST',
-        data
-    })
-
-}
-
+  parentId: number;
+  name: string;
+  path: string;
+  url: string;
+  softUrl: string;
+  perms: string;
+  type: string;
+  icon: string;
+  orderNum: number;
+  reportId: string;
+  contentType: string;
+  isHomepage: number;
+  systemId: number;
+};
+
+export const addData = (data: AddMenuDataType) => {
+  return request('/centerSys/navigation/addMenu', {
+    method: 'POST',
+    data,
+  });
+};
 
 //编辑菜单
 
-
 export type EditMenuDataType = {
-    parentId:number;
-    name:string;
-    path:string;
-    url:string;
-    softUrl:string;
-    perms:string;
-    type:string;
-    icon:string;
-    orderNum:number;
-    reportId:string;
-    contentType:string;
-    isHomepage:number;
-    systemId:number;
-    menuId:number;
-}
-
-export const editData = (data:EditMenuDataType) => {
-
-    return request('/centerSys/navigation/editMenu', {
-        method: 'POST',
-        data
-    })
-
-}
-
+  parentId: number;
+  name: string;
+  path: string;
+  url: string;
+  softUrl: string;
+  perms: string;
+  type: string;
+  icon: string;
+  orderNum: number;
+  reportId: string;
+  contentType: string;
+  isHomepage: number;
+  systemId: number;
+  menuId: number;
+};
+
+export const editData = (data: EditMenuDataType) => {
+  return request('/centerSys/navigation/editMenu', {
+    method: 'POST',
+    data,
+  });
+};
 
 //删除菜单
-export const delData = (menuId:number) => {
-
-    return request('/centerSys/navigation/deleteMenu', {
-        method: 'POST',
-        params:{menuId}
-    })
-
-}
-
-
-
+export const delData = (menuId: number) => {
+  return request('/centerSys/navigation/deleteMenu', {
+    method: 'POST',
+    params: { menuId },
+  });
+};
 
 //获取功能字典
 
-export type  MenuRelaActDicItemType = {
-    code:string;
-    value:string;
-    name:string;
-}
+export type MenuRelaActDicItemType = {
+  code: string;
+  value: string;
+  name: string;
+};
 
 export const getMenuRelaActDic = () => {
-
-    return request<MenuRelaActDicItemType[]>('/centerSys/navigation/getFunctionDict', {
-        method: 'GET',
-    })
-
-}
-
+  return request<MenuRelaActDicItemType[]>('/centerSys/navigation/getFunctionDict', {
+    method: 'GET',
+  });
+};
 
 //保存功能字典
 
-
-export const updateFuncDic = (data:{
-    menuId:number;
-    function:{code:string;name:string}[]
-}) => {
-
-    return request('/centerSys/navigation/addFunction', {
-        method: 'POST',
-        data
-    })
-
-}
-
-
-
-
-
+export const updateFuncDic = (data: { menuId: number; function: { code: string; name: string }[] }) => {
+  return request('/centerSys/navigation/addFunction', {
+    method: 'POST',
+    data,
+  });
+};

+ 79 - 87
src/pages/platform/setting/userManage/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-11 09:43:18
- * @LastEditTime: 2023-03-24 12:28:42
+ * @LastEditTime: 2024-04-01 14:07:34
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/userManage/index.tsx
@@ -42,8 +42,7 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
   const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
   const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
 
-  const [dirData,set_dirData] = useState<UserRelaSeletDataType[]>([]);
-
+  const [dirData, set_dirData] = useState<UserRelaSeletDataType[]>([]);
 
   const columns: ProColumns<TableListItem>[] = [
     {
@@ -72,8 +71,8 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
       title: '在职状态',
       dataIndex: 'isOnService',
       valueEnum: {
-        1: { text: '否', status: 'Default' },
-        0: { text: '是', status: 'Success' },
+        0: { text: '否', status: 'Default' },
+        1: { text: '是', status: 'Success' },
       },
     },
     {
@@ -105,15 +104,13 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
   ];
 
   const getUserData = async (params: TableRequestParamsType) => {
-  
-    const { current = 1, pageSize = 10, name = undefined, account = undefined,departmentId=undefined} = params;
-
+    const { current = 1, pageSize = 10, name = undefined, account = undefined, departmentId = undefined } = params;
 
     const resp = await getUsers({
       current,
       pageSize,
       keyword: name ? name : account,
-      departmentId
+      departmentId,
     });
 
     //获取万最新数据取消重置reload
@@ -189,62 +186,56 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
   };
 
   const getDirecData = async (key?: string) => {
-
     const data = await getUserRelaSeletData(key);
     if (data) {
       set_dirData(data);
     }
-  }
+  };
 
   const tableDataSearchHandle = (paramName: string) => {
-
-
     set_tableDataFilterParams({
       ...tableDataFilterParams,
-      [`${paramName}`]: tableDataSearchKeywords
-    })
-  }
+      [`${paramName}`]: tableDataSearchKeywords,
+    });
+  };
 
   const importData = (name: string) => {
-
     return (
       <ModalForm
         title={`导入${name}数据`}
         width={352}
-        trigger={
-          <span key="3">导入</span>
-        }
-        onFinish={async (values:any) => {
-
-          const { importFile: { fileList } } = values;
+        trigger={<span key="3">导入</span>}
+        onFinish={async (values: any) => {
+          const {
+            importFile: { fileList },
+          } = values;
 
           let formData = new FormData();
+          console.log({ values });
           formData.append('file', fileList[0].originFileObj);
 
           dispatch &&
-          dispatch({
-            type: 'userManageModel/importUsers',
-            payload: formData,
-          });
+            dispatch({
+              type: 'userManageModel/importUsers',
+              payload: formData,
+            });
+          return true;
         }}
       >
         <FormItem name={'importFile'}>
           <KCUpload downloadTemplateFile={() => getUserTemplateHandle()} />
         </FormItem>
-
       </ModalForm>
-    )
-  }
-
+    );
+  };
 
   const setSelectorData = (key: string) => {
-    let result = dirData.filter((t: any) => (t.code == key));
+    let result = dirData.filter((t: any) => t.code == key);
 
     if (result.length > 0) {
-
       let dataArr = result[0].dataVoList;
 
-      let defaultValue = dataArr.filter(t => t.defaultValue == 1);
+      let defaultValue = dataArr.filter((t) => t.defaultValue == 1);
 
       dataArr.sort((prev: UserRelaSeletDataListType, next: UserRelaSeletDataListType) => {
         return prev.sort - next.sort;
@@ -252,77 +243,80 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
 
       return {
         defaultvalue: defaultValue[0] ? defaultValue[0].value : '',
-        list: dataArr.map(t =>{
-             return ({ label: t.value, value: t.code })
-        })
-      }
+        list: dataArr.map((t) => {
+          return { label: t.name, value: t.code };
+        }),
+      };
     }
 
     return {
       defaultvalue: '',
-      list: []
+      list: [],
     };
-  }
-
+  };
 
-  useEffect(()=>{
+  useEffect(() => {
     getDirecData();
-  },[])
-
+  }, []);
 
   //  console.log({state});
 
   return (
     <div className="UserManage">
-      <ActModal  {...state} dispatch={dispatch} />
+      <ActModal {...state} dispatch={dispatch} />
 
-      <div className='toolBar'>
-        <div className='filter'>
-          <div className='filterItem' style={{ marginRight: 16}}>
-            <span className='label'>科室:</span>
+      <div className="toolBar">
+        <div className="filter">
+          <div className="filterItem" style={{ marginRight: 16 }}>
+            <span className="label">科室:</span>
             <ProFormSelect
-                    name="departmentId"
-                    noStyle
-                    style={{width:160}}
-                    placeholder="请选择"
-                    request={async () => {
-                          const resp = await getDepartmentData({pageSize:1000});
-                          if(resp){
-                            return resp.list.map(a=>({label:a.name,value:a.id})) 
-                          }
-                          return [];
-                    }}
-                    fieldProps={{
-                      showSearch:true,
-                      onChange:(val) => {
-                        set_tableDataFilterParams({
-                          ...tableDataFilterParams,
-                          departmentId:val
-                        });
-                      }
-                    }}
+              name="departmentId"
+              noStyle
+              style={{ width: 160 }}
+              placeholder="请选择"
+              request={async () => {
+                const resp = await getDepartmentData({ pageSize: 1000 });
+                if (resp) {
+                  return resp.list.map((a) => ({ label: a.name, value: a.id }));
+                }
+                return [];
+              }}
+              fieldProps={{
+                showSearch: true,
+                onChange: (val) => {
+                  set_tableDataFilterParams({
+                    ...tableDataFilterParams,
+                    departmentId: val,
+                  });
+                },
+              }}
             />
           </div>
-          <div className='filterItem'>
-            <span className='label'>检索:</span>
-            <KCInput placeholder={'请输入姓名/工号'} style={{ width: 160 }} search allowClear
+          <div className="filterItem">
+            <span className="label">检索:</span>
+            <KCInput
+              placeholder={'请输入姓名/工号'}
+              style={{ width: 160 }}
+              search
+              allowClear
               onChange={(e) => {
                 set_tableDataSearchKeywords(e.target.value);
                 if (e.target.value.length == 0) {
                   set_tableDataFilterParams({
                     ...tableDataFilterParams,
-                    name: ''
+                    name: '',
                   });
                 }
               }}
               onSearch={() => tableDataSearchHandle('name')}
-
             />
           </div>
         </div>
-        <div className='btnGroup'>
+        <div className="btnGroup">
           {importData('员工')}
-          <span className='add' onClick={addUserHandle}>新增</span>
+          <span className="add" onClick={addUserHandle}>
+            新增
+          </span>
         </div>
       </div>
 
@@ -334,8 +328,8 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
         params={tableDataFilterParams}
         newVer
         expandable={{
-          expandedRowRender: record => (
-            <div className='userExpandInfo'>
+          expandedRowRender: (record) => (
+            <div className="userExpandInfo">
               <span>进院时间:{record.entryTime}</span>
               <span>手机号:{record.phoneNumber}</span>
               <span>所学专业:{record.major}</span>
@@ -375,12 +369,10 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
   );
 };
 
-export default connect(
-  ({ userManageModel, loading }: { userManageModel: userManageModelState; loading: Loading }) => {
-    //  console.log({userManageModel});
-    return {
-      userManageModel,
-      loading: loading.models.userManageModel,
-    };
-  },
-)(UserManage);
+export default connect(({ userManageModel, loading }: { userManageModel: userManageModelState; loading: Loading }) => {
+  //  console.log({userManageModel});
+  return {
+    userManageModel,
+    loading: loading.models.userManageModel,
+  };
+})(UserManage);

+ 263 - 276
src/pages/platform/setting/userManage/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-03-24 12:31:46
+ * @LastEditTime: 2023-12-14 14:29:22
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/modal.tsx
@@ -34,13 +34,7 @@ interface ActModalProps extends userManageModelState {
 
 const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
 
-const ActModal: React.FC<ActModalProps> = ({
-  dispatch,
-  isShowModal,
-  tableAct,
-  currentEditUser,
-}) => {
-
+const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, currentEditUser }) => {
   const [avatarUrl, setAvatarUrl] = useState<string>('');
   const [loadAvatar, setLoadAvatar] = useState(false);
 
@@ -51,19 +45,18 @@ const ActModal: React.FC<ActModalProps> = ({
     name: 'file',
     maxCount: 1,
     showUploadList: false,
-    onChange(info: { file: any; fileList: any; }) {
-
+    onChange(info: { file: any; fileList: any }) {
       setLoadAvatar(true);
 
       if (info.file.status !== 'uploading') {
         // console.log(info.file, info.fileList);
         const reader = new FileReader();
-        reader.readAsDataURL(info.file.originFileObj);//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
+        reader.readAsDataURL(info.file.originFileObj); //读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
         reader.onload = function (event) {
           if (event.target && typeof event.target.result == 'string') {
-            setAvatarUrl(event.target.result);//base64
+            setAvatarUrl(event.target.result); //base64
           }
-        }
+        };
       }
       if (info.file.status === 'done') {
         setLoadAvatar(false);
@@ -71,7 +64,7 @@ const ActModal: React.FC<ActModalProps> = ({
         message.error(`${info.file.name} 上传失败!`);
       }
     },
-  }
+  };
 
   const onVisibleChangeHandle = (bool: boolean) => {
     // console.log({bool});
@@ -85,6 +78,7 @@ const ActModal: React.FC<ActModalProps> = ({
   };
 
   const onFinishHandle = (data: any & AddUsersDataType) => {
+    console.log({ data });
     if (tableAct == TableActType.ADD) {
       dispatch &&
         dispatch({
@@ -105,21 +99,19 @@ const ActModal: React.FC<ActModalProps> = ({
   };
 
   const getDirecData = async (key?: string) => {
-
     const data = await getUserRelaSeletData(key);
     if (data) {
       set_dirData(data);
     }
-  }
+  };
 
   const setSelectorData = (key: string) => {
-    let result = dirData.filter((t: any) => (t.code == key));
+    let result = dirData.filter((t: any) => t.code == key);
 
     if (result.length > 0) {
-
       let dataArr = result[0].dataVoList;
 
-      let defaultValue = dataArr.filter(t => t.defaultValue == 1);
+      let defaultValue = dataArr.filter((t) => t.defaultValue == 1);
 
       dataArr.sort((prev: UserRelaSeletDataListType, next: UserRelaSeletDataListType) => {
         return prev.sort - next.sort;
@@ -127,17 +119,17 @@ const ActModal: React.FC<ActModalProps> = ({
 
       return {
         defaultvalue: defaultValue[0] ? defaultValue[0].value : '',
-        list: dataArr.map(t => {
-          return ({ label: t.value, value: t.code })
-        })
-      }
+        list: dataArr.map((t) => {
+          return { label: t.name, value: t.code };
+        }),
+      };
     }
 
     return {
       defaultvalue: '',
-      list: []
+      list: [],
     };
-  }
+  };
 
   const uploadButton = (
     <div>
@@ -148,308 +140,303 @@ const ActModal: React.FC<ActModalProps> = ({
 
   useEffect(() => {
     getDirecData();
-  }, [])
+  }, []);
 
   return (
     <KCModal
       width={720}
       visible={isShowModal}
       onVisibleChange={onVisibleChangeHandle}
-      layout='vertical'
-      className='ProfileModal'
+      layout="vertical"
+      className="ProfileModal"
       initialValues={
-        tableAct == TableActType.EDIT ? { ...currentEditUser } : {
-          //设置当新增时的默认值
-          major: (setSelectorData('PROFESSIONAL_TYPE')).defaultvalue,
-          jobTitle: (setSelectorData('POSITION_TYPE')).defaultvalue,
-          doctorLevel: (setSelectorData('PHYSICIAN_TYPE')).defaultvalue,
-          practiceSubject: setSelectorData('PROCESSIONAL_SUBJECTS_TYPE').defaultvalue,
-          title: setSelectorData('TITLE_TYPE').defaultvalue,
-          practiceCate: setSelectorData('JOB_TYPE').defaultvalue,
-          practiceStatus: setSelectorData('PROFESSIONAL_STATUS_TYPE').defaultvalue,
-          position: setSelectorData('POSITION').defaultvalue,
-          departmentId: setSelectorData('PRACTICE_DEPARTMENT_TYPE').defaultvalue,
-          userCate: setSelectorData('PERSONNEL_CATEGORY').defaultvalue,
-          degree: setSelectorData('EDUCATION').defaultvalue,
-
-        }
+        tableAct == TableActType.EDIT
+          ? { ...currentEditUser, departmentId: { label: currentEditUser?.departmentName, value: currentEditUser?.departmentId } }
+          : {
+              //设置当新增时的默认值
+              major: setSelectorData('PROFESSIONAL_TYPE').defaultvalue,
+              jobTitle: setSelectorData('POSITION_TYPE').defaultvalue,
+              doctorLevel: setSelectorData('PHYSICIAN_TYPE').defaultvalue,
+              practiceSubject: setSelectorData('PROCESSIONAL_SUBJECTS_TYPE').defaultvalue,
+              title: setSelectorData('TITLE_TYPE').defaultvalue,
+              practiceCate: setSelectorData('JOB_TYPE').defaultvalue,
+              practiceStatus: setSelectorData('PROFESSIONAL_STATUS_TYPE').defaultvalue,
+              position: setSelectorData('POSITION').defaultvalue,
+              departmentId: setSelectorData('PRACTICE_DEPARTMENT_TYPE').defaultvalue,
+              userCate: setSelectorData('PERSONNEL_CATEGORY').defaultvalue,
+              degree: setSelectorData('EDUCATION').defaultvalue,
+            }
       }
       title={tableAct == TableActType.EDIT ? '编辑用户' : '新增用户'}
       // labelCol={{ span: 5 }}
       // wrapperCol={{ span:8 }}
-      onFinish={async (data) => onFinishHandle(data)}
+      onFinish={async (data) => onFinishHandle({ ...data, departmentId: data.departmentId.value, departmentName: data.departmentId.label })}
     >
+      {dirData ? (
+        <div>
+          <div className="wraper">
+            <div className="left">
+              <span style={{ fontSize: 14, color: '#17181A', marginBottom: 3, display: 'block' }}>照片:</span>
+              <div className="avatarContainer">
+                <Upload
+                  // name="avatar"
+                  listType="picture-card"
+                  showUploadList={false}
+                  {...props}
+                >
+                  {avatarUrl ? <img src={avatarUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
+                </Upload>
+              </div>
 
-      {
-        dirData ? (
-          <div>
-            <div className='wraper'>
-              <div className='left'>
-                <span style={{ fontSize: 14, color: '#17181A', marginBottom: 3, display: 'block' }}>照片:</span>
-                <div className='avatarContainer'>
-                  <Upload
-                    // name="avatar"
-                    listType="picture-card"
-                    showUploadList={false}
-                    {...props}
-                  >
-                    {avatarUrl ? <img src={avatarUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
-                  </Upload>
-                </div>
-
-                <div className='formItem'>
-                  <ProFormRadio.Group
-                    name="isOnService"
-                    label='在职:'
-                    options={[
-                      {
-                        label: '是',
-                        value: 0,
-                      },
-                      {
-                        label: '否',
-                        value: 1,
-                      },
-                    ]}
-                    rules={[{ required: true, message: '请选择专业!' }]}
-                  />
-                </div>
-
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="position"
-                    label="岗位:"
-                    options={setSelectorData('POSITION').list}
-                    placeholder="请选择"
-                    rules={[{ required: true, message: '请选择!' }]}
-                  />
-                </div>
+              <div className="formItem">
+                <ProFormRadio.Group
+                  name="isOnService"
+                  label="在职:"
+                  options={[
+                    {
+                      label: '是',
+                      value: 0,
+                    },
+                    {
+                      label: '否',
+                      value: 1,
+                    },
+                  ]}
+                  rules={[{ required: true, message: '请选择专业!' }]}
+                />
+              </div>
 
+              <div className="formItem">
+                <ProFormSelect
+                  name="position"
+                  label="岗位:"
+                  fieldProps={{ showSearch: true }}
+                  options={setSelectorData('POSITION').list}
+                  placeholder="请选择"
+                  rules={[{ required: true, message: '请选择!' }]}
+                />
+              </div>
+            </div>
+            <div className="right">
+              <div className="formItem">
+                <ProFormText name="name" label="姓名:" placeholder="请输入" rules={[{ required: true, message: '请输入姓名!' }]} />
+              </div>
+              <div className="formItem">
+                <ProFormText name="account" label="工号:" placeholder="请输入" rules={[{ required: true, message: '请输入工号!' }]} />
+              </div>
+              <div className="formItem">
+                <ProFormSelect
+                  name="gender"
+                  label="性别:"
+                  options={[
+                    { label: '男', value: 1 },
+                    { label: '女', value: 2 },
+                  ]}
+                  placeholder="请选择"
+                  rules={[{ required: true, message: '请选择性别!' }]}
+                />
+              </div>
+              <div className="formItem">
+                <KCProSelect
+                  label="所属院区:"
+                  width="md"
+                  name="hospId"
+                  fieldProps={{ showSearch: true }}
+                  request={async () => {
+                    const hospList = await getShareHospList();
+                    if (hospList) {
+                      return hospList.map((t) => ({
+                        label: t.name,
+                        value: t.id,
+                      }));
+                    }
+                    return [];
+                  }}
+                  rules={[
+                    {
+                      required: true,
+                      message: '请选择院区!',
+                    },
+                  ]}
+                />
+              </div>
+              <div className="formItem">
+                <ProFormSelect
+                  name="departmentId"
+                  label="科室:"
+                  request={async () => {
+                    const resp = await getDepartmentData({ pageSize: 1000 });
+                    if (resp) {
+                      return resp.list.map((a) => ({ label: a.name, value: a.code }));
+                    }
+                    return [];
+                  }}
+                  fieldProps={{
+                    labelInValue: true,
+                    showSearch: true,
+                  }}
+                  placeholder="请选择"
+                />
+              </div>
+              <div className="formItem">
+                <ProFormSelect name="userCate" label="人员类别:" fieldProps={{ showSearch: true }} options={setSelectorData('PERSONNEL_CATEGORY').list} placeholder="请选择" />
+              </div>
 
+              <div className="formItem">
+                <ProFormDateTimePicker name="entryTime" label="入职时间" placeholder={'请选择日期'} rules={[{ required: true, message: '请选择日期!' }]} />
+              </div>
+              <div className="formItem">
+                <ProFormSelect
+                  name="title"
+                  label="职称:"
+                  fieldProps={{ showSearch: true }}
+                  options={setSelectorData('TITLE_TYPE').list}
+                  placeholder="请选择"
+                  rules={[{ required: true, message: '请选择职称!' }]}
+                />
+              </div>
+              <div className="formItem">
+                <ProFormSelect
+                  name="jobTitle"
+                  label="职务:"
+                  fieldProps={{ showSearch: true }}
+                  options={setSelectorData('POSITION_TYPE').list}
+                  placeholder="请选择"
+                  rules={[{ required: true, message: '请选择职务!' }]}
+                />
+              </div>
+              <ProFormDependency name={['isOnService']}>
+                {({ isOnService }) => (
+                  <div className="formItem">
+                    <ProFormDateTimePicker disabled={isOnService == 0} label="离职日期:" name="outTime" placeholder={'请选择离职时间'} />
+                  </div>
+                )}
+              </ProFormDependency>
+
+              <div className="formItem">
+                <ProFormText name="graduateSchool" label="毕业院校:" placeholder="请输入" rules={[{ required: false, message: '请输入院校!' }]} />
+              </div>
 
+              <div className="formItem">
+                <ProFormSelect
+                  name="degree"
+                  label="学历:"
+                  fieldProps={{ showSearch: true }}
+                  options={setSelectorData('EDUCATION').list}
+                  placeholder="请选择"
+                  rules={[{ required: true, message: '请选择学历!' }]}
+                />
+              </div>
+
+              <div className="formItem">
+                <ProFormSelect
+                  name="major"
+                  label="所学专业:"
+                  fieldProps={{ showSearch: true }}
+                  options={setSelectorData('PROFESSIONAL_TYPE').list}
+                  placeholder="请选择"
+                  rules={[{ required: true, message: '请选择专业!' }]}
+                />
               </div>
-              <div className='right'>
-                <div className='formItem'>
-                  <ProFormText name="name" label="姓名:" placeholder="请输入" rules={[{ required: true, message: '请输入姓名!' }]} />
-                </div>
-                <div className='formItem'>
-                  <ProFormText name="account" label="工号:" placeholder="请输入" rules={[{ required: true, message: '请输入工号!' }]} />
-                </div>
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="gender"
-                    label="性别:"
-                    options={[
-                      { label: '男', value: 1 },
-                      { label: '女', value: 2 },
-                    ]}
-                    placeholder="请选择"
-                    rules={[{ required: true, message: '请选择性别!' }]}
-                  />
-                </div>
-                <div className='formItem'>
-                  <KCProSelect
-                    label="所属院区:"
-                    width="md"
-                    name="hospId"
-                    request={async () => {
-                      const hospList = await getShareHospList();
-                      if (hospList) {
-                        return hospList.map((t) => ({
-                          label: t.name,
-                          value: t.id,
-                        }));
-                      }
-                      return [];
-                    }}
-                    rules={[
-                      {
-                        required: true,
-                        message: '请选择院区!',
-                      },
-                    ]}
-                  />
-                </div>
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="departmentId"
-                    label="科室:"
-                    request={async () => {
-                      const resp = await getDepartmentData({pageSize:1000});
-                      if(resp){
-                        return resp.list.map(a=>({label:a.name,value:a.id})) 
-                      }
-                      return [];
-                     }}
-                     fieldProps={{
-                        showSearch:true
-                     }}
-                    placeholder="请选择"
-                  />
-                </div>
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="userCate"
-                    label="人员类别:"
-                    options={setSelectorData('PERSONNEL_CATEGORY').list}
-                    placeholder="请选择"
-                  />
-                </div>
-
-                <div className='formItem'>
-                  <ProFormDateTimePicker name="entryTime" label="入职时间" placeholder={'请选择日期'} rules={[{ required: true, message: '请选择日期!' }]} />
-                </div>
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="title"
-                    label="职称:"
-                    options={setSelectorData('TITLE_TYPE').list}
-                    placeholder="请选择"
-                    rules={[{ required: true, message: '请选择职称!' }]}
-                  />
-                </div>
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="jobTitle"
-                    label="职务:"
-                    options={setSelectorData('POSITION_TYPE').list}
-                    placeholder="请选择"
-                    rules={[{ required: true, message: '请选择职务!' }]}
-                  />
-                </div>
-                <ProFormDependency name={['isOnService']}>
-                  {({ isOnService }) => (
-                    <div className='formItem'>
-                      <ProFormDateTimePicker disabled={isOnService == 0} label='离职日期:' name="outTime" placeholder={'请选择离职时间'} />
-                    </div>
-                  )}
-                </ProFormDependency>
-
-                <div className='formItem'>
-                  <ProFormText name="graduateSchool" label="毕业院校:" placeholder="请输入" rules={[{ required: false, message: '请输入院校!' }]} />
-                </div>
-
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="degree"
-                    label="学历:"
-                    options={setSelectorData('EDUCATION').list}
-                    placeholder="请选择"
-                    rules={[{ required: true, message: '请选择学历!' }]}
-                  />
-                </div>
-
-                <div className='formItem'>
-                  <ProFormSelect
-                    name="major"
-                    label="所学专业:"
-                    options={setSelectorData('PROFESSIONAL_TYPE').list}
-                    placeholder="请选择"
-                    rules={[{ required: true, message: '请选择专业!' }]}
-                  />
-                </div>
-
-                <div className='formItem' >
-                  <ProFormText name="idCardNum" label="身份证号:" placeholder="请输入" rules={[{ required:false, message: '请选择!' }]} />
-                </div>
-
-                <div className='formItem'>
-                  <ProFormText name="phoneNumber" label="手机号:" placeholder="请输入" />
-                </div>
-
-
-                <ProFormDependency name={['userCate']}>
-                  {({ userCate }) => (userCate == 6 || userCate == 5) && (
-                    <div className='formItem' style={{ position: 'relative', left: -175 }}>
-                      <ProFormSelect
-                        name="practiceCate"
-                        label="执业类别:"
-                        options={setSelectorData('JOB_TYPE').list}
-                        placeholder="请选择"
-                      />
-                    </div>
-                  )}
-                </ProFormDependency>
 
+              <div className="formItem">
+                <ProFormText name="idCardNum" label="身份证号:" placeholder="请输入" rules={[{ required: false, message: '请选择!' }]} />
+              </div>
 
+              <div className="formItem">
+                <ProFormText name="phoneNumber" label="手机号:" placeholder="请输入" />
+              </div>
 
-                <ProFormDependency name={['userCate']}>
-                  {({ userCate }) => (userCate == 6 || userCate == 5) && (
-                    <div className='formItem' style={{ position: 'relative', left: -175 }}>
+              <ProFormDependency name={['userCate']}>
+                {({ userCate }) =>
+                  (userCate == 6 || userCate == 5) && (
+                    <div className="formItem" style={{ position: 'relative', left: -175 }}>
+                      <ProFormSelect name="practiceCate" label="执业类别:" fieldProps={{ showSearch: true }} options={setSelectorData('JOB_TYPE').list} placeholder="请选择" />
+                    </div>
+                  )
+                }
+              </ProFormDependency>
+
+              <ProFormDependency name={['userCate']}>
+                {({ userCate }) =>
+                  (userCate == 6 || userCate == 5) && (
+                    <div className="formItem" style={{ position: 'relative', left: -175 }}>
                       <ProFormSelect
                         name="practiceSubject"
                         label="执业科目:"
+                        fieldProps={{ showSearch: true }}
                         options={setSelectorData('PROCESSIONAL_SUBJECTS_TYPE').list}
                         placeholder="请选择"
                         rules={[{ required: true, message: '请选择!' }]}
                       />
                     </div>
-                  )}
-                </ProFormDependency>
-
-                <ProFormDependency name={['userCate']}>
-                  {({ userCate }) => (userCate == 6 || userCate == 5) && (
-                    <div className='formItem' style={{ position: 'relative', left: -175 }}>
+                  )
+                }
+              </ProFormDependency>
+
+              <ProFormDependency name={['userCate']}>
+                {({ userCate }) =>
+                  (userCate == 6 || userCate == 5) && (
+                    <div className="formItem" style={{ position: 'relative', left: -175 }}>
                       <ProFormText name="practiceCertificateNo" label="执业证号:" placeholder="请输入" rules={[{ required: true, message: '请选择!' }]} />
                     </div>
-                  )}
-                </ProFormDependency>
-
-                <ProFormDependency name={['userCate']}>
-                  {({ userCate }) => (userCate == 6 || userCate == 5) && (
-                    <div className='formItem' style={{ position: 'relative', left: -175 }}>
+                  )
+                }
+              </ProFormDependency>
+
+              <ProFormDependency name={['userCate']}>
+                {({ userCate }) =>
+                  (userCate == 6 || userCate == 5) && (
+                    <div className="formItem" style={{ position: 'relative', left: -175 }}>
                       <ProFormSelect
                         name="practiceStatus"
                         label="执业状态:"
+                        fieldProps={{ showSearch: true }}
                         options={setSelectorData('PROFESSIONAL_STATUS_TYPE').list}
                         placeholder="请选择"
                         rules={[{ required: true, message: '请选择!' }]}
                       />
                     </div>
-                  )}
-                </ProFormDependency>
-
-                <ProFormDependency name={['userCate']}>
-                  {({ userCate }) => (userCate == 6 || userCate == 5) && (
-                    <div className='formItem' style={{ position: 'relative', left: -175 }}>
+                  )
+                }
+              </ProFormDependency>
+
+              <ProFormDependency name={['userCate']}>
+                {({ userCate }) =>
+                  (userCate == 6 || userCate == 5) && (
+                    <div className="formItem" style={{ position: 'relative', left: -175 }}>
                       <ProFormText name="qualificationCertificateNo" label="资格证号:" placeholder="请输入" rules={[{ required: true, message: '请输入!' }]} />
                     </div>
-                  )}
-                </ProFormDependency>
-
-                <ProFormDependency name={['userCate']}>
-                  {({ userCate }) => (userCate == 6 || userCate == 5) && (
-                    <div className='formItem' style={{ position: 'relative', top: -62 }}>
+                  )
+                }
+              </ProFormDependency>
+
+              <ProFormDependency name={['userCate']}>
+                {({ userCate }) =>
+                  (userCate == 6 || userCate == 5) && (
+                    <div className="formItem" style={{ position: 'relative', top: -62 }}>
                       <ProFormSelect
                         name="doctorLevel"
                         label="医师:"
+                        fieldProps={{ showSearch: true }}
                         options={setSelectorData('PHYSICIAN_TYPE').list}
                         placeholder="请选择"
                         rules={[{ required: true, message: '请选择!' }]}
                       />
                     </div>
-                  )}
-                </ProFormDependency>
-
-              </div>
+                  )
+                }
+              </ProFormDependency>
             </div>
-
-            <div style={{ display: 'flex', flexDirection: 'row', width: '100%' }}>
-              <ProFormTextArea
-                label='备注'
-                name="remark"
-                width={688}
-                placeholder="请输入备注"
-              />
-            </div>
-
-
           </div>
-        ) : ''
-      }
-
-
 
+          <div style={{ display: 'flex', flexDirection: 'row', width: '100%' }}>
+            <ProFormTextArea label="备注" name="remark" width={688} placeholder="请输入备注" />
+          </div>
+        </div>
+      ) : (
+        ''
+      )}
     </KCModal>
   );
 };

+ 36 - 22
src/pages/platform/setting/userManage/model.ts

@@ -1,22 +1,16 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2023-03-20 13:29:04
+ * @LastEditTime: 2024-04-01 11:27:15
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/model.ts
  */
 
 import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
-import {
-  addUsers,
-  delUsers,
-  editUsers,
-  getUsertemplate,
-  importUserData,
-  resetUserPwd,
-} from '@/service/user';
+import { addUsers, delUsers, editUsers, getUsertemplate, importUserData, resetUserPwd } from '@/service/user';
 import { TableListItem } from './typings';
+import axios from 'axios';
 
 export enum TableActType {
   NOACT,
@@ -83,12 +77,10 @@ const userManageModel: userManageModelType = {
     *resetUserPwd({ payload }) {
       yield resetUserPwd({ userId: payload.id });
     },
-    *postEditUserData({ payload }:any, { call, put, select }:any) {
-      const currentEditUserOld = yield select(
-        ({ userManageModel: state }: { userManageModel: userManageModelState }) => {
-          return state.currentEditUser;
-        },
-      );
+    *postEditUserData({ payload }: any, { call, put, select }: any) {
+      const currentEditUserOld = yield select(({ userManageModel: state }: { userManageModel: userManageModelState }) => {
+        return state.currentEditUser;
+      });
 
       yield editUsers({ ...currentEditUserOld, ...payload });
       yield put({
@@ -104,15 +96,37 @@ const userManageModel: userManageModelType = {
       });
     },
     *getUserTemplateReq() {
-      const url = yield getUsertemplate();
-      if(url){
-        window.open(url);
-      }
+      let path = '/gateway/centerSys/user/exportUserTemplate';
+
+      const userData = localStorage.getItem('userData');
+      const { token = '' } = JSON.parse(userData as string);
+
+      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);
+      });
     },
     *importUsers({ payload }, { call, put, select }) {
-      const formData: any = new FormData();
-      formData.append('file', payload);
-      yield importUserData(formData);
+      // const formData: any = new FormData();
+      // formData.append('file', payload);
+      yield importUserData(payload);
       yield put({
         type: 'reloadTable',
         payload: true,

+ 4 - 2
src/pages/platform/setting/userManage/typings.d.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 11:10:58
- * @LastEditTime: 2022-01-13 11:43:54
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2023-04-13 11:06:48
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/typings.d.ts
  */
@@ -15,6 +15,8 @@ export type TableListItem = {
   phoneNum: number;
   idCardNum: number;
   isOnService: number;
+  departmentId:string;
+  [key:string]:any
 };
 
 // export enum TableActType {

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott