Переглянути джерело

添加追踪方法学后台管理相关配置

code4eat 1 рік тому
батько
коміт
70292cb9c5
65 змінених файлів з 3322 додано та 819 видалено
  1. 10 3
      config/config.ts
  2. 1 1
      config/proxy.ts
  3. BIN
      kcim-center_2023_09_22.zip
  4. BIN
      public/images/HBI.png
  5. BIN
      public/images/HBI_gray.png
  6. BIN
      public/images/close.png
  7. BIN
      public/images/copy.png
  8. BIN
      public/images/guanlizhongxin.png
  9. BIN
      public/images/guanlizhongxin_gray.png
  10. BIN
      public/images/jingyiyiliao.png
  11. BIN
      public/images/jingyiyiliao_gray.png
  12. 0 0
      public/images/tixiicon0.png
  13. BIN
      public/images/tixiicon1.png
  14. BIN
      public/images/tixiicon2.png
  15. BIN
      public/images/tixiicon3.png
  16. BIN
      public/images/tixiicon4.png
  17. BIN
      public/images/tixiicon5.png
  18. BIN
      public/images/zanwuneirong.png
  19. BIN
      public/images/zhongtaiguanli.png
  20. BIN
      public/images/zhongtaiguanli_gray.png
  21. 8 0
      public/zhongtaiC.js
  22. 87 58
      src/app.tsx
  23. 3 3
      src/components/NavSelecter/index.tsx
  24. 16 7
      src/components/kcTable/style.less
  25. 53 38
      src/components/topBar/index.tsx
  26. 151 14
      src/components/topBar/style.less
  27. 2 2
      src/components/topBar/typings.d.ts
  28. 38 5
      src/global.less
  29. 18 18
      src/layouts/index.tsx
  30. 70 10
      src/pages/login/index.tsx
  31. 10 0
      src/pages/personalCenter/index.tsx
  32. 15 0
      src/pages/personalCenter/style.less
  33. 83 7
      src/pages/platform/_layout.tsx
  34. 98 3
      src/pages/platform/index.less
  35. 103 58
      src/pages/platform/setting/hospManage/index.tsx
  36. 34 5
      src/pages/platform/setting/hospManage/modals/modal.tsx
  37. 2 2
      src/pages/platform/setting/hospManage/model.ts
  38. 4 2
      src/pages/platform/setting/hospManage/typings.d.ts
  39. 494 0
      src/pages/platform/setting/hospParamsMana/index.tsx
  40. 107 0
      src/pages/platform/setting/hospParamsMana/service.ts
  41. 138 0
      src/pages/platform/setting/hospParamsMana/style.less
  42. 6 2
      src/pages/platform/setting/menuManage/modals/modal.tsx
  43. 5 5
      src/pages/platform/setting/notificationTemplate/index.tsx
  44. 1 1
      src/pages/platform/setting/notificationTemplate/style.less
  45. 252 169
      src/pages/platform/setting/paramsMana/index.tsx
  46. 10 4
      src/pages/platform/setting/paramsMana/service.ts
  47. 123 0
      src/pages/platform/setting/paramsMana/style.less
  48. 265 120
      src/pages/platform/setting/pubDicMana/index.tsx
  49. 30 11
      src/pages/platform/setting/pubDicMana/service.ts
  50. 60 22
      src/pages/platform/setting/pubDicMana/style.less
  51. 263 46
      src/pages/platform/setting/pubDicTypeMana/index.tsx
  52. 32 14
      src/pages/platform/setting/pubDicTypeMana/service.ts
  53. 99 25
      src/pages/platform/setting/pubDicTypeMana/style.less
  54. 285 134
      src/pages/platform/setting/roleManage/index.tsx
  55. 4 3
      src/pages/platform/setting/roleManage/modals/modal.tsx
  56. 11 7
      src/pages/platform/setting/roleManage/model.ts
  57. 212 0
      src/pages/platform/setting/roleManage/style.less
  58. 6 5
      src/pages/platform/setting/systemNavMana/index.tsx
  59. 2 2
      src/pages/platform/setting/userManage/index.tsx
  60. 13 2
      src/pages/platform/setting/userManage/modal.tsx
  61. 24 2
      src/service/hospList.ts
  62. 41 4
      src/service/login.ts
  63. 2 3
      src/service/menu.ts
  64. 29 0
      src/service/public.ts
  65. 2 2
      src/service/role.ts

+ 10 - 3
config/config.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:04:20
- * @LastEditTime: 2023-07-10 13:44:38
+ * @LastEditTime: 2023-09-26 16:55:19
  * @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
@@ -63,6 +63,10 @@ export default defineConfig({
           path: '/budgetManaSystem',
           microApp: 'budgetManaSystem',
         },
+        {
+          path: '/pfmBackMana',
+          microApp: 'pfmBackMana',
+        },
         {
           path: '/channelIndex/channelIndexOne',
           component: '@/pages/channelIndex/channelIndexOne/index.tsx',
@@ -113,7 +117,11 @@ export default defineConfig({
                   component: '@/pages/platform/setting/pubDicTypeMana/index.tsx',
                 },
                 {
-                  path: '/platform/setting/pubDicMana',
+                  path: '/platform/setting/hospParamsMana',
+                  component: '@/pages/platform/setting/hospParamsMana/index.tsx',
+                },
+                {
+                  path: '/platform/setting/pubDicMana/:type',
                   component: '@/pages/platform/setting/pubDicMana/index.tsx',
                 },
                 {
@@ -135,7 +143,6 @@ export default defineConfig({
               ]
             },
           ],
-
         },
         {
           path: '/personalCenter',

+ 1 - 1
config/proxy.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:00:52
- * @LastEditTime: 2023-08-17 18:36:44
+ * @LastEditTime: 2023-09-26 14:22:34
  * @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

BIN
kcim-center_2023_09_22.zip


BIN
public/images/HBI.png


BIN
public/images/HBI_gray.png


BIN
public/images/close.png


BIN
public/images/copy.png


BIN
public/images/guanlizhongxin.png


BIN
public/images/guanlizhongxin_gray.png


BIN
public/images/jingyiyiliao.png


BIN
public/images/jingyiyiliao_gray.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/zanwuneirong.png


BIN
public/images/zhongtaiguanli.png


BIN
public/images/zhongtaiguanli_gray.png


Різницю між файлами не показано, бо вона завелика
+ 8 - 0
public/zhongtaiC.js


+ 87 - 58
src/app.tsx

@@ -1,9 +1,9 @@
 import { useState } from 'react';
 import { PageLoading } from '@ant-design/pro-layout';
-import { notification, Modal } from 'antd';
+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, addQiankunMicroApps, getQiankunMicroApps } from '@/service/login';
 
 import { BasicLayoutProps } from '@ant-design/pro-layout';
 import { logoutHandle } from './global';
@@ -13,6 +13,7 @@ import { SpacicalPageParamsType } from './typings';
 
 
 
+
 const loginPath = '/login';
 
 let hospSign: string = ''; //医院标识
@@ -23,7 +24,7 @@ if (history && history.location.query) {
     const localHospSign = localStorage.getItem('hospSign');
     hospSign = localHospSign ? localHospSign : '';
   }
-} 
+}
 
 
 
@@ -63,16 +64,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 [];
   };
 
