Quellcode durchsuchen

路由添加权限校验

code4eat vor 1 Jahr
Ursprung
Commit
2fe84cf159

+ 76 - 6
config/config.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:04:20
- * @LastEditTime: 2023-12-07 10:49:07
+ * @LastEditTime: 2024-07-22 11:04:57
  * @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
@@ -79,9 +79,9 @@ export default defineConfig({
             autoSetLoading: true,
             autoCaptureError: true,
           },
-          // wrappers: [
-          //   '@/wrappers/auth',
-          // ],
+          wrappers: [
+            '@/wrappers/auth',
+          ],
         },
         {
           path: '/pfmBackMana',
@@ -90,6 +90,9 @@ export default defineConfig({
             autoSetLoading: true,
             autoCaptureError: true,
           },
+          wrappers: [
+            '@/wrappers/auth',
+          ],
         },
         {
           path: '/CostAccountingSys',
@@ -98,6 +101,9 @@ export default defineConfig({
             autoCaptureError: true,
             //loader: (loading:boolean) => <div>loading</div>,
           },
+          wrappers: [
+            '@/wrappers/auth',
+          ],
           // access: 'canVisitThisApp'
         },
         {
@@ -107,7 +113,9 @@ export default defineConfig({
             autoCaptureError: true,
             //loader: (loading:boolean) => <div>loading</div>,
           },
-          // access: 'canVisitThisApp'
+          wrappers: [
+            '@/wrappers/auth',
+          ],
         },
         {
           path: '/personnelManaSystem',
@@ -116,7 +124,20 @@ export default defineConfig({
             autoCaptureError: true,
             //loader: (loading:boolean) => <div>loading</div>,
           },
-          // access: 'canVisitThisApp'
+          wrappers: [
+            '@/wrappers/auth',
+          ],
+        },
+        {
+          path: '/nursingWorkersManaSystem',
+          microApp: 'nursingWorkersManaSystem',
+          microAppProps: {
+            autoCaptureError: true,
+            //loader: (loading:boolean) => <div>loading</div>,
+          },
+          wrappers: [
+            '@/wrappers/auth',
+          ],
         },
         {
           path: '/channelIndex/channelIndexOne',
@@ -127,6 +148,10 @@ export default defineConfig({
           title: '欢迎进入医管平台',
           component: '@/pages/index/index.tsx',
         },
+        {
+          path: '/noAccess',
+          component: './noAccess',
+        },
         {
           title: '精益管管理中台',
           path: '/platform',
@@ -135,6 +160,9 @@ export default defineConfig({
             {
               path: '/platform/sqlEditer',
               component: '@/pages/platform/sqlediter/index.tsx',
+              wrappers: [
+                '@/wrappers/auth',
+              ],
             },
             {
               path: '/platform/setting',
@@ -142,18 +170,30 @@ export default defineConfig({
                 {
                   path: '/platform/setting/userManage',
                   component: '@/pages/platform/setting/userManage/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/hospManage',
                   component: '@/pages/platform/setting/hospManage/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/menuManage',
                   component: '@/pages/platform/setting/menuManage/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/roleManage',
                   component: '@/pages/platform/setting/roleManage/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 // {
                 //   path: '/platform/setting/reports',
@@ -162,38 +202,65 @@ export default defineConfig({
                 {
                   path: '/platform/setting/departmentMana',
                   component: '@/pages/platform/setting/departmentMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/pubDicTypeMana',
                   component: '@/pages/platform/setting/pubDicTypeMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/hospParamsMana',
                   component: '@/pages/platform/setting/hospParamsMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/pubDicMana/:type',
                   component: '@/pages/platform/setting/pubDicMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/indicatorMana',
                   component: '@/pages/platform/setting/indicatorMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/paramsMana',
                   component: '@/pages/platform/setting/paramsMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/systemNavMana',
                   component: '@/pages/platform/setting/systemNavMana/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/notificationTemplate',
                   component: '@/pages/platform/setting/notificationTemplate/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
                 {
                   path: '/platform/setting/kcClassification',
                   component: '@/pages/platform/setting/kcClassification/index.tsx',
+                  wrappers: [
+                    '@/wrappers/auth',
+                  ],
                 },
               ],
             },
@@ -202,6 +269,9 @@ export default defineConfig({
         {
           path: '/personalCenter',
           component: '@/pages/personalCenter/index.tsx',
+          // wrappers: [
+          //   '@/wrappers/auth',
+          // ],
         },
         { path: '/login', layout: false, component: '@/pages/login/index' },
       ],

+ 4 - 16
config/proxy.ts

@@ -1,20 +1,12 @@
 /*
- * @Author: your name
- * @Date: 2022-01-07 10:00:52
-<<<<<<< HEAD
- * @LastEditTime: 2023-04-20 13:31:09
-=======
- * @LastEditTime: 2024-03-18 18:04:31
->>>>>>> dev
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2024-04-09 18:07:34
  * @LastEditors: code4eat awesomedema@gmail.com
- * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @LastEditTime: 2024-07-16 13:49:57
  * @FilePath: /KC-MiddlePlatform/config/proxy.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 
-//118.31.245.65  7004 线上
-//112.124.59.133 7001 测试
-
-//192.168.50.190:7001
 
 const proxy: { [key: string]: any } = {
   dev: {
@@ -33,11 +25,7 @@ const proxy: { [key: string]: any } = {
     },
     //新版评审管理
     '/view': {
-<<<<<<< HEAD
-      target: 'http://47.97.190.5:8807',
-=======
       target: 'http://120.27.235.181:8085/',
->>>>>>> dev
       changeOrigin: true,
       // pathRewrite: { '^/view': '' },
     },

BIN
public/images/beian_icon.png


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
public/zhongtaiA.js


+ 83 - 21
src/app.tsx

@@ -3,12 +3,15 @@ import { PageLoading } from '@ant-design/pro-layout';
 import { notification, Modal, message } from 'antd';
 import { RequestConfig, history } from 'umi';
 import type { RequestOptionsInit } from 'umi-request';
-import { UserDataType, getQiankunMicroApps } from '@/service/login';
+import { UserDataType, getQiankunMicroApps, login } from '@/service/login';
 
 import { BasicLayoutProps } from '@ant-design/pro-layout';
 import { logoutHandle } from './global';
 import { Platforms } from './constant';
 import { SpacicalPageParamsType } from './typings';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { handleLogin } from './pages/login';
+import { getUserPlatformNav } from './service/menu';
 
 window.isParentApp = true;
 
@@ -24,12 +27,18 @@ if (history && history.location.query) {
   }
 }
 
+const IconFont = createFromIconfontCN({
+  scriptUrl: '',
+});
+
 /** 获取用户信息比较慢的时候会展示一个 loading */
 export const initialStateConfig = {
   loading: <PageLoading />,
 };
 
 type InitialStateType = {
+  navData: any[];
+  menuData:any[],//中台菜单
   userData?: UserDataType;
   systemLists?: TopBar.Tab[]; //当前医院可选子系统列表
   openedSysLists?: TopBar.Tab[]; //当前已打开的系统列表
@@ -40,19 +49,55 @@ type InitialStateType = {
   getHospSubSystemListFunc?: () => Promise<any[]>;
 };
 
+
 export async function getInitialState(): Promise<InitialStateType> {
+
   const fetchUserInfo = async () => {
     try {
+      const queryParams = new URLSearchParams(location.search);
+      const importUserData = queryParams.get('userData');
+      const env = queryParams.get('env');
+
+      if (importUserData) {
+        localStorage.setItem('userData', importUserData);
+        return JSON.parse(importUserData);
+      }
+      
       const userData = localStorage.getItem('userData');
+
       if (userData) {
+        if (env === 'demo') {
+          history.replace('/index');
+        }
         return JSON.parse(userData);
       }
+      // 如果没有 userData 且 env 参数为 demo,则发起一个请求
+      if (env === 'demo') {
+        // 获取 hospSign 参数
+        
+        const hospSign = queryParams.get('hospSign');
+        // 发起请求的代码,根据实际需求调整
+        const resp = await handleLogin('demo','123456', hospSign as string);
+        if(resp){
+          history.replace('/index');
+          return resp;
+        }
+      }
+  
       throw Error;
     } catch (error) {
-      history.push(`${loginPath}?hospSign=${hospSign}`);
+      const currentUrlParams = new URLSearchParams(window.location.search);
+      const hospSign = 'yourDefaultHospSign'; // 定义默认的 hospSign,如果需要的话
+
+      // 如果 hospSign 已存在,保留其值,否则添加新的 hospSign 参数
+      if (!currentUrlParams.has('hospSign')) {
+        currentUrlParams.append('hospSign', hospSign);
+      }
+  
+      history.push(`${loginPath}?${currentUrlParams.toString()}`);
     }
     return undefined;
-  };
+};
 
   const getAppIcon = (name: string) => {
     return Platforms.filter((i) => i.name == name).length > 0 ? Platforms.filter((i) => i.name == name)[0].logo : '';
@@ -72,25 +117,32 @@ export async function getInitialState(): Promise<InitialStateType> {
     // }
     return [];
   };
+  
 
   const logout = logoutHandle;
 
   const userData = await fetchUserInfo();
 
   let systemLists: userRelationInfo.OwnAppsItem[] = [];
-
+  // let navData:any[] = [];
   if (userData) {
     systemLists = await getHospSubSystemListFunc();
+    // navData = await getUserPlatformNav();
   }
 
+  
+
   const localInitData = localStorage.getItem('initialState');
+  const currentSelectedTab = localStorage.getItem('currentSelectedTab');
+
 
   return {
-    currentSelectedSys: undefined,
+    currentSelectedSys:currentSelectedTab != null?JSON.parse(currentSelectedTab):undefined,
     openedSysLists: [],
     ...JSON.parse(localInitData ? localInitData : '{}'), //覆盖,恢复tab状态
     userData,
     logout,
+    favicon: '',
     spacicalPageParamsType: [],
     getHospSubSystemListFunc,
     systemLists: systemLists,
@@ -103,9 +155,10 @@ const requestInterceptorsHandle = (url: string, options: RequestOptionsInit) =>
 
   if (userData) {
     const { token } = JSON.parse(userData);
-    authHeader.token = token;
-  }
-
+    if(url.indexOf('/centerSys/route/list') == -1){
+      authHeader.token = token;
+    }
+  }  
   return {
     url: `/gateway${url}`,
     options: { ...options, interceptors: true, headers: authHeader, timeout: 100000000 },
@@ -183,8 +236,6 @@ const errorHandlerFunc = (error: ResponseErr) => {
     const { info } = error;
     const { errorCode, errorMessage } = info;
 
-    console.log({ info });
-
     if (errorCode == 499 || errorCode == 401) {
       //token过期
       Modal.confirm({
@@ -203,20 +254,30 @@ const errorHandlerFunc = (error: ResponseErr) => {
 
     if (errorMessage.length > 20) {
       notification.error({
+        top:72,
         message: ` ${errorCode}:出现错误!`,
         description: errorMessage,
+        icon:<IconFont type="icon-jinggaotishi"  />,
+        style:{padding:16,margin:0,borderRadius:8}
       });
     } else if (false) {
     } else {
       notification.error({
+        top:72,
         message: '错误',
         description: ` ${errorCode}:${errorMessage}`,
+        icon:<IconFont type="icon-jinggaotishi"  />,
+        style:{padding:16,margin:0,borderRadius:8}
       });
     }
   } catch (err) {
     console.log({ errorHandlerFunc: err });
     notification.error({
-      message: '遇到未知错误,查看控制台!',
+      top:72,
+      message: '提示',
+      description:'遇到未知错误,查看控制台!',
+      icon:<IconFont type="icon-jinggaotishi"  />,
+      style:{padding:16,margin:0,borderRadius:8}
     });
   }
 };
@@ -263,10 +324,10 @@ export const qiankun = async () => {
         //   name: 'microApp', // 唯一 id
         //   entry: '//localhost:8808', // 开发
         // },
-        // {
-        //   name: 'app1', // 唯一 id
-        //   entry: '//120.27.235.181:8804',  //测试
-        // },
+        {
+          name: 'nursingWorkersManaSystem', // 唯一 id
+          entry: '//116.169.61.56:29528',  //测试
+        },
         // {
         //   name: 'reviewMana', // 唯一 id
         //   entry: '//120.27.235.181:5000/pfmview/',
@@ -276,6 +337,7 @@ export const qiankun = async () => {
         {
           name: 'budgetManaSystem', // 唯一 id
           entry: '//localhost:8002',
+          //entry: '//116.169.61.56:29528/',  //开发
           //entry: '//120.27.235.181:5000/perform/',  //开发
           //entry: '//47.96.149.190:5000/perform/', //演示
           //entry: '//198.198.203.161:5000/perform/', //淮南
@@ -341,7 +403,7 @@ export function patchRoutes({ routes }: { routes: any }) {
         }));
 
         //console.log({paths});
-
+        
         paths.forEach((a: any) => {
           treeData.routes.push(a);
         });
@@ -362,16 +424,16 @@ export function patchRoutes({ routes }: { routes: any }) {
   treeLoop(routes[0]);
 }
 
-export const layout = ({ initialState: { userData } }: { initialState: InitialStateType }): BasicLayoutProps => {
+export const layout = ({ initialState: {  } }: { initialState: InitialStateType }): BasicLayoutProps => {
   return {
     headerRender: false,
     rightContentRender: () => <>right</>,
     footerRender: () => null,
     onPageChange: () => {
-      //如果没有登录,重定向到 login
-      if (!userData && location.pathname !== '/login') {
-        // history.push('/login');
-      }
+      // //如果没有登录,重定向到 login
+      // if (!userData && location.pathname !== '/login') {
+      //   // history.push('/login');
+      // }
     },
     menuHeaderRender: undefined,
     // ...initialState?.settings,

+ 61 - 0
src/components/ResizableContainer/index.tsx

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

+ 24 - 0
src/components/ResizableContainer/style.less

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

+ 179 - 182
src/components/topBar/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-16 09:12:37
- * @LastEditTime: 2024-04-09 14:27:27
+ * @LastEditTime: 2024-07-18 16:51:08
  * @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
@@ -22,6 +22,7 @@ import { Divider } from 'antd';
 import { updateTokenReq } from '@/service/user';
 import { logoutHandle } from '@/global';
 
+
 interface TopBarType {
   onTabChange?: (data: TopBar.Tab[]) => void; //当tab切换时回调
   openedTabs: TopBar.Tab[]; //已打开的列表
@@ -29,14 +30,15 @@ interface TopBarType {
   userPannelTabClick?: (tag: 'SETTING' | 'LOGOUT' | 'SETUSERINFO') => void;
   onCloseTab?: (data: TopBar.Tab) => void;
   onTabClick?: (data: TopBar.Tab) => void;
-  userData?: { name: string; [key: string]: any };
+  userData?: { name: string;[key: string]: any };
   navData: TopBar.PanelData[];
-  logo?: string;
-  topBarTitle?: string;
+  logo?:string;
+  topBarTitle?:string;
 }
 
+
 const TopBar: React.FC<TopBarType> = (props) => {
-  const { onTabChange, userPannelTabClick, onCloseTab, onTabClick, userData, navData, currentTab, logo = undefined, topBarTitle = '欢迎进入医管平台' } = props;
+  const { onTabChange, userPannelTabClick, onCloseTab, onTabClick, userData, navData, currentTab,logo=undefined,topBarTitle='欢迎进入医管平台' } = props;
   const [systemTabs, setSystemTabs] = useState<TopBar.Tab[]>([]); //已打开的tab
   const [currentSelectedTab, setCurrentSelectedTab] = useState<TopBar.Tab>();
   const [ifOpenPannel, setIfOpenPannel] = useState(false);
@@ -46,32 +48,39 @@ const TopBar: React.FC<TopBarType> = (props) => {
   const [panelData, set_panelData] = useState<TopBar.PanelData[]>([]);
 
   const [onTabSystemTabs, set_onTabSystemTabs] = useState<TopBar.Tab[]>([]); //tab导航可以放下的数量,剩余通过下拉获取
-  const [onTabSystemTabs_hide, set_onTabSystemTabs_hide] = useState<TopBar.Tab[]>([]); //下拉掩藏的导航
+  const [onTabSystemTabs_hide, set_onTabSystemTabs_hide] = useState<TopBar.Tab[]>([]);  //下拉掩藏的导航
 
   const { initialState, setInitialState } = useModel('@@initialState');
-  const [tokenUpdateModalVisible, set_tokenUpdateModalVisible] = useState(false);
+  const [tokenUpdateModalVisible,set_tokenUpdateModalVisible] = useState(false);
   const location = useLocation();
 
   const [showMoreTabPannel, set_showMoreTabPannel] = useState(false);
+  const [password,set_password] = useState<string|undefined>(undefined);
+
 
   const localSavedTab = localStorage.getItem('currentSelectedTab');
 
   const currentSelectedTabFromLocal = localSavedTab ? JSON.parse(localSavedTab) : {};
 
-  let password: undefined | string = undefined;
+
 
   const _systemTabClickHandle = (item: TopBar.Tab) => {
+
     //导航栏tab点击
     // console.log('_systemTabClickHandle',item);
     onTabClick && onTabClick(item);
     localStorage.setItem('currentSelectedTab', JSON.stringify(item));
     setCurrentSelectedTab(item);
+
   };
 
+
+
   const _systemListClickHandle = (data: TopBar.Tab, currentActivedBlockIndex: number, index: number, i: number) => {
     //导航栏系统菜单列表点击回调
+ 
     if (currentSelectedTab?.menuId == data.menuId) return;
-
+    
     //临时保存衣打开过的菜单
     const t = localStorage.getItem('visitedTabs');
 
@@ -88,7 +97,7 @@ const TopBar: React.FC<TopBarType> = (props) => {
 
     _systemTabClickHandle(data); //触发一次tab点击
 
-    set_pageTitle(panelData[currentActivedBlockIndex].child[index].name);
+    set_pageTitle(panelData[currentActivedBlockIndex].child[index].name)
 
     if (panelData[currentActivedBlockIndex].child[index].child) {
       //console.log([...panelData[currentActivedBlockIndex].child[index].child])
@@ -126,12 +135,12 @@ const TopBar: React.FC<TopBarType> = (props) => {
 
   const UserPannel = () => {
     return (
-      <div className="userPannel">
-        <div className="userPannelTab" onClick={() => _userPannelTabClick('SETTING')}>
+      <div className='userPannel'>
+        <div className='userPannelTab' onClick={() => _userPannelTabClick('SETTING')}>
           <SettingOutlined />
           <span>设置</span>
         </div>
-        <div className="userPannelTab" onClick={() => _userPannelTabClick('LOGOUT')}>
+        <div className='userPannelTab' onClick={() => _userPannelTabClick('LOGOUT')}>
           <LogoutOutlined />
           <span>退出</span>
         </div>
@@ -141,10 +150,11 @@ const TopBar: React.FC<TopBarType> = (props) => {
 
   const goChannelIndex = (menuData: any) => {
     setIfOpenPannel(false);
-    onTabClick && onTabClick(menuData);
-  };
+    onTabClick && onTabClick(menuData)
+  }
 
   const goToHome = () => {
+
     const go = () => {
       history.replace('/index');
       setSystemTabs([]); //清空tab导航
@@ -157,7 +167,7 @@ const TopBar: React.FC<TopBarType> = (props) => {
       localStorage.removeItem('selectedKeys');
       // localStorage.removeItem('visitedTabs');
       localStorage.removeItem('openKeys');
-    };
+    }
 
     const currentSelectedSubHop_json = localStorage.getItem('currentSelectedSubHop');
     if (currentSelectedSubHop_json) {
@@ -170,40 +180,47 @@ const TopBar: React.FC<TopBarType> = (props) => {
     } else {
       go();
     }
-  };
+
+  }
 
   const goSystemIndex = (name: string) => {
     if (panelData[currentActivedBlockIndex]) {
-      const result: TopBar.TypeBlock[] = panelData[currentActivedBlockIndex].child.filter((t) => t.name == name);
+      const result: TopBar.TypeBlock[] = panelData[currentActivedBlockIndex].child.filter(t => (t.name == name));
       if (result.length > 0) {
-        _systemTabClickHandle(Object.assign(result[0]));
+        _systemTabClickHandle(Object.assign(result[0]))
         // history.push(result[0].path)
       }
     }
-  };
+  }
 
   const openNav = () => {
     setIfOpenPannel(!ifOpenPannel);
-  };
+  }
+
 
   const moreItemClickHandle = (systemData: TopBar.Tab) => {
     //点击更多应用时
     _systemTabClickHandle(systemData);
     const temp = onTabSystemTabs[onTabSystemTabs.length - 1];
     const _onTabSystemTabs = [...onTabSystemTabs];
-    const b = _onTabSystemTabs.filter((a) => a.systemId != temp.systemId);
+    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]);
-  };
+    set_onTabSystemTabs_hide([...onTabSystemTabs_hide.filter(a => a.systemId != systemData.systemId), temp])
+  }
+
+
 
   const reSetNav = (_panelData: TopBar.PanelData[], cur: TopBar.Tab) => {
-    if (!(_panelData.length > 0)) return;
+
+    if (!(_panelData.length > 0)) return
 
     if (JSON.stringify(cur) != '{}') {
+
       let blockIndex = 0;
       let channelIndex = 0;
 
+
       const _currentSelectedTabFromLocal = cur;
 
       one: for (let index = 0; index < _panelData.length; index++) {
@@ -229,21 +246,23 @@ const TopBar: React.FC<TopBarType> = (props) => {
       }
 
       if (_panelData && _panelData.length > 0 && _panelData[blockIndex].child) {
-        setSystemTabs(_panelData[blockIndex].child[channelIndex].child); //恢复体系列表
+        setSystemTabs(_panelData[blockIndex].child[channelIndex].child);  //恢复体系列表
         setCurrentSelectedTab(_currentSelectedTabFromLocal);
         localStorage.setItem('currentSelectedTab', JSON.stringify(_currentSelectedTabFromLocal));
-        setInitialState((s) => ({ ...s, currentSelectedSys: _currentSelectedTabFromLocal }));
+        setInitialState((s) => ({ ...s, currentSelectedSys: _currentSelectedTabFromLocal }) as any);
       }
 
       // console.log({_currentSelectedTabFromLocal,location});
-      const { pathname } = location;
-      if (pathname.indexOf(_currentSelectedTabFromLocal.path) == -1) {
+      const {pathname} = location;
+      if(pathname.indexOf(_currentSelectedTabFromLocal.path) == -1){
         history.push(_currentSelectedTabFromLocal.path);
       }
 
       //_systemTabClickHandle(_currentSelectedTabFromLocal);  //恢复选中的tab
+
+
     }
-  };
+  }
 
   const [hideTimer, setHideTimer] = useState<null | any>(null);
   const handleTabMoreMouseLeave = () => {
@@ -267,19 +286,21 @@ const TopBar: React.FC<TopBarType> = (props) => {
   };
 
   const updateToken = async () => {
-    const { account } = JSON.parse(localStorage.getItem('userInfo') as string);
-    const hospSign = localStorage.getItem('hospSign');
-    const data = {
-      account,
-      password: password,
-      hospSign,
-    };
-    const resp = await updateTokenReq(data);
-    if (resp) {
-      password = undefined;
-      set_tokenUpdateModalVisible(false);
-    }
-  };
+        const account = (localStorage.getItem('account')) as string;
+        const hospSign = localStorage.getItem('hospSign');
+        const data = {
+          account,
+          password:password,
+          hospSign
+        }
+        const resp = await updateTokenReq(data);
+        if(resp){
+          set_password(undefined);
+          set_tokenUpdateModalVisible(false);
+        }
+
+  }
+
 
   useEffect(() => {
     if (currentSelectedTabFromLocal) {
@@ -287,17 +308,25 @@ const TopBar: React.FC<TopBarType> = (props) => {
     }
 
     set_panelData(navData);
-  }, [navData]);
+
+  }, [navData])
 
   useEffect(() => {
+
     if (currentTab) reSetNav(panelData, currentTab);
+
   }, [currentTab]);
 
-  useEffect(() => {
-    set_pageTitle(topBarTitle);
-  }, [topBarTitle]);
+
+  useEffect(()=>{
+     set_pageTitle(topBarTitle);
+  },[topBarTitle])
+
+
+
 
   useEffect(() => {
+
     if (systemTabs.length > 5) {
       //set_onTabSystemTabs(tabs);
       let _onTabSystemTabs: any[] = [];
@@ -323,47 +352,25 @@ const TopBar: React.FC<TopBarType> = (props) => {
     }
   }, [systemTabs]);
 
+
   useEffect(() => {
+
     //_systemTabClickHandle(currentSelectedTabFromLocal);  //恢复选中的tab
 
     document.body.addEventListener('click', (e: any) => {
-      const classes = [
-        'panel',
-        'typeBlockName',
-        'left',
-        'typeBlockIcon',
-        'typeBlock',
-        'typeBlock active',
-        'active',
-        'right',
-        'row',
-        'rowDetai',
-        'channelName',
-        'channelList',
-        'systemTab',
-        'channelIcon',
-        'rowDetail',
-        'typeBlockIcon typeBlockIcon1',
-        'typeBlockIcon typeBlockIcon2',
-        'typeBlockIcon typeBlockIcon3',
-        'typeBlockIcon typeBlockIcon4',
-        'typeBlockIcon typeBlockIcon5',
-        'typeBlockIcon typeBlockIcon6',
-        'typeBlockIcon typeBlockIcon7',
-        'typeBlockIcon typeBlockIcon8',
-        'typeBlockIcon typeBlockIcon9',
-      ];
+
+      const classes = ['panel', 'typeBlockName', 'left', 'typeBlockIcon', 'typeBlock', 'typeBlock active', 'active', 'right', 'row', 'rowDetai', 'channelName', 'channelList', 'systemTab', 'channelIcon', 'rowDetail','typeBlockIcon typeBlockIcon1','typeBlockIcon typeBlockIcon2','typeBlockIcon typeBlockIcon3','typeBlockIcon typeBlockIcon4','typeBlockIcon typeBlockIcon5','typeBlockIcon typeBlockIcon6','typeBlockIcon typeBlockIcon7','typeBlockIcon typeBlockIcon8','typeBlockIcon typeBlockIcon9'];
       if (e.target) {
-        let key = e.target.className ? e.target.className : '';
-        if (classes.includes(key) || (typeof key == 'string' && key.indexOf('typeBlockIcon') != -1)) {
-          return;
+        let key = e.target.className?e.target.className:'';
+        if (classes.includes(key)||(typeof key == 'string'&&key.indexOf('typeBlockIcon') != -1)) {
+          return
         }
       }
       setIfOpenPannel(false);
     });
-
+    
     // 事件监听器的函数定义
-    const handleStorageChange = (e: any) => {
+    const handleStorageChange = (e:any) => {
       if (e.key === 'tokenExpired') {
         set_tokenUpdateModalVisible(true);
       }
@@ -376,138 +383,128 @@ const TopBar: React.FC<TopBarType> = (props) => {
     return () => {
       window.removeEventListener('removeLocalItemEvent', handleStorageChange);
     };
+
   }, []);
 
   return (
-    <div className="topBar" onClick={(e) => e.stopPropagation()}>
-      <Modal className="TokenUpdateModal" open={tokenUpdateModalVisible} width={400} title={false} footer={false} closable={false}>
-        <div className="content">
-          <div className="title">登录超时锁定</div>
-          <div className="form">
-            <div className="avatar">
-              <img className="avatarImg" src={require('../../../public/images/initAvatar.png')} alt="" />
-              <img className="suoding" src={require('../../../public/images/suoding.png')} alt="" />
-            </div>
-            <div className="name">{userData?.name}</div>
-            <Input.Password onChange={(e) => (password = e.target.value)} className="input" />
-            <div className="updateBtn" onClick={() => updateToken()}>
-              解锁
-            </div>
-            <a onClick={() => logoutHandle()}>退出登录</a>
-          </div>
-        </div>
+    <div className='topBar' onClick={e => e.stopPropagation()}>
+      <Modal className='TokenUpdateModal' open={tokenUpdateModalVisible} width={400} title={false}  footer={false} closable={false}  >
+           <div className='content'>                                                                                                                                                                         
+                <div className='title'>登录超时锁定</div>
+                <div className='form'>
+                      <div className='avatar'>
+                         <img className='avatarImg' src={require('../../../public/images/initAvatar.png')} alt="" />
+                         <img className='suoding' src={require('../../../public/images/suoding.png')} alt="" />
+                      </div>
+                      <div className='name'>{userData?.name}</div>
+                      <Input.Password onChange={(e)=>set_password(e.target.value)} value={password}  className='input' autoComplete='off' />
+                      <div className='updateBtn' onClick={()=>updateToken()}>解锁</div>
+                      <a onClick={()=>logoutHandle()}>退出登录</a>
+                </div>
+           </div>
       </Modal>
-      <div className="logoWrap">
-        {logo && <img className="logo" src={logo} onClick={() => goToHome()} />}
+      <div className='logoWrap'>
+        {logo&&<img className='logo' src={logo} onClick={() => goToHome()} />}
         <Divider type="vertical" style={{ background: 'white', height: 16, opacity: 0.29, position: 'relative', top: 1, marginLeft: 16, marginRight: 8 }} />
         <div className={ifOpenPannel ? 'menu active' : 'menu'} onClick={() => openNav()}>
           <img src={require('../../../public/images/menu.png')} alt="" />
         </div>
-        <span className="systemTitle" onClick={() => goSystemIndex(pageTitle)}>
-          {pageTitle}
-        </span>
+        <span className='systemTitle' onClick={() => goSystemIndex(pageTitle)}>{pageTitle}</span>
       </div>
 
-      <div className="userRelaInfoWrap">
+      <div className='userRelaInfoWrap'>
         <>
           {/**
            * 已打开的tab
            */}
-          <div className="tabWrap">
-            {onTabSystemTabs &&
-              onTabSystemTabs.map((item, index) => (
-                <div key={index} className={currentSelectedTab?.menuId == item.menuId ? `tab on` : `tab`} onClick={() => _systemTabClickHandle(item)}>
-                  <div className="tabText">{item.name} </div>
-                  <div className="closeIconWrap">
-                    <img src={tabCloseIcon} onClick={(e) => closeTabHandle(item, e)} />
-                  </div>
+          <div className='tabWrap'>
+            {onTabSystemTabs && (onTabSystemTabs).map((item, index) => (
+              <div key={index} className={currentSelectedTab?.menuId == item.menuId ? `tab on` : `tab`} onClick={() => _systemTabClickHandle(item)}>
+                <div className='tabText'>{item.name} </div>
+                <div className='closeIconWrap'>
+                  <img src={tabCloseIcon} onClick={(e) => closeTabHandle(item, e)} />
                 </div>
-              ))}
+              </div>
+            ))}
           </div>
-          {systemTabs.length > 5 && (
-            <div className={showMoreTabPannel ? 'tabMore active' : 'tabMore'} onMouseEnter={() => set_showMoreTabPannel(true)} onMouseLeave={handleTabMoreMouseLeave}>
-              {showMoreTabPannel && (
-                <div className="morePannel" onMouseEnter={handleMorePannelMouseEnter} onMouseLeave={handleMorePannelMouseLeave}>
-                  {onTabSystemTabs_hide.map((item, index) => {
-                    return (
-                      <div key={index} className="moreItem" onClick={() => moreItemClickHandle(item)}>
-                        {/* <Tooltip placement="right" title={item.name}> */}
-                        <span>{item.name}</span>
-                        {/* </Tooltip> */}
-                      </div>
-                    );
-                  })}
-                </div>
-              )}
-            </div>
-          )}
+          {systemTabs.length > 5 && <div className={showMoreTabPannel ? 'tabMore active' : 'tabMore'} onMouseEnter={() => set_showMoreTabPannel(true)} onMouseLeave={handleTabMoreMouseLeave} >
+            {showMoreTabPannel && (<div className='morePannel'
+              onMouseEnter={handleMorePannelMouseEnter}
+              onMouseLeave={handleMorePannelMouseLeave}
+            >
+              {
+                onTabSystemTabs_hide.map((item, index) => {
+                  return (<div key={index} className='moreItem' onClick={() => moreItemClickHandle(item)}>
+                    {/* <Tooltip placement="right" title={item.name}> */}
+                    <span>{item.name}</span>
+                    {/* </Tooltip> */}
+                  </div>)
+                })
+              }
+            </div>)}
+          </div>}
         </>
 
-        <div className="notification">
-          <img className="notificationIcon" src={require('../../../public/images/notificationIcon.png')} />
+
+        <div className='notification'>
+          <img className='notificationIcon' src={require('../../../public/images/notificationIcon.png')} />
         </div>
-        <Tooltip className="topBarTooltip" placement="bottomRight" title={<UserPannel />} color="#fff" onOpenChange={(visible) => setArrowRotate(visible)}>
-          <div className="user">
-            <div className="avator">
-              <img src={require('../../../public/images/avatar.png')} />
-            </div>
-            <div className="info">
-              <span className="hospName">{localStorage.getItem('hospAbbreviation')}</span>
-              <span className="name">{userData?.name}</span>
+        <Tooltip className='topBarTooltip' placement='bottomRight' title={<UserPannel />} color="#fff" onOpenChange={(visible) => setArrowRotate(visible)}>
+          <div className='user'>
+            <div className='avator'><img src={require('../../../public/images/avatar.png')} /></div>
+            <div className='info'>
+              <span className='hospName'>{localStorage.getItem('hospAbbreviation')}</span>
+              <span className='name'>{userData?.name}</span>
             </div>
             {/* <img className={arrowRotate ? `arrow on` : `arrow`} src={require('../../../public/images/arrow_white.png')} /> */}
           </div>
         </Tooltip>
       </div>
 
-      {ifOpenPannel && (
-        <div className="panel" onClick={(e) => e.stopPropagation()}>
-          <div className="left">
-            {panelData.map((item, index) => {
-              return (
-                <div className={currentActivedBlockIndex == index ? `typeBlock active` : `typeBlock`} key={index} onClick={() => set_currentActivedBlockIndex(index)}>
-                  {/* <img className='typeBlockIcon' src={item?.icon} alt="" /> */}
-                  <div className={` typeBlockIcon typeBlockIcon${item.icon}`}></div>
-                  <span className="typeBlockName">{item.name}</span>
-                </div>
-              );
-            })}
-          </div>
-          <div className="right">
-            <div className="panelCloseBtn" onClick={() => setIfOpenPannel(false)}></div>
-            {panelData.length > 0 &&
-              panelData[currentActivedBlockIndex] &&
-              panelData[currentActivedBlockIndex].child &&
-              panelData[currentActivedBlockIndex].child.map((item, index: number) => {
-                return (
-                  <div className="row" key={index}>
-                    <img className="channelIcon" src={item.icon ? item.icon : require(`../../../public/images/tongyong_tixi.png`)} alt="" />
-                    <div className="rowDetail">
-                      <div className="channelName" onClick={() => goChannelIndex(item)}>
-                        {item.name}
-                      </div>
-                      <div className="channelList">
-                        {item.child &&
-                          item.child.length > 0 &&
-                          item.child.map((val, i: number) => {
-                            return (
-                              <div
-                                className={currentSelectedTab?.menuId == val.menuId ? 'systemTab on' : 'systemTab'}
-                                key={i}
-                                onClick={() => _systemListClickHandle(val, currentActivedBlockIndex, index, i)}
-                              >
-                                {val.name}
-                              </div>
-                            );
-                          })}
+      {
+        ifOpenPannel && (
+          <div className='panel' onClick={e => e.stopPropagation()}>
+            <div className='left'>
+              {
+                panelData.map((item, index) => {
+                  return (
+                    <div className={currentActivedBlockIndex == index ? `typeBlock active` : `typeBlock`} key={index} onClick={() => set_currentActivedBlockIndex(index)}>
+                      {/* <img className='typeBlockIcon' src={item?.icon} alt="" /> */}
+                      <div className={` typeBlockIcon typeBlockIcon${item.icon}`} ></div>
+                      <span className='typeBlockName'>{item.name}</span>
+                    </div>
+                  )
+                })
+              }
+            </div>
+            <div className='right'>
+              <div className='panelCloseBtn' onClick={() => setIfOpenPannel(false)} ></div>
+              {
+                panelData.length > 0 && panelData[currentActivedBlockIndex] && panelData[currentActivedBlockIndex].child && panelData[currentActivedBlockIndex].child.map((item, index: number) => {
+                  return (
+                    <div className='row' key={index}>
+                      <img className='channelIcon' src={item.icon?item.icon:require(`../../../public/images/tongyong_tixi.png`)} alt="" />
+                      <div className='rowDetail'>
+                        <div className='channelName' onClick={() => goChannelIndex(item)}>{item.name}</div>
+                        <div className='channelList'>
+                          {
+                            item.child && item.child.length > 0 && item.child.map((val, i: number) => {
+                              return (
+                                <div className={currentSelectedTab?.menuId == val.menuId ? 'systemTab on' : 'systemTab'} key={i} onClick={() => _systemListClickHandle(val, currentActivedBlockIndex, index, i)}>{val.name}</div>
+                              )
+                            })
+                          }
+                        </div>
                       </div>
                     </div>
-                  </div>
-                );
-              })}
+                  )
+                })
+              }
+            </div>
           </div>
-        </div>
-      )}
+        )
+      }
+
     </div>
   );
 };

+ 12 - 0
src/global.less

@@ -7,12 +7,18 @@ body {
   margin: 0;
   height: 100%;
   zoom: unset !important;
+  background-color: transparent;
 }
 
 input {
   outline: none !important;
 }
 
+
+.ant-notification {
+    display: none !important;
+}
+
 //overwrite antd-pro css
 
 .kcmp-ant-pro-page-container-warp {
@@ -294,6 +300,12 @@ input {
 //-----------  Menu左侧菜单
 
 .kcmp-ant-layout-sider {
+  flex: auto !important;
+  max-width: 100% !important;
+  min-width: 0 !important;
+  width: 100% !important;
+  border-right: none !important;
+  box-shadow: none !important;
   &.kcmp-ant-layout-sider-collapsed {
     width: 60px !important;
     flex: 0 0 60px !important;

+ 19 - 7
src/layouts/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 13:56:33
- * @LastEditTime: 2024-01-18 15:45:55
+ * @LastEditTime: 2024-07-18 15:23:15
  * @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
@@ -38,10 +38,14 @@ const TopHoc = ({
 
   const onTabClickHandle = async (data: TopBar.Tab) => {
     const { systemId = '', menuId = '' } = data;
+    
+
     const resp = await getAppAccess(systemId.length > 0 ? systemId : menuId);
+
     if (!resp) {
+
       if (JSON.stringify(data) != '{}') {
-        await setInitialState((s) => ({ ...s, currentSelectedSys: data }));
+        await setInitialState((s) => ({ ...s, currentSelectedSys: data }) as any);
         // localStorage.removeItem('currentSelectedTab');
         localStorage.removeItem('selectedKeys');
         // localStorage.removeItem('visitedTabs');
@@ -68,16 +72,19 @@ const TopHoc = ({
       Modal.error({
         title: '当前系统未注册,请联系管理员处理!',
       });
+      
     }
   };
 
   const userPannelTabClickhandle = (tag: string) => {
+
     if (tag == 'LOGOUT') {
       if (initialState) {
         const { logout } = initialState;
         logout && logout();
       }
     }
+
     if (tag == 'SETTING') {
       if (initialState) {
         // setInitialState((s) => ({
@@ -120,12 +127,15 @@ export default function Layout({ children, location, route, history, match }: IR
   const [isEmpty, set_isEmpty] = useState(false);
   const [topBarLogoUrl, set_topBarLogoUrl] = useState<string>('');
   const [topBarTitle, set_topBarTitle] = useState('');
-  const [iframeUrl, set_iframeUrl] = useState<string | undefined>(undefined);
-
+   
+  const queryParams = new URLSearchParams(location.search);
+  const noTopBar = queryParams.get('noTopbar');
+  
   const getNavData = async () => {
     const nav = await getUserPlatformNav();
     if (nav) {
       set_navData(nav as any);
+      setInitialState((t)=>({...t,navData:nav}) as any)
     }
   };
 
@@ -196,6 +206,7 @@ export default function Layout({ children, location, route, history, match }: IR
       contentStyle={{
         margin: 0,
       }}
+      menuRender={false}
       menuItemRender={(item, dom) => {
         return (
           <a
@@ -218,8 +229,8 @@ export default function Layout({ children, location, route, history, match }: IR
         },
       }}
       pageTitleRender={false}
-      headerRender={() =>
-        initialState && (
+      headerRender={noTopBar != 'true'?() =>{
+        return (initialState ) && (
           <TopHoc
             navData={navData}
             topBarTitle={topBarTitle}
@@ -229,6 +240,7 @@ export default function Layout({ children, location, route, history, match }: IR
             openedSysLists={initialState.openedSysLists ? initialState.openedSysLists : []}
           />
         )
+      }:false
       }
     >
       {isEmpty && (
@@ -236,7 +248,7 @@ export default function Layout({ children, location, route, history, match }: IR
           <h1>{emptyPageContent}</h1>
         </div>
       )}
-      {!isEmpty && <div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll', minWidth: 1280 }}>{children}</div>}
+      {!isEmpty && <div style={{ height:noTopBar == 'true'?'auto': `calc(100vh - 48px)`, overflowY: 'scroll', minWidth: 1280 }}>{children}</div>}
     </ProLayout>
   );
 }

+ 5 - 3
src/pages/document.ejs

@@ -1,8 +1,8 @@
 <!--
  * @Author: your name
  * @Date: 2022-02-14 14:02:45
- * @LastEditTime: 2022-03-30 11:16:30
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2024-04-29 11:08:58
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/document.ejs
 -->
@@ -18,7 +18,9 @@
   content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
 />
   <title>精益管理中台</title>
-  <link rel="icon" href="<%= context.config.publicPath +'favicon.ico'%>" type="image/x-icon" />
+  <link rel="icon" href="/favicon.ico" type="image/x-icon" id="favicon">
+  <!-- <link rel="icon" href="<%= context.favicon %>" type="image/x-icon"> -->
+  <!-- <link rel="icon" href="<%= context.config.publicPath +'favicon.ico'%>" type="image/x-icon" /> -->
 </head>
 <body>
   <!-- <div id="root"></div> -->

+ 2 - 2
src/pages/index/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2021-11-10 09:33:30
- * @LastEditTime: 2024-03-28 17:26:40
+ * @LastEditTime: 2024-05-16 17:57:43
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/index.tsx
@@ -121,7 +121,7 @@ const IndexPage: React.FC<IndexPageType> = ({ location }) => {
     }
 
     if (needItem.length > 0) {
-      setspecialPageUrl(`http://eastern1.kcim-bi.163yun.com/dash/integration/56?rid=${needItem[0].value}&toolbar=[]&hideTitle=true&hideScaleBar=false&&scale=screen&hidePageBar=false&token=${token}`);
+      setspecialPageUrl(`http://eastern1.kcim-bi.163yun.com/dash/integration/56?rid=${needItem[0].value}&token=${token}`);
     }
   };
 

+ 166 - 158
src/pages/login/index.tsx

@@ -1,36 +1,74 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 14:58:08
- * @LastEditTime: 2024-03-28 17:50:54
+ * @LastEditTime: 2024-07-09 10:38:24
  * @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, Modal } from 'antd';
+import React, { useRef, useEffect, useState } from 'react';
+import { Select, notification, Row, Col, Modal } from 'antd';
 import './style.less';
 
 import { useModel, history, Location, Helmet } from 'umi';
 
-import { Form, Input, Button, notification } from 'antd';
+import { Form, Input, Button } from 'antd';
 
 import logo from '../../../public/images/kclogo_colorful.png';
 
 import KCSelect from '@/components/kc-select';
 
-import { getHospConfigBySign, getLastLoginSys, getLoginTipType, login } from '@/service/login';
-import Divider from '@ant-design/pro-card/lib/components/Divider';
-import { getSysParamsByCode } from '@/service';
+import { getHospConfigBySign, getLastLoginSys, login } from '@/service/login';
+
 import { KcimCenterSysId } from '@/constant';
 
 const { Option } = Select;
 
+function changeFavicon(src: string) {
+  const link = document.createElement('link');
+  const oldLink = document.getElementById('favicon');
+  link.id = 'favicon';
+  link.rel = 'icon';
+  link.href = src;
+  if (oldLink) {
+    document.head.removeChild(oldLink);
+  }
+  document.head.appendChild(link);
+}
+
 export interface LoginPageType {
   location: Location;
   title: string;
 }
 
+export const handleLogin = async (
+  account: string,
+  password: string,
+  hospSign: string | undefined,
+) => {
+  if (!hospSign) {
+    notification.error({
+      message: '网址标记缺失,请检查网址!',
+    });
+    return null;
+  }
+
+  const resp = await login({
+    account: account,
+    password: password,
+    hospSign: hospSign,
+  });
+
+  if (resp) {
+    localStorage.setItem('userData', JSON.stringify(resp));
+    localStorage.setItem('account', account);
+    localStorage.setItem('tokenExpired', 'false');
+    return resp;
+  }
+  return null;
+};
+
 const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
   const loginPageRef = useRef<HTMLDivElement>(null);
   const [subHospList, setSubHospList] = useState<
@@ -41,9 +79,8 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
       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);
@@ -52,18 +89,11 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
     id: undefined,
     loginTips: '',
     loginPic: '',
-  }); //当前选中的院区
+  }); // 当前选中的院区
 
-  const [hospSign, set_hospSign] = useState<undefined | string>(undefined); //登陆用的hospSign
+  const [hospSign, set_hospSign] = useState<undefined | string>(undefined); // 登陆用的hospSign
 
-  const initLoginPageInfo = async () => {
-    const resp = await getSysParamsByCode(KcimCenterSysId);
-    if (resp) {
-      return [];
-    }
-  };
-
-  //获取当前账号分院列表
+  // 获取当前账号分院列表
   const getSubHospFunc = async () => {
     if (hospSign) {
       const data = await getHospConfigBySign(hospSign);
@@ -89,82 +119,12 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
               localStorage.setItem('currentHospName', temp.systemName);
             }
             return temp;
-          }),
+          })
         );
       }
     }
   };
 
-  const onFinish = async (values: LoginPageTypes.LoginInfo) => {
-    setIfLoading(true);
-    if (!hospSign) {
-      notification.error({
-        message: '网址标记缺失,请检查网址!',
-      });
-      setIfLoading(false);
-      return;
-    }
-    const resp = await login({
-      account: values.account,
-      password: values.password,
-      hospSign: hospSign,
-      // remember:false,
-    });
-
-    setIfLoading(false);
-
-    if (resp) {
-      localStorage.setItem('userData', JSON.stringify(resp));
-      localStorage.setItem('tokenExpired', 'false');
-      setInitialState((s) => ({ ...s, userData: resp }));
-      if (currentSelectedSubHop.loadType) {
-        const lastLoginSysData = await getLastLoginSys({ hospId: currentSelectedSubHop.id, userId: resp.userId });
-        if (lastLoginSysData) {
-          history.replace(lastLoginSysData.path);
-          localStorage.setItem('currentSelectedTab', JSON.stringify({ ...lastLoginSysData, menuId: lastLoginSysData.systemId }));
-        }
-      } else {
-        history.replace('/index');
-      }
-
-      // if(values.password == '123456'){
-      //       //如果密码为默认密码时
-      //       const loginTipeType = await getSysParamsByCode('','1688483840064098304');
-      //       if(loginTipeType){
-
-      //            const needItem = loginTipeType.filter((a:any)=>a.code == '1688483840064098304');
-
-      //            if(needItem.length>0){
-      //                 if(needItem[0].value == 2){
-      //                   Modal.confirm({
-      //                     title:'提醒',
-      //                     content:'您的账号存在密码泄露风险,请尽快修改密码!',
-      //                     okText:'去更改',
-      //                     cancelText:'稍后',
-      //                     onOk(...args) {
-      //                       history.replace('/personalCenter');
-      //                     },
-      //                   })
-      //                 }
-      //                 if(needItem[0].value == 3){
-      //                   Modal.warn({
-      //                     title:'提醒',
-      //                     content:'您的账号存在密码泄露风险,请先修改密码!',
-      //                     okText:'去更改',
-      //                     onOk(...args) {
-      //                       history.replace('/personalCenter');
-      //                     },
-      //                   })
-      //                 }
-      //            }
-      //       }
-
-      // }
-
-      setIfLoading(false);
-    }
-  };
-
   const handleResize = (e: Event) => {
     // console.log('innerWidth',(e.target as Window).innerWidth);
     set_windowWidth((e.target as Window).innerWidth);
@@ -182,6 +142,18 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
     }
   }, [windowWidth]);
 
+  useEffect(() => {
+    if (currentSelectedSubHop) {
+      const { loginPic } = currentSelectedSubHop;
+      if (loginPic.length > 0) {
+        const arr = loginPic.split('|');
+        if (arr.length == 2) {
+          changeFavicon(arr[1]);
+        }
+      }
+    }
+  }, [currentSelectedSubHop]);
+
   useEffect(() => {
     if (hospSign) {
       location.pathname == '/login' && getSubHospFunc();
@@ -189,10 +161,10 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
   }, [hospSign]);
 
   useEffect(() => {
-    //根据hospSign获取分院信息
+    // 根据hospSign获取分院信息
     setInitialState((s) => ({ ...s, currentSelectedSys: undefined, openedSysLists: [] }));
 
-    window.addEventListener('resize', (e) => handleResize(e)); //监听窗口大小改变
+    window.addEventListener('resize', (e) => handleResize(e)); // 监听窗口大小改变
 
     const hospSign = history.location.query?.hospSign as string;
     localStorage.setItem('hospSign', hospSign);
@@ -203,6 +175,26 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
     };
   }, []);
 
+  const onFinish = async (values: { account: string; password: string }) => {
+    setIfLoading(true);
+    const resp = await handleLogin(values.account, values.password, hospSign);
+    setIfLoading(false);
+
+    if (resp) {
+      const currentSelectedSubHop = JSON.parse(localStorage.getItem('currentSelectedSubHop') || '{}');
+      setInitialState((s: any) => ({ ...s, userData: resp }));
+      if (currentSelectedSubHop.loadType) {
+        const lastLoginSysData = await getLastLoginSys({ hospId: currentSelectedSubHop.id, userId: resp.userId });
+        if (lastLoginSysData) {
+          history.replace(lastLoginSysData.path);
+          localStorage.setItem('currentSelectedTab', JSON.stringify({ ...lastLoginSysData, menuId: lastLoginSysData.systemId }));
+        }
+      } else {
+        history.replace('/index');
+      }
+    }
+  };
+
   return (
     <div className="loginPage">
       <Helmet>
@@ -210,76 +202,92 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
       </Helmet>
 
       {location.pathname == '/login' ? (
-        <Row style={{ height: '100%' }}>
-          {ifShowLeftBlock && (
-            <Col flex="500px">
-              <div className="left">
-                <div className="topLogo">
-                  <img className="logo" src={currentSelectedSubHop?.loginPic} alt="康程智医" />
-                  <div className="logoDesc">{(currentSelectedSubHop?.loginTips.split('|'))[0]}</div>
+        <>
+          <Row style={{ height: '100%' }}>
+            {ifShowLeftBlock && (
+              <Col flex="500px">
+                <div className="left">
+                  <div className="topLogo">
+                    {((currentSelectedSubHop?.loginPic).split('|'))[0] && (
+                      <img className="logo" src={((currentSelectedSubHop?.loginPic).split('|'))[0]} alt="康程智医" />
+                    )}
+                    {((currentSelectedSubHop?.loginTips.split('|'))[0]) && (
+                      <div className="logoDesc" style={{ borderLeft: ((currentSelectedSubHop?.loginPic).split('|'))[0] ? '1px solid #CFD6E6' : 'none' }}>
+                        {(currentSelectedSubHop?.loginTips.split('|'))[0]}
+                      </div>
+                    )}
+                  </div>
+                  <img className="loginbanner" src={require('../../../public/images/loginBannner.png')} alt="" />
                 </div>
-                <img className="loginbanner" src={require('../../../public/images/loginBannner.png')} alt="" />
-              </div>
-            </Col>
-          )}
-          <Col flex="auto">
-            <div className="rightLoginArea">
-              {!ifShowLeftBlock && (
-                <div className="topLogo">
-                  <img className="logo" src={currentSelectedSubHop?.loginPic} alt="康程智医" />
-                  <div className="logoDesc">{(currentSelectedSubHop?.loginTips.split('|'))[0]}</div>
+              </Col>
+            )}
+            <Col flex="auto">
+              <div className="rightLoginArea">
+                {!ifShowLeftBlock && (
+                  <div className="topLogo">
+                    <img className="logo" src={currentSelectedSubHop?.loginPic} alt="康程智医" />
+                    <div className="logoDesc">{(currentSelectedSubHop?.loginTips.split('|'))[0]}</div>
+                  </div>
+                )}
+
+                <div className="subHospSelector">
+                  {subHospList.length > 0 && (
+                    <KCSelect
+                      allowClear={false}
+                      style={{ width: 180 }}
+                      defaultValue={hospSign}
+                      onSelect={(val: any, option) => {
+                        set_hospSign(val);
+                        localStorage.setItem('hospAbbreviation', option.item.hospAbbreviation);
+                        localStorage.setItem('currentSelectedSubHop', JSON.stringify(option.item));
+                        set_currentSelectedSubHop(option.item);
+                      }}
+                      suffixIcon={<img style={{ width: '10px', height: '6px' }} src={require('../../../public/images/arrow.png')} />}
+                    >
+                      {subHospList.map((item) => {
+                        return (
+                          <Option value={item.value} item={item} key={item.value}>
+                            {item.name}
+                          </Option>
+                        );
+                      })}
+                    </KCSelect>
+                  )}
                 </div>
-              )}
-
-              <div className="subHospSelector">
-                {subHospList.length > 0 && (
-                  <KCSelect
-                    allowClear={false}
-                    style={{ width: 180 }}
-                    defaultValue={hospSign}
-                    onSelect={(val: any, option) => {
-                      set_hospSign(val);
-                      localStorage.setItem('hospAbbreviation', option.item.hospAbbreviation);
-                      localStorage.setItem('currentSelectedSubHop', JSON.stringify(option.item));
-                      set_currentSelectedSubHop(option.item);
-                    }}
-                    suffixIcon={<img style={{ width: '10px', height: '6px' }} src={require('../../../public/images/arrow.png')} />}
+                <div className="systemName">{currentHospName}</div>
+                <Form onFinish={onFinish}>
+                  <Form.Item name="account" rules={[{ required: true, message: '请输入用户名!' }]}>
+                    <Input className="input" placeholder="请输入用户名" />
+                  </Form.Item>
+
+                  <Form.Item name="password" rules={[{ required: true, message: '请输入密码!' }]}>
+                    <Input.Password className="input" placeholder="请输入密码" />
+                  </Form.Item>
+
+                  <Form.Item>
+                    <Button className="loginBtn" type="primary" htmlType="submit" loading={ifLoading}>
+                      登录
+                    </Button>
+                  </Form.Item>
+                </Form>
+                <div className="bottomCopyright">
+                  {(currentSelectedSubHop?.loginTips.split('|'))[1]}
+                  <span style={{ paddingLeft: 16 }}>{(currentSelectedSubHop?.loginTips.split('|'))[2]}</span>
+                </div>
+
+                <div className="beian">
+                  <a
+                    target="_blank"
+                    href="https://beian.miit.gov.cn/"
+                    style={{ display: 'inline-block', textDecoration: 'none', marginRight: 5 }}
                   >
-                    {subHospList.map((item) => {
-                      return (
-                        <Option value={item.value} item={item} key={item.value}>
-                          {item.name}
-                        </Option>
-                      );
-                    })}
-                  </KCSelect>
-                )}
+                    滇ICP备2024031095号
+                  </a>
+                </div>
               </div>
-              <div className="systemName">{currentHospName}</div>
-              <Form onFinish={onFinish}>
-                <Form.Item name="account" rules={[{ required: true, message: '请输入用户名!' }]}>
-                  <Input className="input" placeholder="请输入用户名" />
-                </Form.Item>
-
-                <Form.Item name="password" rules={[{ required: true, message: '请输入密码!' }]}>
-                  <Input.Password className="input" placeholder="请输入密码" />
-                </Form.Item>
-
-                <Form.Item>
-                  <Button className="loginBtn" type="primary" htmlType="submit" loading={ifLoading}>
-                    登录
-                  </Button>
-                </Form.Item>
-
-                {/* <Form.Item name="remember" valuePropName="checked">
-                    <Checkbox className="checkBtn">记住密码</Checkbox>
-                  </Form.Item> */}
-              </Form>
-              <div className="bottomCopyright">{(currentSelectedSubHop?.loginTips.split('|'))[1]}</div>
-              <div className="versionInfo">{(currentSelectedSubHop?.loginTips.split('|'))[2]}</div>
-            </div>
-          </Col>
-        </Row>
+            </Col>
+          </Row>
+        </>
       ) : (
         children
       )}

+ 18 - 1
src/pages/login/style.less

@@ -163,7 +163,7 @@
 
     .bottomCopyright {
       position: absolute;
-      bottom: 50px;
+      bottom: 40px;
       width: 100%;
       text-align: center;
       font-size: 12px;
@@ -182,6 +182,23 @@
       font-weight: 400;
       color: #515866;
     }
+    .beian {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: center;
+      position: absolute;
+      bottom: 16px;
+      width: 100%;
+      text-align: center;
+      font-size: 12px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #ACB3BF;
+      a {
+        color: #ACB3BF;
+      }
+    }
   }
 
 }

BIN
src/pages/noAccess/images/noAccess.png


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

@@ -0,0 +1,29 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-14 14:14:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2024-07-18 13:56:55
+ * @FilePath: /BudgetManaSystem/src/pages/noAccess/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+import { Link } from 'umi';
+import './style.less';
+const NoAccessPage: React.FC = () => {
+
+  return (
+    <div
+      className='NoAccessPage'
+
+    >
+         <div className='content'>
+              <img className='flagIcon' src={require('./images/noAccess.png')} alt="" />
+              <div className='title'>暂无权限</div>
+              <div className='subTitle'>当前功能暂无权限,请联系管理员分配权限</div>
+              <Link to='/index' replace ><div className='btn'>返回首页</div></Link>
+         </div>
+    </div>
+  );
+};
+
+export default NoAccessPage;

+ 49 - 0
src/pages/noAccess/style.less

@@ -0,0 +1,49 @@
+.NoAccessPage {
+    .content {
+        display: flex;
+        height: 91vh;
+        flex-direction: column;
+        justify-content:flex-start;
+        align-items: center;
+        background: #fff;
+        padding-top: 200px;
+        box-sizing: border-box;
+
+        .flagIcon {
+            width: 160px;
+            height: 140px;
+        }
+
+        .title {
+            font-weight: 500;
+            font-size: 24px;
+            height: 24px;
+            color: #17181A;
+            line-height: 24px;
+            margin-top: 24px;
+            margin-bottom: 16px;
+        }
+
+        .subTitle {
+            font-weight: 400;
+            font-size: 14px;
+            height: 14px;
+            color: #7A8599;
+            line-height: 14px;
+            margin-bottom: 24px;
+        }
+
+        .btn {
+            cursor: pointer;
+            width: 80px;
+            height: 24px;
+            line-height: 24px;
+            text-align: center;
+            background: #3377FF;
+            border-radius: 4px;
+            font-weight: 400;
+            font-size: 14px;
+            color: #FFFFFF;
+        }
+    }
+}

+ 125 - 26
src/pages/platform/_layout.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-06 15:25:39
- * @LastEditTime: 2024-01-16 16:49:31
+ * @LastEditTime: 2024-07-18 16:59:59
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/_layout.tsx
@@ -19,12 +19,70 @@ import { Key, useEffect, useState } from 'react';
 import Icon, { FileOutlined, FolderOutlined, createFromIconfontCN } from '@ant-design/icons';
 import { getAllParams } from '@/service';
 
-import '../../../public/zhongtaiC';
+import '../../../public/zhongtaiA';
+import ResizableContainer from '@/components/ResizableContainer';
+import { Menu } from 'antd';
 
 const IconFont = createFromIconfontCN({
   scriptUrl: '',
 });
 
+interface TransformResult {
+  newTree: any[];
+  firstLeafNode: any | null;
+  firstLeafNodePath: any[];
+}
+
+
+function transformTree(tree: any[]): TransformResult {
+  let firstLeafNode: any | null = null;
+  let firstLeafNodePath: any[] = [];
+
+  function traverse(node: any, path: any[]): any {
+    const newNode: any = {
+      ...node,
+      label: node.name,
+    };
+
+    const newPath = [...path, newNode];
+
+    if (node.children && node.children.length > 0) {
+      newNode.children = node.children.map((child: any) => traverse(child, newPath));
+    } else {
+      if (!firstLeafNode) {
+        firstLeafNode = newNode;
+        firstLeafNodePath = newPath;
+      }
+    }
+
+    // Remove children property if it is an empty array
+    if (node.children && node.children.length === 0) {
+      newNode.children = null;
+    }
+
+    return newNode;
+  }
+
+  const newTree = tree.map(node => traverse(node, []));
+
+  return { newTree, firstLeafNode, firstLeafNodePath };
+}
+
+const findItemByKey: any = (tree: any[], key: string, keyName: string) => {
+  for (const node of tree) {
+    if (node[`${keyName}`] === key) {
+      return node;
+    }
+    if (node.children) {
+      const result = findItemByKey(node.children, key, keyName);
+      if (result) {
+        return result;
+      }
+    }
+  }
+  return null;
+}
+
 export default function Layout({ children, location, route, history, match, ...rest }: IRouteComponentProps) {
   const { initialState, setInitialState } = useModel('@@initialState');
   const [openKeys, set_openKeys] = useState<string[]>([]);
@@ -37,6 +95,11 @@ export default function Layout({ children, location, route, history, match, ...r
 
   const [pageUrl, set_pageUrl] = useState<string | undefined>(undefined);
 
+  const queryParams = new URLSearchParams(location.search);
+  const noMenu = queryParams.get('noMenu');
+
+  const moreConfig: { menuRender?: any } = (isShowPageMenu && noMenu != 'true') ? {} : { menuRender: false }
+
   const { pathname } = location;
 
   const setEmptyPageContent = async (menuId: Key) => {
@@ -104,7 +167,7 @@ export default function Layout({ children, location, route, history, match, ...r
     }
     return url;
   };
-
+ 
   if (initialState?.currentSelectedSys) {
     const { type, url, contentType } = initialState.currentSelectedSys;
     if (type == 1 && contentType == 6) {
@@ -186,27 +249,33 @@ export default function Layout({ children, location, route, history, match, ...r
       logoStyle={{
         display: 'none',
       }}
+      className='platFormLayout'
+      contentStyle={{
+        margin: noMenu != 'true' ? 16 : 0,
+      }}
       location={{}}
       headerContentRender={false}
       headerRender={false}
-      siderWidth={isShowPageMenu ? 200 : 0}
+      siderWidth={(isShowPageMenu && noMenu != 'true') ? 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>
-        );
-      }}
+      collapsedButtonRender={false}
+      // 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
@@ -236,6 +305,7 @@ export default function Layout({ children, location, route, history, match, ...r
           initialState,
         },
         request: async () => {
+         
           if (initialState && initialState.currentSelectedSys) {
             const { systemId, menuId, path } = initialState.currentSelectedSys;
             if (systemId || menuId) {
@@ -278,7 +348,7 @@ export default function Layout({ children, location, route, history, match, ...r
               };
 
               const _menu = getVFromTree(menuData, 'contentType');
-              setInitialState((t) => ({ ...t, spacicalPageParamsType: _menu }));
+              setInitialState((t) => ({ ...t, spacicalPageParamsType: _menu,menuData }) as any);
 
               if (homePage) {
                 // console.log({homePage});
@@ -290,7 +360,7 @@ export default function Layout({ children, location, route, history, match, ...r
                   const selectedKeys = localStorage.getItem('selectedKeys');
                   const openKeys = localStorage.getItem('openKeys');
 
-                  if (selectedKeys && openKeys) {
+                  if (selectedKeys&&openKeys) {
                     const _selectedKeys = JSON.parse(selectedKeys);
                     const _openKeys = JSON.parse(openKeys);
                     set_openKeys(_openKeys);
@@ -320,14 +390,14 @@ export default function Layout({ children, location, route, history, match, ...r
                 arr.map((item: any) =>
                   item.children
                     ? {
-                        ...item,
-                        icon: <FolderOutlined />,
-                        children: addIcon(item.children),
-                      }
+                      ...item,
+                      icon: <FolderOutlined />,
+                      children: addIcon(item.children),
+                    }
                     : {
-                        ...item,
-                        icon: <FileOutlined />,
-                      },
+                      ...item,
+                      icon: <FileOutlined />,
+                    },
                 );
 
               const imgNode = (props: any) => {
@@ -363,9 +433,38 @@ export default function Layout({ children, location, route, history, match, ...r
           return [];
         },
       }}
-      onPageChange={(location) => {}}
+
+      menuRender={(props: any, defaultDom) => {
+        return (
+          <div style={{ display: 'inline-block' }}>
+            <ResizableContainer width={collapsed ? 64 : 200} minWidth={0} maxWidth={600} height={'calc(100vh - 48px)'}>
+              <div style={{background:'#fff',height:'100%'}}>
+                <div className='menuWrapper' style={{ height: 'calc(100% - 40px)', overflowY: 'scroll', overflowX: 'hidden', background: '#fff' }}>
+                  {defaultDom}
+                </div>
+
+                <div style={{
+                  position: 'absolute', zIndex: 10, right: 17, bottom: 9,
+                  display: 'flex', justifyContent: 'center', alignItems: 'center',
+                  cursor: 'pointer', width: 24, height: 24, background: '#fff'
+                }} onClick={
+                  () => {
+                    set_collapsed(collapsed ? false : true);
+                  }
+                }>
+                  <IconFont style={{ display: 'inline-block',fontSize:24 }} className="menuCollapseIcon" type={collapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'} />
+                </div>
+              </div>
+
+            </ResizableContainer>
+          </div>
+
+        );
+      }}
+      onPageChange={(location) => { }}
       layout="side"
       navTheme="light"
+      {...moreConfig}
     >
       {isEmpty && (
         <div className="emptyContainer" style={{ textAlign: 'center', paddingTop: 100 }}>

+ 5 - 7
src/pages/platform/index.less

@@ -6,8 +6,11 @@
 
 // }
 
-
-
+.platFormLayout {
+  &>.kcmp-ant-layout {
+      flex-direction: row;
+  }
+}
 .kcmp-ant-pro-sider-light {
   border-right-color: rgba(54, 61, 77, 0.1);
 
@@ -114,10 +117,5 @@
 .kcmpPageContainer {
   .kcmp-ant-pro-page-container-children-content {
     margin: 0;
-    margin-top: 16px;
-    margin-left: 16px;
-    margin-right: 12px;
-    border-radius: 4px;
-    overflow: hidden;
   }
 }

+ 1 - 0
src/pages/platform/setting/hospManage/index.tsx

@@ -83,6 +83,7 @@ export function extractAttributeValues(tree: TreeNode, attributeName: keyof Tree
       values = values.concat(extractAttributeValues(child, attributeName));
     }
   }
+  
 
   return values;
 }

+ 11 - 8
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: 2024-03-01 16:15:37
+ * @LastEditTime: 2024-07-05 23:47:30
  * @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
  */
@@ -134,10 +134,10 @@ const PubDicMana = () => {
     const currentSelectedHop = localStorage.getItem('currentSelectedSubHop');
     const { systemId: parentId } = currentSelectedTreeNode;
     let hospId = '0';
-    // if (currentSelectedHop) {
-    //     const { id } = JSON.parse(currentSelectedHop);
-    //     hospId = id
-    // }
+    if (currentSelectedHop) {
+        const { id } = JSON.parse(currentSelectedHop);
+        hospId = id
+    }
     if (type == 'EDIT' && pageType) {
       const resp = await editPubDicRelaTbaleData(
         pageType == 1 ? { ...formVal, systemId: parentId, hospId, dictType: currentSelectedTreeNode?.dictType } : { ...formVal, systemId: parentId, hospId, type: currentSelectedTreeNode?.dictType },
@@ -156,6 +156,8 @@ const PubDicMana = () => {
         set_reload(true);
       }
     }
+
+    return true
   };
 
   const UpDataActBtn = ({ record, type }: { record: any; type: 'EDIT' | 'ADD' }) => {
@@ -169,9 +171,9 @@ const PubDicMana = () => {
           return updateTable(type == 'EDIT' ? (pageType == 1 ? { ...val, dictDataId: record.dictDataId } : { ...val, id: record.id }) : val, type);
         }}
       >
-        <ProFormText name="name" label="项目名称:" placeholder="请输入" rules={[{ required: true, message: '项目名称不能为空!' }]} />
-        <ProFormText name="code" label="项目代码:" placeholder="请输入" rules={[{ required: true, message: '项目代码不能为空!' }]} />
-        <ProFormText name="value" label="项目值:" placeholder="请输入" />
+        <ProFormText name="name" label="名称:" placeholder="请输入" rules={[{ required: true, message: '名称不能为空!' }]} />
+        <ProFormText name="code" label="代码:" placeholder="请输入" rules={[{ required: true, message: '代码不能为空!' }]} />
+        <ProFormText name="value" label="对应值:" placeholder="请输入" />
         <ProFormDigit label="顺序号:" name={pageType == 1 ? 'dictSort' : 'sort'} rules={[{ required: true, message: '顺序号不能为空!' }]} />
 
         <ProFormRadio.Group
@@ -265,6 +267,7 @@ const PubDicMana = () => {
     setExpandedKeys(newExpandedKeys as React.Key[]);
     setSearchValue(value);
     setAutoExpandParent(true);
+    
   };
 
   const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {

+ 2 - 1
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: 2024-03-01 15:54:23
+ * @LastEditTime: 2024-07-05 23:47:07
  * @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
  */
@@ -300,6 +300,7 @@ export default function PubDicTypeMana() {
             blockNode={true}
             icon={() => null}
             titleRender={(nodeData: any) => {
+              
               const strTitle = nodeData.name as string;
               const index = strTitle.indexOf(searchValue);
               const beforeStr = strTitle.substring(0, index);

+ 8 - 3
src/pages/platform/setting/roleManage/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 15:22:48
- * @LastEditTime: 2024-01-19 14:42:40
+ * @LastEditTime: 2024-07-02 17:26: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/platform/setting/hospManage/index.tsx
@@ -372,6 +372,8 @@ const DrawerActBtn = ({ record }: { record: any }) => {
       function: [],
     }));
 
+    
+
     const data = {
       hospId: record.hospId,
       roleId: record.roleId,
@@ -380,6 +382,8 @@ const DrawerActBtn = ({ record }: { record: any }) => {
       functionList: [...result, ...needCancelMenus],
     };
 
+ 
+
     const resp = await saveRoleRelaApiPerm(data);
     if (resp) {
       set_drawerTablereload(true);
@@ -628,10 +632,10 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
                       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]);
                       }
 
@@ -675,6 +679,7 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                       set_checkedTableMenuIds([...leftCheckedMenuIds]);
 
                       set_checkBoxCodes([...uniqueFunc(filtedCheckCodes, 'menuId')]);
+                    
                     }
                   },
                 }}

+ 2 - 3
src/pages/platform/setting/systemNavMana/style.less

@@ -11,8 +11,8 @@
   .systemNavManaForm {}
 
   .leftTree {
-    position: fixed;
-    top: 64px;
+    // position: fixed;
+    // top: 64px;
     width: 220px;
     height: calc(100vh - 80px);
     background: #FFF;
@@ -44,7 +44,6 @@
     border-radius: 4px;
     width: calc(100% - 220px);
     padding: 16px;
-    margin-left: 236px;
     background: #FFF;
 
     .checkBtn {

+ 26 - 16
src/pages/platform/setting/userManage/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-12-14 14:29:22
+ * @LastEditTime: 2024-07-18 10:39:51
  * @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
@@ -14,7 +14,7 @@ import { message, Button, Spin, Upload, UploadProps } from 'antd';
 import { userManageModelState, Dispatch } from 'umi';
 import { ProFormDateTimePicker, ProFormDependency, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
 import { getShareHospList } from '@/service/hospList';
-import { AddUsersDataType, getUserRelaSeletData, UserRelaSeletDataListType, UserRelaSeletDataType } from '@/service/user';
+import { AddUsersDataType, getUserRelaSeletData, uploadAvatar, UserRelaSeletDataListType, UserRelaSeletDataType } from '@/service/user';
 import { LoadingOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
 // import { TableActType } from "./typings";
 
@@ -35,6 +35,7 @@ interface ActModalProps extends userManageModelState {
 const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
 
 const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, currentEditUser }) => {
+
   const [avatarUrl, setAvatarUrl] = useState<string>('');
   const [loadAvatar, setLoadAvatar] = useState(false);
 
@@ -45,18 +46,24 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     name: 'file',
     maxCount: 1,
     showUploadList: false,
-    onChange(info: { file: any; fileList: any }) {
+    onChange: async (info: { file: any; fileList: any }) => {
       setLoadAvatar(true);
 
       if (info.file.status !== 'uploading') {
-        // console.log(info.file, info.fileList);
-        const reader = new FileReader();
-        reader.readAsDataURL(info.file.originFileObj); //读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
-        reader.onload = function (event) {
-          if (event.target && typeof event.target.result == 'string') {
-            setAvatarUrl(event.target.result); //base64
-          }
-        };
+
+        const form = new FormData();
+        form.append('file',info.file.originFileObj);
+        const resp = await uploadAvatar(form);
+        if(resp){
+          setAvatarUrl(resp);
+        }
+        // const reader = new FileReader();
+        // reader.readAsDataURL(info.file.originFileObj); //读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
+        // reader.onload = function (event) {
+        //   if (event.target && typeof event.target.result == 'string') {
+        //     setAvatarUrl(event.target.result); //base64
+        //   }
+        // };
       }
       if (info.file.status === 'done') {
         setLoadAvatar(false);
@@ -78,12 +85,12 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
   };
 
   const onFinishHandle = (data: any & AddUsersDataType) => {
-    console.log({ data });
+    // console.log({ data });
     if (tableAct == TableActType.ADD) {
       dispatch &&
         dispatch({
           type: 'userManageModel/postAddUserData',
-          payload: data,
+          payload: {...data,avatarUrl:avatarUrl},
         });
     }
 
@@ -91,7 +98,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
       dispatch &&
         dispatch({
           type: 'userManageModel/postEditUserData',
-          payload: data,
+          payload: {...data,avatarUrl:avatarUrl},
         });
     }
 
@@ -138,6 +145,9 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     </div>
   );
 
+  useEffect(()=>{
+    setAvatarUrl(currentEditUser?currentEditUser.avatarUrl:'');
+  },[currentEditUser]);
   useEffect(() => {
     getDirecData();
   }, []);
@@ -195,11 +205,11 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
                   options={[
                     {
                       label: '是',
-                      value: 0,
+                      value: 1,
                     },
                     {
                       label: '否',
-                      value: 1,
+                      value: 0,
                     },
                   ]}
                   rules={[{ required: true, message: '请选择专业!' }]}

+ 55 - 28
src/pages/platform/setting/userManage/model.ts

@@ -1,14 +1,21 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2024-04-01 11:27:15
+ * @LastEditTime: 2024-06-18 09: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/platform/setting/userManage/model.ts
  */
 
 import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
-import { addUsers, delUsers, editUsers, getUsertemplate, importUserData, resetUserPwd } from '@/service/user';
+import {
+  addUsers,
+  delUsers,
+  editUsers,
+  getUsertemplate,
+  importUserData,
+  resetUserPwd,
+} from '@/service/user';
 import { TableListItem } from './typings';
 import axios from 'axios';
 
@@ -77,12 +84,30 @@ const userManageModel: userManageModelType = {
     *resetUserPwd({ payload }) {
       yield resetUserPwd({ userId: payload.id });
     },
-    *postEditUserData({ payload }: any, { call, put, select }: any) {
-      const currentEditUserOld = yield select(({ userManageModel: state }: { userManageModel: userManageModelState }) => {
-        return state.currentEditUser;
-      });
+    // *postEditUserData({ payload }:any, { call, put, select }:any) {
+    //   const currentEditUserOld = yield select(
+    //     ({ userManageModel: state }: { userManageModel: userManageModelState }) => {
+    //       return state.currentEditUser;
+    //     },
+    //   );
 
-      yield editUsers({ ...currentEditUserOld, ...payload });
+    //   yield editUsers({ ...currentEditUserOld, ...payload });
+    //   yield put({
+    //     type: 'reloadTable',
+    //     payload: true,
+    //   });
+    // },
+    *postEditUserData(
+      { payload }: any,
+      { call, put, select }: any
+    ): Generator<any, void, any> {
+      const currentEditUserOld = yield select(
+        ({ userManageModel: state }: { userManageModel: userManageModelState }) => {
+          return state.currentEditUser;
+        },
+      );
+    
+      yield call(editUsers, { ...currentEditUserOld, ...payload });
       yield put({
         type: 'reloadTable',
         payload: true,
@@ -100,28 +125,30 @@ const userManageModel: userManageModelType = {
 
       const userData = localStorage.getItem('userData');
       const { token = '' } = JSON.parse(userData as string);
-
+      
       axios({
-        method: 'get',
-        url: path,
-        responseType: 'blob',
-        headers: { token },
-      }).then(function (response) {
-        //console.log({ 'chunk': response });
-        const filename = decodeURI(response.headers['content-disposition']);
-        const objectUrl = URL.createObjectURL(
-          new Blob([response.data], {
-            type: 'application/vnd.ms-excel',
-          }),
-        );
-        const link = document.createElement('a');
-        // 设置导出的文件名称
-        link.download = `${filename}` + '.xls';
-        link.style.display = 'none';
-        link.href = objectUrl;
-        link.click();
-        document.body.appendChild(link);
-      });
+          method: 'get',
+          url: path,
+          responseType: 'blob',
+          headers: { token },
+      })
+          .then(function (response) {
+              //console.log({ 'chunk': response });
+              const filename = decodeURI(response.headers["content-disposition"]);
+              const objectUrl = URL.createObjectURL(
+                  new Blob([response.data], {
+                      type: 'application/vnd.ms-excel',
+                  })
+              )
+              const link = document.createElement('a')
+              // 设置导出的文件名称
+              link.download = `${filename}` + '.xls'
+              link.style.display = 'none'
+              link.href = objectUrl
+              link.click()
+              document.body.appendChild(link)
+    
+          });
     },
     *importUsers({ payload }, { call, put, select }) {
       // const formData: any = new FormData();

+ 1 - 0
src/service/indicator.ts

@@ -49,6 +49,7 @@ export const editIndicatorManaList = async (data:any) => {
 };
 
 
+
 //删除指标
 export const delIndicatorManaList = async (params:{id:number}) => {
   return request('/centerSys/indicator/deleteIndicator', {

+ 9 - 1
src/service/user.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 09:55:49
- * @LastEditTime: 2024-03-28 17:33:15
+ * @LastEditTime: 2024-07-11 18:13:46
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/user.ts
@@ -106,6 +106,14 @@ export const resetUserPwd = async (data: { userId: number }) => {
   });
 };
 
+//上传头像
+export const uploadAvatar = async (data:any) => {
+  return request('/centerSys/user/uploadAvatar', {
+    method: 'POST',
+    data: data,
+  });
+};
+
 //获取有数用户列表
 export type GetYoushuUsersRepType = {
   id: number;

+ 0 - 14
src/wrappers/auth.ts

@@ -1,14 +0,0 @@
-/*
- * @Author: code4eat awesomedema@gmail.com
- * @Date: 2023-11-10 14:59:21
- * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-11-10 15:12:41
- * @FilePath: /KC-MiddlePlatform/src/wrappers/auth.ts
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
- */
-import { Redirect } from 'umi';
-
-export default (props: any) => {
-  console.log({ props });
-  return true;
-};

+ 84 - 0
src/wrappers/auth.tsx

@@ -0,0 +1,84 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2024-04-09 18:07:35
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2024-07-18 16:16:07
+ * @FilePath: /KC-MiddlePlatform/src/wrappers/auth.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+import React, { useEffect, useRef, useState } from 'react';
+import { history, useModel } from 'umi';
+import type { IRoute } from 'umi';
+// import { Outlet } from '@umijs/max';
+
+//权限检查函数
+function checkAccess(menu: IRoute[], pathname: string): boolean {
+  // 检查当前路径或其父路径是否匹配
+  const matchPath = (path: string, target: string): boolean => {
+    if (target.startsWith(path)) {
+      return true;
+    }
+    return false;
+  };
+
+  for (const item of menu) {
+    if (matchPath(item.path as string, pathname)) {
+      return true;
+    }
+    if (item.child) {
+      const hasAccess = checkAccess(item.child, pathname);
+      if (hasAccess) {
+        return true;
+      }
+    }
+    if (item.children) {
+      const hasAccess = checkAccess(item.children, pathname);
+      if (hasAccess) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+function removePrefix(input: string, prefix: string): string {
+  if (input.startsWith(prefix)) {
+    return input.slice(prefix.length);
+  }
+  return input;
+}
+
+// 权限包装组件
+const AuthWrapper: React.FC = (props) => {
+  const { initialState } = useModel('@@initialState');
+  const [loading,set_loading] = useState(true);
+  const [dataLoaded, setDataLoaded] = useState(false);
+
+  useEffect(() => {
+    if (!dataLoaded) {
+      const navData = initialState?.navData ?? [];
+      const menuData = initialState?.menuData ?? [];
+
+      if (navData.length > 0 || menuData.length > 0) {
+        setDataLoaded(true);
+
+        const { pathname } = history.location;
+        const needCheckPath = [...navData, ...menuData];
+        const hasAccess = checkAccess(needCheckPath, pathname);
+        console.log({ needCheckPath, pathname, hasAccess });
+
+        if (!hasAccess) {
+          if (!pathname.includes('/platform')) {
+            history.push('/noAccess');
+          }
+        }
+        set_loading(false);
+      }
+    }
+  }, [initialState, dataLoaded]);
+
+  return loading?<>loading</>:<div>{props.children}</div>;
+};
+
+export default AuthWrapper;
+export { checkAccess };

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.