Browse Source

完成最新版更新:添加体系层级及部分表格改造

code4eat 3 năm trước cách đây
mục cha
commit
5fa28551f6
56 tập tin đã thay đổi với 3474 bổ sung1045 xóa
  1. 12 2
      config/config.ts
  2. 1 0
      package.json
  3. BIN
      public/images/avatar.png
  4. BIN
      public/images/jingyiguanliIcon.png
  5. BIN
      public/images/kclogo_colorful.png
  6. BIN
      public/images/menu.png
  7. BIN
      public/images/zhilianganquan.png
  8. 13 10
      src/app.tsx
  9. 141 0
      src/components/NavSelecter/index.tsx
  10. 98 0
      src/components/NavSelecter/style.less
  11. 220 68
      src/components/topBar/index.tsx
  12. 216 123
      src/components/topBar/style.less
  13. 27 5
      src/components/topBar/typings.d.ts
  14. 18 2
      src/constant.ts
  15. 44 19
      src/layouts/index.tsx
  16. 22 0
      src/pages/channelIndex/channelIndexOne/index.tsx
  17. 0 0
      src/pages/channelIndex/channelIndexOne/style.less
  18. 189 0
      src/pages/index/components/FastEntry/index.tsx
  19. 70 0
      src/pages/index/components/FastEntry/style.less
  20. 64 0
      src/pages/index/components/MsgRecord/index.tsx
  21. 66 0
      src/pages/index/components/MsgRecord/style.less
  22. 74 0
      src/pages/index/components/RecentlyVisited/index.tsx
  23. 56 0
      src/pages/index/components/RecentlyVisited/style.less
  24. BIN
      src/pages/index/components/TodoList/images/exclamationMark.png
  25. BIN
      src/pages/index/components/TodoList/images/gou.png
  26. 77 0
      src/pages/index/components/TodoList/index.tsx
  27. 162 0
      src/pages/index/components/TodoList/style.less
  28. 233 42
      src/pages/index/index.less
  29. 142 24
      src/pages/index/index.tsx
  30. 26 57
      src/pages/login/index.tsx
  31. 107 169
      src/pages/login/style.less
  32. 21 27
      src/pages/platform/_layout.tsx
  33. 167 0
      src/pages/platform/components/TreeEditer/index.tsx
  34. 0 0
      src/pages/platform/components/TreeEditer/style.less
  35. 121 152
      src/pages/platform/components/menuEditer/menu.tsx
  36. 68 63
      src/pages/platform/components/usersEditer/index.tsx
  37. 34 18
      src/pages/platform/setting/hospManage/index.tsx
  38. 72 6
      src/pages/platform/setting/hospManage/modals/modal.tsx
  39. 86 28
      src/pages/platform/setting/menuManage/index.tsx
  40. 206 118
      src/pages/platform/setting/menuManage/modals/modal.tsx
  41. 64 5
      src/pages/platform/setting/menuManage/model.ts
  42. 2 2
      src/pages/platform/setting/roleManage/index.tsx
  43. 4 4
      src/pages/platform/setting/roleManage/modals/modal.tsx
  44. BIN
      src/pages/platform/setting/userManage/assets/avatar_empty.png
  45. 3 2
      src/pages/platform/setting/userManage/index.tsx
  46. 225 82
      src/pages/platform/setting/userManage/modal.tsx
  47. 94 0
      src/pages/platform/setting/userManage/style.less
  48. 25 0
      src/pages/platform/sqlediter/index.tsx
  49. 0 0
      src/pages/platform/sqlediter/style.less
  50. 4 4
      src/service/api.d.ts
  51. 22 0
      src/service/dictionary.ts
  52. 4 4
      src/service/hospList.ts
  53. 59 0
      src/service/index.ts
  54. 88 3
      src/service/menu.ts
  55. 23 2
      src/service/user.ts
  56. 4 4
      src/typings.d.ts

+ 12 - 2
config/config.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:04:20
- * @LastEditTime: 2022-03-30 10:59:29
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-06 15:35:23
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/config/config.ts
  */