@@ -101,7 +102,7 @@ export async function getInitialState(): Promise<InitialStateType> {
 }
 
 const requestInterceptorsHandle = (url: string, options: RequestOptionsInit) => {
-   
+
   const userData = localStorage.getItem('userData');
   let authHeader = { token: '' };
 
@@ -136,17 +137,19 @@ const responseInterceptorsHandle = async (response: Response, options: RequestOp
       return _response.data;
     }
 
-    notification.success({
-      message: `操作成功!`,
+    message.success({
+        content:`操作成功!`,
+        duration:1
     });
     return {
       status: _response.status,
       success: true,
     };
   } else {
-    console.log({_response});
+    console.log({ _response });
     notification.error({
-      message: `${_response.msg?_response.msg:_response.message?_response.message:_response.errorMessage}`,
+      message: '错误:',
+      description:`${_response.msg ? _response.msg : _response.message ? _response.message : _response.errorMessage}`
     });
     return false
   }
@@ -179,8 +182,8 @@ const errorHandlerFunc = (error: ResponseErr) => {
       //token过期
       Modal.confirm({
         title: '抱歉,你的登录已过期,请重新登录!',
-        okText:'确定',
-        cancelText:'取消',
+        okText: '确定',
+        cancelText: '取消',
         maskClosable: false,
         // cancelButtonProps:
         onOk: () => {
@@ -196,11 +199,12 @@ const errorHandlerFunc = (error: ResponseErr) => {
         message: ` ${errorCode}:出现错误!`,
         description: errorMessage,
       });
-    } else if(false){
+    } else if (false) {
 
-    }else{
+    } else {
       notification.error({
-        message: ` ${errorCode}:${errorMessage}`,
+        message: '错误',
+        description:` ${errorCode}:${errorMessage}`
       });
     }
   } catch (err) {
@@ -242,40 +246,65 @@ export const request: RequestConfig = {
 };
 
 // 从接口中获取子应用配置,export 出的 qiankun 变量是一个 promise
-export const qiankun = fetch('/config').then(() => ({
-  // 注册子应用信息
-  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',  //本地调试
-    },
-    {
-      name: 'budgetManaSystem', // 唯一 id
-      //entry: '//localhost:8001',
-      entry: '//120.27.235.181:5000/perform/',  //开发
-      //entry: '//47.96.149.190:5000/perform/', //演示
-    },
-    {
-      name: 'PFMBackC', // 唯一 id
-      entry: '//120.27.235.181: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;
+  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/', // 开发
+        },
+      ]
+    }
+  }else{
+    // addQiankunMicroApps({
+    //   name:'pfmBackMana',
+    //   entry: '//120.27.235.181:5000/pfmManager/'
+    // });
+    const apps = localStorage.getItem('apps');
+
+    if(apps){
+      return {
+        apps: JSON.parse(apps)
+      }
+    }else{
+      const resp = await getQiankunMicroApps();
+      if (resp) {
+        localStorage.setItem('apps',JSON.stringify(resp.list));
+        return {
+          apps:resp.list?resp.list:resp
+        }
+      }
+    }
+  }
+  
+}
+
 
 //向子应用透传
 export function useQiankunStateForSlave() {
@@ -306,7 +335,7 @@ export function patchRoutes({ routes }: { routes: any }) {
         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,
+          component: require('@/pages/platform/setting/static/index.tsx').default,
         }));
 
         //console.log({paths});

+ 3 - 3
src/components/NavSelecter/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-06-29 11:05:04
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-08-17 09:39:08
+ * @LastEditTime: 2023-08-25 15:43:54
  * @FilePath: /KC-MiddlePlatform/src/components/NavSelecter/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -151,7 +151,7 @@ const NavSelecter = (props: NavSelecter) => {
                                                         <div className='rowWrap'>
                                                             {
                                                                 item.child?.map(a => {
-                                                                    if (a.type == 3) {
+                                                                    if (a.type == 3||a.type == 1) {
                                                                         return (
                                                                             <div className='tab' key={a.menuId}>
                                                                                 <Checkbox onChange={() => onChange({
@@ -161,7 +161,7 @@ const NavSelecter = (props: NavSelecter) => {
                                                                                     type: a.type,
                                                                                     systemId: a.systemId
                                                                                 })} checked={checkedIds.includes(a.menuId)} ></Checkbox>
-                                                                                <span style={{ marginLeft: 8 }}>{a.name}</span>
+                                                                                <span style={{ display:'inline-block',width:'75%',marginLeft: 8,whiteSpace:'nowrap',textOverflow:'ellipsis',overflow:'hidden' }}>{a.name}</span>
                                                                             </div>
                                                                         )
                                                                     }

+ 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 {

+ 53 - 38
src/components/topBar/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-16 09:12:37
- * @LastEditTime: 2023-06-16 11:17:35
+ * @LastEditTime: 2023-09-14 18:33:14
  * @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
@@ -107,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;
       }
@@ -129,11 +129,11 @@ const TopBar: React.FC<TopBarType> = (props) => {
       <div className='userPannel'>
         <div className='userPannelTab' onClick={() => _userPannelTabClick('SETTING')}>
           <SettingOutlined />
-         <span>设置</span> 
+          <span>设置</span>
         </div>
         <div className='userPannelTab' onClick={() => _userPannelTabClick('LOGOUT')}>
           <LogoutOutlined />
-          <span>退出</span> 
+          <span>退出</span>
         </div>
       </div>
     );
@@ -145,17 +145,33 @@ const TopBar: React.FC<TopBarType> = (props) => {
   }
 
   const goToHome = () => {
-    history.replace('/index');
-    setSystemTabs([]); //清空tab导航
-    onTabChange && onTabChange([]);
-    setCurrentSelectedTab(undefined);
-    set_pageTitle('欢迎进入医管平台');
-    setIfOpenPannel(false);
-    console.log('goToHome');
-    localStorage.removeItem('currentSelectedTab');
-    localStorage.removeItem('selectedKeys');
-    // localStorage.removeItem('visitedTabs');
-    localStorage.removeItem('openKeys');
+    
+    const go = ()=>{
+      history.replace('/index');
+      setSystemTabs([]); //清空tab导航
+      onTabChange && onTabChange([]);
+      setCurrentSelectedTab(undefined);
+      set_pageTitle('欢迎进入医管平台');
+      setIfOpenPannel(false);
+      console.log('goToHome');
+      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) => {
@@ -173,15 +189,15 @@ const TopBar: React.FC<TopBarType> = (props) => {
   }
 
 
-  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 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])
   }
 
 
@@ -285,8 +301,8 @@ const TopBar: React.FC<TopBarType> = (props) => {
     //_systemTabClickHandle(currentSelectedTabFromLocal);  //恢复选中的tab
 
     document.body.addEventListener('click', (e: any) => {
-
-      const classes = ['panel', 'left', 'typeBlockIcon', 'typeBlock', 'active', 'right', 'row', 'rowDetai', 'channelName', 'channelList', 'systemTab', 'channelIcon'];
+      // console.log({e});
+      const classes = ['panel','typeBlockName', 'left', 'typeBlockIcon', 'typeBlock','typeBlock active', 'active', 'right', 'row', 'rowDetai', 'channelName', 'channelList', 'systemTab', 'channelIcon','rowDetail'];
       if (e.target) {
         if (classes.includes(e.target.className)) {
           return
@@ -294,7 +310,6 @@ const TopBar: React.FC<TopBarType> = (props) => {
       }
       setIfOpenPannel(false);
     });
-
   }, []);
 
   return (
@@ -302,7 +317,7 @@ const TopBar: React.FC<TopBarType> = (props) => {
       <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={ifOpenPannel?'menu active':'menu'} onClick={() => openNav()}>
           <img src={require('../../../public/images/menu.png')} alt="" />
         </div>
         <span className='systemTitle' onClick={() => goSystemIndex(pageTitle)}>{pageTitle}</span>
@@ -323,13 +338,13 @@ const TopBar: React.FC<TopBarType> = (props) => {
               </div>
             ))}
           </div>
-          {systemTabs.length > 5 && <div className={showMoreTabPannel?'tabMore active':'tabMore'} onMouseEnter={() => set_showMoreTabPannel(true)} >
+          {systemTabs.length > 5 && <div className={showMoreTabPannel ? 'tabMore active' : 'tabMore'} onMouseEnter={() => set_showMoreTabPannel(true)} >
             {showMoreTabPannel && (<div className='morePannel' onMouseLeave={() => set_showMoreTabPannel(false)}>
               {
                 onTabSystemTabs_hide.map((item, index) => {
-                  return (<div key={index} className='moreItem' onClick={()=>moreItemClickHandle(item)}>
+                  return (<div key={index} className='moreItem' onClick={() => moreItemClickHandle(item)}>
                     {/* <Tooltip placement="right" title={item.name}> */}
-                      <span>{item.name}</span>
+                    <span>{item.name}</span>
                     {/* </Tooltip> */}
                   </div>)
                 })
@@ -342,11 +357,11 @@ const TopBar: React.FC<TopBarType> = (props) => {
         <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)}>
+        <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='avator'><img src={require('../../../public/images/avatar.png')} /></div>
             <div className='info'>
-              <span className='hospName'>{localStorage.getItem('currentHospName')}</span>
+              <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')} /> */}
@@ -357,26 +372,26 @@ const TopBar: React.FC<TopBarType> = (props) => {
       {
         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 className='typeBlockIcon'></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={require('../../../public/images/zhilianganquan.png')} alt="" />
+                      <img className='channelIcon' src={require(`../../../public/images/tixiicon${index>5?0:index}.png`)} alt="" />
                       <div className='rowDetail'>
                         <div className='channelName' onClick={() => goChannelIndex(item)}>{item.name}</div>
                         <div className='channelList'>

+ 151 - 14
src/components/topBar/style.less

@@ -59,8 +59,10 @@
   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: #3377FF;
@@ -109,6 +111,10 @@
         height: 16px;
       }
 
+      &.active {
+        background: rgba(254, 255, 255, 0.1);
+      }
+
       &:hover {
         background: rgba(254, 255, 255, 0.1);
       }
@@ -129,8 +135,7 @@
     flex-direction: row;
     justify-content: flex-end;
     align-items: center;
-    position: fixed;
-    right: 0;
+
 
     .tabWrap {
       display: flex;
@@ -360,14 +365,14 @@
     align-items: stretch;
     position: absolute;
     top: 48px;
-    left: 165px;
+    left:170px;
     min-height: 140px;
-    width: 80%;
-    border-radius: 0px 0px 0px 8px;
+    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;
@@ -386,9 +391,9 @@
         margin: 0 auto;
         border-radius: 4px;
 
-        &>img {
-          width: 32px;
-          height: 32px;
+        &>.typeBlockIcon {
+          width: 40px;
+          height: 40px;
           margin-bottom: 8px;
         }
 
@@ -399,31 +404,159 @@
           color: #515866;
         }
 
-        &.active {
-          background: #F5F7FA;
+        &:nth-child(1){
+
+          .typeBlockIcon {
+                background: url('../../../public/images/jingyiyiliao_gray.png');
+                background-size: contain;
+          }
 
-          &>span {
-            color: #3376FE;
+          &.active {
+            background: #F2F7FF;
+            .typeBlockIcon {
+              background: url('../../../public/images/jingyiyiliao.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+
+          &:hover {
+            // background: #F5F7FA;
+            .typeBlockIcon {
+              background: url('../../../public/images/jingyiyiliao.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+        }
+        &:nth-child(2){
+
+          .typeBlockIcon {
+                background: url('../../../public/images/HBI_gray.png');
+                background-size: contain;
+          }
+
+          &.active {
+            background:#F2F7FF;
+            .typeBlockIcon {
+              background: url('../../../public/images/HBI.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+
+          &:hover {
+            .typeBlockIcon {
+              background: url('../../../public/images/HBI.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+        }
+        &:nth-child(3){
+
+          .typeBlockIcon {
+                background: url('../../../public/images/zhongtaiguanli_gray.png');
+                background-size: contain;
+          }
+
+          &.active {
+            background:#F2F7FF;
+            .typeBlockIcon {
+              background: url('../../../public/images/zhongtaiguanli.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+
+          &:hover{
+            .typeBlockIcon {
+              background: url('../../../public/images/zhongtaiguanli.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+        }
+        &:nth-child(4){
+
+          .typeBlockIcon {
+                background: url('../../../public/images/guanlizhongxin_gray.png');
+                background-size: contain;
+          }
+
+          &.active {
+            background:#F2F7FF;
+            .typeBlockIcon {
+              background: url('../../../public/images/guanlizhongxin.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
+          }
+
+          &:hover{
+            .typeBlockIcon {
+              background: url('../../../public/images/guanlizhongxin.png');
+              background-size: contain;
+            }
+  
+            &>span {
+              color: #3376FE;
+            }
           }
         }
       }
+      
     }
 
     .right {
+      position: relative;
       width: calc(100% - 140px);
       height: 100%;
       padding: 2% 2.5%;
 
+      .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 {
@@ -453,7 +586,7 @@
             align-items: center;
 
             .systemTab {
-              width: 24%;
+              width:180px;
               height: 32px;
               line-height: 32px;
               background: #FFFFFF;
@@ -483,6 +616,10 @@
             }
           }
         }
+
+        &: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;
   };
 

+ 38 - 5
src/global.less

@@ -233,6 +233,7 @@ input {
       font-weight: 500;
       color: #17181A;
       border-bottom: none;
+      padding-bottom: 0;
     }
 
     .kcmp-ant-modal-body {
@@ -279,8 +280,8 @@ input {
 
 
 *::-webkit-scrollbar {
-  width: 2px;
-  height: 2px;
+  width: 4px !important;
+  height: 4px !important;
   /**/
 }
 
@@ -290,22 +291,35 @@ input {
 }
 
 *::-webkit-scrollbar-thumb {
-  background: #bfbfbf;
+  background: rgba(228,231,235,0.7) !important;
   border-radius: 10px;
 }
 
 *::-webkit-scrollbar-thumb:hover {
   width: 4px;
   height: 4px;
-  background: rgb(136, 135, 135);
+  background: rgba(228,231,235,0.7);
 }
 
 *::-webkit-scrollbar-corner {
-  background: rgb(136, 135, 135);
+  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;
+     }
+}
+
+
 
 //--------------------
 
@@ -413,3 +427,22 @@ input {
     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;
+}

+ 18 - 18
src/layouts/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 13:56:33
- * @LastEditTime: 2023-06-16 11:24:51
+ * @LastEditTime: 2023-09-26 17:27:02
  * @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
@@ -35,7 +35,7 @@ const TopHoc = ({ currentSelectedSys, openedSysLists, navData,set_emptyPageConte
       // localStorage.removeItem('visitedTabs');
       localStorage.removeItem('openKeys');
   
-      if(data.contentType == '4'){
+      if(data.contentType == 4){
           //空白页面
           if(data.isSetupMenu){
             //体系菜单掩藏子应用的menu
@@ -66,21 +66,21 @@ 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.replace('/personalCenter');
+      history.push('/personalCenter');
     }
   };
 
@@ -110,7 +110,7 @@ export default function Layout({ children, location, route, history, match }: IR
   const getNavData = async () => {
     const nav = await getUserPlatformNav();
     if (nav) {
-      set_navData(nav);
+      set_navData(nav as any);
 
     }
   }
@@ -192,7 +192,7 @@ export default function Layout({ children, location, route, history, match }: IR
           </div>
         )
       }
-      {!isEmpty&&(<div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll',minWidth:'1280px' }}>{children}</div>)}
+      {!isEmpty&&(<div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll',minWidth:1280 }}>{children}</div>)}
     </ProLayout>
   );
 }

+ 70 - 10
src/pages/login/index.tsx

@@ -1,14 +1,14 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 14:58:08
- * @LastEditTime: 2023-06-15 15:50:53
+ * @LastEditTime: 2023-09-18 15:47:56
  * @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,9 @@ 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 { getAllParams } from '@/service';
 
 const { Option } = Select;
 
@@ -32,13 +33,20 @@ 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>(undefined);  //当前选中的院区
+
+  const [hospSign,set_hospSign] = useState<undefined|string>(undefined);  //登陆用的hospSign
 
   
 
@@ -53,9 +61,15 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
           data.map((t) => ({
             name: t.name,
             value: t.hospSign,
+            id:t.id,
+            hospAbbreviation:t.hospAbbreviation,
+            loadType:t.loadType
           })),
         );
         setCurrentHospName(data[0].systemName);
+        set_currentSelectedSubHop(data[0]);
+        localStorage.setItem('currentSelectedSubHop',JSON.stringify(data[0]));
+        localStorage.setItem('hospAbbreviation',data[0].hospAbbreviation);
         localStorage.setItem('currentHospName',data[0].systemName);
       }
       
@@ -64,7 +78,6 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
 
   const onFinish = async (values: LoginPageTypes.LoginInfo) => {
     setIfLoading(true);
-    const hospSign = localStorage.getItem('hospSign');
     if (!hospSign) {
       notification.error({
         message: '网址标记缺失,请检查网址!',
@@ -84,8 +97,50 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
     if (resp) {
       localStorage.setItem('userData', JSON.stringify(resp));
       setInitialState((s) => ({ ...s, userData: resp }));
-      history.replace('/index');
+      if(currentSelectedSubHop.loadType){
+           const lastLoginSysData = await getLastLoginSys({hospId:currentSelectedSubHop.hospId,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 getAllParams();
+            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);
     }
   };
@@ -119,6 +174,7 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
 
     const hospSign = history.location.query?.hospSign as string;
     localStorage.setItem('hospSign', hospSign);
+    set_hospSign(hospSign);
 
     return ()=>{
       window.removeEventListener('resize',handleResize);
@@ -166,15 +222,19 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
                     allowClear={false}
                     style={{ width: 180 }}
                     defaultValue={subHospList[0].value}
-                    onSelect={(val:any)=>{
-                      localStorage.removeItem('hospSign');
-                      localStorage.setItem('hospSign', val);
+                    onSelect={(val:any,option)=>{
+                      // localStorage.removeItem('hospSign');
+                      // localStorage.setItem('hospSign', val);
+                      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>
                       );

+ 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;

+ 83 - 7
src/pages/platform/_layout.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-06 15:25:39
- * @LastEditTime: 2023-08-07 13:26:58
+ * @LastEditTime: 2023-09-21 17:14:23
  * @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
@@ -16,9 +16,15 @@ import { TreeItemType } from '@/utils';
 import { SpacicalPageParamsType } from '@/typings';
 import { Key, useEffect, useState } from 'react';
 
-import { FileOutlined, FolderOutlined } 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');
   const [openKeys, set_openKeys] = useState<string[]>([]);
@@ -27,6 +33,8 @@ export default function Layout({ children, location, route, history, match, ...r
   const [isShowPageMenu, set_isShowPageMenu] = useState(true);
   const [isEmpty, set_isEmpty] = useState(false);
 
+  const [collapsed,set_collapsed] = useState(false);
+
   const [pageUrl, set_pageUrl] = useState<string | undefined>(undefined);
   
   const { pathname } = location;
@@ -53,6 +61,27 @@ export default function Layout({ children, location, route, history, match, ...r
     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");
@@ -62,6 +91,17 @@ export default function Layout({ children, location, route, history, match, ...r
     // }
   }
 
+
+
+  if(initialState?.currentSelectedSys){
+      const {type,url,contentType} = initialState.currentSelectedSys;
+      if(type == 1&&contentType == 6){
+        return (
+          <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={url} onLoad={() => adjustIframe()} ></iframe>
+        )
+      }
+  }
+
   //临时演示处理
   
   if (location.pathname == '/platform/costMana') {
@@ -145,15 +185,26 @@ export default function Layout({ children, location, route, history, match, ...r
         display: 'none',
       }}
       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={() => {
@@ -183,7 +234,6 @@ export default function Layout({ children, location, route, history, match, ...r
         },
         request: async () => {
 
-
           if (initialState && initialState.currentSelectedSys) {
             const { systemId, menuId, path } = initialState.currentSelectedSys;
             if (systemId || menuId) {
@@ -286,9 +336,34 @@ export default function Layout({ children, location, route, history, match, ...r
                 icon: <FileOutlined />,
               }))
 
+              const imgNode = (props: any) => {
+                return <IconFont type='icon-pingtaiguanli'  />
+              };
+
+              const systemSet = (props: any) => {
+                return <IconFont type='icon-xitongshezhi'  />
+              };
+
+              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];
 
 
@@ -302,6 +377,7 @@ export default function Layout({ children, location, route, history, match, ...r
       onPageChange={(location) => { }}
       layout="side"
       navTheme="light"
+      
     >
       {
         isEmpty && (
@@ -326,7 +402,7 @@ export default function Layout({ children, location, route, history, match, ...r
               <title>精益管理中台</title>
             </Helmet>
 
-            <div className="page" style={{ height: 'calc(100vh - 80px)', overflowY: 'scroll'}}>
+            <div className="page" style={{height: 'calc(100vh - 80px)', overflowY: 'scroll'}}>
               {children}
             </div>
           </PageContainer>

+ 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;
   }

+ 103 - 58
src/pages/platform/setting/hospManage/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 15:22:48
- * @LastEditTime: 2023-08-18 19:06:08
+ * @LastEditTime: 2023-09-15 16:59: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/hospManage/index.tsx
@@ -12,7 +12,7 @@ import { hospManageModelState, ConnectProps, Loading, connect } from 'umi';
 import { Button, Checkbox, Divider, Drawer, Dropdown, Input, Popconfirm, Switch, Table, Tree, TreeProps, message } from 'antd';
 import KCTable from '@/components/kcTable';
 import type { ProColumns } from '@ant-design/pro-table';
-import { getAllHosp, getHospOwnSys, getHospYoushuAccounts, getMenuRelaPerm, hospInit, saveHospMenuApiPerm, setReadOnly } from '@/service/hospList';
+import { getAllHosp, getHospOwnSys, getHospYoushuAccounts, getMenuRelaPerm, hospInit, saveHospMenuApiPerm, setIfCheckAll, setReadOnly } from '@/service/hospList';
 import { TableRequestParamsType } from '@/typings';
 import ActModal from './modals/modal';
 import './style.less';
@@ -51,19 +51,18 @@ interface PageProps extends ConnectProps {
   loading: boolean;
 }
 
-
 interface TreeNode {
-  [key:string]:any;
+  [key: string]: any;
   children?: TreeNode[];
 }
 
-function findParents(
-  nodes: TreeNode[], 
-  targetId: string, 
+export function findParents(
+  nodes: TreeNode[],
+  targetId: string,
   path: TreeNode[] = []
 ): TreeNode[] | null {
   for (const node of nodes) {
-    if (node.menuId === targetId) {
+    if (node.menuId == targetId) {
       return path;
     }
 
@@ -76,7 +75,7 @@ function findParents(
   return null;
 }
 
-function extractAttributeValues(tree: TreeNode, attributeName: keyof TreeNode): any[] {
+export function extractAttributeValues(tree: TreeNode, attributeName: keyof TreeNode): any[] {
   let values: any[] = [];
 
   // 提取当前节点的属性值
@@ -111,13 +110,15 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
   const [oldSelectedMenuIds, set_oldSelectedMenuIds] = useState<any[]>([]);
 
-  const [checkedMenuParentsIds,set_checkedMenuParentsIds] = useState<Key[]>([]);  //所有需要保存的菜单id
+  const [checkedMenuParentsIds, set_checkedMenuParentsIds] = useState<Key[]>([]);  //所有需要保存的菜单id
 
   const [drawerVisible, set_drawerVisible] = useState(false);
 
   const [ifFrozze, set_ifFrozze] = useState(false); //冻结勾选菜单及功能操作
 
-  const [hospAllMenuTree,set_hospAllMenuTree] = useState<any[]>([]);  //医院全量菜单
+  const [hospAllMenuTree, set_hospAllMenuTree] = useState<any[]>([]);  //医院全量菜单
+
+  const [expandedRowKeys,set_expandedRowKeys] = useState<Key[]>([]);
 
   const columnsData: ProColumns<TableListItem>[] = [
     {
@@ -165,7 +166,7 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           const options = record.functionList.map((item: any, index: number) => ({ label: item.name, value: item.code }))
 
           const needItem = checkBoxCodes.filter(a => a.menuId == record.menuId);
-          
+
           const codes = (needItem && needItem.length > 0 && needItem[0].function) ? needItem[0].function.map((a: any) => a.code) : [];
 
           const onCheckGroupChange = (checkedValue: CheckboxValueType[]) => {
@@ -187,9 +188,13 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                 function: transfered
               });
 
-              const menuIdsArr = _temp.map((item: any) => item.menuId);
+              const thisParents = findParents(hospAllMenuTree, record.menuId);
 
-              set_checkedTableMenuIds([...menuIdsArr])
+              const ids = (thisParents as TreeNode[]).map((a) => a.menuId);
+
+              set_checkedMenuParentsIds([...checkedMenuParentsIds, ...ids, record.menuId]);
+
+              set_checkedTableMenuIds([...checkedMenuParentsIds, ...ids, record.menuId])
 
               set_checkBoxCodes([..._temp]);
             } else {
@@ -295,13 +300,14 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
     set_drawerTablereload(false);
     if (currentSelectedTreeNode) {
-      const resp = await getMenuRelaPerm({hospId: record.id,systemId:currentSelectedTreeNode.code});
+      const resp = await getMenuRelaPerm({ hospId: record.id, systemId: currentSelectedTreeNode.code });
       if (resp) {
+        const {checkAll = 0,menuList=[]} = resp;
         let temp: { menuId: any; function: any; }[] = [];
+
         const setTreeRecursion = (data: any) => {
           data.map((item: any, index: number) => {
 
-
             if (item.type == 1) {
               //菜单
               temp.push({
@@ -317,17 +323,18 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           });
 
         }
-         
-        let initCheckedMenuIds:any[] = [];
 
-        resp.forEach((item:any) => {
-          const ids = extractAttributeValues(item,'menuId');
+        let initCheckedMenuIds: any[] = [];
+
+        menuList.forEach((item: any) => {
+          const ids = extractAttributeValues(item, 'menuId');
           initCheckedMenuIds = initCheckedMenuIds.concat(ids);
         });
 
         set_checkedMenuParentsIds(initCheckedMenuIds);
-
-        setTreeRecursion(resp);
+        
+        setTreeRecursion(menuList);
+        set_ifFrozze(checkAll?true:false);
 
         set_checkBoxCodes(temp);
         set_checkedTableMenuIds(temp.map((a: any) => a.menuId));
@@ -351,10 +358,30 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
     set_drawerTablereload(false);
     if (currentSelectedTreeNode) {
-      const resp = await getTableDataRequest({...params,systemId:currentSelectedTreeNode.code});
+      const resp = await getTableDataRequest({ ...params, systemId: currentSelectedTreeNode.code });
       if (resp) {
-
+        let expandKeys:Key[] = [];
         set_hospAllMenuTree(resp);
+
+        const getParentsIds = (data: any) => {
+          data.map((item: any, index: number) => {
+
+            if(item.type == 0){
+              expandKeys.push(item.menuId)
+            }
+
+            if (item.children && item.children.length != 0) {
+              getParentsIds(item.children);
+            }
+
+          });
+
+        }
+
+        getParentsIds(resp);
+        set_expandedRowKeys(expandKeys);
+
+
         return {
           data: resp,
           success: true,
@@ -378,19 +405,19 @@ const DrawerActBtn = ({ record }: { record: any }) => {
       old.splice(old.findIndex(a => a == item.menuId), 1);
 
       return { ...item, hospId: record.id, systemId: currentSelectedTreeNode.code }
-      
+
     });
 
     const needCancelMenus = old.map(a => ({ hospId: record.id, systemId: currentSelectedTreeNode.code, function: [], menuId: a }));
 
     const data = {
-      hospId:record.id,
+      hospId: record.id,
       systemId: currentSelectedTreeNode.code,
-      menuIds:[...new Set(checkedMenuParentsIds)],
-      functionRequestList:[...result,...needCancelMenus]
+      menuIds: [...new Set([...checkedMenuParentsIds])],
+      functionRequestList: checkedMenuParentsIds.length == 0 ? [] : [...result, ...needCancelMenus]
     };
 
-    const resp = await saveHospMenuApiPerm(result.length == 0 ? [{ hospId: record.id, systemId: currentSelectedTreeNode.code }] : data);
+    const resp = await saveHospMenuApiPerm(data);
 
     if (resp) {
       set_drawerTablereload(true);
@@ -405,8 +432,6 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   }
 
   const drawerTableDataSearchHandle = (paramName: string) => {
-
-
     set_drawerTableDataFilterParams({
       ...drawerTableDataFilterParams,
       [`${paramName}`]: drawerTableDataSearchKeywords
@@ -422,7 +447,13 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
   const oneKeySetAll = async (bool: boolean) => {
     set_ifFrozze(bool);
-    const resp = await saveHospMenuApiPerm([{ hospId: record.id, systemId: currentSelectedTreeNode.code, checkAll: bool ? 1 : 0 }]);
+
+    const data = {
+      hospId: record.id,
+      systemId: currentSelectedTreeNode.code,
+      type: bool ? '1': '0'
+    };
+    const resp = await setIfCheckAll(data);
     // if (resp) {
     //   set_drawerTablereload(true);
     //   set_checkBoxCodes([]);
@@ -449,6 +480,7 @@ const DrawerActBtn = ({ record }: { record: any }) => {
       if (treeData[0].children && treeData[0].children.length > 0) {
         const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
 
+        setAutoExpandParent(true);
         set_currentSelectedTreeNode(node);
         setExpandedKeys([nodeParent.code]);
       }
@@ -460,6 +492,11 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   useEffect(() => {
     if (drawerVisible) {
       getTreeReqFunc(record.id);
+    } else {
+      set_drawerVisible(false);
+      set_currentSelectedTreeNode(undefined);
+      set_treeData([]);
+      setExpandedKeys([]);
     }
   }, [drawerVisible]);
 
@@ -476,12 +513,13 @@ const DrawerActBtn = ({ record }: { record: any }) => {
         closable: false,
         destroyOnClose: true,
         extra: <div>anniu</div>,
+
       }}
       submitter={false}
     >
       <div className='setApiPermDrawer'>
         <div className='topbar'>
-          <div className='title'>{`院区功能权限设置(${record.hospName})`}</div>
+          <div className='title'>{`院区菜单权限设置(${record.hospName})`}</div>
           <div className='btnGroup'>
             <span className={ifFrozze ? 'clearBtn disabled' : 'clearBtn'} onClick={() => clearFunction()}>清除功能权限</span>
             <span className='cancel' onClick={() => onCancel()}>取消</span>
@@ -496,7 +534,6 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                 placeholder="请输入"
                 size='small'
                 allowClear
-
                 style={{ marginBottom: 16 }}
                 onChange={onTreeSearchKeyChange}
                 suffix={
@@ -580,19 +617,26 @@ const DrawerActBtn = ({ record }: { record: any }) => {
               </div>
 
               <div className={'btnGroup'}>
-                <a style={{ color: '#17181A' }}><Switch style={{ position: 'relative', marginRight: 4 }} size='small' onChange={(bool) => oneKeySetAll(bool)} />全部</a>
+                <a style={{ color: '#17181A' }}><Switch checked={ifFrozze} style={{ position: 'relative', marginRight: 4 }} size='small' onChange={(bool) => oneKeySetAll(bool)} />全部</a>
                 {/* <UpDataActBtn key={'act'} record={undefined} type='ADD' /> */}
               </div>
 
             </div>
             {currentSelectedTreeNode && <KCTable
               tableAlertRender={false}
-              onLoad={()=>setInitCheckData()}
+              scroll={{y:`calc(100vh - 150px)`}}
+              onLoad={() => setInitCheckData()}
+              expandable={{
+                expandedRowKeys:expandedRowKeys,
+                onExpandedRowsChange(expandedKeys) {
+                    set_expandedRowKeys(expandedKeys as Key[])
+                },
+              }}
               rowSelection={{
                 // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
                 // 注释该行则默认不显示下拉选项
                 checkStrictly: false,
-
+                hideSelectAll: true,
                 onChange(selectedRowKeys, selectedRows, info) {
                   //console.log({selectedRowKeys, selectedRows, info});
                   if (selectedRowKeys.length == 0) {
@@ -613,15 +657,15 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                   if (selected) {
                     //选中
 
-                    const parents = findParents(hospAllMenuTree,record.menuId);
-                    const ids = (parents as TreeNode[]).map((a)=>a.menuId);
-                    
+                    const parents = findParents(hospAllMenuTree, record.menuId);
+                    const ids = (parents as TreeNode[]).map((a) => a.menuId);
 
-                    if(record.children){
-                      const childIds = extractAttributeValues(record,'menuId');
-                      set_checkedMenuParentsIds([...checkedMenuParentsIds,...ids,...childIds,record.menuId]);
-                    }else{
-                      set_checkedMenuParentsIds([...checkedMenuParentsIds,...ids,record.menuId]);
+
+                    if (record.children) {
+                      const childIds = extractAttributeValues(record, 'menuId');
+                      set_checkedMenuParentsIds([...checkedMenuParentsIds, ...ids, ...childIds, record.menuId]);
+                    } else {
+                      set_checkedMenuParentsIds([...checkedMenuParentsIds, ...ids, record.menuId]);
                     }
 
                     selectedRows.forEach(a => {
@@ -657,9 +701,9 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
                   } else {
 
-                    const ids = extractAttributeValues(record,'menuId');
+                    const ids = extractAttributeValues(record, 'menuId');
 
-                    const filtedMenuIds = checkedMenuParentsIds.filter((a)=>!ids.includes(a));
+                    const filtedMenuIds = checkedMenuParentsIds.filter((a) => !ids.includes(a));
                     set_checkedMenuParentsIds(filtedMenuIds);
 
                     let _tempCheckedCodes = [...checkBoxCodes];
@@ -694,6 +738,7 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
   const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
   const [tabIds, set_tabIds] = useState<Key[]>([]);
   const [open, set_open] = useState(false);
+  const [currentEditHosp,set_currentEditHosp]  = useState<undefined|any>(undefined);
   const [navSelecterData, set_navSelecterData] = useState<NavSelecterData[]>([]);
 
 
@@ -702,9 +747,8 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
 
   const columns: ProColumns<TableListItem>[] = [
     {
-      title: 'ID',
+      title: '院区ID',
       dataIndex: 'id',
-      hideInTable: true,
     },
     {
       title: '院区名称',
@@ -728,7 +772,7 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
     // },
     {
       title: '主院名称',
-      dataIndex: 'mainHospName',
+      dataIndex: 'parentName',
     },
     {
       title: '医院等级',
@@ -740,7 +784,7 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
     // },
     {
       title: '医院性质',
-      dataIndex: 'hospitalNature',
+      dataIndex: 'hospitalNatureName',
     },
     // {
     //   title: '医院编码',
@@ -750,10 +794,10 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
       title: '系统名称',
       dataIndex: 'systemName',
     },
-    {
-      title: '互通',
-      dataIndex: 'dataShare',
-    },
+    // {
+    //   title: '互通',
+    //   dataIndex: 'dataShare',
+    // },
     // {
     //   title: '变更日期',
     //   dataIndex: 'updateTime',
@@ -798,9 +842,9 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
             { key: '1', label: <a key="link4" onClick={() => youshuAccountBind(record)}>报告</a> },
             // { key: '2', label: <DrawerActBtn record={record} /> },
             // { key: '3', label: <a key="link5" onClick={() => initHospData(record)}>初始化</a> },
-            { key: '4', label: <a key="link6" onClick={() => setOnlyRead(record)}>初始化只读</a> },
+            { key: '4', label: <a key="link6" onClick={() => setOnlyRead(record)}>按系统初始化</a> },
             {
-              key: '6', label: <a key="link5" onClick={() => initHospData(record)}>初始化</a>,
+              key: '6', label: <a key="link5" onClick={() => initHospData(record)}>按菜单初始化</a>,
             },
             {
               key: '5', label: <a key="link7" onClick={() => editHandle(record)}>编辑</a>,
@@ -884,6 +928,7 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
     const { selectedMenuIds, allMenuVO } = await getSpacifyHospMenu({ hospId: record.id });
     set_navSelecterData(allMenuVO);
     set_tabIds(selectedMenuIds);
+    set_currentEditHosp(record);
 
     dispatch &&
       dispatch({
@@ -969,7 +1014,7 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
       <ActModal {...state} dispatch={dispatch} />
       {
         open && (
-          <NavSelecter title='系统权限设置' data={navSelecterData} onVisibleChange={(bool) => set_open(bool)} value={tabIds} onChecked={onCheckedHandle} />
+          <NavSelecter title={`系统权限设置(${currentEditHosp?.hospName})`} data={navSelecterData} onVisibleChange={(bool) => set_open(bool)} value={tabIds} onChecked={onCheckedHandle} />
         )
       }
       <div className='toolBar'>

+ 34 - 5
src/pages/platform/setting/hospManage/modals/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-08-16 17:02:37
+ * @LastEditTime: 2023-09-28 11:14: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/setting/userManage/modal.tsx
@@ -107,10 +107,17 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     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;
@@ -132,6 +139,8 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     if (tableAct == TableActType.EDIT) {
       return {
         ...currentEdit,
+        parentId:currentEdit?.parentId,
+        parentName:currentEdit?.parentName,
         isDataShare: currentEdit?.dataShare == '是' ? 1 : 0,
       };
     }
@@ -174,7 +183,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
 
       return {
            defaultvalue:defaultValue[0]?defaultValue[0].value:'',
-           list:dataArr.map(t=>({label:t.value,value:t.code,defaultValue:t.defaultValue}))
+           list:dataArr.map(t=>({label:t.name,value:t.code,defaultValue:t.defaultValue}))
       }
     }
     return {
@@ -206,7 +215,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
       visible={isShowModal}
       onVisibleChange={onVisibleChangeHandle}
       layout="horizontal"
-      width={800}
+      width={480}
       initialValues={setInitialValues()}
       title={setModalTitle()}
       labelCol={{ 
@@ -260,7 +269,10 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
                   <KCProSelect
                     label="选择主院"
                     width="md"
-                    name="mainHospId"
+                    name="parentId"
+                    fieldProps={{
+                        labelInValue:true
+                    }}
                     request={async () => {
                       const hospList:any[] = await getHospList();
                       if (hospList) {
@@ -289,6 +301,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             request={async () => {
               return setSelectorData('HOSPITAL_LEVEL').list;    
             }}
+            fieldProps={{showSearch:true}}
             rules={[
               {
                 required: true,
@@ -303,6 +316,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             request={async () => {
               return setSelectorData('HOSPITAL_TYPE').list;
             }}
+            fieldProps={{showSearch:true}}
             rules={[
               {
                 required: true,
@@ -317,6 +331,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
             request={async () => {
               return setSelectorData('HOSPITAL_NATURE').list;
             }}
+            fieldProps={{showSearch:true}}
             rules={[
               {
                 required: true,
@@ -355,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 && (

+ 2 - 2
src/pages/platform/setting/hospManage/model.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2023-08-18 17:24:40
+ * @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;

+ 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;
+        }
+      }
+
+    }
+  }
+
+}

+ 6 - 2
src/pages/platform/setting/menuManage/modals/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-05-10 10:52:16
+ * @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
@@ -298,6 +298,10 @@ const ActModal: React.FC<ActModalProps> = ({
                             label: '静态',
                             value: 5,
                           },
+                          {
+                            label: '外部系统嵌入',
+                            value: 6,
+                          },
                         ]}
                         rules={[
                           {
@@ -325,7 +329,7 @@ const ActModal: React.FC<ActModalProps> = ({
                         {({ contentType }) => {
                           return (
                             contentType &&
-                            contentType != 0 && contentType != 4 && (
+                            contentType != 0 && contentType != 4&&contentType != 6 && (
                               //页面内容为非一般时,填写对应有数Id
                               <ProFormDigit
                                 label="报告Id"

+ 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;

+ 252 - 169
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-05-12 09:41:18
+ * @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,getParamsManaTableData, 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:ProColumns[] = [
+
+
+    const columns: ProColumns[] = [
+        {
+            title: '参数代码',
+            dataIndex: 'code',
+
+        },
         {
             title: '参数名称',
             dataIndex: 'name',
@@ -41,30 +63,29 @@ export default function ParamsMana() {
         {
             title: '参数说明',
             dataIndex: 'description',
+            ellipsis: true
         },
         {
             title: '参数值',
             dataIndex: 'value',
-            width:200,
-            ellipsis:true
+            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: '操作',
@@ -86,7 +107,14 @@ 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) => {
@@ -113,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);
             }
@@ -136,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
@@ -162,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>
         )
     }
@@ -241,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} reload={reload} rowKey='id' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
+
         </div>
     )
 }

+ 10 - 4
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-04-13 13:28:21
+ * @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
  */
@@ -51,9 +51,14 @@ export const getParamsManaTableData = (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}
+    });
+  }
 };
 
 
@@ -113,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;
+      }
+    }
+
+  }
+
+}

+ 265 - 120
src/pages/platform/setting/pubDicMana/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-10 17:36:08
+ * @LastEditTime: 2023-09-22 14:41:14
  * @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,28 +14,41 @@ 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',
+});
 
 const PubDicMana = () => {
 
     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 [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 columns = [
         {
@@ -54,19 +67,24 @@ const PubDicMana = () => {
         {
             title: '默认',
             dataIndex: 'data.0.dictDefault',
-            render: (_: any, record:any) => {
+            render: (_: any, record: any) => {
                 return record.dictDefault == 1 ? '是' : '否'
             },
 
         },
         {
             title: '序号',
-            dataIndex: 'dictSort',
+            dataIndex: pageType == 1?'dictSort':'sort',
 
         },
         {
-            title: '适用院区',
-            dataIndex: 'hospName',
+            title: '扩展1',
+            dataIndex: 'expandOne',
+
+        },
+        {
+            title: '扩展2',
+            dataIndex: 'expandTwo',
 
         },
         {
@@ -92,47 +110,46 @@ const PubDicMana = () => {
 
 
     const getTableData = async (params: any) => {
-        const { dictType } = params;
-        if (dictType) {
-            const resp = await getPubDicRelaTbaleData(params);
+        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,
-                    pageSize: resp.pageSize,
-                    totalPage: resp.totalPage,
                 }
             }
         }
         return []
     }
 
-    const getTypeList = async () => {
-        const resp = await getData({ pageSize: 1000, current: 1 });
-        if (resp) {
-            set_typeList(resp.list);
-            set_showTypeListArr(resp.list);
-        }
-    }
 
     const delTableData = async (record: any) => {
-          const resp = await delData(record.dictDataId);
-          if(resp){
-            set_reload(true);
-          }
+        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") => {
-        if (type == 'EDIT') {
-            const resp = await editPubDicRelaTbaleData({...formVal});
+        const currentSelectedHop = localStorage.getItem('currentSelectedSubHop');
+        let hospId = '0';
+        if (currentSelectedHop) {
+            const { id } = JSON.parse(currentSelectedHop);
+            hospId = id
+        }
+        if (type == 'EDIT' && pageType) {
+            const resp = await editPubDicRelaTbaleData(pageType == 1?{ ...formVal, hospId,dictType: currentSelectedTreeNode?.dictType }:{...formVal, hospId,type: currentSelectedTreeNode?.dictType}, pageType);
             if (resp) {
                 set_reload(true);
             }
         }
-        if (type == 'ADD') {
-            const resp = await addPubDicRelaTbaleData({...formVal,dictType:currentSelectedType?.dictType});
+        if (type == 'ADD' && pageType) {
+            const resp = await addPubDicRelaTbaleData(pageType == 1?{ ...formVal, hospId, dictType: currentSelectedTreeNode?.dictType }:{...formVal, hospId, type: currentSelectedTreeNode?.dictType}, pageType);
             if (resp) {
                 set_reload(true);
             }
@@ -142,7 +159,7 @@ const PubDicMana = () => {
     }
 
     const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
-       
+
         return (
             <ModalForm
                 title={`${type == 'EDIT' ? '编辑' : '新增'}公用字典(职称)`}
@@ -152,7 +169,7 @@ const PubDicMana = () => {
                     type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
                 }
                 onFinish={(val) => {
-                    return updateTable(type == 'EDIT'?{...val,dictDataId:record.dictDataId}:val, type);
+                    return updateTable(type == 'EDIT' ? (pageType == 1?{ ...val, dictDataId: record.dictDataId }:{...val,id: record.id}) : val, type);
                 }}
             >
                 <ProFormText
@@ -173,10 +190,10 @@ const PubDicMana = () => {
                     placeholder="请输入"
 
                 />
-                <ProFormDigit label="顺序号:" name="dictSort" rules={[{ required: true, message: '顺序号不能为空!' }]} />
+                <ProFormDigit label="顺序号:" name={pageType == 1 ? 'dictSort' : 'sort'} rules={[{ required: true, message: '顺序号不能为空!' }]} />
 
                 <ProFormRadio.Group
-                    name="dictDefault"
+                    name={pageType == 1 ? 'dictDefault' : 'defaultFlag'}
                     label="默认:"
                     fieldProps={{
                         buttonStyle: 'solid'
@@ -193,37 +210,29 @@ const PubDicMana = () => {
                     ]}
                     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 []
+                {
+                    true && (
+                        <>
+                            <ProFormText
+                                name="expandOne"
+                                label="扩展一:"
+                                placeholder="请输入"
 
-                    }}
-                    rules={[{ required: true, message: '院区不能为空!' }]}
-                />
+                            />
+                            <ProFormText
+                                name="expandTwo"
+                                label="扩展二:"
+                                placeholder="请输入"
 
+                            />
+                        </>
+                    )
+                }
             </ModalForm>
         )
     }
 
-    const editHandle = (record: any) => {
 
-    }
 
     const tableDataSearchHandle = (paramName: string) => {
 
@@ -234,102 +243,236 @@ const PubDicMana = () => {
         })
     }
 
-    useEffect(()=>{
-        if(currentSelectedType){
-            set_tableDataFilterParams({...tableDataFilterParams,dictType:currentSelectedType.dictType})
+
+    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 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);
+            }
+        }
+    };
+    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('初始化成功!');
+                    }
+                }
+            },
+        })
+    }
+
+    useEffect(() => {
+
+        if (currentSelectedTreeNode) {
+            console.log({ currentSelectedTreeNode });
+            set_reload(true)
         }
-    },[currentSelectedType])
+
+    }, [currentSelectedTreeNode]);
 
     useEffect(() => {
-        if (showTypeListArr.length > 0) {
-            set_currentSelectedType(showTypeListArr[0]);
-            set_tableDataFilterParams({ ...tableDataFilterParams, dictType: showTypeListArr[0].dictType });
+        //初始化左侧树结构数据后
+
+        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]);
+            }
         }
-    }, [showTypeListArr])
+    }, [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(() => {
-        getTypeList();
-    }, [])
+        if (pageType) getTreeReqFunc(pageType);
+    }, [pageType]);
+
 
     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);
-                    }}
-                
-                />
+                <div className='search'>
+                    <Input
+                        className='searchInput'
+                        placeholder="请输入"
+                        size='small'
+                        allowClear
+
+                        style={{ marginBottom: 16 }}
+                        onChange={onTreeSearchKeyChange}
+                        suffix={
+                            <SearchIcon type='iconsousuo' />
+                        }
+                    />
+                </div>
                 <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>
-                            )
-                        })
+                        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'
+
+                                        }}>{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>
-                            <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({
+                                        set_tableDataFilterParams(pageType == 1?{
                                             ...tableDataFilterParams,
                                             typeName: ''
-                                        });
+                                        }:{...tableDataFilterParams,dictName:''});
                                     }
                                 }}
-                                onSearch={() => tableDataSearchHandle('typeName')}
+                                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 }}>
-                    {currentSelectedType && <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='dictDataId' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />}
+                    {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>
@@ -338,3 +481,5 @@ const PubDicMana = () => {
 
 
 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;

+ 263 - 46
src/pages/platform/setting/pubDicTypeMana/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-24 12:10:56
+ * @LastEditTime: 2023-09-08 09:58:46
  * @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
  */
@@ -11,15 +11,27 @@
 
 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 { 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';
+
+
+const SearchIcon = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
 
 
 export default function PubDicTypeMana() {
@@ -27,12 +39,18 @@ 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 [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 = [
+
+    const columns:ProColumns[] = [
         {
             title: '类型名称',
             dataIndex: 'dictName',
@@ -46,11 +64,13 @@ export default function PubDicTypeMana() {
             title: '说明',
             dataIndex: 'remark',
         },
-        // {
-        //     title: '院区',
-        //     dataIndex: 'hospName',
-
-        // },
+        {
+            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',
@@ -62,7 +82,7 @@ export default function PubDicTypeMana() {
                     <Popconfirm
                         title="是否确认删除?"
                         key="del"
-                        onConfirm={()=>delTableData(record)}
+                        onConfirm={() => delTableData(record)}
                     >
                         <a>删除</a>
                     </Popconfirm>
@@ -73,43 +93,61 @@ export default function PubDicTypeMana() {
     ]
 
 
+    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 getTableData = async (params: any) => {
-        const resp = await getData(params);
+        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,
-                pageSize: resp.pageSize,
-                totalPage: resp.totalPage,
             }
         }
         return []
     }
 
-    const delTableData = async (record:any)=>{
-          const resp = await delData(record.dictId);
-          if(resp){
+    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({...formVal,hospId:0});
+            const resp = await addData({
+                 dictName:formVal.dictName,
+                 dictType:formVal.dictType,
+                 remark:formVal.remark,
+                 systemId:currentSelectedTreeNode.code 
+            });
             if (resp) {
                 set_reload(true);
             }
         }
         if (type == 'EDIT') {
-            const {dictId} = currentEdit;
-            const resp = await editData({...formVal,dictId,hospId:0});
+            const { dictId } = currentEdit;
+            const resp = await editData({
+                 dictId, 
+                 dictName:formVal.dictName,
+                 dictType:formVal.dictType,
+                 remark:formVal.remark,
+                 systemId:currentSelectedTreeNode.code 
+            });
             if (resp) {
                 set_reload(true);
             }
@@ -177,9 +215,8 @@ export default function PubDicTypeMana() {
         )
     }
 
-    const editHandle = (record: any) => {
+    
 
-    }
 
     const tableDataSearchHandle = (paramName: string) => {
 
@@ -190,34 +227,214 @@ export default function PubDicTypeMana() {
         })
     }
 
+    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 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]);
+            }
+        }
+    }, [treeData]);
+
+
+    useEffect(()=>{
+        getTreeReqFunc();
+    },[]);
+
+
     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: ''
-                                    });
+            <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} />
                             }}
-                            onSearch={() => tableDataSearchHandle('typeName')}
-
                         />
+                    )
+                }
+            </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>
+                    <div className='btnGroup'>
+                        <UpDataActBtn record type='ADD' />
                     </div>
                 </div>
-                <div className='btnGroup'>
-                    <UpDataActBtn record type='ADD' />
+                <div style={{ marginTop: 16 }}>
+                    {currentSelectedTreeNode&&<KCTable columns={columns as ProColumns[]} reload={reload} rowKey='dictId' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />}
                 </div>
             </div>
-            <div style={{ marginTop: 16 }}>
-                <KCTable columns={columns as ProColumns[]} reload={reload} rowKey='dictId' newVer params={tableDataFilterParams} request={(params) => getTableData(params)} />
-            </div>
         </div>
     )
 }

+ 32 - 14
src/pages/platform/setting/pubDicTypeMana/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-07 10:28:57
+ * @LastEditTime: 2023-09-01 10:42:11
  * @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
  */
@@ -25,13 +25,7 @@ export type PubDicTypeData = {
 
 
 export const getData = (params?:any) => {
-  return request<{
-       current:number;
-       list:PubDicTypeData[];
-       pageSize:number;
-       totalCount:number;
-       totalPage:number;
-  }>('/centerSys/sysdictdata/getDictType', {
+  return request('/centerSys/sysdictdata/getSystemDict', {
     method: 'GET',
     params:{...params}
   });
@@ -40,16 +34,29 @@ export const getData = (params?:any) => {
 
 //新增表格数据
 export type AddTableDataType = {
-  hospId:number;
   dictName:string;
   dictType:string;
-  remark:string
+  remark:string;
+  systemId:string;
 }
 export const addData = (data:AddTableDataType) => {
-  return request('/centerSys/sysdictdata/addDictType', {
+  return request('/centerSys/sysdictdata/addSystemDict', {
     method: 'POST',
     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}
+    });
+  }
 };
 
 
@@ -57,14 +64,14 @@ export const addData = (data:AddTableDataType) => {
 //编辑表格数据
 export type EditTableDataType = {
   dictId:number;
-  hospId:number;
+  systemId:string;
   dictName:string;
   dictType:string;
   remark:string
 }
 
 export const editData = (data:EditTableDataType) => {
-  return request('/centerSys/sysdictdata/editDictType', {
+  return request('/centerSys/sysdictdata/editSystemDict', {
     method: 'POST',
     data
   });
@@ -72,13 +79,24 @@ export const editData = (data:EditTableDataType) => {
 
 //删除表格操作
 export const delData = (dictId:string) => {
-  return request('/centerSys/sysdictdata/deleteDictType', {
+  return request('/centerSys/sysdictdata/deleteSystemDict', {
     method: 'POST',
     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;
+        }
       }
-    }
 
+    }
   }
+
 }

+ 285 - 134
src/pages/platform/setting/roleManage/index.tsx

@@ -1,15 +1,15 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 15:22:48
- * @LastEditTime: 2023-05-25 18:36:55
+ * @LastEditTime: 2023-09-20 15:51:06
  * @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/hospManage/index.tsx
  */
 
-import { FC, useEffect, useState } from 'react';
+import { FC, Key, useEffect, useState } from 'react';
 import { roleManageModelState, ConnectProps, Loading, connect } from 'umi';
-import {Checkbox, Divider, Dropdown, Input, Popconfirm, Table, TreeProps } from 'antd';
+import { Checkbox, Divider, Dropdown, Input, Popconfirm, Switch, Table, TreeProps } from 'antd';
 import KCTable from '@/components/kcTable';
 import type { ProColumns } from '@ant-design/pro-table';
 import { getAllRoles, getRoleHasBindMenus, getRoleHasBindUsers, getRolePermRelaMenu, initRoleFunc, initRoleReadOnlyFunc, saveRoleRelaApiPerm } from '@/service/role';
@@ -29,8 +29,11 @@ import { DataNode } from 'antd/es/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 { getTreeData, getTreeDataRespType } from '../systemNavMana/service';
-import { getHospOwnSys } from '@/service/hospList';
+import { getTableDataRequest, getTreeData, getTreeDataRespType } from '../systemNavMana/service';
+import { getHospOwnSys, getMenuRelaPerm } from '@/service/hospList';
+import { extractAttributeValues, findParents } from '../hospManage';
+import { TreeNode } from 'antd/lib/tree-select';
+import ProCardDivider from '@ant-design/pro-card/lib/components/Divider';
 
 export enum TableActType {
   NOACT,
@@ -46,15 +49,20 @@ interface PageProps extends ConnectProps {
   loading: boolean;
 }
 
+interface TreeNode {
+  [key: string]: any;
+  children?: TreeNode[];
+}
+
 const SearchIcon = createFromIconfontCN({
   scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
 });
 
-
+const selectSystem:{systemId:string,type:number}[] = [];
 
 const DrawerActBtn = ({ record }: { record: any }) => {
 
-    
+  
   const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
   const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>(undefined);
   const [drawerTablereload, set_drawerTablereload] = useState(false);
@@ -67,12 +75,23 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
   const [drawerTableDataSearchKeywords, set_drawerTableDataSearchKeywords] = useState<string>('');
 
+  const [checkedMenuParentsIds, set_checkedMenuParentsIds] = useState<Key[]>([]);  //所有需要保存的菜单id
+
   const [checkedTableMenuIds, set_checkedTableMenuIds] = useState<any[]>([]);
 
-  const [oldSelectedMenuIds,set_oldSelectedMenuIds] = useState<any[]>([]);
+  const [oldSelectedMenuIds, set_oldSelectedMenuIds] = useState<any[]>([]);
 
   const [drawerVisible, set_drawerVisible] = useState(false);
 
+  const [hospAllMenuTree, set_hospAllMenuTree] = useState<any[]>([]);  //角色可选的全量菜单
+
+  const [expandedRowKeys, set_expandedRowKeys] = useState<any[]>([]);
+
+  const [selectSystem,set_selectSystem] = useState<{systemId:string,type:number}[]>([]); //角色已绑定的系统
+
+  const [ifTixiMenu,set_ifTixiMenu] = useState(false);
+  const [ifTixiMenuAuth,set_ifTixiMenuAuth] = useState(false);
+
   const columnsData: ProColumns<TableListItem>[] = [
     {
       title: '名称',
@@ -125,10 +144,9 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           const onCheckGroupChange = (checkedValue: CheckboxValueType[]) => {
 
             if (checkedValue.length > 0) {
-              const _temp = checkBoxCodes;
+              const _temp = [...checkBoxCodes];
               const index = checkBoxCodes.findIndex((item) => item.menuId == record.menuId);
 
-
               const needed = options.filter((item: any) => checkedValue.includes(item.value));
               const transfered = needed.map((item: any) => ({ name: item.label, code: item.value }));
 
@@ -142,9 +160,11 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                 function: transfered
               });
 
-              const menuIdsArr = _temp.map((item: any) => item.menuId);
 
-              set_checkedTableMenuIds([...menuIdsArr])
+              set_checkedMenuParentsIds([...checkedMenuParentsIds, record.menuId]);
+
+              set_checkedTableMenuIds([...checkedTableMenuIds, record.menuId])
+
 
               set_checkBoxCodes([..._temp]);
             } else {
@@ -154,8 +174,6 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
               _temp.splice(index, 1);
 
-              const menuIdsArr = _temp.map((item: any) => item.menuId);
-              set_checkedTableMenuIds([...menuIdsArr])
               set_checkBoxCodes([..._temp]);
 
             }
@@ -178,14 +196,16 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   ];
 
   const getTreeReqFunc = async (hospId: string) => {
-    const resp = await getHospOwnSys(hospId);
-    set_treeData(resp);
+    if (hospId) {
+      const resp = await getHospOwnSys(hospId);
+      set_treeData(resp);
+    }
   }
 
   const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
     //console.log('selected', selectedKeys, info);
-    const { node } = info;
-    set_currentSelectedTreeNode(node);
+    const { node }:{node:any}= info;
+    set_currentSelectedTreeNode({...node});
   };
 
   const dataList: any[] = [];
@@ -243,23 +263,96 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   generateList(treeData as any);
 
 
+  // const getTableData = async (params: any, sort: any, filter: any) => {
+  //   set_drawerTablereload(false);
+  //   if (currentSelectedTreeNode && record.hospId && record.roleId) {
+
+  //   }
+  //   return []
+  // }
+
   const getTableData = async (params: any, sort: any, filter: any) => {
-    //console.log({record});
+
+    set_drawerTablereload(false);
+    const currentHosp = localStorage.getItem('currentSelectedSubHop');
+
+    if (currentSelectedTreeNode&&currentHosp) {
+      const {id} = JSON.parse(currentHosp);
+      const resp = await getMenuRelaPerm({ hospId:id, systemId: currentSelectedTreeNode.code });
+      if (resp) {
+        const {menuList} = resp;
+        let expandKeys:Key[] = [];
+        set_hospAllMenuTree(menuList);
+
+        const getParentsIds = (data: any) => {
+          data.map((item: any, index: number) => {
+
+            if(item.type == 0){
+              expandKeys.push(item.menuId)
+            }
+
+            if (item.children && item.children.length != 0) {
+              getParentsIds(item.children);
+            }
+
+          });
+
+        }
+
+        getParentsIds(menuList);
+        set_expandedRowKeys(expandKeys);
+        
+        return {
+          data: menuList,
+          success: true,
+        }
+      }
+      return {
+        data: [],
+        success: true
+      }
+    }
+
+    return []
+  }
+
+  const setInitCheckData = async () => {
     set_drawerTablereload(false);
-    if (currentSelectedTreeNode&&record.hospId&&record.roleId) {
+    if (currentSelectedTreeNode && record.hospId && record.roleId) {
       // console.log({params,record});
-      const resp = await getRolePermRelaMenu({ ...params, hospId: record.hospId,roleId:record.roleId});
+      const resp = await getRolePermRelaMenu({hospId: record.hospId, roleId: record.roleId,systemId:currentSelectedTreeNode.code });
       if (resp) {
         let temp: { menuId: any; function: any; }[] = [];
+        let expandKeys: Key[] = [];
+        let selectedMenuIds:Key[] = []; 
+        const { menuList = [],selectSystem=[] } = resp;
+        set_selectSystem(selectSystem);
+
+       
+        if(currentSelectedTreeNode.type == 1){
+          //判断体系菜单是否授权
+          const needItem = selectSystem.filter((a:any)=>a.systemId == currentSelectedTreeNode.code);
+          if(needItem.length>0){
+               set_ifTixiMenuAuth(true);
+          }else{
+               set_ifTixiMenuAuth(false);
+          }
+        }
+    
         const setTreeRecursion = (data: any) => {
           data.map((item: any, index: number) => {
-
-
+            if (item.type == 0) {
+              expandKeys.push(item.menuId);
+            }
+            if(item.type == 1){
+              selectedMenuIds.push(item.menuId);
+            }
             if (item.type == 1 && item.functionCheckList) {
               //菜单
               temp.push({
                 menuId: item.menuId,
                 function: item.functionCheckList
+
               });
             }
 
@@ -270,15 +363,17 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           });
         }
 
-        setTreeRecursion(resp);
+      
+        setTreeRecursion(menuList);
 
+        set_checkedMenuParentsIds([...expandKeys,...selectedMenuIds]);
         set_checkBoxCodes(temp);
-    
-        set_checkedTableMenuIds(temp.map((a: any) => a.menuId));
-        set_oldSelectedMenuIds(temp.map((a: any) => a.menuId));
+        set_checkedTableMenuIds(selectedMenuIds);
+        set_oldSelectedMenuIds(selectedMenuIds);
+
 
         return {
-          data: resp,
+          data: menuList,
           success: true,
         }
       }
@@ -288,30 +383,39 @@ const DrawerActBtn = ({ record }: { record: any }) => {
       }
     }
     return []
-    
+
   }
 
   const saveResult = async () => {
 
-    let old = oldSelectedMenuIds;
+    let old = [...oldSelectedMenuIds];
     //const needCancelMenus = needCancelCheckedMenus.map(a=>({hospId: record.id ,systemId: currentSelectedTreeNode.code,function:[],menuId:a}));
     const result = checkBoxCodes.map((item: any) => {
-            old.splice(old.findIndex(a=>a == item.menuId),1);
-            return { ...item, hospId: record.hospId,roleId:record.roleId,systemId: currentSelectedTreeNode.code }
+      old.splice(old.findIndex(a => a == item.menuId), 1);
+      return { ...item, hospId: record.hospId, roleId: record.roleId, systemId: currentSelectedTreeNode.code }
     });
 
 
-    const needCancelMenus = old.map(a => ({ 
-      hospId: record.hospId, 
+
+    const needCancelMenus = old.map(a => ({
+      hospId: record.hospId,
       systemId: currentSelectedTreeNode.code,
-      menuId:a,
-      roleId:record.roleId, function: [], 
+      menuId: a,
+      roleId: record.roleId, function: [],
     }));
-   
-    const data = [...result, ...needCancelMenus];
-    
 
-    const resp = await saveRoleRelaApiPerm(result.length == 0?[{hospId: record.hospId,roleId:record.roleId,systemId: currentSelectedTreeNode.code}]:data);
+    console.log({checkedTableMenuIds});
+
+
+    const data = {
+      hospId: record.hospId,
+      roleId: record.roleId,
+      systemId: currentSelectedTreeNode.code,
+      menuIds: ifTixiMenu?(ifTixiMenuAuth?[currentSelectedTreeNode.code]:[]):[...new Set(checkedMenuParentsIds),currentSelectedTreeNode.code],
+      functionList: [...result, ...needCancelMenus]
+    };
+
+    const resp = await saveRoleRelaApiPerm(data);
     if (resp) {
       set_drawerTablereload(true);
       set_checkBoxCodes([]);
@@ -334,74 +438,82 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   }
 
 
-  const oneKeySetReadOnly = (bool:boolean)=>{
-     
-      if(bool){
-        const _temp = checkBoxCodes.map((item:any)=>{
-              const needed = item.function.filter((a:any)=>a.code == 'search');
-              return {...item,function:needed}
-        })
-        set_checkBoxCodes([..._temp]);
-      }
-
+  const clearFunction = () => {
+    let emptyFunc = checkBoxCodes.map((a) => ({ ...a, function: [] }));
+    set_checkBoxCodes(emptyFunc);
   }
 
 
   useEffect(() => {
-    if (currentSelectedTreeNode) {
-      set_drawerTableDataFilterParams({ ...drawerTableDataFilterParams, systemId: currentSelectedTreeNode.code })
-    }
+    console.log({currentSelectedTreeNode});
+    if (currentSelectedTreeNode && !currentSelectedTreeNode.children) {  
 
-    //切换系统清空数据
-    set_checkBoxCodes([]);
-    set_checkedTableMenuIds([]);
+      // setInitCheckData(); 
+      
+      set_ifTixiMenu(currentSelectedTreeNode.type == 1);
+
+      setInitCheckData()
 
+      set_drawerTableDataFilterParams({ ...drawerTableDataFilterParams, systemId: currentSelectedTreeNode.code });
+      //切换系统清空数据
+      set_checkBoxCodes([]);
+      set_checkedTableMenuIds([]);
+    }
 
   }, [currentSelectedTreeNode]);
 
   useEffect(() => {
     //初始化左侧树结构数据后
-
     if (treeData?.length > 0) {
 
       if (treeData[0].children && treeData[0].children.length > 0) {
         const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
-
+        setAutoExpandParent(true);
         set_currentSelectedTreeNode(node);
         setExpandedKeys([nodeParent.code]);
       }
     }
   }, [treeData]);
 
+  useEffect(()=>{
+       console.log({checkedMenuParentsIds});
+  },[checkedMenuParentsIds])
 
 
   useEffect(() => {
-    getTreeReqFunc(record.hospId);
-
-  }, []);
+    if (drawerVisible) {
+      getTreeReqFunc(record.hospId);
+    } else {
+      set_drawerVisible(false);
+      set_currentSelectedTreeNode(undefined);
+      set_treeData([]);
+      setExpandedKeys([]);
+    }
+  }, [drawerVisible]);
 
 
   return (
     <DrawerForm
       trigger={
-        <a key="link3" onClick={()=>set_drawerVisible(true)}>功能</a>
+        <a key="link3" onClick={() => set_drawerVisible(true)}>菜单</a>
       }
       drawerProps={{
-          open:drawerVisible,
-          afterOpenChange(open) {
-              set_drawerVisible(open)
-          },
-          closable:false,
-          extra:null
+        open: drawerVisible,
+        afterOpenChange(open) {
+          set_drawerVisible(open)
+        },
+        closable: false,
+        extra: null
       }}
 
       width={908}
       submitter={false}
     >
-      <div className='setApiPermDrawer'>
+      <div className='setApiPermDrawer_roleMana'>
         <div className='topbar'>
           <div className='title'>{`角色功能权限设置(${record.roleName})`}</div>
           <div className='btnGroup'>
+            {currentSelectedTreeNode&&currentSelectedTreeNode.type == 5 &&<span className={'clearBtn'} onClick={() => clearFunction()}>清除功能权限</span>}
             <span className='cancel' onClick={() => onCancel()}>取消</span>
             <span className='save' onClick={() => saveResult()}>保存</span>
           </div>
@@ -477,33 +589,53 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           </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_drawerTableDataSearchKeywords(e.target.value);
-                      if (e.target.value.length == 0) {
-                        set_drawerTableDataFilterParams({
-                          ...drawerTableDataFilterParams,
-                          name: ''
-                        });
-                      }
-                    }}
-                    onSearch={() => drawerTableDataSearchHandle('name')}
+            {
+              !ifTixiMenu&& (
+                <div className='tableToolbar'>
+                  <div className='filter'>
+                    <div className='filterItem'>
+                      <span className='label'>检索:</span>
+                      <KCInput placeholder={'请输入'} style={{ width: 160 }} search allowClear
+                        onChange={(e) => {
+                          set_drawerTableDataSearchKeywords(e.target.value);
+                          if (e.target.value.length == 0) {
+                            set_drawerTableDataFilterParams({
+                              ...drawerTableDataFilterParams,
+                              name: ''
+                            });
+                          }
+                        }}
+                        onSearch={() => drawerTableDataSearchHandle('name')}
+
+                      />
+                    </div>
+                  </div>
+
+                  <div className={'btnGroup'}>
+                    {/* <a style={{color: '#17181A'}}><Switch style={{position:'relative',marginRight:4}} size='small'  onChange={(bool)=>oneKeySetReadOnly(bool)} />只读</a> */}
+                    {/* <UpDataActBtn key={'act'} record={undefined} type='ADD' /> */}
+                  </div>
 
-                  />
                 </div>
-              </div>
+              )
+            }
 
-              <div className={'btnGroup'}>
-                   {/* <a style={{color: '#17181A'}}><Switch style={{position:'relative',marginRight:4}} size='small'  onChange={(bool)=>oneKeySetReadOnly(bool)} />只读</a> */}
-                {/* <UpDataActBtn key={'act'} record={undefined} type='ADD' /> */}
+            {
+              ifTixiMenu && <div className='tixiMenuSet'>
+                <img src={require('../../../../../public/images/zanwuneirong.png')} style={{ width: 100, height: 88 }} alt="" />
+                <div className='despcrip'>当前所选系统没有可管理的菜单/功能权限</div>
+                <div>授予系统权限:<Switch size='small' checked={ifTixiMenuAuth} onChange={bool=>set_ifTixiMenuAuth(bool)} /></div>
               </div>
-
-            </div>
-            {currentSelectedTreeNode && <KCTable
+            }
+            {!ifTixiMenu && <KCTable
+              scroll={{ y: `calc(100vh - 150px)` }}
+              tableAlertRender={false}
+              expandable={{
+                expandedRowKeys: expandedRowKeys,
+                onExpandedRowsChange(expandedKeys) {
+                  set_expandedRowKeys(expandedKeys as Key[])
+                },
+              }}
               rowSelection={{
                 // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
                 // 注释该行则默认不显示下拉选项
@@ -517,31 +649,46 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                     set_checkBoxCodes([]);
                   }
                 },
+
                 selectedRowKeys: checkedTableMenuIds,
-                selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+                hideSelectAll: true,
                 onSelect: (record, selected, selectedRows, nativeEvent) => {
                   //console.log({ record, selected, selectedRows, nativeEvent });
 
-                  let checkedData = checkBoxCodes;
+                  let checkedData = [...checkBoxCodes];
 
                   if (selected) {
                     //选中
+                    const parents = findParents(hospAllMenuTree,record.menuId);
+                    const parentsIds = parents?parents.map(a=>a.menuId):[];
+
+                    if (record.children) {
+                      const childIds = extractAttributeValues(record, 'menuId');
+                      console.log({parentsIds,childIds});
+                      set_checkedMenuParentsIds([...checkedMenuParentsIds, ...childIds,...parentsIds]);
+                      
+                    } else {
+                      console.log([...checkedMenuParentsIds, record.menuId,...parentsIds]);
+                      set_checkedMenuParentsIds([...checkedMenuParentsIds, record.menuId,...parentsIds]);
+                    }
+
                     selectedRows.forEach(a => {
                       if (a.functionList) {
                         checkedData.push({
                           menuId: a.menuId,
                           function: a.functionList
                         });
-                      
+
                       }
-                      
+
                     });
+
                     //更新表格row选中状态
                     if (record.type == 0) {
                       //选中的是目录
                       const ids = record.children.map((item: any) => item.menuId);
                       const totalData = Array.from(new Set([...checkedTableMenuIds, ...ids]));
-                  
+
                       set_checkedTableMenuIds([...totalData]);
                     }
                     if (record.type == 1) {
@@ -550,20 +697,27 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
                     }
 
-                    set_checkBoxCodes([...checkedData]);
+                    set_checkBoxCodes([...uniqueFunc(checkedData, 'menuId')]);
+
 
                   } else {
 
                     //取消勾选\
-                    let _tempCheckedCodes = checkBoxCodes;
-          
-                    const leftCheckedMenuIds = selectedRows.map(a=>a.menuId);
+                    let _tempCheckedCodes = [...checkBoxCodes];
+
+                    const ids = extractAttributeValues(record, 'menuId');
+
+                    const filtedMenuIds = checkedMenuParentsIds.filter((a) => ![...ids, record.menuId].includes(a));
 
-                    const filtedCheckCodes = _tempCheckedCodes.filter(a=>(leftCheckedMenuIds.includes(a.menuId)));
+                    set_checkedMenuParentsIds(filtedMenuIds);
+
+                    const leftCheckedMenuIds = selectedRows.map(a => a.menuId);
+
+                    const filtedCheckCodes = _tempCheckedCodes.filter(a => (leftCheckedMenuIds.includes(a.menuId)));
 
                     set_checkedTableMenuIds([...leftCheckedMenuIds]);
-              
-                    set_checkBoxCodes([...uniqueFunc(filtedCheckCodes,'menuId')]);
+
+                    set_checkBoxCodes([...uniqueFunc(filtedCheckCodes, 'menuId')]);
 
                   }
                 }
@@ -625,11 +779,9 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
         <a key="link4" onClick={() => editUserBind(record)}>
           用户
         </a>,
+        <Divider key="9" type="vertical" style={{ margin: '0 1px' }} />,
+        <DrawerActBtn key="link7" record={record} />,
         <Divider key="3" type="vertical" style={{ margin: '0 1px' }} />,
-        <a key="link" onClick={() => editHandle(record)}>
-          编辑
-        </a>,
-        <Divider key="1" type="vertical" style={{ margin: '0 1px' }} />,
         <Popconfirm
           title="是否确定删除?"
           onConfirm={() => delHandle(record)}
@@ -640,13 +792,12 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
         >
           <a>删除</a>
         </Popconfirm>,
-         <Divider key="9" type="vertical" style={{ margin: '0 1px' }} />,
+        <Divider key="10" type="vertical" style={{ margin: '0 1px' }} />,
         <Dropdown key='4' menu={{
           items: [
-            { key:'0',label: <a key="link3" onClick={() => editMenuBind(record)}>菜单</a>},
-            { key: '5', label: <DrawerActBtn key="link7" record={record} /> },
-            { key: '2', label: <a key="link4" onClick={() => initRoleData('func',record)} >初始化功能</a> },
-            { key: '6', label: <a key="link6" onClick={() => initRoleData('read',record)}>初始化只读</a> },
+            { key: '5', label: <a key="link" onClick={() => editHandle(record)}>编辑</a> },
+            { key: '2', label: <a key="link4" onClick={() => initRoleData('func', record)} >初始化权限</a> },
+            //{ key: '6', label: <a key="link6" onClick={() => initRoleData('read',record)}>初始化只读</a> },
           ]
         }}>
           <a>
@@ -658,7 +809,7 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
 
   ];
 
- 
+
 
   const getData = async (params: TableRequestParamsType) => {
     const { current = 1, pageSize = 10, roleName } = params;
@@ -752,27 +903,27 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
       });
   };
 
-  const initRoleData =async (type:string,record:any) => {
-        if(type == 'func'){
-              const resp = await initRoleFunc({roleId:record.roleId,hospId:record.hospId});
-              if(resp){
-                dispatch &&
-                dispatch({
-                  type: 'roleManageModel/reloadTable',
-                });
-              }
-        }
-        if(type == 'read'){
-          const resp = await initRoleReadOnlyFunc({roleId:record.roleId,hospId:record.hospId});
-          if(resp){
-            dispatch &&
-            dispatch({
-              type: 'roleManageModel/reloadTable',
-            });
-          }
+  const initRoleData = async (type: string, record: any) => {
+    if (type == 'func') {
+      const resp = await initRoleFunc({ roleId: record.roleId, hospId: record.hospId });
+      if (resp) {
+        dispatch &&
+          dispatch({
+            type: 'roleManageModel/reloadTable',
+          });
+      }
+    }
+    if (type == 'read') {
+      const resp = await initRoleReadOnlyFunc({ roleId: record.roleId, hospId: record.hospId });
+      if (resp) {
+        dispatch &&
+          dispatch({
+            type: 'roleManageModel/reloadTable',
+          });
+      }
     }
   }
-  
+
 
   //  console.log({state});
 
@@ -803,7 +954,7 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
           <span className='add' onClick={addHandle}>新增</span>
         </div>
       </div>
-      
+
       <KCTable
         rowKey="roleId"
         columns={columns}

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

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-06-20 14:58:42
+ * @LastEditTime: 2023-09-18 18:07: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/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 '..';
@@ -76,6 +76,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
       return { ...currentEdit };
     }
     if (tableAct == TableActType.ADD) {
+      console.log({hospId});
       return { hospId: hospId };
     }
     if (tableAct == TableActType.EDITMENU || tableAct == TableActType.EDITRELAUSER) {
@@ -116,7 +117,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 @@
     }
 
   }
+ 
 }

+ 6 - 5
src/pages/platform/setting/systemNavMana/index.tsx

@@ -4,7 +4,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-16 09:42:52
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-06-12 16:15:33
+ * @LastEditTime: 2023-08-31 15:12:37
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -150,7 +150,8 @@ const MonthlyInfoCheck: React.FC = () => {
                 2: '大屏',
                 3: '填报',
                 4: '空白',
-                5: '静态'
+                5: '静态',
+                6:'外部系统嵌入'
             }
 
         },
@@ -319,7 +320,7 @@ const MonthlyInfoCheck: React.FC = () => {
                     menuId: record.menuId,
                     function: data
                 });
-                if (resp) {
+                if (resp){
                     set_reload(true);
                 }
             }
@@ -403,7 +404,7 @@ const MonthlyInfoCheck: React.FC = () => {
 
     const getParentKey = (key: React.Key, tree: any[]): React.Key => {
         let parentKey: React.Key;
-        for (let i = 0; i < tree.length; i++) {
+        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)) {
@@ -735,7 +736,7 @@ const MonthlyInfoCheck: React.FC = () => {
                     treeData && treeData.length > 0 && (
                         <DirectoryTree
                             fieldNames={{ title: 'name', key: 'code' }}
-                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+                            rootStyle={{ overflowY: 'scroll', overflowX: 'hidden' }}
                             onSelect={onSelect}
                             onExpand={onExpand}
                             expandedKeys={expandedKeys}

+ 2 - 2
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: 2023-09-28 11:20:52
  * @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
@@ -253,7 +253,7 @@ 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 })
+             return ({ label: t.name, value: t.code })
         })
       }
     }

+ 13 - 2
src/pages/platform/setting/userManage/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-06-30 18:29:30
+ * @LastEditTime: 2023-09-28 11:21: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
@@ -129,7 +129,7 @@ const ActModal: React.FC<ActModalProps> = ({
       return {
         defaultvalue: defaultValue[0] ? defaultValue[0].value : '',
         list: dataArr.map(t => {
-          return ({ label: t.value, value: t.code })
+          return ({ label: t.name, value: t.code })
         })
       }
     }
@@ -220,6 +220,7 @@ const ActModal: React.FC<ActModalProps> = ({
                   <ProFormSelect
                     name="position"
                     label="岗位:"
+                    fieldProps={{ showSearch:true}}
                     options={setSelectorData('POSITION').list}
                     placeholder="请选择"
                     rules={[{ required: true, message: '请选择!' }]}
@@ -253,6 +254,7 @@ const ActModal: React.FC<ActModalProps> = ({
                     label="所属院区:"
                     width="md"
                     name="hospId"
+                    fieldProps={{ showSearch:true}}
                     request={async () => {
                       const hospList = await getShareHospList();
                       if (hospList) {
@@ -293,6 +295,7 @@ const ActModal: React.FC<ActModalProps> = ({
                   <ProFormSelect
                     name="userCate"
                     label="人员类别:"
+                    fieldProps={{ showSearch:true}}
                     options={setSelectorData('PERSONNEL_CATEGORY').list}
                     placeholder="请选择"
                   />
@@ -305,6 +308,7 @@ const ActModal: React.FC<ActModalProps> = ({
                   <ProFormSelect
                     name="title"
                     label="职称:"
+                    fieldProps={{ showSearch:true}}
                     options={setSelectorData('TITLE_TYPE').list}
                     placeholder="请选择"
                     rules={[{ required: true, message: '请选择职称!' }]}
@@ -314,6 +318,7 @@ const ActModal: React.FC<ActModalProps> = ({
                   <ProFormSelect
                     name="jobTitle"
                     label="职务:"
+                    fieldProps={{ showSearch:true}}
                     options={setSelectorData('POSITION_TYPE').list}
                     placeholder="请选择"
                     rules={[{ required: true, message: '请选择职务!' }]}
@@ -335,6 +340,7 @@ const ActModal: React.FC<ActModalProps> = ({
                   <ProFormSelect
                     name="degree"
                     label="学历:"
+                    fieldProps={{ showSearch:true}}
                     options={setSelectorData('EDUCATION').list}
                     placeholder="请选择"
                     rules={[{ required: true, message: '请选择学历!' }]}
@@ -345,6 +351,7 @@ const ActModal: React.FC<ActModalProps> = ({
                   <ProFormSelect
                     name="major"
                     label="所学专业:"
+                    fieldProps={{ showSearch:true}}
                     options={setSelectorData('PROFESSIONAL_TYPE').list}
                     placeholder="请选择"
                     rules={[{ required: true, message: '请选择专业!' }]}
@@ -366,6 +373,7 @@ const ActModal: React.FC<ActModalProps> = ({
                       <ProFormSelect
                         name="practiceCate"
                         label="执业类别:"
+                        fieldProps={{ showSearch:true}}
                         options={setSelectorData('JOB_TYPE').list}
                         placeholder="请选择"
                       />
@@ -381,6 +389,7 @@ const ActModal: React.FC<ActModalProps> = ({
                       <ProFormSelect
                         name="practiceSubject"
                         label="执业科目:"
+                        fieldProps={{ showSearch:true}}
                         options={setSelectorData('PROCESSIONAL_SUBJECTS_TYPE').list}
                         placeholder="请选择"
                         rules={[{ required: true, message: '请选择!' }]}
@@ -403,6 +412,7 @@ const ActModal: React.FC<ActModalProps> = ({
                       <ProFormSelect
                         name="practiceStatus"
                         label="执业状态:"
+                        fieldProps={{ showSearch:true}}
                         options={setSelectorData('PROFESSIONAL_STATUS_TYPE').list}
                         placeholder="请选择"
                         rules={[{ required: true, message: '请选择!' }]}
@@ -425,6 +435,7 @@ const ActModal: React.FC<ActModalProps> = ({
                       <ProFormSelect
                         name="doctorLevel"
                         label="医师:"
+                        fieldProps={{ showSearch:true}}
                         options={setSelectorData('PHYSICIAN_TYPE').list}
                         placeholder="请选择"
                         rules={[{ required: true, message: '请选择!' }]}

+ 24 - 2
src/service/hospList.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 09:15:59
- * @LastEditTime: 2023-08-18 17:26:26
+ * @LastEditTime: 2023-09-14 14:00:11
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/hospList.ts
@@ -204,6 +204,14 @@ export const setReadOnly = async (hospId:string) => {
   });
 };
 
+//院区菜单全部按钮
+export const setIfCheckAll= async (params:{systemId:string,hospId:string,type:string}) => {
+  return request(`/centerSys/hospital/setAll`, {
+    method: 'POST',
+    params
+  });
+};
+
 
 
 //获取当前院的系统列表
@@ -211,4 +219,18 @@ export const getHospOwnSys = async (hospId:string) => {
   return request(`/centerSys/hospital/getSystemList?hospId=${hospId}`, {
     method: 'GET'
   });
-};
+};
+
+//获取当前院区所有科室
+export const getCurrentHospAllDepartments = async () => {
+  return request(`/centerSys/sysdepartment/getHospDepartment`, {
+    method: 'GET'
+  });
+};
+
+//获取当前院区所有人员信息
+export const getCurrentHospAllEmps = async () => {
+  return request(`/centerSys/user/getUserByHospId`, {
+    method: 'GET'
+  });
+};

+ 41 - 4
src/service/login.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-11 10:35:56
- * @LastEditTime: 2023-04-03 09:27:14
+ * @LastEditTime: 2023-09-27 15:00:37
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/service/login.ts
@@ -12,7 +12,10 @@ import { request } from 'umi';
 export const getHospConfigBySign = async (hospSign: string) => {
   return request<
     {
+      loadType:number;
+      hospAbbreviation: any;
       hospSign: string;
+      id:string;
       name: string;
       systemName: string;
     }[]
@@ -22,13 +25,31 @@ export const getHospConfigBySign = async (hospSign: string) => {
   });
 };
 
-//获取该账户拥有的子应用列表
-export const getHospSubSystemList = async () => {
-  return request<userRelationInfo.OwnAppsItem[]>('/centerSys/user/getSystemList', {
+
+//获取上次登陆的系统
+
+export const getLastLoginSys = async (params:{hospId:string,userId:number}) => {
+  return request('/centerSys/parameter/getLastSystem', {
     method: 'GET',
+    params
+  });
+};
+
+//获取登陆密码为默认密码时的判断类型
+
+export const getLoginTipType = async () => {
+  return request('/centerSys/parameter/getList?pageSize=500&current=1', {
+    method: 'GET'
   });
 };
 
+//获取该账户拥有的子应用列表
+export const getHospSubSystemList = async () => {
+  // return request<userRelationInfo.OwnAppsItem[]>('/centerSys/user/getSystemList', {
+  //   method: 'GET',
+  // });
+};
+
 export type UserDataType = {
   name: string;
   token: string;
@@ -48,3 +69,19 @@ export const logout = async () => {
     method: 'POST',
   });
 };
+
+//获取qiankun 子应用列表
+export const getQiankunMicroApps = async () => {
+  return request('/centerSys/route/list?current=1&pageSize=500', {
+    method: 'GET',
+  });
+};
+
+
+//新增qiankun 子应用列表
+export const addQiankunMicroApps = async (data:{name:string;entry:string}) => {
+  return request('/centerSys/route/save', {
+    method: 'POST',
+    data
+  });
+};

+ 2 - 3
src/service/menu.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-10 10:27:15
- * @LastEditTime: 2023-03-16 19:11:06
+ * @LastEditTime: 2023-09-07 17:38:41
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/hospInfo.ts
@@ -136,7 +136,7 @@ export type UserPlatformNav = {
   type:number;
   path:string;
   systemId:string;
-  contentType:string;
+  contentType:number;
   child:UserPlatformNav[];
 }
 
@@ -173,7 +173,6 @@ export const menuSetToHomePage = async (data:{menuId:string;menuName:string;}) =
     method: 'POST',
     params: data,
   });   
-
 }
 
 //菜单目录列表

+ 29 - 0
src/service/public.ts

@@ -0,0 +1,29 @@
+/*
+ * @Author: your name
+ * @Date: 2021-11-11 10:35:56
+ * @LastEditTime: 2023-09-14 13:32:22
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/service/login.ts
+ */
+
+import { request } from 'umi';
+
+
+//获取公用字典数据
+export const getPubDicData = async (code?: string) => {
+    const resp = await request('/centerSys/sysdictdata/getDictData', {
+        method: 'GET',
+    });
+    if (resp) {
+        const result = resp.filter((a: any) => a.code == code);
+        if (result.length > 0) {
+            return Promise.resolve(result[0]);
+        }
+        return Promise.resolve([]);
+    }
+
+    return Promise.resolve([]);
+};
+
+

+ 2 - 2
src/service/role.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-18 14:56:29
- * @LastEditTime: 2023-03-23 14:07:59
+ * @LastEditTime: 2023-09-15 15:01:04
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/role.ts
@@ -120,7 +120,7 @@ export const roleBindUsers = async (data: {
 export const getRolePermRelaMenu = async (params: {
   hospId: number;
   roleId: string;
-  systemId:number,
+  systemId:string,
   name?:string;
 }) => {
   return request('/centerSys/role/getMenuList', {

Деякі файли не було показано, через те що забагато файлів було змінено