@@ -17,6 +17,7 @@ export default defineConfig({
   nodeModulesTransform: {
     type: 'none',
   },
+  title:false,
   publicPath: '/',
   dva: {
     immer: true,
@@ -43,8 +44,13 @@ export default defineConfig({
           path: '/app1',
           microApp: 'app1',
         },
+        {
+          path: '/channelIndex/channelIndexOne',
+          component: '@/pages/channelIndex/channelIndexOne/index.tsx',
+        },
         {
           path: '/index',
+          title:'欢迎进入医管平台',
           component: '@/pages/index/index.tsx',
         },
         {
@@ -52,6 +58,10 @@ export default defineConfig({
           path: '/platform',
           component: '@/pages/platform/_layout.tsx',
           routes: [
+            {
+              path: '/platform/sqlEditer',
+              component: '@/pages/platform/sqlediter/index.tsx',
+            },
             {
               path: '/platform/setting/userManage',
               component: '@/pages/platform/setting/userManage/index.tsx',

+ 1 - 0
package.json

@@ -28,6 +28,7 @@
     "@ant-design/pro-form": "^1.18.3",
     "@ant-design/pro-layout": "^6.15.3",
     "@ant-design/pro-table": "^2.30.8",
+    "@monaco-editor/react": "^4.4.5",
     "cross-env": "^7.0.3",
     "password-quality-calculator": "^1.0.4",
     "react": "16.x",

BIN
public/images/avatar.png


BIN
public/images/jingyiguanliIcon.png


BIN
public/images/kclogo_colorful.png


BIN
public/images/menu.png


BIN
public/images/zhilianganquan.png


+ 13 - 10
src/app.tsx

@@ -29,9 +29,9 @@ export const initialStateConfig = {
 
 type InitialStateType = {
   userData?: UserDataType;
-  systemLists?: userRelationInfo.OwnAppsItem[]; //当前医院可选子系统列表
-  openedSysLists?: userRelationInfo.OwnAppsItem[]; //当前已打开的系统列表
-  currentSelectedSys?: userRelationInfo.OwnAppsItem; //当前选中的tab
+  systemLists?: TopBar.Tab[]; //当前医院可选子系统列表
+  openedSysLists?: TopBar.Tab[]; //当前已打开的系统列表
+  currentSelectedSys?: TopBar.Tab; //当前选中的tab
   logout?: () => Promise<boolean>;
   spacicalPageParamsType?: SpacicalPageParamsType[];
   getHospSubSystemListFunc?: () => Promise<any[]>;
@@ -110,6 +110,8 @@ const requestInterceptorsHandle = (url: string, options: RequestOptionsInit) =>
 };
 
 const responseInterceptorsHandle = async (response: Response, options: RequestOptionsInit) => {
+
+
   const _response: {
     data?: any;
     status: number;
@@ -117,13 +119,12 @@ const responseInterceptorsHandle = async (response: Response, options: RequestOp
     msg?: string;
   } = await response.clone().json();
 
+
   if (_response.status == 200) {
     if (_response.data) {
       return _response.data;
     }
-    // notification.success({
-    //   message: `${_response.msg}`,
-    // });
+
     notification.success({
       message: `操作成功!`,
     });
@@ -155,9 +156,10 @@ interface ResponseErr extends Error {
 }
 
 const errorHandlerFunc = (error: ResponseErr) => {
+
   try {
     const { info } = error;
-    const { errorCode, errorMessage } = info;
+    const { errorCode , errorMessage } = info;
 
     if (errorCode == 499) {
       //token过期
@@ -196,6 +198,7 @@ export const request: RequestConfig = {
   timeout: 10000,
   errorConfig: {
     adaptor: (resData) => {
+
       if (!resData.success && resData.status != 200) {
         return {
           ...resData,
@@ -227,9 +230,9 @@ export const qiankun = fetch('/config').then(() => ({
   apps: [
     {
       name: 'app1', // 唯一 id
-      // entry: '//112.124.59.133:8804',  //开发
+      entry: '//112.124.59.133:8804',  //测试
       // entry: '//118.31.245.65:8804', //线上
-      entry: '//localhost:8804', // html entry
+      //entry: '//localhost:8804', // 开发
     },
   ],
   // 完整生命周期钩子请看 https://qiankun.umijs.org/zh/api/#registermicroapps-apps-lifecycles
@@ -257,7 +260,7 @@ export const layout = ({ initialState: { userData } }: { initialState: InitialSt
     onPageChange: () => {
       //如果没有登录,重定向到 login
       if (!userData && location.pathname !== '/login') {
-        history.push('/login');
+        // history.push('/login');
       }
     },
     menuHeaderRender: undefined,

+ 141 - 0
src/components/NavSelecter/index.tsx

@@ -0,0 +1,141 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-06-29 11:05:04
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-01 11:07:09
+ * @FilePath: /KC-MiddlePlatform/src/components/NavSelecter/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { Tabs, Checkbox, Button } from 'antd';
+import React, { useEffect, useState } from 'react';
+import './style.less';
+
+const { TabPane } = Tabs;
+
+
+
+export type NavSelecterItemType = {
+    name: string;
+    menuId: number|string;
+    path:string;
+    systemId:string;
+}
+
+
+export type NavSelecterData = {
+    name: string;
+    menuId: number|string;
+    path:string;
+    systemId:string;
+    child?: NavSelecterData[]
+}
+
+export interface NavSelecter {
+    onVisibleChange?: (t: boolean) => void;
+    onChecked?:(t:NavSelecterItemType[]) => void;
+    value?:NavSelecterItemType[];
+    data?: NavSelecterData[];
+}
+
+const NavSelecter = (props: NavSelecter) => {
+
+    const { onVisibleChange, data,value=[],onChecked } = props;
+    const [checkedIds,set_checkedIds] = useState<(string|number)[]>([]);
+    const [checkedItems,set_checkedItems] = useState<NavSelecterItemType[]>([]);
+
+
+    const onChange = (tab:NavSelecterItemType) => {
+        
+        let _checkedIds = checkedIds;
+        let _checkedItems = [...checkedItems]; 
+
+        if(_checkedIds.includes(tab.menuId)){
+            _checkedIds.splice(checkedIds.indexOf(tab.menuId),1);
+            _checkedItems.splice(_checkedItems.findIndex(t=>t.menuId == tab.menuId),1);
+            set_checkedIds([..._checkedIds]);
+            set_checkedItems([..._checkedItems]);
+        }else{
+            
+            _checkedIds.push(tab.menuId);
+            _checkedItems.push(tab);
+            set_checkedItems([..._checkedItems]);
+            set_checkedIds([..._checkedIds]);
+        }
+    };
+
+    const onMaskClick = (e: React.MouseEvent) => {
+
+        onVisibleChange && onVisibleChange(false);
+    }
+
+    const onCommit = ()=>{
+        onChecked&&onChecked(checkedItems);
+        onVisibleChange && onVisibleChange(false);
+    }
+
+    const onReset = ()=>{
+        set_checkedItems([]);
+        set_checkedIds([]);
+    }
+
+    useEffect(()=>{
+
+        set_checkedIds(value?.map(t=>t.menuId));
+        set_checkedItems(value);
+
+    },[value]);
+
+
+    return (
+        <div className="navSelecter" onClick={(e) => onMaskClick(e)}>
+            <div className='container'>
+                <div className='content' onClick={(e) => e.stopPropagation()}>
+                    <Tabs defaultActiveKey="1" >
+                        {
+                            data?.map((val) => (
+                                <TabPane tab={val.name} key={val.menuId}>
+                                    {
+                                        val.child?.map((item) => (
+                                            <div className='row' key={item.menuId}>
+                                                <div className='rowName'>{item.name}</div>
+                                                <div className='rowWrap'>
+                                                    {
+                                                        item.child?.map(a => (
+                                                            <div className='tab' key={a.menuId}>
+                                                                <Checkbox onChange={() => onChange({
+                                                                       name: a.name,
+                                                                       menuId:a.menuId ,
+                                                                       path:a.path,
+                                                                       systemId:a.systemId
+                                                                })} checked={checkedIds.includes(a.menuId)} ></Checkbox>
+                                                                <span style={{ marginLeft: 8 }}>{a.name}</span>
+                                                            </div>
+                                                        ))
+                                                    }
+                                                </div>
+                                            </div>
+                                        ))
+                                    }
+                                </TabPane>
+                            ))
+                        }
+                    </Tabs>
+                </div>
+                <div className='footer' onClick={e=>e.stopPropagation()}>
+                    <span className='count'>{`已选中${checkedIds.length}项`}</span>
+                    <div className='btnGroup'>
+                        <Button style={{marginRight:8}} onClick={onReset}>重置</Button>
+                        <Button type="primary" onClick={onCommit}>确定</Button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    )
+}
+
+
+export default NavSelecter;

+ 98 - 0
src/components/NavSelecter/style.less

@@ -0,0 +1,98 @@
+.navSelecter {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  z-index: 999;
+  background-color: rgba(41, 44, 51, 0.5);
+
+  .container {
+    width: 70%;
+    height: 60%;
+    padding-top: 12px;
+    background: #FFFFFF;
+    border-radius: 4px;
+    border: 1px solid #CFD6E6;
+
+    .content {
+        padding: 24px;
+      height: calc(100% - 56px);
+      .row {
+        margin-bottom: 16px;
+
+        .rowName {
+          font-size: 12px;
+          height: 12px;
+          line-height: 12px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #7A8599;
+          margin-bottom: 8px;
+        }
+
+        .rowWrap {
+          display: flex;
+          flex-direction: row;
+          justify-content: flex-start;
+          flex-wrap: wrap;
+
+          .tab {
+            display: flex;
+            flex-direction: row;
+            align-items: center;
+            width: 24.2%;
+            height: 32px;
+            padding: 0 8px;
+            cursor: pointer;
+            background: #F5F7FA;
+            border-radius: 4px;
+            transform: all 0.3s ease-in;
+            margin-right: 1%;
+            margin-bottom: 8px;
+
+            &>span {
+              font-size: 12px;
+              font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+              font-weight: 400;
+              color: #17181A;
+            }
+
+            &:nth-child(4n) {
+              margin-right: 0;
+            }
+
+            &:hover {
+              &>span {
+                color: #3376FE;
+              }
+
+              background: rgba(51, 119, 255, 0.08);
+            }
+          }
+        }
+
+        &:last-child {
+          margin-bottom: 0;
+        }
+      }
+    }
+
+    .footer {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      height: 56px;
+      padding: 0 24px;
+      background: #FFFFFF;
+      border-radius: 0px 0px 4px 4px;
+      border-top: 1px solid #CFD6E6;
+
+    }
+  }
+
+}

+ 220 - 68
src/components/topBar/index.tsx

@@ -1,15 +1,15 @@
 /*
  * @Author: your name
  * @Date: 2021-11-16 09:12:37
- * @LastEditTime: 2022-03-29 16:10:09
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-05 09:32:13
+ * @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
  */
 
 import React, { useEffect, useState } from 'react';
 
-import styles from './style.less';
+import './style.less';
 
 import { Tooltip } from 'antd';
 import { LogoutOutlined, SettingOutlined } from '@ant-design/icons';
@@ -19,40 +19,73 @@ import platFormMenuIcon from '../../../public/images/platformMenu.png';
 import tabCloseIcon from '../../../public/images/tabCloseIcon.png';
 
 import { history } from 'umi';
+import { Divider } from 'antd';
+import { addFastEntry, getUserPlatformNav } from '@/service/menu';
+import { NavSelecterData } from '../NavSelecter';
 
 interface TopBarType {
   onTabChange?: (data: TopBar.Tab[]) => void; //当tab切换时回调
-  sysList: TopBar.Tab[]; //可选系统列表
   openedTabs: TopBar.Tab[]; //已打开的列表
   currentTab?: TopBar.Tab | undefined; //当前tab
   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[];
 }
 
+
+const localSavedTab = localStorage.getItem('currentSelectedTab');
+const currentSelectedTabFromLocal = localSavedTab ? JSON.parse(localSavedTab) : {};
+
 const TopBar: React.FC<TopBarType> = (props) => {
-  const { onTabChange, sysList = [], openedTabs = [], currentTab, userPannelTabClick, onCloseTab, onTabClick, userData } = props;
+  const { onTabChange, userPannelTabClick, onCloseTab, onTabClick, userData, navData,currentTab } = props;
   const [systemTabs, setSystemTabs] = useState<TopBar.Tab[]>([]); //已打开的tab
   const [currentSelectedTab, setCurrentSelectedTab] = useState<TopBar.Tab>();
   const [ifOpenPannel, setIfOpenPannel] = useState(false);
   const [arrowRotate, setArrowRotate] = useState(false);
-  // const [opendedTabs,setOpendedTabs] = useState<SystemListItem[]>([]);
+  const [pageTitle, set_pageTitle] = useState('欢迎进入医管平台');
+  const [currentActivedBlockIndex, set_currentActivedBlockIndex] = useState(0);
+  const [panelData, set_panelData] = useState<TopBar.PanelData[]>([]);
 
   const _systemTabClickHandle = (item: TopBar.Tab) => {
     //导航栏tab点击
 
-    setCurrentSelectedTab(item);
     onTabClick && onTabClick(item);
+    localStorage.setItem('currentSelectedTab', JSON.stringify(item));
+    setCurrentSelectedTab(item);
+
   };
 
-  const _systemListClickHandle = (data: TopBar.Tab) => {
+
+  const _systemListClickHandle = (data: TopBar.Tab, currentActivedBlockIndex: number, index: number, i: number) => {
     //导航栏系统菜单列表点击回调
-    const findIndex = systemTabs.findIndex((t) => t.id == data.id);
-    if (findIndex != -1) return;
+    if (currentSelectedTab?.menuId == data.menuId) return;
+
+    
+      //临时保存衣打开过的菜单
+    const t = localStorage.getItem('visitedTabs');
+
+    if(t){
+      let visitedTabs = JSON.parse(t);
+      let index = visitedTabs.findIndex((t:TopBar.Tab)=>t.menuId == data.menuId);
+      if(index == -1){
+        visitedTabs.push(data);
+        localStorage.setItem('visitedTabs',JSON.stringify(visitedTabs));
+      }
+    }else{
+      localStorage.setItem('visitedTabs',JSON.stringify([data]));
+    }
+
     _systemTabClickHandle(data); //触发一次tab点击
-    setSystemTabs([...systemTabs, data]);
-    onTabChange && onTabChange([...systemTabs, data]);
+
+    set_pageTitle(panelData[currentActivedBlockIndex].child[index].name)
+
+    if (panelData[currentActivedBlockIndex].child[index].child) {
+      console.log([...panelData[currentActivedBlockIndex].child[index].child])
+      setSystemTabs([...panelData[currentActivedBlockIndex].child[index].child]);
+    }
+    setIfOpenPannel(false);
   };
 
   const _userPannelTabClick = (tag: 'SETTING' | 'LOGOUT') => {
@@ -66,13 +99,14 @@ const TopBar: React.FC<TopBarType> = (props) => {
     let delIndex = -1;
 
     const filtered = _systemTabs.filter((t, index) => {
-      if (t.id == item.id) {
+      if (t.menuId == item.menuId) {
         delIndex = index;
       }
-      return t.id != item.id;
+      return t.menuId != item.menuId;
     });
 
     setSystemTabs([...filtered]);
+
     if (delIndex != 0) {
       _systemTabClickHandle(_systemTabs[delIndex - 1]); //自动切换为前一个tab
     }
@@ -83,12 +117,12 @@ const TopBar: React.FC<TopBarType> = (props) => {
 
   const UserPannel = () => {
     return (
-      <div className={styles.userPannel}>
-        <div className={styles.userPannelTab} onClick={() => _userPannelTabClick('SETTING')}>
+      <div className='userPannel'>
+        <div className='userPannelTab' onClick={() => _userPannelTabClick('SETTING')}>
           <SettingOutlined />
           设置
         </div>
-        <div className={styles.userPannelTab} onClick={() => _userPannelTabClick('LOGOUT')}>
+        <div className='userPannelTab' onClick={() => _userPannelTabClick('LOGOUT')}>
           <LogoutOutlined />
           退出
         </div>
@@ -96,80 +130,198 @@ const TopBar: React.FC<TopBarType> = (props) => {
     );
   };
 
-  useEffect(() => {
-    if (openedTabs.length == 1) {
-      //当有且仅当只有一个的时候,默认激活
-      setCurrentSelectedTab(openedTabs[0]);
-      history.push(openedTabs[0].path);
-    }
-    if (openedTabs.length == 0) {
-      //当所有tab都关闭时
-      setCurrentSelectedTab(undefined);
+  const goChannelIndex = () => {
+    setIfOpenPannel(false);
+    history.push('/channelIndex/channelIndexOne')
+  }
+
+  const goToHome = () => {
+    history.replace('/index');
+    setSystemTabs([]); //清空tab导航
+    onTabChange && onTabChange([]);
+    setCurrentSelectedTab(undefined);
+    set_pageTitle('欢迎进入医管平台');
+    setIfOpenPannel(false);
+    localStorage.removeItem('currentSelectedTab');
+  }
+
+  const goSystemIndex = (name:string)=>{
+       if(panelData[currentActivedBlockIndex]){
+            const result:TopBar.TypeBlock[] = panelData[currentActivedBlockIndex].child.filter(t=>(t.name == name));
+            if(result.length>0){
+                history.push(result[0].path)
+            }
+       }
+  }
+
+  const openNav = () => {
+    setIfOpenPannel(!ifOpenPannel);
+  }
+
+  
+
+  const reSetNav = (_panelData: TopBar.PanelData[], cur: TopBar.Tab) => {
+
+
+    if (!(_panelData.length > 0)) return
+
+    if (cur) {
+
+      let blockIndex = 0;
+      let channelIndex = 0;
+
+
+      const _currentSelectedTabFromLocal = cur;
+
+      one: for (let index = 0; index < _panelData.length; index++) {
+        blockIndex = index;
+        if (_panelData[index] && _panelData[index].child) {
+          two: for (let i = 0; i < _panelData[index].child.length; i++) {
+
+            channelIndex = i;
+            if (_panelData && _panelData.length > 0) {
+              const _systems = _panelData[index].child[i].child;
+              if (_systems && _systems.length > 0) {
+                for (let k = 0; k < _systems.length; k++) {
+                  if (_systems[k].menuId == _currentSelectedTabFromLocal.menuId) {
 
-      if (sysList.length > 1) {
-        //有多个应用时
-        history.replace('/index');
+                     set_pageTitle(_panelData[blockIndex].child[channelIndex].name); //设置体系标题
+                     
+                    break one;
+                  }
+                }
+              }
+            }
+
+          }
+        }
+      }
+
+      if (_panelData && _panelData.length > 0 && _panelData[blockIndex].child) {
+        setSystemTabs(_panelData[blockIndex].child[channelIndex].child);  //恢复体系列表
       }
+
+      _systemTabClickHandle(_currentSelectedTabFromLocal);  //恢复选中的tab
+
     }
-  }, [openedTabs]);
+  }
 
   useEffect(() => {
-    // console.log('Topbar props',props);
-    currentSelectedTab && _systemTabClickHandle(currentSelectedTab);
-    currentSelectedTab && setSystemTabs([...systemTabs, currentSelectedTab]);
-  }, [currentSelectedTab]);
+    if (currentSelectedTabFromLocal) {
+
+      reSetNav(navData, currentSelectedTabFromLocal);
+    }
+    set_panelData(navData);
+  }, [navData])
+
+  useEffect(()=>{
+
+    if(currentTab)reSetNav(panelData,currentTab);
+    
+  },[currentTab])
+  
 
   useEffect(() => {
-    setSystemTabs(openedTabs);
-    currentTab && setCurrentSelectedTab(currentTab);
-  }, [props]);
+
+
+    _systemTabClickHandle(currentSelectedTabFromLocal);  //恢复选中的tab
+
+    document.body.addEventListener('click', (e:any) => {
+
+      const classes = ['panel', 'left','typeBlockIcon', 'typeBlock', 'active', 'right', 'row', 'rowDetai', 'channelName', 'channelList', 'systemTab', 'channelIcon'];
+      if (e.target) {
+        if (classes.includes(e.target.className)) {
+          return
+        }
+      }
+      setIfOpenPannel(false);
+    });
+
+  }, []);
 
   return (
-    <div className={styles.topBar}>
-      <div className={styles.logoWrap}>
-        <img className={styles.logo} src={logo} />
+    <div className='topBar' onClick={e => e.stopPropagation()}>
+      <div className='logoWrap'>
+        <img className='logo' src={logo} onClick={() => goToHome()} />
+        <Divider type="vertical" style={{ background: 'white', height: 16, opacity: 0.29, position: 'relative', top: 1, marginLeft: 24, marginRight: 8 }} />
+        <div className='menu' onClick={() => openNav()}>
+          <img src={require('../../../public/images/menu.png')} alt="" />
+        </div>
+        <span className='systemTitle' onClick={()=>goSystemIndex(pageTitle)}>{pageTitle}</span>
       </div>
-      {sysList.length > 1 && (
+
+      <div className='userRelaInfoWrap'>
         <>
-          <div className={ifOpenPannel ? `${styles.platformMenu} ${styles.on}` : `${styles.platformMenu}`} onClick={() => setIfOpenPannel(!ifOpenPannel)}>
-            <img src={platFormMenuIcon} />
-            <div className={styles.systemPannel}>
-              {sysList.map((item) => (
-                <div key={item.id} className={styles.systemList} onClick={() => _systemListClickHandle(item)}>
-                  <img src={item.icon} alt="" />
-                  <div className={styles.systemListName}>{item.name}</div>
-                </div>
-              ))}
-            </div>
-          </div>
           {/**
            * 已打开的tab
            */}
-          <div className={styles.tabWrap}>
-            {systemTabs.map((item) => (
-              <div key={item.id} className={currentSelectedTab?.id == item.id ? `${styles.tab} ${styles.on}` : `${styles.tab}`} onClick={() => _systemTabClickHandle(item)}>
-                <div className={styles.tabText}>{item.name} </div>
-                <div className={styles.closeIconWrap}>
-                  <img src={tabCloseIcon} onClick={(e) => closeTabHandle(item, e)} alt="close" />
+          <div className='tabWrap'>
+            {systemTabs&&systemTabs.map((item, index) => (
+              <div key={index} className={currentSelectedTab?.menuId == item.menuId ? `tab on` : `tab`} onClick={() => _systemTabClickHandle(item)}>
+                <div className='tabText'>{item.name} </div>
+                <div className='closeIconWrap'>
+                  <img src={tabCloseIcon} onClick={(e) => closeTabHandle(item, e)}  />
                 </div>
               </div>
             ))}
           </div>
         </>
-      )}
 
-      <div className={styles.userRelaInfoWrap}>
-        <div className={styles.notification}>
-          <img className={styles.notificationIcon} src={require('../../../public/images/notificationIcon.png')} />
-        </div>
+
+        {/* <div className='notification'>
+          <img className='notificationIcon' src={require('../../../public/images/notificationIcon.png')} />
+        </div> */}
         <Tooltip title={<UserPannel />} color="#fff" onVisibleChange={(visible) => setArrowRotate(visible)}>
-          <div className={styles.user}>
-            <img className={styles.avator} src={require('../../../public/images/Mask.png')} />
-            <span className={styles.name}>{userData?.name}</span>
-            <img className={arrowRotate ? `${styles.arrow} ${styles.on}` : `${styles.arrow}`} src={require('../../../public/images/arrow_white.png')} />
+          <div className='user'>
+            <img className='avator' src={require('../../../public/images/Mask.png')} />
+            <span className='name'>{userData?.name}</span>
+            <img className={arrowRotate ? `arrow on` : `arrow`} src={require('../../../public/images/arrow_white.png')} />
           </div>
         </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="" />
+                      <span>{item.name}</span>
+                    </div>
+                  )
+                })
+              }
+            </div>
+            <div className='right'>
+              {
+                panelData.length > 0 && panelData[currentActivedBlockIndex] && panelData[currentActivedBlockIndex].child && panelData[currentActivedBlockIndex].child.map((item, index: number) => {
+                  return (
+                    <div className='row' key={index}>
+                      <img className='channelIcon' src={require('../../../public/images/zhilianganquan.png')} alt="" />
+                      <div className='rowDetail'>
+                        <div className='channelName' onClick={() => goChannelIndex()}>{item.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>
   );
 };

+ 216 - 123
src/components/topBar/style.less

@@ -1,6 +1,7 @@
 .userPannel {
   width: 100px;
   background-color: white;
+
   .userPannelTab {
     display: flex;
     flex-direction: row;
@@ -29,7 +30,6 @@
   z-index: 999;
   display: flex;
   flex-direction: row;
-  justify-content: flex-start;
   align-items: center;
   width: 100%;
   height: 48px;
@@ -41,161 +41,122 @@
   }
 
   .logoWrap {
-    width: 200px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    width: 350px;
 
     .logo {
       width: 108px;
       height: 18px;
     }
-  }
 
-  .platformMenu {
-    position: relative;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    width: 32px;
-    height: 32px;
-    border-radius: 4px;
-    cursor: pointer;
-    margin-right: 16px;
-
-    img {
-      width: 16px;
-      height: 16px;
+    .systemTitle {
+      cursor: pointer;
     }
 
-    .systemPannel {
-      display: none;
-      position: absolute;
-      left: 0;
-      top: 50px;
-      z-index: 99;
-      flex-direction: row;
-      justify-content: flex-start;
+    .menu {
+      cursor: pointer;
+      display: flex;
+      justify-content: center;
       align-items: center;
-      background: #ffffff;
-      padding: 16px 20px;
-      box-shadow: 0px 6px 10px 0px rgba(26, 34, 51, 0.2);
-      border-radius: 8px;
-      border: 1px solid #e6eaf2;
-
-      .systemList {
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-        align-items: center;
-        width: 80px;
-        height: 98px;
-        margin-right: 10px;
-        border-radius: 8px;
-
-        .systemListName {
-          font-size: 12px;
-          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-          font-weight: 400;
-          color: #666e80;
-          line-height: normal;
-        }
-
-        & > img {
-          width: 40px;
-          height: 40px;
-          background: #ffb44d;
-          border-radius: 10px;
-          margin-bottom: 16px;
-        }
+      width: 32px;
+      height: 32px;
+      border-radius: 4px;
+      margin-right: 8px;
+      transition: all 0.3s ease-in;
+      background: rgba(254, 255, 255, 0);
 
-        &:last-child {
-          margin-right: 0;
-        }
 
-        &:hover {
-          background: #f7f8fa;
+      &>img {
+        width: 16px;
+        height: 16px;
+      }
 
-          .name {
-            font-size: 12px;
-            font-family: SourceHanSansCN-Bold, SourceHanSansCN;
-            font-weight: bold;
-            color: #334466;
-          }
-        }
+      &:hover {
+        background: rgba(254, 255, 255, 0.1);
       }
     }
 
-    &.on {
-      background: #0b54e6;
-
-      .systemPannel {
-        display: flex;
-      }
+    &>span {
+      font-size: 14px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #FFFFFF;
     }
   }
 
-  .tabWrap {
+
+  .userRelaInfoWrap {
     display: flex;
+    width: 55%;
     flex-direction: row;
-    justify-content: flex-start;
+    justify-content: flex-end;
     align-items: center;
+    position: fixed;
+    right: 0;
+    padding-right: 16px;
 
-    .tab {
+    .tabWrap {
       display: flex;
-      width: 92px;
+      width: 60%;
       flex-direction: row;
-      justify-content: space-between;
+      justify-content:flex-end;
       align-items: center;
-      padding: 8px 9px;
-      padding-right: 0;
-      border-radius: 4px;
-      opacity: 0.8;
-      margin-right: 16px;
-      cursor: pointer;
-      box-sizing: border-box;
-
-      .tabText {
-        width: 56px;
-        font-size: 14px;
-        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-        font-weight: 500;
-        color: #ffffff;
-        white-space: nowrap;
-        overflow-x: hidden;
-        text-overflow: ellipsis;
-      }
-      .closeIconWrap {
+      margin-right: 24px;
+      .tab {
         display: flex;
-        justify-content: center;
+        width: 25%;
+        height: 32px;
+        line-height: 32px;
+        text-align: center;
+        flex-direction: row;
+        justify-content: space-between;
         align-items: center;
-        padding: 0px 9px;
-        img {
-          width: 8px;
-          height: 8px;
+        padding: 0 2%;
+        border-radius: 4px;
+        opacity: 0.8;
+        margin-right:1%;
+        cursor: pointer;
+        box-sizing: border-box;
+
+        .tabText {
+          width: 100%;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+          font-weight: 500;
+          color: #ffffff;
+          white-space: nowrap;
+          overflow-x: hidden;
+          text-overflow: ellipsis;
         }
-      }
 
-      &:hover {
-        background: #5387ee;
-      }
+        .closeIconWrap {
+          display: none;
+          justify-content: center;
+          align-items: center;
+          padding: 0px 9px;
 
-      &.on {
-        opacity: 1;
-        background: #0b54e6;
-      }
+          img {
+            width: 8px;
+            height: 8px;
+          }
+        }
+
+        &:hover {
+          background: #5387ee;
+        }
 
-      &:last-child {
-        margin-right: 0;
+        &.on {
+          opacity: 1;
+          background: #0b54e6;
+        }
+
+        &:last-child {
+          margin-right: 0;
+        }
       }
     }
-  }
-
-  .userRelaInfoWrap {
-    display: flex;
-    flex-direction: row;
-    justify-content: center;
-    align-items: center;
-    position: fixed;
-    right: 0;
-    padding-right: 16px;
 
     .notification {
       display: flex;
@@ -218,6 +179,7 @@
       flex-direction: row;
       justify-content: center;
       align-items: center;
+
       .avator {
         width: 26px;
         height: 26px;
@@ -243,4 +205,135 @@
       }
     }
   }
+
+  .panel {
+    display: flex;
+    flex-direction: row;
+    align-items:stretch;
+    position: absolute;
+    top: 48px;
+    left: 165px;
+    min-height: 140px;
+    width: 80%;
+    border-radius: 0px 0px 0px 8px;
+    background: #F5F7FA;
+    box-shadow: 0px 10px 20px 0px rgba(31, 71, 153, 0.2);
+    border-radius: 0px 0px 8px 8px;
+    opacity: 0.98;
+
+    .left {
+      width: 140px;
+      padding-top: 16px;
+      padding-bottom: 16px;
+      background-color: #ffffff;
+
+      .typeBlock {
+        display: flex;
+        cursor: pointer;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        width: 108px;
+        height: 108px;
+        margin: 0 auto;
+        border-radius: 4px;
+
+        &>img {
+          width: 32px;
+          height: 32px;
+          margin-bottom: 8px;
+        }
+
+        &>span {
+          font-size: 12px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #515866;
+        }
+
+        &.active {
+          background: #F5F7FA;
+
+          &>span {
+            color: #3376FE;
+          }
+        }
+      }
+    }
+
+    .right {
+      width: calc(100% - 140px);
+      height: 100%;
+      padding: 2% 2.5%;
+
+      .row {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: flex-start;
+
+        .channelIcon {
+          width: 24px;
+          height: 24px;
+          margin-right: 24px;
+        }
+
+        .rowDetail {
+          width: 100%;
+          .channelName {
+            display: inline-block;
+            font-size: 14px;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            color: #7A8599;
+            margin-bottom: 8px;
+            cursor: pointer;
+            transition: all 0.3s ease-in;
+            &:hover {
+              color: #3376FE;
+            }
+          }
+
+          .channelList {
+            display: flex;
+            width: 100%;
+            min-height: 30px;
+            flex-direction: row;
+            flex-wrap: wrap;
+            align-items: center;
+
+            .systemTab {
+              width: 24%;
+              height: 32px;
+              line-height: 32px;
+              background: #FFFFFF;
+              border-radius: 4px;
+              font-size: 12px;
+              font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+              font-weight: 400;
+              color: #17181A;
+              padding-left: 8px;
+              margin-right: 1%;
+              cursor: pointer;
+              transition: all 0.3 ease-in;
+              overflow: hidden;
+              white-space: nowrap;
+              text-overflow: ellipsis;
+              margin-bottom: 8px;
+
+              &.on {
+                color: white;
+                background: linear-gradient(90deg, #3376FE 0%, #66A6FF 100%);
+              }
+
+              &:hover {
+                color: white;
+                background: linear-gradient(90deg, #3376FE 0%, #66A6FF 100%);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 }

+ 27 - 5
src/components/topBar/typings.d.ts

@@ -1,18 +1,40 @@
 /*
  * @Author: your name
  * @Date: 2022-01-10 13:56:19
- * @LastEditTime: 2022-03-04 11:47:59
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-01 11:09:54
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/components/topBar/typings.d.ts
  */
 
 declare namespace TopBar {
   export type Tab = {
-    id: number;
+    menuId: number | string;
+    systemId: string;
     name: string;
-    icon: string;
-    url: string;
+    icon?: string;
+    url?: string;
     path: string;
   };
+
+
+  export type TypeBlock = {
+    icon?: string;
+    name: string;
+    menuId: number | string;
+    path: string;
+    child: Tab[]
+  }
+
+  export type PanelData = {
+    name: string;
+    menuId: number | string;
+    path: string;
+    icon?: string;
+    systemId: string;
+    child: TypeBlock[]
+  }
+
 }
+
+

+ 18 - 2
src/constant.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-14 16:09:09
- * @LastEditTime: 2022-02-14 16:32:54
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-01 09:19:18
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/constant.ts
  */
@@ -28,6 +28,22 @@ export const MenuTypes = [
     label: '系统',
     value: 3,
   },
+  {
+    label: '有数Bi',
+    value: 4,
+  },
+  {
+    label: '体系',
+    value: 5,
+  },
+  {
+    label: '中心层',
+    value: 6,
+  },
+  // {
+  //   label: '平台层',
+  //   value: 7,
+  // },
 ];
 
 export const Platforms = [

+ 44 - 19
src/layouts/index.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 13:56:33
- * @LastEditTime: 2022-03-30 10:07:30
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-04 16:44:54
+ * @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
  */
@@ -11,16 +11,17 @@ import { IRouteComponentProps, useModel, history } from 'umi';
 import ProLayout from '@ant-design/pro-layout';
 
 import TopBar from '@/components/topBar';
+import { useEffect, useState } from 'react';
+import { getPlatformMenu, getUserPlatformNav } from '@/service/menu';
+import { NavSelecterData } from '@/components/NavSelecter';
 
-import { Modal } from 'antd';
-
-const TopHoc = ({ systemLists, openedSysLists, currentSelectedSys }: { systemLists: TopBar.Tab[]; openedSysLists: TopBar.Tab[]; currentSelectedSys: TopBar.Tab | undefined }) => {
+const TopHoc = ({ currentSelectedSys,openedSysLists,navData }: { currentSelectedSys: TopBar.Tab | undefined ,openedSysLists:TopBar.Tab[],navData:TopBar.PanelData[]}) => {
   const { initialState, setInitialState } = useModel('@@initialState');
 
-  localStorage.setItem('initialState', JSON.stringify(initialState)); //缓存tab状态,防止刷新丢失
-
+  
   const onTabChangeHandle = async (data: TopBar.Tab[]) => {
-    await setInitialState((s) => ({ ...s, openedSysLists: [...data] }));
+    // await setInitialState((s) => ({ ...s, openedSysLists: [...data] }));
+    // localStorage.setItem('initialState', JSON.stringify(initialState)); //缓存tab状态,防止刷新丢失
   };
 
   const onTabClickHandle = async (data: TopBar.Tab) => {
@@ -40,10 +41,11 @@ const TopHoc = ({ systemLists, openedSysLists, currentSelectedSys }: { systemLis
         setInitialState((s) => ({
           ...s,
           currentSelectedSys: {
-            id: -1,
+            menuId: -1,
             name: '个人中心',
             icon: '',
             url: '',
+            systemId:'-1',
             path: '/personalCenter',
           },
         }));
@@ -53,38 +55,61 @@ const TopHoc = ({ systemLists, openedSysLists, currentSelectedSys }: { systemLis
 
   return (
     <TopBar
+      navData={navData}
       userData={initialState?.userData}
-      sysList={systemLists}
       openedTabs={openedSysLists}
       onTabChange={onTabChangeHandle}
       onTabClick={onTabClickHandle}
       currentTab={currentSelectedSys}
       userPannelTabClick={userPannelTabClickhandle}
     />
+
   );
 };
 
 export default function Layout({ children, location, route, history, match }: IRouteComponentProps) {
   const { initialState, setInitialState } = useModel('@@initialState');
-  const viewportH = window.innerHeight;
-  // console.log({children, location, route, history, match});
-  if (location.pathname == '/index' || location.pathname == '/login') {
-    return <div>{children}</div>;
+  const [navData,set_navData] = useState<TopBar.PanelData[]>([]);
+  
+  const getNavData = async () => {
+    const nav = await getUserPlatformNav();
+    if (nav) {
+      set_navData(nav);
+
+    } 
   }
-  // return <div style={{height:'calc(100vh - 48px)'}}>{children}</div>
 
+  useEffect(()=>{
+    if(location.pathname != '/login'){
+      getNavData();
+    }
+  },[])
+  
+  if (location.pathname == '/login') {
+    return <div>{children}</div>;
+  }
+  
   return (
     <ProLayout
       layout="top"
       contentStyle={{
         margin: 0,
       }}
+      menu={{
+        request:async ()=>{
+            return [{
+                path:'/index',
+                name:'欢迎进入医管平台'
+            }]
+        },
+      }}
+      pageTitleRender={false}
       headerRender={() =>
         initialState && (
-          <TopHoc
-            systemLists={initialState.systemLists ? initialState.systemLists : []}
-            openedSysLists={initialState.openedSysLists ? initialState.openedSysLists : []}
-            currentSelectedSys={initialState.currentSelectedSys ? initialState.currentSelectedSys : undefined}
+          <TopHoc 
+            navData = {navData}
+            currentSelectedSys={initialState.currentSelectedSys}
+            openedSysLists={initialState.openedSysLists?initialState.openedSysLists:[]}
           />
         )
       }

+ 22 - 0
src/pages/channelIndex/channelIndexOne/index.tsx

@@ -0,0 +1,22 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-06-08 10:07:57
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-06-08 10:26:33
+ * @FilePath: /KC-MiddlePlatform/src/pages/channelIndex/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import React from 'react'
+
+import './style.less'
+
+
+export const ChannelIndex = () => {
+  return (
+    <div>ChannelIndex</div>
+  )
+}
+

+ 0 - 0
src/pages/channelIndex/channelIndexOne/style.less


+ 189 - 0
src/pages/index/components/FastEntry/index.tsx

@@ -0,0 +1,189 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-27 14:17:59
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-04 17:36:12
+ * @FilePath: /KC-MiddlePlatform/src/pages/index/components/FastEntry/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+//快速入口模块
+import { history, useModel } from 'umi';
+import { useEffect, useState } from 'react';
+import './style.less';
+import { Empty } from 'antd';
+import NavSelecter, { NavSelecterData, NavSelecterItemType } from '@/components/NavSelecter';
+import { addFastEntry, AddFastEntryDataType, getUserPlatformNav } from '@/service/menu';
+
+
+
+
+export type FastEntryTabType = {
+    name: string;
+    path: string;
+    systemId:string;
+    menuId:number|string;
+}
+export interface FastEntryType {
+    data: FastEntryTabType[];
+}
+
+export const FastEntry = (props: FastEntryType) => {
+
+    const { initialState, setInitialState } = useModel('@@initialState');
+
+    const [tabs, set_tabs] = useState<FastEntryTabType[]>([]);
+    const [open,set_open] = useState(false);
+    const [navSelecterData,set_navSelecterData] = useState<NavSelecterData[]>([]);
+  
+
+    const tabClickHandle = async (tab: FastEntryTabType) => {
+        await setInitialState((s) => ({ ...s, currentSelectedSys:tab,currentTab:tab})); 
+    }
+
+    
+
+    const getNavData =async () => {
+          
+        const navData = await getUserPlatformNav();
+        
+        set_navSelecterData(navData)
+    }
+
+    const onCheckedHandle = async (data:NavSelecterItemType[])=>{
+        const resp = await addFastEntry(data as AddFastEntryDataType[]);
+        if(resp){
+            set_tabs(data);   
+        }
+        
+    }
+
+    const addHandle = ()=>{
+        getNavData();
+        set_open(true);
+    }
+
+
+    useEffect(() => {
+        const { data } = props;
+        set_tabs(data);
+    }, [props]);
+
+
+
+    useEffect(()=>{
+        
+        // set_navSelecterData([
+        //       {
+        //         name:'精益医疗管理',
+        //         key:0,
+        //         children:[
+        //             {
+        //                 name:'质量安全管理',
+        //                 key:1,
+        //                 children:[
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:2
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:3
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:4
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:20
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:21
+        //                     }
+        //                 ]
+        //             },
+        //             {
+        //                 name:'质量安全管理2',
+        //                 key:30,
+        //                 children:[
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:31
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:32
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:33
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:34
+        //                     },
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:35
+        //                     }
+        //                 ]
+        //             }
+        //         ]
+        //       },
+        //       {
+        //         name:'HBI',
+        //         key:5,
+        //         children:[
+        //             {
+        //                 name:'质量安全管理',
+        //                 key:6,
+        //                 children:[
+        //                     {
+        //                         name:'质量管理及十大安全目标',
+        //                         key:7
+        //                     }
+        //                 ]
+        //             }
+        //         ]
+        //       }
+        // ])      
+    },[])
+
+    return (
+        <div className='fastEntry'>
+
+            <div className='topTitle'>
+                <span className='name'>快速入口</span>
+                <span className='addBtn' onClick={()=>addHandle()}>添加</span>
+            </div>
+            
+            {
+                open&&(
+                     <NavSelecter data={navSelecterData} onVisibleChange={(bool)=>set_open(bool)} value={tabs} onChecked={onCheckedHandle} />
+                )
+            }
+
+            <div className='wrap'>
+                {
+                    tabs.map((item, index) => {
+                        return (
+                            <div className='tab' onClick={() => tabClickHandle(item)} key={index}>{item.name}</div>
+                        )
+                    })
+                }
+                {
+                    tabs.length == 0 && (
+                        <div className='empty'>
+                            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+                        </div>
+                    )
+                }
+            </div>
+        </div>
+    )
+}

+ 70 - 0
src/pages/index/components/FastEntry/style.less

@@ -0,0 +1,70 @@
+.fastEntry {
+  flex-grow: 1;
+  min-height: 153px;
+  background: #FFFFFF;
+  border-radius: 4px;
+  margin-right: 16px;
+  .topTitle {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    height: 48px;
+    padding: 0 16px;
+    border-bottom: 1px solid #E6EAF2;
+
+    .name {
+      font-size: 16px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #17181A;
+    }
+
+    .addBtn {
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #3376FE;
+      cursor: pointer;
+    }
+  }
+
+  .wrap {
+    display: flex;
+    flex-direction: row;
+    padding: 16px;
+    padding-bottom: 0;
+    flex-wrap: wrap;
+    .empty {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      
+    }
+    .tab {
+      width: 19.2%;
+      margin-right:1%;
+      font-size: 14px;
+      text-align: left;
+      line-height: 32px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #525866;
+      height: 32px;
+      padding-left: 1%;
+      background: #F5F7FA;
+      margin-bottom: 8px;
+      border-radius: 4px;
+      cursor: pointer;
+
+      &:hover {
+        color: #3376FE;
+      }
+
+      &:nth-child(5n){
+          margin-right: 0;
+      }
+    }
+  }
+}

+ 64 - 0
src/pages/index/components/MsgRecord/index.tsx

@@ -0,0 +1,64 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-30 09:50:41
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-01 10:57:09
+ * @FilePath: /KC-MiddlePlatform/src/pages/index/components/RecentlyVisited/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+//消息记录模块
+
+import { useEffect, useState } from 'react';
+import './style.less';
+
+import { Empty } from 'antd';
+
+
+export type MsgRecordItemType = {
+      title:string;
+      date:string;
+}
+
+export interface MsgRecordType {
+      list:MsgRecordItemType[]
+}
+
+export const MsgRecord = (props:MsgRecordType) => {
+    
+    const {list:data} = props
+
+    const [list, set_list] = useState<MsgRecordItemType[]>([]);
+
+    useEffect(()=>{
+        set_list(data);
+    },[props])
+
+    return (
+        <div className='RecentlyVisited'>
+                <div className='topTitle'>
+                    <span className='name'>消息记录</span>
+                </div>
+                <div className='wrap'>
+                    {
+                        list.map((val,index)=>(
+                              <div className='list' key={index}>
+                                    <div className='msgTitle'>{val.title}</div>
+                                    <div className='msgDate'>{val.date}</div>
+                              </div>
+                        ))
+                    }
+                    {
+                        list.length == 0 && (
+                            <div className='empty'>
+                                <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+                            </div>
+                        )
+                    }
+                </div>
+        </div>
+    )
+}

+ 66 - 0
src/pages/index/components/MsgRecord/style.less

@@ -0,0 +1,66 @@
+.RecentlyVisited {
+  width: 30%;
+  min-height: 153px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+  .topTitle {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    height: 48px;
+    padding: 0 16px;
+    border-bottom: 1px solid #E6EAF2;
+
+    .name {
+      font-size: 16px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #17181A;
+    }
+
+  }
+
+  .wrap {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    padding: 16px;
+
+    .empty {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+
+    }
+
+    .list {
+      margin-bottom: 24px;
+      cursor: pointer;
+      .msgTitle {
+        height: 14px;
+        line-height: 14px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+        margin-bottom: 8px;
+      }
+
+      .msgDate {
+        height: 12px;
+        line-height: 12px;
+        font-size: 12px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #7A8599;
+      }
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+}

+ 74 - 0
src/pages/index/components/RecentlyVisited/index.tsx

@@ -0,0 +1,74 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-30 09:50:41
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-01 00:23:36
+ * @FilePath: /KC-MiddlePlatform/src/pages/index/components/RecentlyVisited/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+//最近访问模块
+
+import { useEffect, useState } from 'react';
+import './style.less';
+import {history, useModel} from 'umi';
+import { Empty } from 'antd';
+import { NavSelecterItemType } from '@/components/NavSelecter';
+
+
+
+export type RecentlyVisitedItemsType = {
+        name:string;
+        path:string;
+        menuId:string;
+        systemId:string;
+}
+export interface RecentlyVisitedPropsType {
+       data:RecentlyVisitedItemsType[]
+}
+
+export const RecentlyVisited = (props:RecentlyVisitedPropsType) => {
+
+    const {data} = props;
+
+    const { initialState, setInitialState } = useModel('@@initialState');
+
+    const [tabs, set_tabs] = useState<RecentlyVisitedItemsType[]>([]);
+
+    const clickHandle = async (val:NavSelecterItemType)=>{
+        //更新currentSelectedSys/currentTab触发导航跳转
+        await setInitialState((s) => ({ ...s, currentSelectedSys:val,currentTab:val})); 
+    }
+
+    useEffect(()=>{
+        set_tabs(data);
+    },[data])
+    
+
+    return (
+        <div className='RecentlyVisited'>
+            <div className='topTitle'>
+                <span className='name'>最近访问</span>
+            </div>
+            <div className='wrap'>
+                {
+                    tabs.map((item, index) => {
+                        return (
+                            <div className='tab' onClick={()=>clickHandle(item)} key={index}>{item.name}</div>
+                        )
+                    })
+                }
+                {
+                    tabs.length == 0 && (
+                        <div className='empty'>
+                            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+                        </div>
+                    )
+                }
+            </div>
+        </div>
+    )
+}

+ 56 - 0
src/pages/index/components/RecentlyVisited/style.less

@@ -0,0 +1,56 @@
+.RecentlyVisited {
+  width: 30%;
+  min-height: 153px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+  .topTitle {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    height: 48px;
+    padding: 0 16px;
+    border-bottom: 1px solid #E6EAF2;
+
+    .name {
+      font-size: 16px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #17181A;
+    }
+
+  }
+
+  .wrap {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    padding: 16px;
+
+    .empty {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      
+    }
+
+    .tab {
+      width: 50%;
+      height: 32px;
+      font-size: 14px;
+      line-height: 32px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #525866;
+      margin-bottom: 8px;
+      cursor: pointer;
+
+      &:hover {
+        color: #3376FE;
+      }
+    }
+  }
+
+}

BIN
src/pages/index/components/TodoList/images/exclamationMark.png


BIN
src/pages/index/components/TodoList/images/gou.png


+ 77 - 0
src/pages/index/components/TodoList/index.tsx

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

+ 162 - 0
src/pages/index/components/TodoList/style.less

@@ -0,0 +1,162 @@
+.TodoList {
+  flex-grow: 1;
+  min-height: 300px;
+  background: #FFFFFF;
+  border-radius: 4px;
+  margin-right: 16px;
+  padding-bottom: 24px;
+  .topTitle {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    height: 48px;
+    padding: 0 16px;
+    border-bottom: 1px solid #E6EAF2;
+
+    .name {
+      font-size: 16px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #17181A;
+    }
+
+    .actBtn {
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #3376FE;
+      cursor: pointer;
+    }
+  }
+
+  .wrap {
+    display: flex;
+    flex-direction: column;
+    padding: 16px;
+    padding-bottom: 0;
+
+    .todoList {
+      position: relative;
+      margin-bottom: 24px;
+      .checkBtn {
+        position: absolute;
+        right: 24px;
+        top:50%;
+        cursor: pointer;
+        margin-top: -16px;
+        width: 32px;
+        height: 32px;
+        border-radius: 50%;
+        background: #F5F7FA;
+        background-image: url('./images/gou.png');
+        background-position: center center;
+        background-size: 15px 15px;
+        background-repeat: no-repeat;
+      }
+      .status {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: center;
+        margin-bottom: 6px;
+
+        .todoStatus {
+          height: 24px;
+          line-height: 24px;
+          background: #E5F9F9;
+          border-radius: 6px;
+          font-size: 12px;
+          font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+          font-weight: 500;
+          color: #2FC0C0;
+          margin-right: 16px;
+          padding-left: 4px;
+          padding-right: 10px;
+
+          &.green {
+            &::before {
+              position: relative;
+              top:3px;
+              display: inline-block;
+              content: '';
+              width: 16px;
+              height: 16px;
+              margin-right: 6px;
+              background: #2FC0C0;
+              border-radius: 4px;
+              background-image: url('./images/exclamationMark.png');
+              background-size: 10px 10px;
+              background-position: center center;
+              background-repeat: no-repeat;
+          
+            }
+          }
+          &.orange {
+            color: #FFAA33;
+            background-color: #FCF7F0;
+            &::before {
+              position: relative;
+              top:3px;
+              display: inline-block;
+              content: '';
+              width: 16px;
+              height: 16px;
+              margin-right: 6px;
+              background: #FFAA33;
+              border-radius: 4px;
+              background-image: url('./images/exclamationMark.png');
+              background-size: 10px 10px;
+              background-position: center center;
+              background-repeat: no-repeat;
+          
+            }
+          }
+          &.red {
+            color: #FF6666;
+            background-color: #FCF0F0;
+            &::before {
+              position: relative;
+              top:3px;
+              display: inline-block;
+              content: '';
+              width: 16px;
+              height: 16px;
+              margin-right: 6px;
+              background:#FF6666;
+              border-radius: 4px;
+              background-image: url('./images/exclamationMark.png');
+              background-size: 10px 10px;
+              background-position: center center;
+              background-repeat: no-repeat;
+          
+            }
+          }
+
+
+        }
+
+        .date {
+          font-size: 12px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #7A8599;
+        }
+      }
+      .detail {
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #666F80;
+        &>span {
+            font-weight: bold;
+            color: #17181A;
+        }
+      }
+
+      &:last-child {
+          margin-bottom: 0;
+      }
+    }
+  }
+}

+ 233 - 42
src/pages/index/index.less

@@ -1,54 +1,245 @@
 .indexPage {
-  font-size: 0;
-  min-width: 1100px;
-  height: 100vh;
-
-  .block {
-    display: flex;
-    flex-direction: row;
-    justify-content: center;
-    align-items: center;
-    position: absolute;
-    z-index: 10;
-    width: 800px;
-    height: 400px;
-    left: 50%;
-    top: 50%;
-    margin-left: -400px;
-    margin-top: -200px;
-    background: #ffffff;
-    border-radius: 24px;
-    overflow: hidden;
-    .systemSelector {
+  height:100%;
+  background: #F5F7FA;
+  .pageContainer {
+    padding: 16px;
+    .profileCard {
       display: flex;
-      flex-direction: row;
-      justify-content: center;
-      align-items: center;
-
-      .sysItem {
+      flex-direction: column;
+      justify-content: flex-start;
+      padding: 32px;
+      background: #FFFFFF;
+      border-radius: 4px;
+  
+      .wraper {
         display: flex;
-        flex-direction: column;
-        justify-content: center;
-        align-items: center;
-        margin-right: 80px;
-        cursor: pointer;
-        .icon {
-          width: 64px;
-          height: 64px;
-          margin-bottom: 16px;
+        flex: 1;
+  
+        .avatar {
+          width: 80px;
+          height: 80px;
+          margin-right: 24px;
+  
+          img {
+            width: 100%;
+          }
         }
-        .sysName {
-          height: 12px;
-          font-size: 12px;
+  
+        .description {
+          width: calc(100% - 104px);
+  
+          .rowOne {
+            display: flex;
+            flex: 1;
+            flex-direction: row;
+            justify-content: space-between;
+            align-items: flex-start;
+            padding-top: 16px;
+  
+            .info {
+              .name {
+                height: 20px;
+                font-size: 20px;
+                font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+                font-weight: bold;
+                color: #17181A;
+                line-height: 30px;
+                margin-bottom: 16px;
+              }
+  
+              .baseInfo {
+                height: 14px;
+                font-size: 14px;
+                font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                font-weight: 400;
+                color: #666E80;
+                line-height: 21px;
+              }
+            }
+  
+            .staffBaseInfo {
+              display: flex;
+              flex: 1;
+              flex-direction: row;
+              justify-content: flex-end;
+              align-items: flex-start;
+  
+              .staffBaseInfoSpan {
+                display: flex;
+                flex-direction: column;
+                justify-content: center;
+                align-items: center;
+  
+                .spanName {
+                  height: 14px;
+                  font-size: 14px;
+                  font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                  font-weight: 400;
+                  color: #666E80;
+                  line-height: 14px;
+                  margin-bottom: 16px;
+                }
+  
+                .spanValue {
+                  height: 20px;
+                  font-size: 20px;
+                  font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+                  font-weight: bold;
+                  color: #17181A;
+                  line-height: 20px;
+  
+                  &.status {
+                    color: #FFB54D;
+                  }
+                }
+              }
+  
+              .Divider {
+                height: 24px;
+                margin-left: 5%;
+                margin-right: 5%;
+                margin-top: 10px;
+              }
+            }
+          }
+  
+          .rowTwo {
+            display: flex;
+            flex: 1;
+            margin-top: 45px;
+            flex-direction: row;
+            justify-content: flex-start;
+            align-items: center;
+  
+            .medicalInfoSpan {
+              display: flex;
+              width: 20%;
+              height: 45px;
+              flex-direction: column;
+              align-items: flex-start;
+              margin-right: 10%;
+  
+              .span {
+                height: 14px;
+                font-size: 14px;
+                font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                font-weight: 400;
+                color: #666E80;
+                line-height: 14px;
+                margin-bottom: 16px;
+  
+                span {
+                  color: #17181A;
+                }
+  
+                &:last-child {
+                  margin-bottom: 0;
+                }
+              }
+
+              &:first-child {
+                 width: 40%;
+              }
+  
+              &:last-child {
+                margin-right: 0;
+              }
+            }
+          }
+        }
+      }
+  
+      .profileFooter {
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        padding-top: 25px;
+        margin-top: 32px;
+        border-top: 1px solid #DFE3EB;
+  
+        .flowInstruction {
+          height: 14px;
+          font-size: 14px;
           font-family: SourceHanSansCN-Normal, SourceHanSansCN;
           font-weight: 400;
-          color: #334466;
+          color: #17181A;
+          line-height: 14px;
+          cursor: pointer;
+  
+          &::before {
+            position: relative;
+            display: inline-block;
+            content: '';
+            top: 2px;
+            width: 16px;
+            height: 16px;
+            margin-right: 8px;
+            // background-image: url('../../../../public/images/alert.png');
+            // background-size: cover;
+          }
         }
-
-        &:last-child {
-          margin-right: 0;
+  
+        .action {
+          display: flex;
+          flex-direction: row;
+  
+          .editProfile {
+            height: 14px;
+            font-size: 14px;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            color: #26334D;
+            line-height: 14px;
+            margin-right: 32px;
+            cursor: pointer;
+  
+            &::before {
+              position: relative;
+              display: inline-block;
+              content: '';
+              top: 3px;
+              width: 16px;
+              height: 16px;
+              margin-right: 8px;
+              // background-image: url('../../../../public/images/box.png');
+              // background-size: cover;
+            }
+          }
+  
+          .qualificationApply {
+            height: 14px;
+            font-size: 14px;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            color: #26334D;
+            line-height: 14px;
+            cursor: pointer;
+  
+            &::before {
+              position: relative;
+              display: inline-block;
+              content: '';
+              top: 3px;
+              width: 16px;
+              height: 16px;
+              margin-right: 8px;
+              // background-image: url('../../../../public/images/blueFile.png');
+              // background-size: cover;
+            }
+          }
         }
       }
     }
+    .cardTwo {
+      display: flex;
+      flex-direction: row;
+      padding-top: 16px;
+      margin-bottom: 16px;
+    }
+    .cardThree {
+      display: flex;
+      flex-direction: row;
+      margin-bottom: 16px;
+    }
   }
 }

+ 142 - 24
src/pages/index/index.tsx

@@ -1,15 +1,24 @@
 /*
  * @Author: your name
  * @Date: 2021-11-10 09:33:30
- * @LastEditTime: 2022-03-30 11:35:41
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 10:17:22
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/index.tsx
  */
 
 import { useModel, history, Location, Helmet } from 'umi';
 import './index.less';
-import LoginPage from '../login';
+import { Skeleton, Divider } from 'antd';
+import { useState,useEffect } from 'react';
+import avatar from '../../../public/images/avatar.png';
+import TopBar from '@/components/topBar';
+import { FastEntry, FastEntryTabType } from './components/FastEntry';
+import { RecentlyVisited, RecentlyVisitedItemsType } from './components/RecentlyVisited';
+import { todoItem, TodoList } from './components/TodoList';
+import { getUserIndexData, todoListAct, UserInfo } from '@/service';
+import { MsgRecord } from './components/MsgRecord';
+
 
 export interface IndexPageType {
   location: Location;
@@ -19,40 +28,149 @@ const IndexPage: React.FC<IndexPageType> = ({ location }) => {
   const {
     systemLists, //当前医院可选子系统列表
     setInitialState,
+    userData
   } = useModel('@@initialState', (model) => {
     return {
       systemLists: model.initialState?.systemLists,
       setInitialState: model.setInitialState,
+      userData: model.initialState?.userData,
     };
   });
 
-  const selectSysHandle = async (systemInfo: userRelationInfo.OwnAppsItem) => {
-    console.log({ systemInfo });
-    await setInitialState((s) => ({
-      ...s,
-      currentSelectedSys: systemInfo,
-      openedSysLists: [systemInfo],
-    }));
-    const { query } = history.location;
-    const { redirect } = query as { redirect: string };
+  const [loading, setLoading] = useState(false);
+  const [userInfo,set_userInfo]  = useState<UserInfo>();
+
+  const [fastEntry,set_fastEntry] = useState<FastEntryTabType[]>([]);
+  const [recentlyVisitedList,set_recentlyVisitedList] = useState<RecentlyVisitedItemsType[]>([]);
+  const [todoList,set_todoList] = useState<todoItem[]>([]);
+  const [msgRecord,set_msgRecord] = useState([]);
+  
+
+
+
+
+  const getIndexPageDataFunc =async () => {
+        const resp = await getUserIndexData();
+        if(resp){
+          
+          set_userInfo(resp.userInfo);
+
+          const fastEntryList = resp.fastEntrance.map((item:any)=>({
+            name:item.name,
+            path:item.path,
+            menuId:item.menuId,
+            systemId:item.systemId
+          }));
+
+          set_fastEntry(fastEntryList);
+
+          set_todoList(resp.todoList.map((t:any)=>({
+            status:1,
+            content:t.content,
+            createDate:t.createDate,
+            taskLevel:t.taskLevel,
+
+          })));
+
+          set_msgRecord(resp.messageRecords.map((t:any)=>({
+                title:t.recordTitle,
+                date:t.createDate
+          })));
+        }
+  }
+
+  const todoListClickHandle = async (id:number)=>{
+        const resp = await todoListAct([id]);
+        if(resp){
+          getIndexPageDataFunc();
+        }
+  }
+
+  
+  useEffect(()=>{
+    getIndexPageDataFunc();
+    const t = localStorage.getItem('visitedTabs');
+    if(t){
+      const visitedPaths = JSON.parse(t);
+      set_recentlyVisitedList(visitedPaths);
+    }
+  },[])
 
-    history.push(redirect || systemInfo.path);
-  };
 
   return (
     <div className="indexPage">
-      <LoginPage title='单点登录平台' location={location}>
-        <div className="block">
-          <div className="systemSelector">
-            {systemLists?.map((t) => (
-              <div className="sysItem" key={t.id} onClick={() => selectSysHandle(t)}>
-                <img className="icon" src={t.icon} alt="" />
-                <span className="sysName">{t.name}</span>
+      <Helmet>
+        <title>欢迎进入医管平台</title>
+      </Helmet>
+      <div className='pageContainer'>
+        <div className="profileCard">
+          <Skeleton loading={loading} active avatar>
+            <div className='wraper'>
+              <div className="avatar">
+                <img src={avatar} alt="头像" />
               </div>
-            ))}
-          </div>
+              <div className="description">
+                <div className="rowOne">
+                  <div className="info">
+                    <div className="name">{userInfo?.name}</div>
+                    <div className="baseInfo">
+                      {`${userInfo?.gender} | ${userInfo?.title?userInfo?.title:'-'} | ${userInfo?.major?userInfo?.major:'-'}`}
+                    </div>
+                  </div>
+                  <div className='staffBaseInfo'>
+                    <div className='staffBaseInfoSpan'>
+                      <span className='spanName'>人员工号</span>
+                      <span className='spanValue'>{userInfo?.id?userInfo?.id:'-'}</span>
+                    </div>
+                    <Divider type="vertical" className='Divider' />
+                    <div className='staffBaseInfoSpan'>
+                      <span className='spanName'>人员类别</span>
+                      <span className='spanValue'>{userInfo?.jobTitle?userInfo?.jobTitle:'-'}</span>
+                    </div>
+                    <Divider type="vertical" className='Divider' />
+                    <div className='staffBaseInfoSpan'>
+                      <span className='spanName'>所属科室</span>
+                      <span className='spanValue'>{userInfo?.departmentName?userInfo?.departmentName:'-'}</span>
+                    </div>
+                    <Divider type="vertical" className='Divider' />
+                    <div className='staffBaseInfoSpan'>
+                      <span className='spanName'>进院日期</span>
+                      <span className='spanValue'>{userInfo?.entryTime?userInfo?.entryTime:'-'}</span>
+                    </div>
+
+                  </div>
+                </div>
+                <div className="rowTwo">
+                  <div className='medicalInfoSpan'>
+                    <div className='span'>资格证号:<span>{userInfo?.qualificationCertificateNo?userInfo?.qualificationCertificateNo:'-'}</span></div>
+                    <div className='span'>执业证号:<span>{userInfo?.practiceCertificateNo?userInfo?.practiceCertificateNo:'-'}</span></div>
+                  </div>
+                  <div className='medicalInfoSpan'>
+                    <div className='span'>医师级别:<span>{userInfo?.doctorLevel?userInfo?.doctorLevel:'-'}</span></div>
+                    <div className='span'>执业状态:<span>{userInfo?.practiceStatus?userInfo?.practiceStatus:'-'}</span></div>
+                  </div>
+                  <div className='medicalInfoSpan'>
+                    <div className='span'>执业科目:<span>{userInfo?.practiceCate?userInfo?.practiceCate:'-'}</span></div>
+                    <div className='span'>备注:<span>{userInfo?.remark?userInfo?.remark:'-'}</span></div>
+                  </div>
+                  <div className='medicalInfoSpan'>
+                    <div className='span'>执业类别:<span>{userInfo?.userCate?userInfo?.userCate:'-'}</span></div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </Skeleton>
+        </div>
+        <div className='cardTwo'>
+          <FastEntry data={fastEntry}  />
+          <RecentlyVisited data={recentlyVisitedList} />
         </div>
-      </LoginPage>
+        <div className='cardThree'>
+           <TodoList todoList={todoList} todoListClickHandle={todoListClickHandle} />
+           <MsgRecord list={msgRecord}/>
+        </div>
+      </div>
+
     </div>
   );
 };

+ 26 - 57
src/pages/login/index.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2021-11-09 14:58:08
- * @LastEditTime: 2022-04-27 16:18:59
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-06-27 17:29:04
+ * @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
  */
@@ -13,22 +13,23 @@ import './style.less';
 
 import { useModel, history, Location, Helmet } from 'umi';
 
-import { Form, Input, Button, Checkbox, notification } from 'antd';
+import { Form, Input, Button, notification } from 'antd';
 
-import logo from '../../../public/images/kc-logo.png';
+import logo from '../../../public/images/kclogo_colorful.png';
 
 import KCSelect from '@/components/kc-select';
 
 import { getHospConfigBySign, login } from '@/service/login';
+import Divider from '@ant-design/pro-card/lib/components/Divider';
 
 const { Option } = Select;
 
 export interface LoginPageType {
   location: Location;
-  title:string;
+  title: string;
 }
 
-const LoginPage: React.FC<LoginPageType> = ({ location, children,title }) => {
+const LoginPage: React.FC<LoginPageType> = ({ location, children, title }) => {
   const [transitionObj, setTransitionObj] = useState<string>();
   const [transformObj, setTransformObj] = useState<string>();
   const loginPageRef = useRef<HTMLDivElement>(null);
@@ -97,48 +98,17 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children,title }) => {
     if (resp) {
       localStorage.setItem('userData', JSON.stringify(resp));
       localStorage.setItem('hospSign', hospSign);
-
-      if (initialState && initialState.getHospSubSystemListFunc) {
-        const data = await initialState.getHospSubSystemListFunc();
-
-        await setInitialState((s) => ({
-          ...s,
-          systemLists: data,
-          userData: resp,
-        }));
-
-        if (data.length > 1) {
-          //当前医院拥有多个子平台时,进入选择
-          history.replace('/index');
-          return;
-        }
-
-        if (data.length == 1) {
-          //直接进入该应用
-          history.replace(data[0].path);
-          await setInitialState((s) => ({
-            ...s,
-            currentSelectedSys: data[0],
-            openedSysLists: [data[0]],
-            systemLists: data,
-            userData: resp,
-          }));
-          return;
-        }
-
-        if (data.length == 0) {
-          return;
-        }
-      }
+      setInitialState((s) => ({ ...s,userData:resp }));
+      history.replace('/index');
 
       setIfLoading(false);
     }
   };
 
-  
-  useEffect(()=>{
-    setCurrentHospName(title);  
-  },[title]);
+
+  useEffect(() => {
+    setCurrentHospName(title);
+  }, [title]);
 
 
   useEffect(() => {
@@ -149,24 +119,26 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children,title }) => {
 
 
   return (
-    <div className="loginPage" onMouseMove={onMouseMoveHandle} onMouseLeave={onMouseLeaveHandle} ref={loginPageRef}>
+    <div className="loginPage" >
       <Helmet>
         <title>{currentHospName}</title>
       </Helmet>
-      <div className="circleBigOne" style={{ transform: transformObj, transition: transitionObj }}></div>
-      <div className="circleBigerOne"></div>
-      <div className="circleLittleOne" style={{ transform: transformObj, transition: transitionObj }}></div>
+
       {location.pathname == '/login' ? (
-        <div className="loginBlock">
-          <div className="left">
-            <img className="bannerImg" src={require('../../../public/images/loginBannner.png')} />
+        <>
+          <div className='left'>
+            <div className='topLogo'>
+              <img className='logo' src={logo} alt="康程智医" />
+              <div className='logoDesc'>助力医疗机构高质量发展</div>
+            </div>
+            <img className='loginbanner' src={require('../../../public/images/loginBannner.png')} alt="" />
           </div>
           <div className="rightLoginArea">
             <div className="subHospSelector">
               {subHospList.length > 0 && (
                 <KCSelect
                   allowClear={false}
-                  style={{ width: 150 }}
+                  style={{ width: 180}}
                   defaultValue={subHospList[0].value}
                   suffixIcon={<img style={{ width: '10px', height: '6px' }} src={require('../../../public/images/arrow.png')} />}
                 >
@@ -199,16 +171,13 @@ const LoginPage: React.FC<LoginPageType> = ({ location, children,title }) => {
                     <Checkbox className="checkBtn">记住密码</Checkbox>
                   </Form.Item> */}
             </Form>
+            <div className='bottomCopyright'>© 2022 康程智医(成都)技术部出品</div>
           </div>
-        </div>
+        </>
+        
       ) : (
         children
       )}
-
-      <div className="bottomLogo">
-        <img className="logo" src={logo} />
-        <div className="copyright">© 2021 康程智医(成都)技术部出品</div>
-      </div>
     </div>
   );
 };

+ 107 - 169
src/pages/login/style.less

@@ -1,199 +1,137 @@
 .loginPage {
+  display: flex;
+  flex-direction: row;
   position: relative;
   width: 100%;
   height: 100vh;
-  min-width: 1100px;
-  background-image: linear-gradient(to right, #3264f2, #3b76f3);
   overflow: hidden;
-
-  .circleBigOne {
-    width: 300px;
-    height: 300px;
-    margin-top: 12.8%;
-    margin-left: 11%;
-    z-index: 1;
-    border-radius: 50%;
-    background: linear-gradient(
-      126deg,
-      #6699ff 0%,
-      rgba(102, 153, 255, 0) 100%
-    );
-    opacity: 0.6;
-    // transform: rotate(60deg);
-    // background-image: linear-gradient(to right, #5083F9 ,#3C71F5);
-  }
-
-  .circleBigerOne {
-    position: absolute;
-    width: 500px;
-    height: 500px;
-    border-radius: 50%;
-    right: -120px;
-    z-index: 1;
-    transform: rotate(350deg);
-    background: linear-gradient(36deg, #5990ff 0%, rgba(88, 143, 252, 0) 100%);
-    opacity: 0.6;
-  }
-
-  .circleLittleOne {
-    position: absolute;
-    width: 78px;
-    height: 78px;
-    top: 7%;
-    left: 50%;
-    margin-left: -30px;
-    border-radius: 50%;
-    z-index: 1;
-    // transform: rotate(60deg);
-    // background-image: linear-gradient(to right, #5083F9 ,#3C71F5);
-    background: linear-gradient(126deg, #5990ff 0%, rgba(88, 143, 252, 0) 100%);
-    opacity: 0.6;
-
-    &::after {
-      position: absolute;
-      display: block;
-      content: '';
-      width: 80px;
-      height: 22px;
-      top: 88px;
-      background: #0d2980;
-      opacity: 0.1;
-      border-radius: 50%;
-      filter: blur(3px);
+ 
+  .left {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 40%;
+    height: 100%;
+    position: relative;
+    background: #F7FAFC;
+    .topLogo {
+        position: absolute;
+        top:40px;
+        left:40px;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        .logo {
+          width: 160px;
+          height: 32px;
+        }
+        .logoDesc {
+          height: 16px;
+          font-size: 12px;
+          line-height: 16px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          color: #7A8599;
+          margin-left: 16px;
+          padding-left: 16px;
+          border-left: 1px solid #CFD6E6;
+        }
+    }
+    .loginbanner {
+      width: 70%;
     }
   }
-
-  .loginBlock {
+  .rightLoginArea {
+    position: relative;
     display: flex;
-    flex-direction: row;
+    width: 60%;
+    height: 100%;
+    flex-direction: column;
     justify-content: center;
     align-items: center;
-    position: absolute;
-    z-index: 10;
-    width: 800px;
-    height: 400px;
-    left: 50%;
-    top: 50%;
-    margin-left: -400px;
-    margin-top: -200px;
-    background: #ffffff;
-    border-radius: 24px;
-    overflow: hidden;
 
-    .left {
-      display: flex;
-      width: 50%;
-      height: 100%;
-      justify-content: center;
-      align-items: center;
-      text-align: center;
-      background: linear-gradient(135deg, #fafcff 0%, #f2f9ff 100%);
-      .bannerImg {
-        width: 72%;
+    .subHospSelector {
+      margin-bottom: 24px;
+      .kcmp-ant-select .kcmp-ant-select-selector {
+        border-radius: 16px;
+        padding-left: 20px !important;
+        background: #F5F7FA;
       }
     }
-    .rightLoginArea {
-      display: flex;
-      width: 50%;
-      height: 100%;
-      flex-direction: column;
-      justify-content: center;
-      align-items: flex-start;
-      padding-left: 60px;
+    .systemName {
+      font-size: 32px;
+      height: 32px;
+      line-height: 32px;
+      font-family: SourceHanSansCN-Light, SourceHanSansCN;
+      font-weight: 300;
+      color: #1a2233;
+      margin-bottom: 32px;
+    }
+    .input {
+      width: 280px;
+      height: 40px;
+      background: #ffffff;
+      border-radius: 4px;
+      border: 1px solid #cfd7e6;
+    }
 
-      .subHospSelector {
-        margin-bottom: 10px;
-      }
-      .systemName {
-        font-size: 24px;
-        height: 24px;
-        line-height: 24px;
-        font-family: SourceHanSansCN-Light, SourceHanSansCN;
-        font-weight: 300;
-        color: #1a2233;
-        margin-bottom: 32px;
-      }
-      .input {
-        width: 280px;
-        height: 40px;
-        background: #ffffff;
-        border-radius: 4px;
-        border: 1px solid #cfd7e6;
-      }
+    .loginBtn {
+      width: 280px;
+      height: 40px;
+      background: #3377ff;
+      border-radius: 4px;
+    }
 
-      .loginBtn {
-        width: 280px;
-        height: 40px;
-        background: #3377ff;
-        border-radius: 4px;
+    .checkBtn {
+      .kcmp-ant-checkbox-checked .kcmp-ant-checkbox-inner {
+        background-color: #407fff;
+        border-color: #407fff;
       }
+    }
 
-      .checkBtn {
-        .kcmp-ant-checkbox-checked .kcmp-ant-checkbox-inner {
-          background-color: #407fff;
-          border-color: #407fff;
-        }
-      }
+    .kcmp-ant-select {
+      border: none;
+      outline: none;
+    }
+    .kcmp-ant-select-focused {
+      border: none;
+      outline: none;
+    }
+    .kcmp-ant-select-selector {
+      border: none;
+      outline: none;
+    }
 
-      .kcmp-ant-select {
-        border: none;
-        outline: none;
-      }
-      .kcmp-ant-select-focused {
-        border: none;
-        outline: none;
-      }
+    .kcmp-ant-select-focused:not(.kcmp-ant-select-disabled).kcmp-ant-select:not(.kcmp-ant-select-customize-input)
       .kcmp-ant-select-selector {
-        border: none;
-        outline: none;
-      }
-
-      .kcmp-ant-select-focused:not(.kcmp-ant-select-disabled).kcmp-ant-select:not(.kcmp-ant-select-customize-input)
-        .kcmp-ant-select-selector {
-        border-color: transparent;
-        box-shadow: none;
-        padding: 0;
-      }
-
-      .kcmp-ant-select-single:not(.kcmp-ant-select-customize-input)
-        .kcmp-ant-select-selector {
-        width: 100%;
-        height: 32px;
-        padding: 0;
-      }
-
-      .kcmp-ant-select-selection-item {
-        font-size: 14px;
-        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
-        font-weight: 400;
-        color: #666f80;
-      }
+      border-color: transparent;
+      box-shadow: none;
+      padding: 0;
     }
-  }
 
-  .bottomLogo {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    flex-direction: column;
-    position: absolute;
-    z-index: 10;
-    width: 400px;
-    left: 50%;
-    bottom: 40px;
-    margin-left: -200px;
+    .kcmp-ant-select-single:not(.kcmp-ant-select-customize-input)
+      .kcmp-ant-select-selector {
+      width: 100%;
+      height: 32px;
+      padding: 0;
+    }
 
-    .logo {
-      width: 144px;
-      height: 24px;
-      margin-bottom: 12px;
+    .kcmp-ant-select-selection-item {
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #666f80;
     }
 
-    .copyright {
+    .bottomCopyright {
+      position: absolute;
+      bottom: 24px;
+      width: 100%;
+      text-align: center;
       font-size: 12px;
       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
       font-weight: 400;
-      color: #ffffff;
+      color: #515866;
     }
   }
+
 }

+ 21 - 27
src/pages/platform/_layout.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-06 15:25:39
- * @LastEditTime: 2022-03-30 11:15:54
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-06 15:41:35
+ * @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
  */
@@ -30,8 +30,9 @@ export default function Layout({ children, location, route, history, match, ...r
         display: 'none',
       }}
       location={{
-            
+
       }}
+      pageTitleRender={false}
       disableContentMargin
       menuItemRender={(item, dom) => (
         <a
@@ -54,16 +55,18 @@ export default function Layout({ children, location, route, history, match, ...r
       }}
       menu={{
         autoClose: false,
-        params: {},
+        params: {
+          initialState
+        },
         request: async () => {
           if (initialState) {
-            const systemId = initialState.currentSelectedSys?.id;
+            const systemId = initialState.currentSelectedSys?.menuId;
             if (systemId) {
-              const menuData = await getPlatformMenu(systemId);
+              const menuData = await getPlatformMenu(Number(systemId));
 
               if (menuData.length > 0) {
-                set_openKeys([menuData[0].key]);
-                set_selectedKeys([menuData[0].key]);
+                set_openKeys([menuData[0].key, menuData[0].children[0].key]);
+                set_selectedKeys([menuData[0].key, menuData[0].children[0].key]);
               }
 
               const getVFromTree = (data: TreeItemType[], key: string) => {
@@ -92,22 +95,12 @@ export default function Layout({ children, location, route, history, match, ...r
 
               setInitialState((t) => ({ ...t, spacicalPageParamsType: _menu }));
 
-              return menuData;
+              return [...menuData,{
+                name:'SQL编辑器',
+                path:'/platform/sqlEditer'
+              }];
+
 
-              // return [
-              //   {
-              //     "path":"/platform",
-              //     "name":"系统设置",
-              //     "softUrl":"/","icon":"",
-              //     "children":[
-              //       {"path":"/platform/setting/hospManage","name":"院区管理","softUrl":"/","icon":"","children":[]},
-              //       {"path":"/platform/setting/roleManage","name":"角色管理","softUrl":"/","icon":"","children":[]},
-              //       {"path":"/platform/setting/menuManage","name":"菜单管理","softUrl":"/","icon":"","children":[]},
-              //       {"path":"/platform/setting/userManage","name":"用户管理","softUrl":"/","icon":"","children":[]},
-              //       {"path":"/platform/setting/reports","name":"报表展示","softUrl":"/","icon":"","children":[]}
-              //     ]
-              //   }
-              // ]
             }
             return [];
           }
@@ -119,19 +112,20 @@ export default function Layout({ children, location, route, history, match, ...r
       headerRender={false}
       navTheme="light"
     >
-      <Helmet>
-        <title>精益管理中台</title>
-      </Helmet>
       <PageContainer
         className="kcmpPageContainer"
         header={{
-          title:false,
+          title: false,
         }}
         style={{
           margin: 0,
         }}
       >
 
+        <Helmet>
+          <title>精益管理中台</title>
+        </Helmet>
+
         <div className="page" style={{ height: 'calc(100vh - 98px)', overflowY: 'scroll' }}>
           {children}
         </div>

+ 167 - 0
src/pages/platform/components/TreeEditer/index.tsx

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

+ 0 - 0
src/pages/platform/components/TreeEditer/style.less


+ 121 - 152
src/pages/platform/components/menuEditer/menu.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-14 14:03:42
- * @LastEditTime: 2022-03-09 17:03:14
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 10:03:07
+ * @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/modals/menu.tsx
  */
@@ -10,8 +10,8 @@
 import React, { Key, useEffect, useState } from 'react';
 import KCTable from '@/components/kcTable';
 import { Popconfirm } from 'antd';
-import { Input } from 'antd';
-import { getAllMenus } from '@/service/menu';
+import { Input,Transfer, Tree  } from 'antd';
+import { getAllMenus, getAllMenusDataType, getHospAllMenus } from '@/service/menu';
 import { ProColumns } from '@ant-design/pro-table';
 import type { MenuItemDataType } from '@/service/menu';
 
@@ -20,138 +20,142 @@ import './style.less';
 import { MenuTypes } from '@/constant';
 import { getValsFromTree } from '@/utils';
 
+import type { TransferDirection, TransferItem } from 'antd/es/transfer';
+import type { DataNode } from 'antd/es/tree';
+
 const { Search } = Input;
 
 export interface MenuEditerType {
   value?: React.Key[] | React.Key[];
-  onChange?: (selectedRowKeys: React.Key[], selectedRows: any[]) => {};
+  onChange?: (selectedRowKeys: React.Key[], selectedRows?: any[]) => {};
   noAction?: boolean;
+  hospId?:number|string;
 }
 
-const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction = false }) => {
-  const columns: ProColumns<MenuItemDataType>[] = [
-    {
-      title: 'ID',
-      dataIndex: 'menuId',
-      hideInTable: true,
-    },
-    {
-      title: 'parentId',
-      dataIndex: 'parentId',
-      hideInTable: true,
-    },
-    {
-      title: '菜单名称',
-      dataIndex: 'name',
-      hideInSearch: false,
-      render: (text, record) => {
-        if (record.children && record.children.length > 0) {
-          return text;
-        } else {
-          //叶子节点
-          return record.parentId != '0' ? (
-            //非第一级
-            <div>
-              <FileOutlined style={{ marginRight: 10, marginLeft: 30 }} />
-              {text}
-            </div>
-          ) : (
-            text
-          );
-        }
-      },
-    },
-    {
-      title: '类型',
-      dataIndex: 'isHospital',
-      render: (number, record) => {
-        const findType = MenuTypes.filter((t) => t.value == record.type);
-        return findType[0].label;
-      },
-    },
-    // {
-    //   title: '操作',
-    //   width: 100,
-    //   key: 'option',
-    //   valueType: 'option',
-    //   render: (text, record) =>
-    //     record.parentId == '0'
-    //       ? [
-    //           <Popconfirm
-    //             title="是否初始化?"
-    //             onConfirm={() => {}}
-    //             // onCancel={cancel}
-    //             okText="确定"
-    //             cancelText="取消"
-    //             key="link2"
-    //           >
-    //             <a>初始化</a>
-    //           </Popconfirm>,
-    //         ]
-    //       : [],
-    // },
-  ];
+const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction = false,hospId }) => {
+ 
 
   const getData = async () => {
-    const resp = await getAllMenus();
-    const data = resp.list ? resp.list : [];
-    setAllMenuData(data);
-    setDataSource(data);
+  
+    if(hospId){
+      const resp = await getHospAllMenus(hospId);
+      if(resp){
+        const data = resp.allMenuVO;
+      
+        const convertData = (data: Array<any>) => {
+          data.forEach((item) => {
+              item.children = item.child;  
+              if (item.child) {
+                  convertData(item.child);
+              }
+          });
+        };
+        convertData(data);
+        setDataSource(data);
+      }
+     
+    }else{
+      const resp = await getAllMenus();
+      const data = resp.list ? resp.list : [];
+      setDataSource(data);
+    }
   };
 
-  const onChangeHandle = (selectedRowKeys: React.Key[], selectedRows: any[]) => {
-    const menus = selectedRows.filter((t) => t.type == 1); //筛选出所有菜单
+  
 
-    const menuIds = menus.map((t) => t.menuId);
 
-    console.log({ selectedRowKeys, selectedRows });
+  const [dataSource, setDataSource] = useState<any[]>([]);
 
-    setSelectedKeys(selectedRowKeys);
-    onChange && onChange(menuIds, selectedRows);
-  };
+  const [targetKeys, setTargetKeys] = useState<string[]>([]);
 
-  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
-  const [dataSource, setDataSource] = useState<MenuItemDataType[]>([]);
-  const [allMenuData, setAllMenuData] = useState<MenuItemDataType[]>([]);
-  const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
-
-  const deeper = (data: MenuItemDataType[], keyword: string) => {
-    let result: MenuItemDataType[] = [];
-
-    data.forEach((t, index) => {
-      if (t.name.includes(keyword)) {
-        result.push({ ...t, children: [] }); //不带出子集
-      } else {
-        if (t.children && t.children.length > 0) {
-          result.push({ ...t, children: deeper(t.children, keyword) });
-        }
-      }
-    });
-    return result;
+  const onTransFerChange = (keys: string[]) => {
+    setTargetKeys(keys);
+    onChange&&onChange(keys)
   };
-
-  const onSearchHandle = (value: string) => {
-    if (value.length == 0) {
-      setDataSource(allMenuData);
-      return;
+  
+  interface TreeTransferProps {
+    dataSource: MenuItemDataType[];
+    targetKeys: string[];
+    onChange: (targetKeys: string[], direction: TransferDirection, moveKeys: string[]) => void;
+  }
+  
+
+  const isChecked = (selectedKeys:(string|number)[], eventKeys: (string|number)[]) => {
+    
+    const isIncludesFunc = (arr1:(string|number)[],arr2:(string|number)[])=>{
+           
+          return arr2.every((item)=>arr1.includes(item))
     }
-    const result = deeper(dataSource, value);
-    console.log({ result });
-    setDataSource(result);
-  };
+    return isIncludesFunc(selectedKeys,eventKeys)
+  }
 
-  const onExpandedRowsChangeHandle = (expandedRows: readonly Key[]) => {
-    setExpandedRowKeys(expandedRows);
-  };
+  const generateTree = (treeNodes: MenuItemDataType[] = [], checkedKeys: string[] = []): any[] => {
 
-  useEffect(() => {
-    if (dataSource.length > 0) {
-      setSelectedKeys(value); //设置默认选中项
-      setExpandedRowKeys(value); //已选中的项默认展开
+      return treeNodes.map(({ children,menuId,name, ...props }) => ({
+        key:menuId,
+        title:name,
+        disabled: checkedKeys.includes(menuId as string),
+        children: generateTree(children, checkedKeys),
+        ...props
+      }));
+  
+
+  }
+    
+
+
+  const TreeTransfer = ({ dataSource, targetKeys, ...restProps }: TreeTransferProps) => {
+
+    const transferDataSource: MenuItemDataType[] = [];
+
+    function flatten(list: MenuItemDataType[] = []) {
+      list.forEach(item => {
+        transferDataSource.push(item as MenuItemDataType);
+        flatten(item.children);
+      });
     }
-    const openresult = getValsFromTree(dataSource, 'menuId');
-    setExpandedRowKeys(openresult);
-  }, [dataSource]);
+
+    flatten(dataSource);
+  
+    return (
+      <Transfer
+        {...restProps}
+        targetKeys={targetKeys}
+        rowKey={record => record.menuId}
+        dataSource={transferDataSource}
+        className="tree-transfer"
+        render={item => item.name!}
+        showSelectAll={true}
+      >
+        {({ direction, onItemSelect, selectedKeys,onItemSelectAll }) => {
+          if (direction === 'left') {
+            const checkedKeys = [...selectedKeys, ...targetKeys];
+            return (
+              <Tree
+                blockNode
+                checkable
+                checkStrictly={false}
+                defaultExpandAll
+        
+                checkedKeys={checkedKeys}
+                treeData={generateTree(dataSource, targetKeys)}
+                onCheck={(keys,{ node: { key } }) => {
+                  onItemSelectAll(keys as string[], !isChecked(checkedKeys, keys as Key[]));
+                }}
+                onSelect={(keys, { node: { key } }) => {
+                  onItemSelectAll(keys as string[], !isChecked(checkedKeys, keys));
+                }}
+              />
+            );
+          }
+        }}
+      </Transfer>
+    );
+  };
+   
+  useEffect(()=>{
+    setTargetKeys(value as string[]);
+  },[value])
 
   useEffect(() => {
     getData();
@@ -159,42 +163,7 @@ const MenuEditer: React.FC<MenuEditerType> = ({ value = [], onChange, noAction =
 
   return (
     <div className="MenuEditer">
-      <div className="search">
-        <span className="label">搜索:</span>
-        <Search
-          className="valueArea"
-          onSearch={onSearchHandle}
-          allowClear={true}
-          placeholder="请输入"
-        />
-      </div>
-      <KCTable
-        rowKey="menuId"
-        columns={columns.filter((t) => (noAction ? t.title != '操作' : t))}
-        dataSource={dataSource}
-        search={false}
-        options={false}
-        pagination={false}
-        expandable={{
-          expandedRowKeys: expandedRowKeys,
-          expandIcon: ({ expanded, onExpand, record }) => {
-            // console.log({expanded, onExpand, record});
-            return expanded
-              ? record.children.length > 0 && (
-                  <DownOutlined onClick={(e) => onExpand(record, e)} style={{ marginRight: 10 }} />
-                )
-              : record.children.length > 0 && (
-                  <RightOutlined onClick={(e) => onExpand(record, e)} style={{ marginRight: 10 }} />
-                );
-          },
-          onExpandedRowsChange: onExpandedRowsChangeHandle,
-        }}
-        rowSelection={{
-          checkStrictly: false,
-          selectedRowKeys: selectedKeys,
-          onChange: onChangeHandle,
-        }}
-      />
+    <TreeTransfer dataSource={dataSource}  targetKeys={targetKeys} onChange={onTransFerChange} />
     </div>
   );
 };

+ 68 - 63
src/pages/platform/components/usersEditer/index.tsx

@@ -1,91 +1,46 @@
 /*
  * @Author: your name
  * @Date: 2022-01-19 14:53:37
- * @LastEditTime: 2022-01-20 10:28:32
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 09:20:34
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/components/usersEditer/index.tsx
  */
 
 import React, { useEffect, useState } from 'react';
 import KCTable from '@/components/kcTable';
-import { Input } from 'antd';
+import { Input,Transfer } from 'antd';
 import { getUsers } from '@/service/user';
 import type { EditUsersDataType } from '@/service/user';
 import { ProColumns } from '@ant-design/pro-table';
 import { TableRequestParamsType } from '@/typings';
 import './style.less';
 
+import type { TransferDirection } from 'antd/es/transfer';
+
 export interface UserEditerType {
   value?: React.Key[] | React.Key[];
   onChange?: (selectedRowKeys: React.Key[]) => {};
   noAction?: boolean;
+  total?:[]
 }
 
+
 const UserEditer: React.FC<UserEditerType> = ({
   value = [],
   onChange,
   noAction = false,
+  total = []
 }) => {
-  const columns: ProColumns<EditUsersDataType>[] = [
-    {
-      title: 'ID',
-      dataIndex: 'id',
-      hideInTable: true,
-    },
-    {
-      title: '姓名',
-      dataIndex: 'name',
-      hideInSearch: false,
-    },
-    {
-      title: '工号',
-      dataIndex: 'account',
-    },
-    {
-      title: '在职状态',
-      dataIndex: 'isOnService',
-      render: (number, record) => {
-        return record.isOnService == 0 ? '在职' : '离职';
-      },
-    },
-  ];
-
-  const getData = async (
-    params: { name?: string } & TableRequestParamsType,
-  ) => {
-    const { current = 1, pageSize = 10, keyword } = params;
-    const resp = await getUsers({
-      current,
-      pageSize,
-      keyword,
-    });
-    return {
-      data: resp.list ? resp.list : [],
-      success: true,
-      total: resp.totalCount,
-    };
-  };
-
-  const onChangeHandle = (
-    selectedRowKeys: React.Key[],
-    selectedRows: any[],
-  ) => {
-    if (selectedRows.length == 0) {
-      //取消选择时
-      setSelectedKeys([]);
-    }
-  };
 
-  const onSearchHandle = (
-    e: React.ChangeEvent & { target: { value: string } },
-  ) => {
-    setKeyword(e.target.value);
-  };
 
+  
   const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
   const [keyword, setKeyword] = useState('');
 
+  const [data, setData] = useState<EditUsersDataType[]>([]);
+  const [targetKeys, setTargetKeys] = useState<React.Key[]>([]);
+
   //record: T, selected: boolean, selectedRows: T[], nativeEvent: Event
   const onSelectHandle = (
     record: EditUsersDataType,
@@ -103,20 +58,70 @@ const UserEditer: React.FC<UserEditerType> = ({
     }
   };
 
+
+  const onChangeHandle = (
+    selectedRowKeys: React.Key[],
+    selectedRows: any[],
+  ) => {
+    if (selectedRows.length == 0) {
+      //取消选择时
+      setSelectedKeys([]);
+    }
+  };
+
+  const onSearchHandle = (
+    e: React.ChangeEvent & { target: { value: string } },
+  ) => {
+    setKeyword(e.target.value);
+  };
+
+
+
+  const filterOption = (inputValue: string, option: EditUsersDataType) =>
+  option.name&&option.name.indexOf(inputValue) > -1;
+
+  const handleChange = (newTargetKeys: string[]) => {
+    setTargetKeys(newTargetKeys);
+    onChange&&onChange(newTargetKeys);
+  };
+
+  const handleSearch = (dir: TransferDirection, value: string) => {
+   
+  };
+
+
+
+
   useEffect(() => {
     onChange && onChange(selectedKeys);
   }, [selectedKeys]);
 
   useEffect(() => {
-    setTimeout(() => {
-      //让设置key的操作进入宏任务,等待微任务执行完毕
-      setSelectedKeys(value);
-    }, 500);
+   setTargetKeys(value);
+   setData(total)
+
   }, []);
 
   return (
     <div className="UserEditer">
-      <div className="search">
+
+      
+    <Transfer
+      dataSource={data}
+      showSearch
+      pagination={{pageSize:20}}
+      rowKey={record => `${record.id}`}
+      showSelectAll={true}
+      // filterOption={filterOption}
+      targetKeys={targetKeys as string[]}
+      onChange={handleChange}
+      onSearch={handleSearch}
+      render={item => item.name?item.name:''}
+    />
+
+
+
+      {/* <div className="search">
         <span className="label">搜索人员:</span>
         <Input
           className="valueArea"
@@ -138,7 +143,7 @@ const UserEditer: React.FC<UserEditerType> = ({
           onChange: onChangeHandle,
           onSelect: onSelectHandle,
         }}
-      />
+      /> */}
     </div>
   );
 };

+ 34 - 18
src/pages/platform/setting/hospManage/index.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 15:22:48
- * @LastEditTime: 2022-03-02 15:47:20
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-06 11:37:25
+ * @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
  */
@@ -47,37 +47,53 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
       dataIndex: 'hospName',
       hideInSearch: false,
     },
-    {
-      title: '是否主院',
-      dataIndex: 'isHospital',
-      render: (text) => {
-        return text == 0 ? '是' : '否';
-      },
-    },
+    // {
+    //   title: '是否主院',
+    //   dataIndex: 'isHospital',
+    //   render: (text) => {
+    //     return text == 0 ? '是' : '否';
+    //   },
+    // },
     {
       title: '医院标识',
       dataIndex: 'hospSign',
     },
-    {
-      title: '简称',
-      dataIndex: 'hospAbbreviation',
-    },
+    // {
+    //   title: '简称',
+    //   dataIndex: 'hospAbbreviation',
+    // },
     {
       title: '主院名称',
       dataIndex: 'mainHospName',
     },
+    {
+      title: '医院等级',
+      dataIndex: 'hospitalLevel',
+    },
+    {
+      title: '医院类型',
+      dataIndex: 'hospitalType',
+    },
+    {
+      title: '医院性质',
+      dataIndex: 'hospitalNature',
+    },
+    {
+      title: '医院编码',
+      dataIndex: 'hospitalCode',
+    },
     {
       title: '系统名称',
       dataIndex: 'systemName',
     },
     {
-      title: '是否互通',
+      title: '互通',
       dataIndex: 'dataShare',
     },
-    {
-      title: '变更日期',
-      dataIndex: 'updateTime',
-    },
+    // {
+    //   title: '变更日期',
+    //   dataIndex: 'updateTime',
+    // },
     {
       title: '操作',
       width: 250,

+ 72 - 6
src/pages/platform/setting/hospManage/modals/modal.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2022-03-04 09:06:04
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 11:10:32
+ * @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
  */
@@ -15,12 +15,13 @@ import { hospManageModelState, Dispatch } from 'umi';
 import { ProFormText, ProFormRadio, ProFormDependency, ProFormDigit } from '@ant-design/pro-form';
 import type { ProColumns } from '@ant-design/pro-table';
 import { EditableProTable } from '@ant-design/pro-table';
-import { getHospList, getHospYoushuAccounts, YoushuAccountsType } from '@/service/hospList';
+import { getHospList, getHospYoushuAccounts, getMainHosp, YoushuAccountsType } from '@/service/hospList';
 import type { AddUsersDataType } from '@/service/user';
 import { randomString } from '@/utils';
 import { TableActType } from '..';
 import { Form } from 'antd';
 import MenuEditer from '@/pages/platform/components/menuEditer/menu';
+import { getPlatformDictionary } from '@/service/dictionary';
 
 interface ActModalProps extends hospManageModelState {
   dispatch: Dispatch | undefined;
@@ -155,9 +156,9 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     //加装key字段
     const fixedDataSource = currentEdit?.youshuUsers
       ? currentEdit.youshuUsers.map((t) => ({
-          ...t,
-          key: Number((Math.random() * 1000000).toFixed(0)),
-        }))
+        ...t,
+        key: Number((Math.random() * 1000000).toFixed(0)),
+      }))
       : [];
     setDataSource(fixedDataSource);
   }, [currentEdit]);
@@ -248,8 +249,73 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
               }
             }}
           </ProFormDependency>
+          <KCProSelect
+            label="医院等级"
+            width="md"
+            name="hospitalLevel"
+            request={async () => {
+              const resp = await getPlatformDictionary('HOSPITAL_LEVEL');
+              if (resp) {
+                return resp[0].dataVoList.map((t) => ({
+                  label: t.value,
+                  value: t.code,
+                }));
+              }
+              return [];
+            }}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+          <KCProSelect
+            label="医院类型"
+            width="md"
+            name="hospitalType"
+            request={async () => {
+              const resp = await getPlatformDictionary('HOSPITAL_TYPE');
+              if (resp) {
+                return resp[0].dataVoList.map((t) => ({
+                  label: t.value,
+                  value: t.code,
+                }));
+              }
+              return [];
+            }}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+          <KCProSelect
+            label="医院性质"
+            width="md"
+            name="hospitalNature"
+            request={async () => {
+              const resp = await getPlatformDictionary('HOSPITAL_NATURE');
+              if (resp) {
+                return resp[0].dataVoList.map((t) => ({
+                  label: t.value,
+                  value: t.code,
+                }));
+              }
+              return [];
+            }}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+          
           <ProFormText width="md" name="hospSign" label="医院标识" disabled />
           <ProFormText width="md" name="hospAbbreviation" label="简称" placeholder="请输入" />
+          <ProFormText width="md" name="hospitalCode" label="编码" placeholder="请输入" />
           <ProFormText width="md" name="systemName" label="系统名称" placeholder="请输入" />
           <ProFormRadio.Group
             name="isDataShare"

+ 86 - 28
src/pages/platform/setting/menuManage/index.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 15:22:48
- * @LastEditTime: 2022-03-03 16:10:32
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-06 18:32:17
+ * @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
  */
@@ -25,6 +25,8 @@ export enum TableActType {
   ADD,
   DEL,
   EDIT,
+  SET,
+  MOVEANDCOPY,//复制移动
 }
 
 interface PageProps extends ConnectProps {
@@ -87,38 +89,81 @@ const MenuManage: FC<PageProps> = ({ menuManageModel: state, dispatch }) => {
     //   title: '变更人',
     //   dataIndex: 'mainHospName',
     // },
-    {
-      title: '变更日期',
-      dataIndex: 'modifyTime',
-    },
+    // {
+    //   title: '变更日期',
+    //   dataIndex: 'modifyTime',
+    // },
     {
       title: '操作',
-      width: 220,
+      width: 400,
       key: 'option',
       valueType: 'option',
-      render: (text, record) => [
-        <a key="link" onClick={() => editHandle(record)}>
-          编辑
-        </a>,
-        <Divider key="1" type="vertical" style={{ margin: '0 3px' }} />,
-        <Popconfirm
-          title="是否确定删除?"
-          onConfirm={() => delHandle(record)}
-          // onCancel={cancel}
-          okText="确定"
-          cancelText="取消"
-          key="link2"
-        >
-          <a>删除</a>
-        </Popconfirm>,
-        <Divider key="2" type="vertical" style={{ margin: '0 3px' }} />,
-        <a key="link3" onClick={() => addHandle(record.menuId, record)}>
-          添加
-        </a>,
-      ],
+      render: (text, record) => {
+
+           return record.type == 1?[
+            <a key="link" onClick={() => setHomePage(record)}>
+              设为首页
+            </a>,
+            <Divider key="1" type="vertical" style={{ margin: '0 1px'}} />,
+            <a key="link" onClick={() => editHandle(record)}>
+              编辑
+            </a>,
+            <Divider key="1" type="vertical" style={{ margin: '0 1px'}} />,
+            <Popconfirm
+              title="是否确定删除?"
+              onConfirm={() => delHandle(record)}
+              // onCancel={cancel}
+              okText="确定"
+              cancelText="取消"
+              key="link2"
+            >
+              <a>删除</a>
+            </Popconfirm>,
+            <Divider key="2" type="vertical" style={{ margin: '0 1px' }} />,
+            <a key="link3" onClick={() => addHandle(record.menuId, record)}>
+              添加
+            </a>,
+            <Divider key="1" type="vertical" style={{ margin: '0 1px' }} />,
+             <a key="link3" onClick={() => moveAndCopy(record)}>
+               复制/移动
+             </a>,
+          ]:[
+            <a key="link" onClick={() => editHandle(record)}>
+              编辑
+            </a>,
+            <Divider key="1" type="vertical" style={{ margin: '0 1px' }} />,
+            <Popconfirm
+              title="是否确定删除?"
+              onConfirm={() => delHandle(record)}
+              // onCancel={cancel}
+              okText="确定"
+              cancelText="取消"
+              key="link2"
+            >
+              <a>删除</a>
+            </Popconfirm>,
+            <Divider key="2" type="vertical" style={{ margin: '0 1px' }} />,
+            <a key="link3" onClick={() => addHandle(record.menuId, record)}>
+              添加
+            </a>,
+          ]
+      }
+
     },
   ];
 
+  const setHomePage = (record:MenuItemDataType)=>{
+    dispatch &&
+    dispatch({
+      type: 'menuManageModel/edit',
+      payload: {
+        data: record,
+        act: TableActType.SET,
+        isShowModal: true,
+      },
+    });
+  }
+
   const getData = async (params: { name?: string } & TableRequestParamsType) => {
     const { current = 1, pageSize = 1000, name } = params;
     const resp = await getAllMenus();
@@ -160,6 +205,19 @@ const MenuManage: FC<PageProps> = ({ menuManageModel: state, dispatch }) => {
     };
   };
 
+  const moveAndCopy = (record:MenuItemDataType)=>{
+  
+    dispatch &&
+    dispatch({
+      type: 'menuManageModel/edit',
+      payload: {
+        act: TableActType.MOVEANDCOPY,
+        isShowModal: true,
+        data: record ? record : null,
+      },
+    });
+  }
+
   const addHandle = (parentId?: string, record?: MenuItemDataType) => {
     dispatch &&
       dispatch({
@@ -205,7 +263,7 @@ const MenuManage: FC<PageProps> = ({ menuManageModel: state, dispatch }) => {
         reload={reloadTable}
         toolBarRender={() => [
           <Button key="3" type="primary" onClick={() => addHandle()}>
-            新增主菜单
+            新增中心
           </Button>,
         ]}
         request={(params) => getData(params)}

+ 206 - 118
src/pages/platform/setting/menuManage/modals/modal.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2022-03-09 16:53:54
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 11:03:29
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/modal.tsx
  */
@@ -12,10 +12,14 @@ import KCModal from '@/components/KCModal';
 import KCProSelect from '@/components/KCProSelect';
 import { menuManageModelState, Dispatch } from 'umi';
 
-import { ProFormText, ProFormDependency, ProFormDigit } from '@ant-design/pro-form';
+import { Form } from 'antd'
+
+import { ProFormText, ProFormDependency, ProFormDigit, ProFormRadio } from '@ant-design/pro-form';
 import type { AddUsersDataType } from '@/service/user';
 import { randomString } from '@/utils';
 import { MenuTypes } from '@/constant';
+import TreeEditer from '@/pages/platform/components/TreeEditer';
+
 // import { TableActType } from "./typings";
 
 export enum TableActType { //表格操作类型枚举
@@ -23,6 +27,8 @@ export enum TableActType { //表格操作类型枚举
   ADD,
   DEL,
   EDIT,
+  SET,
+  MOVEANDCOPY
 }
 
 interface ActModalProps extends menuManageModelState {
@@ -48,6 +54,7 @@ const ActModal: React.FC<ActModalProps> = ({
   };
 
   const onFinishHandle = (data: any & AddUsersDataType) => {
+
     if (tableAct == TableActType.ADD) {
       dispatch &&
         dispatch({
@@ -63,18 +70,46 @@ const ActModal: React.FC<ActModalProps> = ({
           payload: data,
         });
     }
+    if (tableAct == TableActType.SET) {
+      dispatch &&
+        dispatch({
+          type: 'menuManageModel/setHomePage',
+          payload: data,
+        });
+    }
+
+    if (tableAct == TableActType.MOVEANDCOPY) {
+      dispatch &&
+        dispatch({
+          type: 'menuManageModel/transformMenu',
+          payload: data,
+        });
+    }
 
     return true;
   };
 
   const menuTypeOptionFiler = () => {
+
+
     if (parentId == '0') {
       //顶级目录
-      return MenuTypes.filter((t) => t.label == '系统');
+      return MenuTypes.filter((t) => t.label == '中心层');
+    }
+
+    if (record?.type == 6) {
+      //中心层
+      return MenuTypes.filter((t) => t.label != '中心层');
+    }
+
+    if (record?.type == 5) {
+      //体系
+      return MenuTypes.filter((t) => (t.label == '系统' || t.label == '菜单'));
     }
+
     if (record?.type == 3) {
       //子系统
-      return MenuTypes.filter((t) => t.label == '菜单' || t.label == '目录');
+      return MenuTypes.filter((t) => t.label == '目录' || t.label == '菜单');
     }
     if (record?.type == 1) {
       //子系统菜单目录
@@ -87,6 +122,13 @@ const ActModal: React.FC<ActModalProps> = ({
     return MenuTypes;
   };
 
+  const setModalFormTitle = (key: TableActType) => {
+    if (key == TableActType.ADD) return '新增';
+    if (key == TableActType.EDIT) return '编辑菜单';
+    if (key == TableActType.SET) return '设置首页';
+    if (key == TableActType.MOVEANDCOPY) return '复制/移动';
+  }
+
   return (
     <KCModal
       visible={isShowModal}
@@ -98,125 +140,171 @@ const ActModal: React.FC<ActModalProps> = ({
           ? { ...currentEdit }
           : { hospSign: randomString(16), isDataShare: 0 }
       }
-      title={tableAct == TableActType.EDIT ? '编辑菜单' : '新增菜单'}
+      // title={tableAct == TableActType.EDIT ? '编辑菜单' : tableAct == TableActType.SET ? '设为首页' : '新增菜单'}
+      title={setModalFormTitle(tableAct)}
       labelCol={{
         span: 6,
       }}
       wrapperCol={{ span: 12 }}
       onFinish={async (data) => onFinishHandle(data)}
     >
-      <ProFormText
-        width="md"
-        name="name"
-        label="菜单名称"
-        placeholder="请输入"
-        rules={[
-          {
-            required: true,
-            message: '请输入菜单名称!',
-          },
-        ]}
-      />
-      <KCProSelect
-        label="类型"
-        width="md"
-        name="type"
-        options={menuTypeOptionFiler()}
-        rules={[
-          {
-            required: true,
-            message: '请选择!',
-          },
-        ]}
-      />
-      <ProFormText
-        width="md"
-        name="url"
-        label="URL"
-        placeholder="请输入"
-        rules={[
-          {
-            required: false,
-            message: '请输入!',
-          },
-        ]}
-      />
-      <ProFormText
-        width="md"
-        name="path"
-        label="PATH"
-        placeholder="请输入"
-        rules={[
-          {
-            required: true,
-            message: '请输入!',
-          },
-        ]}
-      />
-      <ProFormText width="md" name="icon" label="菜单icon" placeholder="请输入" />
-      <ProFormDependency name={['type']}>
-        {({ type }) => {
-          return (
-            type == 1 && (
-              //类型时菜单时
-              <>
-                <KCProSelect
-                  label="内容类型"
-                  width="md"
-                  name="contentType"
-                  initialValue={0}
-                  options={[
-                    {
-                      label: '一般',
-                      value: 0, //普通页面,默认值
-                    },
-                    {
-                      label: '报告',
-                      value: 1,
-                    },
-                    {
-                      label: '大屏',
-                      value: 2,
-                    },
-                    {
-                      label: '填报',
-                      value: 3,
-                    },
-                  ]}
-                  rules={[
-                    {
-                      required: true,
-                      message: '请选择!',
-                    },
-                  ]}
-                />
-                <ProFormDependency name={['contentType']}>
-                  {({ contentType }) => {
-                    return (
-                      contentType &&
-                      contentType != 0 && (
-                        //页面内容为非一般时,填写对应有数Id
-                        <ProFormDigit
-                          label="报告Id"
-                          name="reportId"
-                          min={1}
-                          fieldProps={{ precision: 0 }}
-                          rules={[
-                            {
-                              required: true,
-                              message: '请填写id!',
-                            },
-                          ]}
-                        />
-                      )
-                    );
-                  }}
-                </ProFormDependency>
-              </>
-            )
-          );
-        }}
-      </ProFormDependency>
+      {
+        tableAct == TableActType.SET && (
+          <>
+            <ProFormText
+              width="md"
+              name="menuName"
+              label="首页名称"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: false,
+                  message: '请输入名称(可选)',
+                },
+              ]}
+            />
+          </>
+        )
+      }
+      {
+        tableAct == TableActType.MOVEANDCOPY && (
+          <Form.Item name='treeEditer'>
+            <TreeEditer />
+          </Form.Item>
+        )
+      }
+      {
+        (tableAct == TableActType.ADD || tableAct == TableActType.EDIT) && (
+          <>
+            <ProFormText
+              width="md"
+              name="name"
+              label="名称"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: true,
+                  message: '请输入名称!',
+                },
+              ]}
+            />
+            <KCProSelect
+              label="类型"
+              width="md"
+              name="type"
+              options={menuTypeOptionFiler()}
+              rules={[
+                {
+                  required: true,
+                  message: '请选择!',
+                },
+              ]}
+            />
+            <ProFormText
+              width="md"
+              name="url"
+              label="URL"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: false,
+                  message: '请输入!',
+                },
+              ]}
+            />
+            <ProFormText
+              width="md"
+              name="path"
+              label="PATH"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: true,
+                  message: '请输入!',
+                },
+              ]}
+            />
+            <ProFormText width="md" name="icon" label="icon" placeholder="请输入" />
+            <ProFormDependency name={['type']}>
+              {({ type }) => {
+                return (
+                  type == 1 && (
+                    //类型时菜单时
+                    <>
+                      <KCProSelect
+                        label="内容类型"
+                        width="md"
+                        name="contentType"
+                        initialValue={0}
+                        options={[
+                          {
+                            label: '一般',
+                            value: 0, //普通页面,默认值
+                          },
+                          {
+                            label: '报告',
+                            value: 1,
+                          },
+                          {
+                            label: '大屏',
+                            value: 2,
+                          },
+                          {
+                            label: '填报',
+                            value: 3,
+                          },
+                        ]}
+                        rules={[
+                          {
+                            required: true,
+                            message: '请选择!',
+                          },
+                        ]}
+                      />
+                      <ProFormRadio.Group
+                        name="isHomepage"
+                        label="是否为首页"
+                        options={[
+                          {
+                            label: '是',
+                            value: 1,
+                          },
+                          {
+                            label: '否',
+                            value: 0,
+                          },
+                        ]}
+                      />
+                      <ProFormDependency name={['contentType']}>
+                        {({ contentType }) => {
+                          return (
+                            contentType &&
+                            contentType != 0 && (
+                              //页面内容为非一般时,填写对应有数Id
+                              <ProFormDigit
+                                label="报告Id"
+                                name="reportId"
+                                min={1}
+                                fieldProps={{ precision: 0 }}
+                                rules={[
+                                  {
+                                    required: true,
+                                    message: '请填写id!',
+                                  },
+                                ]}
+                              />
+                            )
+                          );
+                        }}
+                      </ProFormDependency>
+                    </>
+                  )
+                );
+              }}
+            </ProFormDependency>
+          </>
+        )
+      }
     </KCModal>
   );
 };

+ 64 - 5
src/pages/platform/setting/menuManage/model.ts

@@ -1,23 +1,26 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2022-02-09 10:45:10
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-06 18:34:46
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/model.ts
  */
 
 import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
 
-import { addMenu, editMenu, delMenu } from '@/service/menu';
+import { addMenu, editMenu, delMenu, menuSetToHomePage, transformMenu } from '@/service/menu';
 
 import type { MenuItemDataType } from '@/service/menu';
+import { TreeEditerValueType } from '../../components/TreeEditer';
 
 export enum TableActType {
   NOACT,
   ADD,
   DEL,
   EDIT,
+  SET,
+  MOVEANDCOPY
 }
 
 export interface menuManageModelState {
@@ -38,6 +41,8 @@ export interface menuManageModelType {
     postAddData: Effect;
     postEditData: Effect;
     delRequest: Effect;
+    setHomePage:Effect;
+    transformMenu:Effect;
   };
   reducers: {
     add: Reducer<menuManageModelState>;
@@ -65,6 +70,16 @@ const menuManageModel: menuManageModelType = {
   effects: {
     *query({ payload }, { call, put }) {},
     *postAddData({ payload }, { call, put, select }) {
+      const currentEdit: MenuItemDataType = yield select(
+        ({
+          menuManageModel: state,
+        }: {
+          menuManageModel: menuManageModelState;
+        }) => {
+          return state.currentEdit;
+        },
+      );
+
       const parentId: string = yield select(
         ({
           menuManageModel: state,
@@ -74,7 +89,9 @@ const menuManageModel: menuManageModelType = {
           return state.parentId;
         },
       );
-      yield addMenu({ parentId: parentId, ...payload });
+
+      
+      yield addMenu({ parentId: parentId, ...payload,isHomepage:0});
       yield put({
         type: 'reloadTable',
         payload: true,
@@ -95,22 +112,64 @@ const menuManageModel: menuManageModelType = {
         JSON.stringify({
           ...currentEditOld,
           id: currentEditOld.menuId,
+          children:undefined,
           menuId: undefined,
         }),
       );
-      yield editMenu({ ..._currentEditOld, ...payload });
+      yield editMenu({ ..._currentEditOld, ...payload,children:undefined,isHomepage:_currentEditOld.isHomepage?_currentEditOld.isHomepage:0});
       yield put({
         type: 'reloadTable',
         payload: true,
       });
     },
     *delRequest({ payload }, { put }) {
+      console.log({payload});
       yield delMenu(payload);
       yield put({
         type: 'reloadTable',
         payload: true,
       });
     },
+    *setHomePage({ payload }, { call, put, select }){
+      const currentEdit: MenuItemDataType = yield select(
+        ({
+          menuManageModel: state,
+        }: {
+          menuManageModel: menuManageModelState;
+        }) => {
+          return state.currentEdit;
+        },
+      );
+
+        yield menuSetToHomePage({
+           menuId:currentEdit.menuId,
+           menuName:payload.menuName
+        });
+        yield put({
+          type: 'reloadTable',
+          payload: true,
+        });
+    },
+    *transformMenu({ payload }, {select,put }){
+      
+          const currentEdit: MenuItemDataType = yield select(
+            ({
+              menuManageModel: state,
+            }: {
+              menuManageModel: menuManageModelState;
+            }) => {
+              return state.currentEdit;
+            },
+          );
+          
+          const {treeEditer}:{treeEditer:TreeEditerValueType} = payload;
+          // console.log({treeEditer});
+          yield transformMenu(treeEditer.actType,currentEdit.menuId,treeEditer.selectedKeysValue[0]);
+          yield put({
+            type: 'reloadTable',
+            payload: true,
+          });
+    }
   },
   reducers: {
     reloadTable(state, action) {

+ 2 - 2
src/pages/platform/setting/roleManage/index.tsx

@@ -166,7 +166,7 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
 
   const editUserBind = async (record: TableListItem) => {
     //编辑角色与人员的绑定关系
-    const { userIds = [] } = await getRoleHasBindUsers({
+    const { userIds = [],users=[] } = await getRoleHasBindUsers({
       hospId: record.hospId,
       roleId: record.roleId,
     });
@@ -174,7 +174,7 @@ const RoleManage: FC<PageProps> = ({ roleManageModel: state, dispatch }) => {
       dispatch({
         type: 'roleManageModel/edit',
         payload: {
-          data: { ...record, bindUserIds: userIds },
+          data: { ...record, bindUserIds: userIds,allUsers:users },
           act: TableActType.EDITRELAUSER,
           isShowModal: true,
         },

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

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2022-03-10 16:36:29
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 09:47:36
+ * @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
  */
@@ -98,13 +98,13 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     >
       {tableAct == TableActType.EDITMENU && (
         <Form.Item name="bindMenuIds">
-          <MenuEditer noAction={true} />
+          <MenuEditer noAction={true} hospId={currentEdit?.hospId} />
         </Form.Item>
       )}
 
       {tableAct == TableActType.EDITRELAUSER && (
         <Form.Item name="bindUserIds">
-          <UserEditer noAction={true} />
+          <UserEditer total={currentEdit?currentEdit.allUsers:[]} noAction={true} />
         </Form.Item>
       )}
 

BIN
src/pages/platform/setting/userManage/assets/avatar_empty.png


+ 3 - 2
src/pages/platform/setting/userManage/index.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-11 09:43:18
- * @LastEditTime: 2022-03-07 14:44:22
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-01 09:53:01
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/userManage/index.tsx
  */
@@ -181,6 +181,7 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
   return (
     <div className="UserManage">
       <ActModal {...state} dispatch={dispatch} />
+
       <KCTable
         rowKey="id"
         headerTitle="查询表格"

+ 225 - 82
src/pages/platform/setting/userManage/modal.tsx

@@ -1,21 +1,25 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2022-01-13 16:42:17
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-06 15:14:25
+ * @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
  */
 
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import KCModal from '@/components/KCModal';
 import KCProSelect from '@/components/KCProSelect';
+import { message, Button, Spin, Upload } from 'antd';
 import { userManageModelState, Dispatch } from 'umi';
-import { ProFormText } from '@ant-design/pro-form';
+import { ProFormDateTimePicker, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
 import { getHospList } from '@/service/hospList';
-import type { AddUsersDataType } from '@/service/user';
+import { AddUsersDataType, getUserRelaSeletData, UserRelaSeletDataListType, UserRelaSeletDataType } from '@/service/user';
+import { LoadingOutlined, UploadOutlined } from '@ant-design/icons';
 // import { TableActType } from "./typings";
 
+import './style.less';
+
 export enum TableActType {
   NOACT,
   ADD,
@@ -27,12 +31,50 @@ interface ActModalProps extends userManageModelState {
   dispatch: Dispatch | undefined;
 }
 
+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);
+
+  //字典
+  const [dirData, set_dirData] = useState<UserRelaSeletDataType[]>([]);
+
+  // let dirData: UserRelaSeletDataType[] = []
+
+  const props = {
+    name: 'file',
+    maxCount: 1,
+    showUploadList: false,
+    onChange(info: { file: { originFileObj: File, status: string; name: 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
+          }
+        }
+      }
+      if (info.file.status === 'done') {
+        setLoadAvatar(false);
+      } else if (info.file.status === 'error') {
+        message.error(`${info.file.name} 上传失败!`);
+      }
+    },
+  }
+
   const onVisibleChangeHandle = (bool: boolean) => {
     // console.log({bool});
     if (!bool) {
@@ -63,95 +105,196 @@ const ActModal: React.FC<ActModalProps> = ({
     return true;
   };
 
-  // console.log({isShowModal,tableAct,currentEditUser})
+  const getDirecData = async (key?: string) => {
+
+    const data = await getUserRelaSeletData(key);
+    if (data) {
+      set_dirData(data);
+    }
+  }
+
+  const setSelectorData = (key: string) => {
+    const result = dirData.filter((t: any) => (t.code == key));
+    if (result.length > 0) {
+      return result[0].dataVoList.map((t: any) => ({
+        label: t.code, value: t.value
+      }))
+    }
+    return [];
+  }
+
+  useEffect(() => {
+    getDirecData();
+  }, [])
 
   return (
     <KCModal
       visible={isShowModal}
       onVisibleChange={onVisibleChangeHandle}
       layout="horizontal"
+      className='ProfileModal'
       initialValues={
         tableAct == TableActType.EDIT ? { ...currentEditUser } : undefined
       }
       title={tableAct == TableActType.EDIT ? '编辑用户' : '新增用户'}
-      labelCol={{
-        span: 4,
-      }}
-      width={600}
+      labelCol={{ span: 5 }}
+      wrapperCol={{ span: 18 }}
       onFinish={async (data) => onFinishHandle(data)}
     >
-      <KCProSelect
-        label="院区"
-        width="md"
-        name="hospId"
-        request={async () => {
-          const hospList = await getHospList();
-          if (hospList) {
-            return hospList.map((t) => ({
-              label: t.name,
-              value: t.id,
-            }));
-          }
-          return [];
-        }}
-        rules={[
-          {
-            required: true,
-            message: '请选择院区!',
-          },
-        ]}
-      />
-      <ProFormText
-        width="md"
-        name="name"
-        label="姓名"
-        placeholder="请输入"
-        rules={[
-          {
-            required: true,
-            message: '请输入姓名!',
-          },
-        ]}
-      />
-      <ProFormText
-        width="md"
-        name="account"
-        label="工号"
-        placeholder="请输入"
-        rules={[
-          {
-            required: true,
-            message: '请输入工号!',
-          },
-        ]}
-      />
-      <ProFormText
-        width="md"
-        name="phoneNum"
-        label="电话"
-        placeholder="请输入"
-      />
-      <ProFormText
-        width="md"
-        name="idCardNum"
-        label="身份证号码"
-        placeholder="请输入"
-      />
-      <KCProSelect
-        label="类型"
-        width="md"
-        name="isOnService"
-        options={[
-          {
-            value: 1,
-            label: '离职',
-          },
-          {
-            value: 0,
-            label: '在职',
-          },
-        ]}
-      />
+
+      {
+        dirData ? (
+          <div>
+            <div className='wraper'>
+              <div className='left'>
+                <div className='avatarContainer'>
+                  <span>个人照片:</span>
+                  <div className='avatar'>
+                    {avatarUrl && <img src={avatarUrl} alt="avatar" />}
+                    {loadAvatar && <Spin className='spin' indicator={antIcon} />}
+                  </div>
+                  <Upload {...props} className='UploadBtn'>
+                    <Button icon={<UploadOutlined />}>上传照片(100*130)</Button>
+                  </Upload>
+                </div>
+                <div className='formItem'>
+                  <KCProSelect
+                    label="院区"
+                    width="md"
+                    name="hospId"
+                    request={async () => {
+                      const hospList = await getHospList();
+                      if (hospList) {
+                        return hospList.map((t) => ({
+                          label: t.name,
+                          value: t.id,
+                        }));
+                      }
+                      return [];
+                    }}
+                    rules={[
+                      {
+                        required: true,
+                        message: '请选择院区!',
+                      },
+                    ]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="major"
+                    label="所学专业:"
+                    request={async () => setSelectorData('PROFESSIONAL_TYPE')}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择专业!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="jobTitle"
+                    label="职务:"
+                    request={async () => setSelectorData('POSITION_TYPE')}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择职务!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="idCardNum" label="身份证号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="phoneNum" label="手机号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="qualificationCertificateNo" label="资格证号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="doctorLevel"
+                    label="医师级别:"
+                    request={async () => setSelectorData('PHYSICIAN_TYPE')}
+                    placeholder="请选择"
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="a"
+                    label="执业科目:"
+                    request={async () => setSelectorData('PROCESSIONAL_SUBJECTS_TYPE')}
+                    placeholder="请选择"
+                  />
+                </div>
+              </div>
+              <div className='right'>
+                <div className='formItem'>
+                  <ProFormText name="name" label="姓名:" placeholder="请输入" rules={[{ required: true, message: '请输入姓名!' }]} />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="account" label="工号:" placeholder="请输入" rules={[{ required: true, message: '请输入工号!' }]} />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="b"
+                    label="性别:"
+                    request={async () => [
+                      { label: '男', value: '男' },
+                      { label: '女', value: '女' },
+                    ]}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择性别!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="text" label="科室:" placeholder="请输入" rules={[{ required: true, message: '请输入工号!' }]} />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="title"
+                    label="职称:"
+                    request={async () => setSelectorData('TITLE_TYPE')}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择职称!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormDateTimePicker name="entryTime" label="入职时间" placeholder={'请选择日期'} />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="practiceCertificateNo" label="执业证号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="practiceCate"
+                    label="执业类别:"
+                    request={async () => setSelectorData('JOB_TYPE')}
+                    placeholder="请选择"
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="practiceStatus"
+                    label="执业状态:"
+                    request={async () => setSelectorData('PROFESSIONAL_STATUS_TYPE')}
+                    placeholder="请选择"
+                  />
+                </div>
+              </div>
+            </div>
+
+            <div style={{display:'flex',flexDirection:'row',width:'100%'}}>
+              <div style={{paddingLeft:36}}>备注:</div>
+              <ProFormTextArea
+                name="remark"
+                width='xl'
+                placeholder="请输入备注"
+              />
+            </div>
+
+          </div>
+        ) : ''
+      }
+
+
+
     </KCModal>
   );
 };

+ 94 - 0
src/pages/platform/setting/userManage/style.less

@@ -1,3 +1,97 @@
 .UserManage {
   height: 100%;
 }
+
+.ProfileModal {
+  .wraper {
+    display: flex;
+    flex-direction: row;
+
+    .left {
+      width: 50%;
+
+      .avatarContainer {
+        display: flex;
+        flex-direction: row;
+        margin-bottom: 42px;
+        margin-left: 11px;
+
+        .avatar {
+          position: relative;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          width: 96px;
+          height: 128px;
+          border-radius: 4px;
+          background-image: url(./assets/avatar_empty.png);
+          background-size: cover;
+
+          .spin {
+            position: absolute;
+            top: 45%;
+            left: 0;
+            bottom: 0;
+            right: 0;
+          }
+
+          &>img {
+            width: 100%;
+          }
+        }
+
+        .UploadBtn {
+          margin-left: 18px;
+          margin-top: 45px;
+        }
+
+        &>span {
+          height: 14px;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #17181A;
+          line-height: 14px;
+          margin-top: 5px;
+          margin-right: 10px;
+        }
+      }
+
+      .formItem {
+
+        // margin-bottom: 16px;
+        .mq-ant-form-item {
+          // margin-bottom: 0;
+        }
+      }
+    }
+
+    .right {
+      width: 50%;
+
+      .formItem {
+
+        // margin-bottom: 16px;
+        .mq-ant-form-item {
+          .mq-ant-picker {
+            width: 100%;
+          }
+        }
+      }
+    }
+  }
+  .remarkArea {
+    .mq-ant-col-5 {
+      flex: 0 0 10%;
+    }
+    .mq-ant-col-18 {
+      max-width: 100%;
+      .pro-field-xl {
+          width: 662px;
+      }
+    }
+    .pro-field-xl {
+      width: 100%;
+    }
+  }
+}

+ 25 - 0
src/pages/platform/sqlediter/index.tsx

@@ -0,0 +1,25 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-06 15:29:43
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-06 15:43:19
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/sqlediter/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import React from 'react'
+import Editor from "@monaco-editor/react";
+
+function SQLEditer() {
+    return (
+        <Editor
+          height="60vh"
+          defaultLanguage="sql"
+          defaultValue="// some comment"
+        />
+    );
+}
+
+export default SQLEditer

+ 0 - 0
src/pages/platform/sqlediter/style.less


+ 4 - 4
src/service/api.d.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2021-11-11 11:23:56
- * @LastEditTime: 2022-03-04 11:41:56
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-06-07 09:44:50
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/api.d.ts
  */
@@ -45,8 +45,8 @@ declare namespace userRelationInfo {
   export type OwnAppsItem = {
     id: number;
     name: string;
-    icon: string;
-    url: string;
+    icon?: string;
+    url?: string;
     path: string;
   };
 }

+ 22 - 0
src/service/dictionary.ts

@@ -0,0 +1,22 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-06 11:46:24
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-06 14:27:48
+ * @FilePath: /KC-MiddlePlatform/src/service/dictionary.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { request } from 'umi';
+
+//获取平台字典
+
+export const getPlatformDictionary = async (key:string) => {
+    return request<{code:string;value:string|number;dataVoList:{code:string;value:string|number;}[]}[]>('/master/centerSys/sysdictdata/getDictData', {
+      method: 'GET',
+      params: { dictType:key },
+    });
+};

+ 4 - 4
src/service/hospList.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 09:15:59
- * @LastEditTime: 2022-03-02 17:16:06
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 10:55:13
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/hospList.ts
  */
@@ -16,7 +16,7 @@ export const getHospList = async () => {
       id: number;
       name: string;
     }[]
-  >('/master/centerSys/hospital/currentAndShareHosp', {
+  >('/master/centerSys/hospital/getAllMainList', {
     method: 'GET',
   });
 };
@@ -26,7 +26,7 @@ export const getMainHosp = async () => {
   return request<{
     id: number;
     name: string;
-  }>('/master/centerSys/hospital/getMainList', {
+  }[]>('/master/centerSys/hospital/getMainList', {
     method: 'GET',
   });
 };

+ 59 - 0
src/service/index.ts

@@ -0,0 +1,59 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-06-27 15:43:25
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-07 10:12:21
+ * @FilePath: /KC-MiddlePlatform/src/service/index.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+import { request } from 'umi';
+
+
+
+//获取用户首页数据
+
+export interface UserInfo {
+    gender:                     string;
+    title:                      string;
+    departmentId:               string;
+    doctorLevel:                string;
+    userCate:                   string;
+    qualificationCertificateNo: string;
+    account:                    string;
+    jobTitle:                   string;
+    entryTime:                  string;
+    remark:                     string;
+    name:                       string;
+    id:                         string;
+    departmentName:             string;
+    practiceStatus:             string;
+    avatarUrl:                  string;
+    practiceCate:               string;
+    practiceCertificateNo:      string;
+    major:                      string;
+}
+
+export const getUserIndexData = async () => {
+    return request<{
+        userInfo:UserInfo,
+        recentVisit:any,
+        fastEntrance:any,
+        todoList:any,
+        messageRecords:any
+    }>('/master/centerSys/index/getMyIndex', {
+      method: 'GET',
+    });
+};
+
+
+//消息处理
+
+export const todoListAct = async (data:number[]) => {
+    return request('/master/centerSys/index/handleMessage', {
+      method: 'POST',
+      data: data,
+    });
+};
+

+ 88 - 3
src/service/menu.ts

@@ -1,17 +1,18 @@
 /*
  * @Author: your name
  * @Date: 2022-01-10 10:27:15
- * @LastEditTime: 2022-01-20 14:00:10
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-07 09:44:15
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/hospInfo.ts
  */
 
 import { TableRequestParamsType, TableResponseDataType } from '@/typings';
+import { Key } from 'react';
 import { request } from 'umi';
 
 //获取平台菜单
-export const getPlatformMenu = async (systemId: number) => {
+export const getPlatformMenu = async (systemId?: number) => {
   return request('/master/centerSys/user/getMenuNav', {
     method: 'GET',
     params: { systemId },
@@ -30,6 +31,8 @@ export interface MenuItemDataType {
   softUrl?: string;
   type: number;
   url?: string;
+  key?:string;
+  isHomepage:number;
   modifyTime: string;
   children: MenuItemDataType[];
 }
@@ -48,6 +51,14 @@ export const getAllMenus = async () => {
   });
 };
 
+//获取院区所拥有的菜单
+export const getHospAllMenus = async (hospId:string|number) => {
+  return request<{selectedMenuIds:string[];allMenuVO:getAllMenusDataType[]}>('/master/centerSys/hospital/getHospCheckedMenu', {
+    method: 'GET',
+    params:{hospId}
+  });
+};
+
 //菜单管理-新增菜单
 
 export type AddMenuDataType = {
@@ -109,3 +120,77 @@ export const getSpacifyHospMenu = async (data: { hospId: number }) => {
     params: data,
   });
 };
+
+
+//获取用户在平台中所拥有的导航菜单
+
+export type UserPlatformNav = {
+  menuId:string|number;
+  name:string;
+  type:number;
+  path:string;
+  systemId:string;
+  child:UserPlatformNav[];
+}
+
+export const getUserPlatformNav =async () => {
+  return request<UserPlatformNav[]>('/master/centerSys/user/getUserMenu', {
+    method: 'GET',
+  });
+}
+
+
+//添加快速入口
+
+export type AddFastEntryDataType = {
+  menuId:string|number;
+  systemId:string|number;
+  name:string;
+  path:string;
+}
+
+export const addFastEntry = async (data:AddFastEntryDataType[]) => {
+     
+  return request('/master/centerSys/index/addFastEntrance', {
+    method: 'POST',
+    data: data,
+  });   
+
+}
+
+
+
+//菜单设为首页
+export const menuSetToHomePage = async (data:{menuId:string;menuName:string;}) => {
+  return request('/master/centerSys/menu/setHomePage', {
+    method: 'POST',
+    params: data,
+  });   
+
+}
+
+//菜单目录列表
+export const getMenuDirectory = async () => {
+  return request<{list:MenuItemDataType[]}>('/master/centerSys/menu/catalogList', {
+    method: 'GET',
+  });   
+
+}
+
+//复制/移动菜单
+
+export const transformMenu = async (type:'MOVE'|'COPY',menuId:Key,catalogId:Key) => {
+  if(type == 'COPY'){
+    return request('/master/centerSys/menu/copyMenu', {
+      method: 'POST',
+      params:{menuId,catalogId},
+    });   
+  }
+  if(type == 'MOVE'){
+    return request('/master/centerSys/menu/moveMenu', {
+      method: 'POST',
+      params:{menuId,catalogId},
+    });   
+  }
+
+}

+ 23 - 2
src/service/user.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 09:55:49
- * @LastEditTime: 2022-03-10 16:36:24
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-01 11:56:01
+ * @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
  */
@@ -110,3 +110,24 @@ export const getYoushuUsers = async () => {
     method: 'GET',
   });
 };
+
+
+//获取用户相关的字典表
+
+export type UserRelaSeletDataListType = {
+      code:string;
+      value:string;
+}
+export interface UserRelaSeletDataType {
+  code:string;
+  dataVoList:UserRelaSeletDataListType[];
+  value:string;
+}
+
+export const getUserRelaSeletData = async (key?:string) => {
+  return request<UserRelaSeletDataType[]>('/master/centerSys/sysdictdata/getDictData', {
+    method: 'GET',
+    params:{'dictType':key}
+  });
+};
+

+ 4 - 4
src/typings.d.ts

@@ -1,18 +1,18 @@
 /*
  * @Author: your name
  * @Date: 2021-11-19 16:31:19
- * @LastEditTime: 2022-03-09 15:43:55
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-06-07 09:40:42
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/typings.d.ts
  */
 
 type SystemListItem = {
   //平台列表项
-  icon: string;
+  icon?: string;
   id: string;
   name: string;
-  url: string;
+  url?: string;
   path: string;
 };