Kaynağa Gözat

修复菜单穿梭bug

code4eat 3 yıl önce
ebeveyn
işleme
8e37477ef7
70 değiştirilmiş dosya ile 6019 ekleme ve 1112 silme
  1. 85 4
      config/config.ts
  2. 3 2
      config/proxy.ts
  3. 5 3
      package.json
  4. BIN
      public/images/avatar.png
  5. BIN
      public/images/jingyiguanliIcon.png
  6. BIN
      public/images/kclogo_colorful.png
  7. BIN
      public/images/menu.png
  8. BIN
      public/images/zhilianganquan.png
  9. 16 11
      src/app.tsx
  10. BIN
      src/components/NavSelecter/images/close.png
  11. 159 0
      src/components/NavSelecter/index.tsx
  12. 122 0
      src/components/NavSelecter/style.less
  13. 234 71
      src/components/topBar/index.tsx
  14. 216 123
      src/components/topBar/style.less
  15. 34 5
      src/components/topBar/typings.d.ts
  16. 17 1
      src/constant.ts
  17. 2 0
      src/global.less
  18. 5 2
      src/global.tsx
  19. 111 17
      src/layouts/index.tsx
  20. 22 0
      src/pages/channelIndex/channelIndexOne/index.tsx
  21. 0 0
      src/pages/channelIndex/channelIndexOne/style.less
  22. 190 0
      src/pages/index/components/FastEntry/index.tsx
  23. 70 0
      src/pages/index/components/FastEntry/style.less
  24. 71 0
      src/pages/index/components/MsgRecord/index.tsx
  25. 79 0
      src/pages/index/components/MsgRecord/style.less
  26. 76 0
      src/pages/index/components/RecentlyVisited/index.tsx
  27. 56 0
      src/pages/index/components/RecentlyVisited/style.less
  28. BIN
      src/pages/index/components/TodoList/images/exclamationMark.png
  29. BIN
      src/pages/index/components/TodoList/images/gou.png
  30. 76 0
      src/pages/index/components/TodoList/index.tsx
  31. 162 0
      src/pages/index/components/TodoList/style.less
  32. 233 42
      src/pages/index/index.less
  33. 146 24
      src/pages/index/index.tsx
  34. 26 57
      src/pages/login/index.tsx
  35. 107 169
      src/pages/login/style.less
  36. 4 4
      src/pages/personalCenter/components/security.tsx
  37. 135 58
      src/pages/platform/_layout.tsx
  38. 168 0
      src/pages/platform/components/TreeEditer/index.tsx
  39. 0 0
      src/pages/platform/components/TreeEditer/style.less
  40. 163 151
      src/pages/platform/components/menuEditer/menu.tsx
  41. 68 63
      src/pages/platform/components/usersEditer/index.tsx
  42. 45 22
      src/pages/platform/setting/hospManage/index.tsx
  43. 115 11
      src/pages/platform/setting/hospManage/modals/modal.tsx
  44. 1108 0
      src/pages/platform/setting/indicatorMana/DrawerForm/drawer.tsx
  45. 20 0
      src/pages/platform/setting/indicatorMana/DrawerForm/style.less
  46. 107 0
      src/pages/platform/setting/indicatorMana/TreeDirectory/index.tsx
  47. 0 0
      src/pages/platform/setting/indicatorMana/TreeDirectory/style.less
  48. 453 0
      src/pages/platform/setting/indicatorMana/index.tsx
  49. 37 0
      src/pages/platform/setting/indicatorMana/style.less
  50. 106 38
      src/pages/platform/setting/menuManage/index.tsx
  51. 264 118
      src/pages/platform/setting/menuManage/modals/modal.tsx
  52. 64 5
      src/pages/platform/setting/menuManage/model.ts
  53. 2 2
      src/pages/platform/setting/roleManage/index.tsx
  54. 4 4
      src/pages/platform/setting/roleManage/modals/modal.tsx
  55. BIN
      src/pages/platform/setting/userManage/assets/avatar_empty.png
  56. 5 4
      src/pages/platform/setting/userManage/index.tsx
  57. 262 84
      src/pages/platform/setting/userManage/modal.tsx
  58. 94 0
      src/pages/platform/setting/userManage/style.less
  59. 98 0
      src/pages/platform/sqlediter/index.tsx
  60. 0 0
      src/pages/platform/sqlediter/style.less
  61. 4 4
      src/service/api.d.ts
  62. 31 0
      src/service/department.ts
  63. 41 0
      src/service/dictionary.ts
  64. 26 4
      src/service/hospList.ts
  65. 59 0
      src/service/index.ts
  66. 67 0
      src/service/indicator.ts
  67. 105 3
      src/service/menu.ts
  68. 1 0
      src/service/role.ts
  69. 36 2
      src/service/user.ts
  70. 4 4
      src/typings.d.ts

+ 85 - 4
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-18 10:25:40
+ * @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,
@@ -29,10 +30,12 @@ export default defineConfig({
     },
   },
   lessLoader: {
-    modifyVars: { '@ant-prefix': 'kcmp-ant' },
+    modifyVars: { '@ant-prefix': 'kcmp-ant','root-entry-name': 'default' },
   }, //
   theme: {
     '@primary-color': '#3376FE',
+    '@primary-color-hover':'#3376FE',
+    // '@root-entry-name':'root-entry-name'
   },
   routes: [
     {
@@ -43,8 +46,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 +60,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',
@@ -68,11 +80,80 @@ export default defineConfig({
               path: '/platform/setting/roleManage',
               component: '@/pages/platform/setting/roleManage/index.tsx',
             },
+            // {
+            //   path: '/platform/setting/reports',
+            //   component: '@/pages/platform/setting/reports/index.tsx',
+            // },
+            {
+              path: '/platform/setting/indicatorMana',
+              component: '@/pages/platform/setting/indicatorMana/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/0',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/1',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/2',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/3',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/4',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/5',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/6',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/7',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/8',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/9',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/10',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/11',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/12',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/13',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
+            {
+              path: '/platform/setting/reports/14',
+              component: '@/pages/platform/setting/reports/index.tsx',
+            },
             {
-              path: '/platform/setting/reports',
+              path: '/platform/setting/reports/15',
               component: '@/pages/platform/setting/reports/index.tsx',
             },
           ],
+          
         },
         {
           path: '/personalCenter',

+ 3 - 2
config/proxy.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:00:52
- * @LastEditTime: 2022-04-27 16:17:04
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-26 09:31:13
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/config/proxy.ts
  */
@@ -16,6 +16,7 @@ const proxy: { [key: string]: any } = {
   dev: {
     '/master': {
       target: 'http://112.124.59.133:7001/',
+      // target: 'http://112.124.59.133:7002/',
       changeOrigin: true,
       pathRewrite: { '^/master': '' },
     },

+ 5 - 3
package.json

@@ -25,15 +25,17 @@
     "@ant-design/icons": "^4.5.0",
     "@ant-design/pro-card": "^1.14.17",
     "@ant-design/pro-descriptions": "^1.6.8",
-    "@ant-design/pro-form": "^1.18.3",
-    "@ant-design/pro-layout": "^6.15.3",
+    "@ant-design/pro-form": "^1.70.3",
+    "@ant-design/pro-layout": "^6.38.13",
     "@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",
     "react-dev-inspector": "^1.1.1",
     "react-dom": "16.x",
-    "umi": "^3.5.20"
+    "umi": "^3.5.20",
+    "antd":"^4.21.6"
   },
   "devDependencies": {
     "@types/express": "^4.17.13",

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


+ 16 - 11
src/app.tsx

@@ -1,7 +1,7 @@
 import { useState } from 'react';
 import { PageLoading } from '@ant-design/pro-layout';
 import { notification, Modal } from 'antd';
-import { RequestConfig, history } from 'umi';
+import { RequestConfig, history, useModel } from 'umi';
 import type { RequestOptionsInit } from 'umi-request';
 import { getHospSubSystemList, UserDataType } from '@/service/login';
 
@@ -29,10 +29,11 @@ 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>;
+  childAppIsShowMenu?:boolean; 
   spacicalPageParamsType?: SpacicalPageParamsType[];
   getHospSubSystemListFunc?: () => Promise<any[]>;
 };
@@ -110,6 +111,8 @@ const requestInterceptorsHandle = (url: string, options: RequestOptionsInit) =>
 };
 
 const responseInterceptorsHandle = async (response: Response, options: RequestOptionsInit) => {
+
+
   const _response: {
     data?: any;
     status: number;
@@ -117,13 +120,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 +157,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 +199,7 @@ export const request: RequestConfig = {
   timeout: 10000,
   errorConfig: {
     adaptor: (resData) => {
+
       if (!resData.success && resData.status != 200) {
         return {
           ...resData,
@@ -227,9 +231,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
@@ -241,6 +245,7 @@ export const qiankun = fetch('/config').then(() => ({
 
 //向子应用透传
 export function useQiankunStateForSlave() {
+
   const [masterState, setMasterState] = useState({});
 
   return {
@@ -257,7 +262,7 @@ export const layout = ({ initialState: { userData } }: { initialState: InitialSt
     onPageChange: () => {
       //如果没有登录,重定向到 login
       if (!userData && location.pathname !== '/login') {
-        history.push('/login');
+        // history.push('/login');
       }
     },
     menuHeaderRender: undefined,

BIN
src/components/NavSelecter/images/close.png


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

@@ -0,0 +1,159 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-06-29 11:05:04
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-14 15:37:31
+ * @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;
+    type: number;
+    systemId: string;
+}
+
+
+export type NavSelecterData = {
+    name: string;
+    menuId: number | string;
+    path: string;
+    systemId: string;
+    type: number;
+    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='closeBtn' onClick={(e) => onMaskClick(e)}>
+                    <img src={require('./images/close.png')} />
+                </div>
+                <div className='content' onClick={(e) => e.stopPropagation()}>
+                    <div>
+                        <Tabs defaultActiveKey="1" >
+
+                            {
+                                data?.map((val) => (
+                                    
+                                        <TabPane tab={val.name} key={val.menuId}>
+                                            <div className='contentInner'>
+                                            {
+                                                val.child?.map((item) => (
+                                                    <div className='row' key={item.menuId}>
+                                                        <div className='rowName'>{item.name}</div>
+                                                        <div className='rowWrap'>
+                                                            {
+                                                                item.child?.map(a => {
+                                                                    if (a.type == 3) {
+                                                                        return (
+                                                                            <div className='tab' key={a.menuId}>
+                                                                                <Checkbox onChange={() => onChange({
+                                                                                    name: a.name,
+                                                                                    menuId: a.menuId,
+                                                                                    path: a.path,
+                                                                                    type: a.type,
+                                                                                    systemId: a.systemId
+                                                                                })} checked={checkedIds.includes(a.menuId)} ></Checkbox>
+                                                                                <span style={{ marginLeft: 8 }}>{a.name}</span>
+                                                                            </div>
+                                                                        )
+                                                                    }
+                                                                })
+                                                            }
+                                                        </div>
+                                                    </div>
+                                                ))
+                                            }
+                                            </div>
+                                        </TabPane>
+                                    
+                                ))
+                            }
+
+                        </Tabs>
+                    </div>
+                </div>
+                <div className='footer' onClick={e => e.stopPropagation()}>
+                    <span className='count'>{`已选中${checkedIds.length}项`}</span>
+                    <div className='btnGroup'>
+                        <Button style={{ marginRight: 8 }} onClick={onReset}>重置</Button>
+                        <Button type="primary" onClick={onCommit}>确定</Button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    )
+}
+
+
+export default NavSelecter;

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

@@ -0,0 +1,122 @@
+.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 {
+    position: relative;
+    width: 70%;
+    height: 60%;
+    padding-top: 12px;
+    background: #FFFFFF;
+    border-radius: 4px;
+    border: 1px solid #CFD6E6;
+
+    .closeBtn {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      position: absolute;
+      right: 20px;
+      top: 10px;
+      width: 30px;
+      height: 30px;
+      cursor: pointer;
+
+      &>img {
+        width: 10px;
+        height: 10px;
+      }
+    }
+
+    .content {
+      padding: 24px;
+      height: calc(100% - 56px);
+      overflow-y: hidden;
+
+      .contentInner {
+          height:368px;
+          overflow-y: scroll;
+      }
+      .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;
+
+    }
+  }
+
+}

+ 234 - 71
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-14 16:07:56
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/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';
@@ -18,41 +18,75 @@ import logo from '../../../public/images/kc-logo.png';
 import platFormMenuIcon from '../../../public/images/platformMenu.png';
 import tabCloseIcon from '../../../public/images/tabCloseIcon.png';
 
-import { history } from 'umi';
+import { history, useModel } 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 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 localSavedTab = localStorage.getItem('currentSelectedTab');
+
+  const currentSelectedTabFromLocal = localSavedTab ? JSON.parse(localSavedTab) : {};
 
   const _systemTabClickHandle = (item: TopBar.Tab) => {
     //导航栏tab点击
-
-    setCurrentSelectedTab(item);
+    console.log('_systemTabClickHandle',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 +100,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 +118,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 +131,208 @@ 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 = (menuData:any) => {
+    setIfOpenPannel(false);
+    onTabClick&&onTabClick(menuData)
+  }
+
+  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){
+              _systemTabClickHandle(Object.assign(result[0]))
+                // history.push(result[0].path)
+            }
+       }
+  }
+
+  const openNav = () => {
+    setIfOpenPannel(!ifOpenPannel);
+  }
+
+  
+
+  const reSetNav = (_panelData: TopBar.PanelData[], cur: TopBar.Tab) => {
+    
+    if (!(_panelData.length > 0)) return
+
+    if (JSON.stringify(cur) != '{}') {
+
+      let blockIndex = 0;
+      let channelIndex = 0;
+
+
+      const _currentSelectedTabFromLocal = cur;
+
+      one: for (let index = 0; index < _panelData.length; index++) {
+        blockIndex = index;
+    
+        if (_panelData[index] && _panelData[index].child) {
+          two: for (let i = 0; i < _panelData[index].child.length; i++) {
+
+            channelIndex = i;
+            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) {
+                    set_currentActivedBlockIndex(blockIndex);
+                     set_pageTitle(_panelData[blockIndex].child[channelIndex].name); //设置体系标题
+                     
+                    break one;
+                  }
+                }
+              }
+            }
 
-      if (sysList.length > 1) {
-        //有多个应用时
-        history.replace('/index');
+          }
+        }
       }
+
+      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]);
+  useEffect(() => { 
+    if (currentSelectedTabFromLocal) {
+
+      reSetNav(navData, currentSelectedTabFromLocal);
+    }
+      
+    set_panelData(navData);
+  }, [navData])
+
+  useEffect(()=>{
+
+    if(currentTab)reSetNav(panelData,currentTab);
+ 
+    
+  },[currentTab]);
+
+  // useEffect(()=>{
+  //   if(currentSelectedSys){
+  //     onTabClickHandle(currentSelectedSys);
+  //   }
+  // },[currentSelectedSys])
+  
 
   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)}>{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%);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 }

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

@@ -1,18 +1,47 @@
 /*
  * @Author: your name
  * @Date: 2022-01-10 13:56:19
- * @LastEditTime: 2022-03-04 11:47:59
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-11 18:12:01
+ * @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;
+    type:number;
+    contentType:string;
+    isSetupMenu?:number;
   };
+
+
+  export type TypeBlock = {
+    icon?: string;
+    name: string;
+    menuId: number | string;
+    path: string;
+    type:number;
+    contentType:string;
+    systemId: string;
+    child: Tab[]
+  }
+
+  export type PanelData = {
+    name: string;
+    menuId: number | string;
+    path: string;
+    icon?: string;
+    systemId: string;
+    type:number;
+    child: TypeBlock[]
+  }
+
 }
+
+

+ 17 - 1
src/constant.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-14 16:09:09
- * @LastEditTime: 2022-06-21 17:33:54
+ * @LastEditTime: 2022-07-26 09:45:51
  * @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 = [

+ 2 - 0
src/global.less

@@ -16,4 +16,6 @@ input {
   max-width: 100%;
 }
 
+
+
 //--------------------

+ 5 - 2
src/global.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2021-12-21 11:05:37
- * @LastEditTime: 2022-03-29 15:17:32
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-13 10:49:58
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/global.tsx
  */
@@ -20,6 +20,9 @@ export const logoutHandle = async () => {
   // await logout();
   localStorage.removeItem('userData');
   localStorage.removeItem('initialState');
+  localStorage.removeItem('currentSelectedTab');
+  localStorage.removeItem('isChildShowMenu');
+  // localStorage.removeItem('visitedTabs');
 };
 
 (function () {

+ 111 - 17
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-12 09:24:24
+ * @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,21 +11,44 @@ import { IRouteComponentProps, useModel, history } from 'umi';
 import ProLayout from '@ant-design/pro-layout';
 
 import TopBar from '@/components/topBar';
+import { Key, useEffect, useState } from 'react';
+import { getPlatformMenu, getSpecifyMenuDetail, getUserPlatformNav } from '@/service/menu';
+import { NavSelecterData } from '@/components/NavSelecter';
 
-import { Modal } from 'antd';
 
-const TopHoc = ({ systemLists, openedSysLists, currentSelectedSys }: { systemLists: TopBar.Tab[]; openedSysLists: TopBar.Tab[]; currentSelectedSys: TopBar.Tab | undefined }) => {
+
+const TopHoc = ({ currentSelectedSys, openedSysLists, navData,set_emptyPageContent }: {set_emptyPageContent:any; 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] }));
+
   };
 
   const onTabClickHandle = async (data: TopBar.Tab) => {
-    await setInitialState((s) => ({ ...s, currentSelectedSys: data }));
-    history.push(data.path);
+    // console.log({data});
+    if(JSON.stringify(data) != '{}'){
+      await setInitialState((s) => ({ ...s, currentSelectedSys: data }));
+  
+      if(data.contentType == '4'){
+          //空白页面
+          if(data.isSetupMenu){
+            //体系菜单掩藏子应用的menu
+            localStorage.setItem('isChildShowMenu','false');
+          }
+          
+          history.push(`${data.path}?isEmpty=true&menuId=${data.menuId}`);
+      }else{
+        if(data.isSetupMenu){
+          //体系菜单掩藏子应用的menu
+          localStorage.setItem('isChildShowMenu','false');
+        }else{
+          localStorage.setItem('isChildShowMenu','true');
+        }
+  
+        history.push(data.path);
+      }
+    }
   };
 
   const userPannelTabClickhandle = (tag: string) => {
@@ -40,10 +63,13 @@ const TopHoc = ({ systemLists, openedSysLists, currentSelectedSys }: { systemLis
         setInitialState((s) => ({
           ...s,
           currentSelectedSys: {
-            id: -1,
+            menuId: -1,
             name: '个人中心',
             icon: '',
             url: '',
+            systemId: '-1',
+            type:1,
+            contentType:'0',
             path: '/personalCenter',
           },
         }));
@@ -51,27 +77,64 @@ 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') {
+  const [navData, set_navData] = useState<TopBar.PanelData[]>([]);
+  const [emptyPageContent, set_emptyPageContent] = useState('');
+  const [isEmpty,set_isEmpty] = useState(false);
+
+  const getNavData = async () => {
+    const nav = await getUserPlatformNav();
+    if (nav) {
+      set_navData(nav);
+
+    }
+  }
+
+
+  const getEmptyPageContent =async (menuId:Key) => {
+    const menuItem = await getSpecifyMenuDetail(menuId);
+    set_emptyPageContent(menuItem.description);
+  }
+
+
+  useEffect(() => {
+    if (location.pathname != '/login') {
+      getNavData();
+    }
+    if(location.query.isEmpty == 'true'&&location.query.menuId){
+      getEmptyPageContent(location.query.menuId as string)
+    }
+  }, [])
+
+  useEffect(()=>{
+  
+    if(location.pathname != '/platform'){
+      //排除已有系统的空白页面
+      set_isEmpty(location.query.isEmpty == 'true');
+    }
+  })
+
+  if (location.pathname == '/login') {
     return <div>{children}</div>;
   }
-  // return <div style={{height:'calc(100vh - 48px)'}}>{children}</div>
 
   return (
     <ProLayout
@@ -79,17 +142,48 @@ export default function Layout({ children, location, route, history, match }: IR
       contentStyle={{
         margin: 0,
       }}
+      menuItemRender={(item, dom) => {
+        return (
+          <a
+            onClick={() => {
+              history.push(`${item.path}${item.contentType == 4 ? `?isEmpty=true&menuId=${item.key}` : ''}` || '/');
+            }}
+          >
+            {dom}
+          </a>
+        )
+      }}
+      menu={{
+
+        request: async () => {
+          return [
+            {
+              path: '/index',
+              name: '欢迎进入医管平台'
+            }
+          ]
+        },
+      }}
+      pageTitleRender={false}
       headerRender={() =>
         initialState && (
           <TopHoc
-            systemLists={initialState.systemLists ? initialState.systemLists : []}
+            navData={navData}
+            set_emptyPageContent={set_emptyPageContent}
+            currentSelectedSys={initialState.currentSelectedSys}
             openedSysLists={initialState.openedSysLists ? initialState.openedSysLists : []}
-            currentSelectedSys={initialState.currentSelectedSys ? initialState.currentSelectedSys : undefined}
           />
         )
       }
     >
-      <div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll' }}>{children}</div>
+      {
+        isEmpty&& (
+          <div style={{ textAlign: 'center', paddingTop: 100,height:'93vh' }}>
+            <h1>{emptyPageContent}</h1>
+          </div>
+        )
+      }
+      {!isEmpty&&(<div style={{ height: `calc(100vh - 48px)`, overflowY: 'scroll' }}>{children}</div>)}
     </ProLayout>
   );
 }

+ 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


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

@@ -0,0 +1,190 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-27 14:17:59
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-12 09:48:06
+ * @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;
+    type:number;
+    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 as any,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;
+      }
+    }
+  }
+}

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

@@ -0,0 +1,71 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-30 09:50:41
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-14 17:04:40
+ * @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;
+      resolveTime:string;
+      isProcess:number;
+      content: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='msgRecord'>
+                <div className='topTitle'>
+                    <span className='name'>消息记录</span>
+                </div>
+                <div className='wrap'>
+                    {
+                        list.map((val,index)=>(
+                              <div className='list' key={index}>
+                                    <div className='msgTitle' dangerouslySetInnerHTML={{__html:val.content}}></div>
+                                    {/* <div className='msgTitle'>{`${val.title}审核${val.isProcess?'已通过':'未通过'}`}</div> */}
+                                    <div className='msgDate'>
+                                        <span>{val.resolveTime}</span>
+                                        <span>{`审核${val.isProcess?'已通过':'未通过'}`}</span>
+                                    </div>
+                              </div>
+                        ))
+                    }
+                    {
+                        list.length == 0 && (
+                            <div className='empty'>
+                                <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+                            </div>
+                        )
+                    }
+                </div>
+        </div>
+    )
+}

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

@@ -0,0 +1,79 @@
+.msgRecord {
+  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:column;
+    flex-wrap: wrap;
+    padding: 16px;
+
+    .empty {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+
+    }
+
+    .list {
+      margin-bottom: 24px;
+      cursor: pointer;
+      .msgTitle {
+        width: 300px;
+        height: 14px;
+        line-height: 14px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+        margin-bottom: 8px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space:nowrap;
+
+        &>span {
+          font-weight: bold;
+          color: #17181A;
+        }
+      }
+
+      .msgDate {
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+        height: 12px;
+        line-height: 12px;
+        font-size: 12px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #7A8599;
+      }
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+}

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

@@ -0,0 +1,76 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-30 09:50:41
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-12 09:46:26
+ * @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;
+        type:number;
+        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触发导航跳转
+        console.log({val});
+        await setInitialState((s) => ({ ...s, currentSelectedSys:val as any,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


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

@@ -0,0 +1,76 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-05-30 10:49:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-07 17:53:44
+ * @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 'todoStatus green';
+        if(val.taskLevel == 2)return 'todoStatus orange';
+        if(val.taskLevel == 1)return 'todoStatus 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='todoList'  key={index}>
+                                   <div className='checkBtn' onClick={()=>checkBtnHandle(item)}></div>
+                                   <div className='status'>
+                                         <div className={setTodoClass(item)}>医务管理系统 / 医资授予</div>
+                                         <span className='date'>{item.createDate}</span>
+                                   </div>
+                                   <div className='detail' dangerouslySetInnerHTML={{__html:item.content}}></div>
+                            </div>
+                        )
+                    })
+                }
+            </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;
+    }
   }
 }

+ 146 - 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-14 16:41: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/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,153 @@ 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)=>({
+            id:t.id,
+            status:1,
+            content:t.content,
+            createDate:t.createDate,
+            taskLevel:t.taskLevel,
+
+          })));
+
+          set_msgRecord(resp.messageRecords.map((t:any)=>({
+                title:t.recordTitle,
+                date:t.createDate,
+                resolveTime:t.resolveTime,
+                isProcess:t.isProcess,
+                content:t.content
+          })));
+        }
+  }
+
+  const 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?`${new Date(userInfo?.entryTime).getFullYear()}-${(new Date(userInfo?.entryTime).getMonth()+1)>10?(new Date(userInfo?.entryTime).getMonth()+1):'0'+(new Date(userInfo?.entryTime).getMonth()+1)}-${(new Date(userInfo?.entryTime).getDate())>10?(new Date(userInfo?.entryTime).getDate()):'0'+(new Date(userInfo?.entryTime).getDate())}`:'-'}</span>
+                    </div>
+
+                  </div>
+                </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;
     }
   }
+
 }

+ 4 - 4
src/pages/personalCenter/components/security.tsx

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2022-03-03 17:42:10
- * @LastEditTime: 2022-03-09 16:45:48
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-21 16:13: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/personalCenter/components/security.tsx
  */
@@ -12,7 +12,7 @@ import KCModal from '@/components/KCModal';
 import { ProFormText } from '@ant-design/pro-form';
 import { Form, Alert, Progress, notification, Modal } from 'antd';
 import PasswordQualityCalculator from 'password-quality-calculator';
-import { editUsers } from '@/service/user';
+import { editUsers, editUsersPsd } from '@/service/user';
 import { useModel } from 'umi';
 
 type Unpacked<T> = T extends (infer U)[] ? U : T;
@@ -95,7 +95,7 @@ const SecurityView: React.FC = () => {
     const userData = localStorage.getItem('userData');
 
     if (userData) {
-      const resp = await editUsers({
+      const resp = await editUsersPsd({
         id: JSON.parse(userData).userId,
         password: newPassword,
       });

+ 135 - 58
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-19 10:09:28
+ * @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
  */
@@ -10,38 +10,81 @@
 import { IRouteComponentProps, useModel, Helmet } from 'umi';
 // import { CrownOutlined, UserOutlined, SmileOutlined } from '@ant-design/icons';
 import ProLayout, { PageContainer } from '@ant-design/pro-layout';
-import { getPlatformMenu } from '@/service/menu';
+import { getPlatformMenu, getSpecifyMenuDetail } from '@/service/menu';
 import './index.less';
 import { TreeItemType } from '@/utils';
 import { SpacicalPageParamsType } from '@/typings';
-import { useState } from 'react';
+import { Key, useEffect, useState } from 'react';
+import IconFont from '@ant-design/icons/lib/components/IconFont';
+import { FileOutlined, FolderOutlined, SmileOutlined } from '@ant-design/icons';
 
 export default function Layout({ children, location, route, history, match, ...rest }: IRouteComponentProps) {
   const { initialState, setInitialState } = useModel('@@initialState');
   const [openKeys, set_openKeys] = useState<string[]>([]);
   const [selectedKeys, set_selectedKeys] = useState<string[]>([]);
+  const [emptyPageContent, set_emptyPageContent] = useState('');
+  const [isShowPageMenu,set_isShowPageMenu] = useState(true);
+  const [isEmpty,set_isEmpty] = useState(false);
+
+  //const isShowMenu = localStorage.getItem('isChildShowMenu');
   // console.log({ children, location, route, history, match});
+
+
+
+  const setEmptyPageContent =async (menuId:Key) => {
+    const menuItem = await getSpecifyMenuDetail(menuId);
+    if(menuItem.isSetupMenu){
+      set_isShowPageMenu(false);
+    }
+    set_emptyPageContent(menuItem.description);
+  }
+
+  useEffect(()=>{
+
+    const isShowMenu = localStorage.getItem('isChildShowMenu');
+    set_isShowPageMenu(isShowMenu == 'true')
+  });
+
+  useEffect(()=>{
+
+    // console.log({location});
+    // console.log(location.query.isEmpty == 'true');
+
+    if(location.query.menuId){
+      setEmptyPageContent(location.query.menuId as string);   
+    } 
+    
+    set_isEmpty(location.query.isEmpty == 'true');
+  },[location])
+
+
   return (
     <ProLayout
       style={{
         height: 'calc(100vh - 50px)',
       }}
+      iconfontUrl="//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js"
       logoStyle={{
         display: 'none',
       }}
       location={{
-            
+
       }}
+      siderWidth={isShowPageMenu? 220 : 0}
+      pageTitleRender={false}
       disableContentMargin
-      menuItemRender={(item, dom) => (
-        <a
-          onClick={() => {
-            history.push(item.path || '/');
-          }}
-        >
-          {dom}
-        </a>
-      )}
+      menuItemRender={(item, dom) => {
+  
+        return (
+          <a
+            onClick={() => {
+              history.push(`${item.path}${item.contentType == '4' ? `?isEmpty=true&menuId=${item.key}` : ''}` || '/');
+            }}
+          >
+            {dom}
+          </a>
+        )
+      }}
       menuProps={{
         openKeys: [...openKeys],
         selectedKeys: [...selectedKeys],
@@ -54,29 +97,34 @@ 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;
-            if (systemId) {
-              const menuData = await getPlatformMenu(systemId);
-
-              if (menuData.length > 0) {
-                set_openKeys([menuData[0].key]);
-                set_selectedKeys([menuData[0].key]);
-              }
+        
+          if (initialState&&initialState.currentSelectedSys) {
+            const {systemId,menuId} = initialState.currentSelectedSys;
+            if (systemId||menuId) {
+              //只有当存在systemId
+              const menuData = await getPlatformMenu(systemId||menuId);
+              let homePage:TreeItemType|undefined;
+      
 
               const getVFromTree = (data: TreeItemType[], key: string) => {
                 let result: SpacicalPageParamsType[] = [];
                 function looper(data: TreeItemType[], key: string) {
                   data.forEach((t) => {
-                    if (t[key] && t[key] != 0) {
+                    if(t.isHomepage){
+                      homePage = t;
+                    }
+                    if (t[key] && t[key] == 1) {
                       //非一般页面
                       result.push({
                         contentType: t[key],
                         path: t['path'],
                         reportId: t['reportId'],
                         url: t['youshuUrl'],
+                        
                       });
                     }
                     if (t.children && t.children.length > 0) {
@@ -90,24 +138,41 @@ export default function Layout({ children, location, route, history, match, ...r
 
               const _menu = getVFromTree(menuData, 'contentType');
 
+              // console.log({_menu});
+
               setInitialState((t) => ({ ...t, spacicalPageParamsType: _menu }));
+              
+              if(homePage){
+                // console.log({homePage});
+                set_openKeys([homePage.key]);
+                set_selectedKeys([homePage.key]); 
+                history.push(homePage.path)
+              }else{
+                set_openKeys([menuData[0].key]);
+                set_selectedKeys([menuData[0].key]);
+                history.push(menuData[0].path)
+              }
+              
+              // console.log({homePage})
+              // return [...menuData, {
+              //   name: 'SQL编辑器',
+              //   path: '/platform/sqlEditer'
+              // }];
+
+              const addIcon = (arr:any) => arr.map((item:any) => (item.children?{
+                ...item,
+                icon: <FolderOutlined />,
+                children: addIcon(item.children)
+              }:{
+                ...item,
+                icon:<FileOutlined />,
+              }))
+               
+              const result = addIcon(menuData);
+
+              return [...result];
+
 
-              return menuData;
-
-              // 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,23 +184,35 @@ export default function Layout({ children, location, route, history, match, ...r
       headerRender={false}
       navTheme="light"
     >
-      <Helmet>
-        <title>精益管理中台</title>
-      </Helmet>
-      <PageContainer
-        className="kcmpPageContainer"
-        header={{
-          title:false,
-        }}
-        style={{
-          margin: 0,
-        }}
-      >
-
-        <div className="page" style={{ height: 'calc(100vh - 98px)', overflowY: 'scroll' }}>
-          {children}
-        </div>
-      </PageContainer>
+      {
+        isEmpty&& (
+          <div className='emptyContainer' style={{ textAlign: 'center', paddingTop: 100 }}>
+            <h1>{emptyPageContent}</h1>
+          </div>
+        )
+      }
+      {
+        !isEmpty&& (
+          <PageContainer
+            className="kcmpPageContainer"
+            header={{
+              title: false,
+            }}
+            style={{
+              margin: 0,
+            }}
+          >
+
+            <Helmet>
+              <title>精益管理中台</title>
+            </Helmet>
+
+            <div className="page" style={{ height: 'calc(100vh - 98px)', overflowY: 'scroll' }}>
+              {children}
+            </div>
+          </PageContainer>
+        )
+      }
     </ProLayout>
   );
 }

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

@@ -0,0 +1,168 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-06 09:31:32
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-12 16:57:30
+ * @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


+ 163 - 151
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-21 15:01: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/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,185 @@ 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 [_selectedKeys,set__selectedKeys] = useState<string[]>([]);
+
+  const [sourceSelectedKeys,set_sourceSelectedKeys] = useState<string[]>([]);
+
+  const onTransFerChange = (keys: string[]) => {
+    let _keys = Array.from(new Set(keys));
+    setTargetKeys(_keys);
+    onChange&&onChange(_keys)
   };
+  
+  interface TreeTransferProps {
+    dataSource: MenuItemDataType[];
+    targetKeys: string[];
+    onChange: (targetKeys: string[], direction: TransferDirection, moveKeys: string[]) => void;
+  }
+  
 
-  const onSearchHandle = (value: string) => {
-    if (value.length == 0) {
-      setDataSource(allMenuData);
-      return;
+  const isChecked = (selectedKeys:(string|number)[], eventKeys: (string|number)[]) => {
+
+    // console.log({selectedKeys,eventKeys});
+
+    const isIncludesFunc = (arr1:(string|number)[],arr2:(string|number)[])=>{
+
+          if(arr2.length == 0){
+            return true;
+          }
+          return arr2.every((item)=>arr1.includes(item))
     }
-    const result = deeper(dataSource, value);
-    console.log({ result });
-    setDataSource(result);
-  };
 
-  const onExpandedRowsChangeHandle = (expandedRows: readonly Key[]) => {
-    setExpandedRowKeys(expandedRows);
-  };
 
-  useEffect(() => {
-    if (dataSource.length > 0) {
-      setSelectedKeys(value); //设置默认选中项
-      setExpandedRowKeys(value); //已选中的项默认展开
+    return isIncludesFunc(selectedKeys,eventKeys)
+  }
+
+
+
+  const generateTree = (treeNodes: MenuItemDataType[] = [], checkedKeys: string[] = []): any[] => {
+
+      return treeNodes.map(({ children,menuId,name, ...props }) => ({
+        key:menuId,
+        title:name,
+        disabled: checkedKeys.includes(menuId as string),
+        children: generateTree(children, checkedKeys),
+        ...props
+      }));
+  
+
+  }
+
+  const onSelectChangeHandle = (_sourceSelectedKeys:Key[], targetSelectedKeys:Key[])=>{
+        console.log({_sourceSelectedKeys,targetSelectedKeys});
+        set_sourceSelectedKeys(_sourceSelectedKeys as string[]);
+        // set_selectedKeysVal(sourceSelectedKeys as string[]);
+        // setTargetKeys(targetSelectedKeys as string[]);
+  }
+    
+
+
+  const TreeTransfer = ({ dataSource, targetKeys, ...restProps }: TreeTransferProps) => {
+
+    const transferDataSource: MenuItemDataType[] = [];
+
+    function flatten(list: MenuItemDataType[] = []) {
+      list.forEach(item => {
+        transferDataSource.push(item as MenuItemDataType);
+        flatten(item.children);
+      });
     }
-    const openresult = getValsFromTree(dataSource, 'menuId');
-    setExpandedRowKeys(openresult);
-  }, [dataSource]);
+
+    flatten(dataSource);
+  
+    return (
+      <Transfer
+        {...restProps}
+        listStyle={{width:100,height:600}}
+        targetKeys={targetKeys}
+        rowKey={record => record.menuId}
+        dataSource={transferDataSource}
+        className="tree-transfer"
+        // onSelectChange={onSelectChangeHandle}
+        // selectedKeys={_selectedKeys}
+        render={item => item.name!}
+        showSelectAll={true}
+      >
+        {({ direction, onItemSelect, selectedKeys,onItemSelectAll }) => {
+          if (direction === 'left') {
+            const checkedKeys = [...selectedKeys, ...targetKeys];
+            return (
+              <Tree
+                blockNode
+                checkable
+                checkStrictly={false}
+                defaultExpandAll
+                height={600}
+
+                checkedKeys={checkedKeys}
+                treeData={generateTree(dataSource, targetKeys)}
+                onCheck={(keys,{node}) => {
+                 
+                  // 差集
+                  let difference = (keys as Key[]).filter(v => !targetKeys.includes(v as string) );
+                  const map = (list:any, cb:any) => {
+                    return list.reduce((res:any, v:any) => {
+                        res.push(cb(v));
+                        if(Array.isArray(v.child)) res = res.concat(map(v.child, cb))
+                        return res;
+                    }, []);
+                  }
+                  
+
+                  if(!node.checked){
+                         //选中
+                         onItemSelectAll(difference as string[],true);
+                  }else{
+                         //取消勾选
+                         const cancelKeys = map(node.children,(v:any)=>v.key);
+                         onItemSelectAll([node.key,...cancelKeys] as string[],false)
+                  }
+                  
+                }}
+                onSelect={(keys, { node: { key } }) => {}}
+              />
+            );
+          }
+        }}
+      </Transfer>
+    );
+  };
+   
+  useEffect(()=>{
+    setTargetKeys(value as string[]);
+  },[value])
 
   useEffect(() => {
     getData();
@@ -159,42 +206,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>
   );
 };

+ 45 - 22
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-08 18:05:52
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/hospManage/index.tsx
  */
@@ -12,7 +12,7 @@ import { hospManageModelState, ConnectProps, Loading, connect } from 'umi';
 import { Button, Divider, Popconfirm } from 'antd';
 import KCTable from '@/components/kcTable';
 import type { ProColumns } from '@ant-design/pro-table';
-import { getAllHosp, getHospYoushuAccounts } from '@/service/hospList';
+import { getAllHosp, getHospYoushuAccounts, hospInit } from '@/service/hospList';
 import { TableRequestParamsType } from '@/typings';
 import ActModal from './modals/modal';
 import './style.less';
@@ -47,40 +47,56 @@ 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,
+      width: 300,
       key: 'option',
       valueType: 'option',
       render: (text, record) => [
@@ -102,10 +118,13 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
         <a key="link3" onClick={() => editMenuBind(record)}>
           菜单
         </a>,
-        <Divider key="2" type="vertical" style={{ margin: '0 1px' }} />,
-        <a key="link3" onClick={() => youshuAccountBind(record)}>
+        <Divider key="3" type="vertical" style={{ margin: '0 1px' }} />,
+        <a key="link4" onClick={() => youshuAccountBind(record)}>
           报告
         </a>,
+        <a key="link5" onClick={() => initHospData(record)}>
+          初始化
+        </a>,
       ],
     },
   ];
@@ -204,6 +223,10 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
     }
   };
 
+  const initHospData = async (record: TableListItem)=>{
+        const resp = await hospInit(record.id);
+  }
+
   return (
     <div className="HospManage">
       <ActModal {...state} dispatch={dispatch} />

+ 115 - 11
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-13 11:23:50
+ * @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 type { AddUsersDataType } from '@/service/user';
+import { getHospList, getHospYoushuAccounts, getMainHosp, YoushuAccountsType } from '@/service/hospList';
+import type { AddUsersDataType, UserRelaSeletDataListType } from '@/service/user';
 import { randomString } from '@/utils';
 import { TableActType } from '..';
 import { Form } from 'antd';
 import MenuEditer from '@/pages/platform/components/menuEditer/menu';
+import { getPlatformDictionary, PlatformPubDirDataType } from '@/service/dictionary';
 
 interface ActModalProps extends hospManageModelState {
   dispatch: Dispatch | undefined;
@@ -32,6 +33,8 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
   const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
   const [dataSource, setDataSource] = useState<DataSourceType[]>([]);
 
+  const [dirData,set_dirData] = useState<PlatformPubDirDataType[]>([]);
+
   const columns: ProColumns<DataSourceType>[] = [
     {
       title: 'id',
@@ -92,7 +95,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
   };
 
   const onFinishHandle = (data: any & AddUsersDataType) => {
-    console.log({ data });
+
     if (tableAct == TableActType.ADD) {
       dispatch &&
         dispatch({
@@ -138,7 +141,13 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
       };
     }
     if (tableAct == TableActType.ADD) {
-      return { hospSign: randomString(16), isDataShare: 0 };
+      return { 
+        hospSign: randomString(16),
+        isDataShare: 0,
+        hospitalLevel:setSelectorData('HOSPITAL_LEVEL').defaultvalue,
+        hospitalType:setSelectorData('HOSPITAL_TYPE').defaultvalue,
+        hospitalNature:setSelectorData('HOSPITAL_NATURE').defaultvalue
+      };
     }
     if (tableAct == TableActType.EDITMENU) {
       return { ...currentEdit };
@@ -151,17 +160,56 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     }
   };
 
+  const getDirecData = async (key?: string) => {
+
+    const data = await getPlatformDictionary();
+    if (data) {
+      set_dirData(data);
+    }
+  }
+
+  const setSelectorData = (key: string) => {
+    let result = dirData.filter((t: any) => (t.code == key));
+
+    if (result.length > 0) {
+      
+      let dataArr = result[0].dataVoList;
+
+      let defaultValue = dataArr.filter(t=>t.defaultValue == 1);
+
+      dataArr.sort((prev:any,next:any)=>{
+        return prev.sort - next.sort;
+      });
+
+      return {
+           defaultvalue:defaultValue[0]?defaultValue[0].value:'',
+           list:dataArr.map(t=>({label:t.code,value:t.value,defaultValue:t.defaultValue}))
+      }
+    }
+    return {
+      defaultvalue:'',
+      list:[]
+    };
+  }
+
+
   useEffect(() => {
     //加装key字段
     const fixedDataSource = currentEdit?.youshuUsers
       ? currentEdit.youshuUsers.map((t) => ({
-          ...t,
-          key: Number((Math.random() * 1000000).toFixed(0)),
-        }))
+        ...t,
+        key: Number((Math.random() * 1000000).toFixed(0)),
+      }))
       : [];
     setDataSource(fixedDataSource);
   }, [currentEdit]);
 
+
+
+  useEffect(()=>{
+    getDirecData();
+  },[])
+
   return (
     <KCModal
       visible={isShowModal}
@@ -248,9 +296,65 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
               }
             }}
           </ProFormDependency>
+          <KCProSelect
+            label="医院等级"
+            width="md"
+            name="hospitalLevel"
+            request={async () => {
+              return setSelectorData('HOSPITAL_LEVEL').list;    
+            }}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+          <KCProSelect
+            label="医院类型"
+            width="md"
+            name="hospitalType"
+            request={async () => {
+              return setSelectorData('HOSPITAL_TYPE').list;
+            }}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+          <KCProSelect
+            label="医院性质"
+            width="md"
+            name="hospitalNature"
+            request={async () => {
+              return setSelectorData('HOSPITAL_NATURE').list;
+            }}
+            rules={[
+              {
+                required: true,
+                message: '请选择!',
+              },
+            ]}
+          />
+
           <ProFormText width="md" name="hospSign" label="医院标识" disabled />
-          <ProFormText width="md" name="hospAbbreviation" label="简称" placeholder="请输入" />
-          <ProFormText width="md" name="systemName" label="系统名称" placeholder="请输入" />
+          <ProFormText width="md" name="hospAbbreviation" label="简称" placeholder="请输入"
+            rules={[
+              {
+                required: true,
+              },
+            ]} />
+          
+          <ProFormText width="md" name="systemName" label="系统名称" placeholder="请输入"
+            rules={[
+              {
+                required: true,
+              },
+            ]}
+          />
+          <ProFormText width="md" name="hospitalCode" label="编码" placeholder="请输入" />
           <ProFormRadio.Group
             name="isDataShare"
             label="是否数据分享"

+ 1108 - 0
src/pages/platform/setting/indicatorMana/DrawerForm/drawer.tsx

@@ -0,0 +1,1108 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-13 15:27:51
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-21 15:26:14
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/indicatorMana/drawer.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import React, { useEffect, useRef, useState } from 'react'
+import { Drawer, Cascader, Button, Form } from 'antd'
+import ProForm, { ProFormCascader, ProFormDependency, ProFormDigit, ProFormInstance, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+
+import './style.less';
+import { getIndicatorDictionary, IndicatorDictionaryDataType } from '@/service/dictionary';
+import { DefaultOptionType } from 'antd/lib/select';
+import { getHospDepartment } from '@/service/department';
+import { getUsers } from '@/service/user';
+import { addIndicatorManaList } from '@/service/indicator';
+
+
+
+export interface IndicatorDrawerForm {
+    visible: boolean;
+    record?: any;
+    onVisibleChange?: (bool: boolean) => void;
+    onFinish?: (formData: any) => void;
+    onChange?: (data: any) => void;
+    actType: 'EDIT' | 'ADD'
+
+}
+
+
+
+const DrawerForm = (props: IndicatorDrawerForm) => {
+
+    const { visible = false, onChange, onFinish, record, onVisibleChange, actType } = props;
+
+    const [_visible, _setVisible] = useState(false);
+
+    const [renderType, set_renderType] = useState<'ADD' | 'EDIT'>('ADD');
+
+    const [dirData, set_dirData] = useState<IndicatorDictionaryDataType[]>([]);
+
+    const baseInfoformRef = useRef<ProFormInstance>();
+    const manaInfoformRef = useRef<ProFormInstance>();
+    const showSetInfoformRef = useRef<ProFormInstance>();
+    const adminInfoformRef = useRef<ProFormInstance>();
+
+    const showDrawer = () => {
+        _setVisible(true);
+        onVisibleChange && onVisibleChange(true);
+    };
+
+    const onClose = () => {
+        _setVisible(false);
+        onVisibleChange && onVisibleChange(false);
+    };
+
+
+    const commitHandle = () => {
+        let commitData: any[] = [];
+        if (baseInfoformRef.current && baseInfoformRef.current.validateFieldsReturnFormatValue) {
+            baseInfoformRef.current?.validateFieldsReturnFormatValue().then(val => {
+                // console.log('baseInfoformRef',val);
+                commitData.push({
+                    baseInfoformRef: val
+                })
+            })
+
+        }
+        if (manaInfoformRef.current && manaInfoformRef.current.validateFieldsReturnFormatValue) {
+            manaInfoformRef.current?.validateFieldsReturnFormatValue().then(val => {
+                console.log('manaInfoformRef', val);
+                //_indicatorTypeList
+                // manaInfoformRef.current?.getFieldsValue();
+                // console.log('w',manaInfoformRef.current?.getFieldValue('_indicatorTypeList'))
+                const _indicatorTypeLists = manaInfoformRef.current?.getFieldValue('_indicatorTypeList');
+                const _indicatorExternalList = manaInfoformRef.current?.getFieldValue('_indicatorExternalList');
+
+                // console.log({_indicatorTypeLists,_indicatorExternalList});
+
+
+                commitData.push({
+                    manaInfoformRef: {
+                        ...val,
+                        indicatorTypeList: _indicatorTypeLists ? _indicatorTypeLists : val.indicatorTypeList ? val.indicatorTypeList.map((t: any) => t[t.length - 1]) : [],
+                        indicatorExternalList: _indicatorExternalList ? _indicatorExternalList : val.indicatorExternalList ? val.indicatorExternalList.map((t: any) => t[t.length - 1]) : [],
+                    }
+                })
+            })
+
+        }
+        if (showSetInfoformRef.current && showSetInfoformRef.current.validateFieldsReturnFormatValue) {
+            showSetInfoformRef.current?.validateFieldsReturnFormatValue().then(val => {
+                // console.log('showSetInfoformRef',val);
+                commitData.push({
+                    showSetInfoformRef: val
+                })
+            })
+
+        }
+        if (adminInfoformRef.current && adminInfoformRef.current.validateFieldsReturnFormatValue) {
+            adminInfoformRef.current?.validateFieldsReturnFormatValue().then(val => {
+
+                const _indicatorMenuList = adminInfoformRef.current?.getFieldValue('_indicatorMenuList');
+                if (val.indicatorMenuList) {
+                    commitData.push({
+                        adminInfoformRef: {
+                            ...val,
+                            indicatorMenuList: _indicatorMenuList ? _indicatorMenuList : val.indicatorMenuList ? val.indicatorMenuList.map((t: any) => t[t.length - 1]) : []
+                        },
+
+                    })
+                }
+            })
+
+        }
+
+        setTimeout(() => {
+            console.log({ commitData });
+            onFinish && onFinish(commitData);
+        }, 1000)
+
+    }
+
+    const getDataFromDir = async () => {
+        const dirData = await getIndicatorDictionary();
+        set_dirData(dirData);
+    }
+
+    const getSelectorData = (code: string, type?: 'Cascader') => {
+        const result = dirData.filter(t => t.code == code);
+
+        if (type == 'Cascader' && result.length > 0) {
+            return result[0].children
+        }
+
+
+        if (result.length > 0) {
+            return result[0].children.map(t => ({ label: t.name, value: t.code }))
+        }
+        return [];
+    }
+
+
+
+    const setFormInit = (key: string) => {
+
+        if (key == 'indicatorTypeList') {
+            if (record && record.indicatorTypeList) {
+                const indicatorTypeListVal = record.indicatorTypeList ? record.indicatorTypeList.map((t: string) => t.split('/')) : [];
+                const _indicatorTypeList = indicatorTypeListVal.map((t: any) => t.slice(1, t.length));
+                // console.log({indicatorTypeListVal,_indicatorTypeList})
+                return _indicatorTypeList
+            }
+        }
+        if (key == 'indicatorMenuList') {
+            if (record && record.indicatorMenuList) {
+                const a = record.indicatorMenuList ? record.indicatorMenuList.map((t: string) => t.split('/')) : [];
+                const b = a.map((t: any) => t.slice(1, t.length));
+                // console.log({a,b})
+                return b
+            }
+        }
+
+        if (key == 'indicatorExternalList') {
+            if (record && record.indicatorExternalList) {
+                const a = record.indicatorExternalList ? record.indicatorExternalList.map((t: string) => t.split('/')) : [];
+                const b = a.map((t: any) => t.slice(1, t.length));
+                // console.log({a,b})
+                return b
+            }
+        }
+    }
+
+
+    useEffect(() => {
+        if (visible) {
+            getDataFromDir();
+        }
+        _setVisible(visible);
+    }, [visible]);
+
+    useEffect(() => {
+        set_renderType(actType);
+    }, [actType]);
+
+
+
+    return (
+        <div >
+            <Drawer
+                className='DrawerForm'
+                width={1000} title={renderType == 'ADD' ? '新增指标' : '管理信息'}
+                placement="right"
+                onClose={onClose}
+                visible={_visible}
+                destroyOnClose
+                footer={
+                    <div>
+                        <Button style={{ marginRight: 20 }} onClick={() => onClose()}>取消</Button>
+                        <Button type="primary" onClick={() => commitHandle()}>确定</Button>
+                    </div>
+                }
+                bodyStyle={{ background: 'rgba(153, 166, 191, 0.1)', padding: 0, scrollbarWidth: 'thin' }}
+            >
+
+                <div className='card'>
+                    <div className='cardTitle' >指标基本信息</div>
+                    <div className='formContent'>
+                        <ProForm
+                            layout={'vertical'}
+                            formRef={baseInfoformRef}
+                            grid={true}
+                            initialValues={renderType == 'ADD' ? { attributeType: 1 } : { ...record }}
+                            rowProps={{
+                                gutter: [16, 16],
+                            }}
+                            submitter={{
+                                render: () => null
+                            }}
+                        >
+
+
+                            <ProFormText colProps={{ md: 12, xl: 8 }} name="name" label="指标名称" placeholder="请输入" fieldProps={{}} rules={[{ required: true, message: '这是必填项' }]} />
+                            <ProFormText colProps={{ md: 12, xl: 8 }} name="code" label="指标编码" placeholder="请输入" rules={[{ required: true, message: '这是必填项' }]} />
+                            <ProFormText colProps={{ md: 12, xl: 8 }} name="nationalCode" label="国家编码" placeholder="请输入" />
+
+
+
+                            <ProFormRadio.Group
+                                name="attributeType"
+                                label="指标属性"
+                                colProps={{ md: 12, xl: 8 }}
+                                options={[
+                                    {
+                                        label: '定性',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '定量',
+                                        value: 2,
+                                    },
+                                ]}
+                            />
+                            <ProFormTextArea colProps={{ md: 12, xl: 8 }}
+                                name="targetDefinition" label="指标定义" placeholder="请输入"
+                                rules={[{ required: true, message: '这是必填项' }]}
+                                fieldProps={{
+                                    allowClear: true,
+                                    autoSize: true
+                                }}
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="dimension"
+                                label="指标维度"
+                                options={[
+                                    {
+                                        label: '结构面',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '过程面',
+                                        value: 2,
+                                    },
+                                    {
+                                        label: '结果面',
+                                        value: 3,
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormDependency name={['attributeType']}>
+                                {
+                                    ({ attributeType }) => {
+                                        if (attributeType == 2) {
+                                            return (
+                                                <>
+                                                    <ProFormSelect
+                                                        colProps={{ md: 12, xl: 8 }}
+                                                        name="directionType"
+                                                        label="管理指向"
+                                                        options={[
+                                                            {
+                                                                label: '正向',
+                                                                value: 1,
+                                                            },
+                                                            {
+                                                                label: '负向',
+                                                                value: 2,
+                                                            },
+                                                            {
+                                                                label: '区间',
+                                                                value: 3,
+                                                            },
+                                                            {
+                                                                label: '监测达标',
+                                                                value: 4,
+                                                            },
+                                                            {
+                                                                label: '监测比较',
+                                                                value: 5,
+                                                            },
+                                                        ]}
+                                                        placeholder="请选择"
+                                                    />
+                                                    <ProForm.Group colProps={{ md: 12, xl: 8 }}>
+                                                        <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
+                                                            <div>
+                                                                <ProFormDigit
+                                                                    label="指标区间"
+                                                                    name="lowerLimit"
+                                                                    min={0}
+                                                                    max={10000}
+                                                                    placeholder='最小值'
+                                                                    fieldProps={{ precision: 3 }}
+                                                                />
+                                                            </div>
+                                                            -
+                                                            <div style={{ position: 'relative', top: 15 }}>
+                                                                <ProFormDigit
+                                                                    name="upperLimit"
+                                                                    min={0}
+                                                                    max={10000}
+                                                                    placeholder='最大值'
+                                                                    fieldProps={{ precision: 3 }}
+                                                                />
+                                                            </div>
+                                                        </div>
+                                                    </ProForm.Group>
+
+                                                    <ProFormSelect
+                                                        colProps={{ md: 12, xl: 8 }}
+                                                        name="unit"
+                                                        label="单位"
+                                                        request={async () => {
+                                                            const dirData = await getIndicatorDictionary();
+                                                            const result = dirData.filter(t => t.code == 'Department');
+
+                                                            if (result.length > 0) {
+                                                                return result[0].children.map(t => ({ label: t.name, value: t.code }))
+                                                            }
+                                                            return []
+                                                        }}
+                                                        placeholder="请选择"
+                                                    />
+
+                                                    <ProFormDependency name={['unit']}>
+                                                        {
+                                                            ({ unit }) => {
+                                                                return (unit == '173' || unit == '326') ? (
+                                                                    <ProForm.Group colProps={{ md: 12, xl: 8 }}>
+                                                                        <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
+                                                                            <div>
+                                                                                <ProFormText name="molecule" label='公式' width={120} placeholder="请输入分子" />
+                                                                            </div>
+
+                                                                            /
+                                                                            <div style={{ position: 'relative', top: 15 }}>
+                                                                                <ProFormText width={120} name="denominator" placeholder="请输入分母" />
+                                                                            </div>
+                                                                            {unit == '173'?`*100%`:`‰`}
+
+                                                                        </div>
+                                                                    </ProForm.Group>
+                                                                ) : (
+                                                                    <ProForm.Group colProps={{ md: 12, xl: 8 }}>
+                                                                        <ProFormText name="molecule" label='公式' placeholder="请输入公式" />
+                                                                    </ProForm.Group>
+                                                                )
+                                                            }
+                                                        }
+                                                    </ProFormDependency>
+
+                                                    <ProFormSelect
+                                                        colProps={{ md: 12, xl: 8 }}
+                                                        name="moleculeSourcType"
+                                                        label="分子数据来源"
+                                                        options={[
+                                                            {
+                                                                label: '定期填报',
+                                                                value: 1,
+                                                            },
+                                                            {
+                                                                label: '表单导入',
+                                                                value: 2,
+                                                            },
+                                                            {
+                                                                label: '系统导入',
+                                                                value: 3,
+                                                            },
+                                                            {
+                                                                label: '异动时填报',
+                                                                value: 4,
+                                                            },
+                                                        ]}
+                                                        placeholder="请选择"
+                                                    />
+                                                    <ProFormSelect
+                                                        colProps={{ md: 12, xl: 8 }}
+                                                        name="denominatorSourceType"
+                                                        label="分母数据来源"
+                                                        options={[
+                                                            {
+                                                                label: '定期填报',
+                                                                value: 1,
+                                                            },
+                                                            {
+                                                                label: '表单导入',
+                                                                value: 2,
+                                                            },
+                                                            {
+                                                                label: '系统导入',
+                                                                value: 3,
+                                                            },
+                                                            {
+                                                                label: '异动时填报',
+                                                                value: 4,
+                                                            },
+                                                        ]}
+                                                        placeholder="请选择"
+                                                    />
+                                                    {/* <ProFormText colProps={{ md: 12, xl: 8 }} name="moleculeSourcDesc" label='分子来源说明' placeholder="请输入" /> */}
+                                                    <ProFormTextArea colProps={{ md: 12, xl: 8 }}
+                                                        name="moleculeSourcDesc" label="分子来源说明" placeholder="请输入"
+                                                        fieldProps={{
+                                                            allowClear: true,
+                                                            autoSize: true
+                                                        }}
+                                                    />
+                                                    {/* <ProFormText colProps={{ md: 12, xl: 8 }} name="denominatorSourceDesc" label='分母来源说明' placeholder="请输入" /> */}
+                                                    <ProFormTextArea colProps={{ md: 12, xl: 8 }}
+                                                        name="denominatorSourceDesc" label="分母来源说明" placeholder="请输入"
+                                                        fieldProps={{
+                                                            allowClear: true,
+                                                            autoSize: true
+                                                        }}
+                                                    />
+
+                                                </>
+                                            )
+                                        }
+                                    }
+                                }
+                            </ProFormDependency>
+                        </ProForm>
+                    </div>
+                </div>
+
+
+                <div className='card'>
+                    <div className='cardTitle' >指标管理信息</div>
+                    <div className='formContent'>
+                        <ProForm
+                            formRef={manaInfoformRef}
+                            layout={'vertical'}
+                            autoFocusFirstInput={false}
+                            grid={true}
+                            initialValues={renderType == 'ADD' ? { indicatorTypeList: [], indicatorExternalList: [] } : {
+                                ...record,
+                                indicatorMenuList: setFormInit('indicatorMenuList'),
+                                // indicatorTypeList:record.indicatorTypeList?record.indicatorTypeList.map((t:string)=>t.split('/')).slice(1,record.indicatorTypeList.map((t:string)=>t.split('/')).length - 1):[],
+                                indicatorTypeList: setFormInit('indicatorTypeList'),
+                                indicatorExternalList: setFormInit('indicatorExternalList'),
+                                // indicatorCommitteeList:record.indicatorCommitteeList[0]?record.indicatorCommitteeList[0].split('/'):[]
+
+                            }}
+                            rowProps={{
+                                gutter: [16, 16],
+                            }}
+                            submitter={{
+                                render: () => null
+                            }}
+                        >
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="divisionId"
+                                label="负责科室"
+                                request={async () => {
+                                    const data = await getHospDepartment();
+                                    return data.map(t => ({ label: t.name, value: t.code }))
+                                }}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="principalId"
+                                label="负责人"
+                                request={async () => {
+                                    const data = await getUsers({ pageSize: 1000, current: 1 });
+                                    return data.list.map(t => ({ label: t.name, value: t.code }))
+                                }}
+                                placeholder="请选择"
+                            />
+                            {/* <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="principalId"
+                                label="负责人"
+                                request={async ()=>{
+                                    const data = await getUsers({pageSize:1000,current:1});
+                                       return data.list.map(t=>({label:t.name,value:t.code}))
+                                }}
+                                placeholder="请选择"
+                            /> */}
+
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="manageLevel"
+                                label="指标管理级别"
+                                fieldProps={{
+                                    // mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={[
+                                    {
+                                        label: '院级指标/日常',
+                                        value: 0,
+                                    },
+                                    {
+                                        label: '院级指标/重点监测',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '科级指标/日常',
+                                        value: 2,
+                                    },
+                                    {
+                                        label: '科级指标/重点监测',
+                                        value: 3,
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="analysisType"
+                                label="分析方式"
+                                options={[
+                                    {
+                                        label: '数值',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '监测比较',
+                                        value: 2,
+                                    },
+                                    {
+                                        label: '目标值达标分析',
+                                        value: 3,
+                                    },
+                                    {
+                                        label: '数值趋势分析',
+                                        value: 4,
+                                    },
+                                    {
+                                        label: '标准差异常分析',
+                                        value: 5,
+                                    },
+                                    {
+                                        label: '四分位数值分析',
+                                        value: 6,
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            {/* <Form.Item  >
+                                    <DiyFormCascader data={getSelectorData('IndicatorType', 'Cascader')} />
+                            </Form.Item> */}
+
+                            <ProFormCascader
+                                colProps={{ md: 12, xl: 8 }}
+                                name="indicatorTypeList"
+                                label="指标类别"
+                                fieldProps={{
+                                    maxTagCount: 'responsive',
+                                    multiple: true,
+                                    showCheckedStrategy: 'SHOW_CHILD',
+                                    fieldNames: { label: 'name', value: 'code', children: 'children' },
+                                    options: getSelectorData('IndicatorType', 'Cascader'),
+                                    onChange(value, selectOptions) {
+                                        console.log({ value, selectOptions });
+
+                                        var nodes: any[] = [];
+
+                                        function parseTreeJson(array: any[]) {
+                                            if (!array) return [];
+                                            for (let index = 0; index < array.length; index++) {
+                                                const element = array[index];
+                                                // 判断element.children是对象
+                                                if (element.children && typeof (element.children) == 'object') {
+                                                    parseTreeJson(element.children)
+                                                } else {
+                                                    // 判断是否为子节点
+                                                    if (!(element.children || typeof (element.children) == 'object')) {
+                                                        // 获得符合的 node
+                                                        nodes.push(element);
+                                                    }
+                                                }
+                                            }
+                                        }
+
+                                        if (value.length > 0) {
+                                            for (let index = 0; index < value.length; index++) {
+
+                                                let current = value[index];
+                                                let key = current[current.length - 1];
+                                                const result = selectOptions[index].filter((t: any) => t.code == key);
+
+                                                if (result[0].children) {
+                                                    //非直接叶子节点
+                                                    parseTreeJson(result[0].children);
+                                                }
+                                                if (!result[0].children) {
+                                                    //直接叶子节点
+                                                    nodes.push({ code: result[0].code })
+                                                }
+
+                                            }
+                                        }
+
+                                        const codes = nodes.map((t) => t.code);
+                                        manaInfoformRef.current?.setFieldsValue({ '_indicatorTypeList': codes });
+                                    },
+                                }}
+
+                            />
+                            <ProFormText
+                                label="管理目标值"
+                                colProps={{ md: 12, xl: 8 }}
+                                name="targetValue"
+                            />
+
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="indicatorDepartmentList"
+                                label="职能科室归属"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={getSelectorData('IndicatorDepartment') as DefaultOptionType[]}
+                                placeholder="请选择"
+                            />
+
+                            <ProFormDigit colProps={{ md: 12, xl: 8 }} name="reference" label="同级参考值" placeholder="请输入" />
+                            {/* <ProFormText colProps={{ md: 12, xl: 8 }} name="referenceDesc" label="参考值来源说明" placeholder="请输入" /> */}
+                            <ProFormTextArea colProps={{ md: 12, xl: 8 }}
+                                name="referenceDesc" label="参考值来源说明" placeholder="请输入"
+                                fieldProps={{
+                                    allowClear: true,
+                                    autoSize: true
+                                }}
+                            />
+
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="indicatorCommitteeList"
+                                label="委员会归属"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={getSelectorData('IndicatorCommittee') as DefaultOptionType[]}
+                                placeholder="请选择"
+                            />
+
+                            <ProFormCascader
+                                colProps={{ md: 12, xl: 8 }}
+                                name="indicatorExternalList"
+                                label="外部指标"
+                                fieldProps={{
+                                    multiple: true,
+                                    maxTagCount: 'responsive',
+                                    fieldNames: { label: 'name', value: 'code', children: 'children' },
+                                    options: getSelectorData('IndicatorExternal', 'Cascader'),
+                                    onChange(value, selectOptions) {
+                                        // console.log({ value, selectOptions });
+
+                                        var nodes: any[] = [];
+
+                                        function parseTreeJson(array: any[]) {
+                                            if (!array) return [];
+                                            for (let index = 0; index < array.length; index++) {
+                                                const element = array[index];
+                                                // 判断element.children是对象
+                                                if (element.children && typeof (element.children) == 'object') {
+                                                    parseTreeJson(element.children)
+                                                } else {
+                                                    // 判断是否为子节点
+                                                    if (!(element.children || typeof (element.children) == 'object')) {
+                                                        // 获得符合的 node
+                                                        nodes.push(element);
+                                                    }
+                                                }
+                                            }
+                                        }
+
+
+                                        if (value.length > 0) {
+                                            for (let index = 0; index < value.length; index++) {
+
+                                                let current = value[index];
+                                                let key = current[current.length - 1];
+                                                const result = selectOptions[index].filter((t: any) => t.code == key);
+                                                console.log({ result });
+                                                if (result[0].children) {
+                                                    //非直接叶子节点
+                                                    parseTreeJson(result[0].children);
+                                                }
+                                                if (!result[0].children) {
+                                                    //直接叶子节点
+                                                    nodes.push({ code: result[0].code })
+                                                }
+
+                                            }
+                                        }
+
+
+                                        const codes = nodes.map((t) => t.code);
+                                        manaInfoformRef.current?.setFieldsValue({ '_indicatorExternalList': codes });
+                                    },
+                                }}
+                            />
+                            {/* <ProFormText colProps={{ md: 12, xl: 8 }} name="remark" label="其他备注" placeholder="请输入" /> */}
+                            <ProFormTextArea colProps={{ md: 12, xl: 8 }}
+                                name="remark" label="其他备注" placeholder="请输入"
+                                fieldProps={{
+                                    allowClear: true,
+                                    autoSize: true
+                                }}
+                            />
+                        </ProForm>
+                    </div>
+                </div>
+
+
+                <div className='card'>
+                    <div className='cardTitle' >指标展示设定</div>
+                    <div className='formContent'>
+                        <ProForm
+                            formRef={showSetInfoformRef}
+                            layout={'vertical'}
+                            grid={true}
+                            autoFocusFirstInput={false}
+                            rowProps={{
+                                gutter: [16, 16],
+                            }}
+                            initialValues={renderType == 'ADD' ? {} : renderType == 'EDIT' && record ? {
+                                ...record,
+                                caseBreakdown: record.caseBreakdown ? record.caseBreakdown.split('/') : [],
+                                chartType: record.chartType ? record.chartType.split('/') : [],
+                                dataDownload: record.dataDownload ? record.dataDownload.split('/') : [],
+                                dataSum: record.dataSum ? record.dataSum.split('/') : [],
+                                drillLevel: record.drillLevel ? record.drillLevel.split('/') : [],
+                            } : {}}
+                            submitter={{
+                                render: () => null
+                            }}
+                        >
+
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="appearDate"
+                                label="呈现期间"
+                                options={[
+                                    {
+                                        label: '年',
+                                        value: '年',
+                                    },
+                                    {
+                                        label: '季',
+                                        value: '季',
+                                    },
+                                    {
+                                        label: '月',
+                                        value: '月',
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="chartType"
+                                label="图表形态"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={[
+                                    {
+                                        label: '统计表',
+                                        value: '统计表',
+                                    },
+                                    {
+                                        label: '直方图',
+                                        value: '直方图',
+                                    },
+                                    {
+                                        label: '趋势图',
+                                        value: '趋势图',
+                                    },
+                                    {
+                                        label: '其他',
+                                        value: '其他',
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="dataSum"
+                                label="数据汇总呈现"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={[
+                                    { label: '全院', value: '全院' },
+                                    { label: '分院', value: '分院' },
+                                ]}
+                                placeholder="请选择"
+                            />
+
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="drillLevel"
+                                label="资料下钻层级"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={[
+                                    {
+                                        label: '全院',
+                                        value: '全院',
+                                    },
+                                    {
+                                        label: '分院区',
+                                        value: '分院区',
+                                    },
+                                    {
+                                        label: '科别',
+                                        value: '科别',
+                                    },
+                                    {
+                                        label: '医师别',
+                                        value: '医师别',
+                                    },
+                                    {
+                                        label: '个案',
+                                        value: '个案',
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="dataDownload"
+                                label="资料下载"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={[
+                                    {
+                                        label: '全院',
+                                        value: '全院',
+                                    },
+                                    {
+                                        label: '分院区',
+                                        value: '分院区',
+                                    },
+                                    {
+                                        label: '科别',
+                                        value: '科别',
+                                    },
+                                    {
+                                        label: '医师别',
+                                        value: '医师别',
+                                    },
+                                    {
+                                        label: '个案数',
+                                        value: '个案数',
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="caseBreakdown"
+                                label="个案明细字段"
+                                fieldProps={{
+                                    mode: 'multiple',
+                                    maxTagCount: 'responsive'
+                                }}
+                                options={[
+                                    {
+                                        label: '看诊科别',
+                                        value: '看诊科别',
+                                    },
+                                    {
+                                        label: '就诊日期',
+                                        value: '就诊日期',
+                                    },
+                                    {
+                                        label: '住院科别',
+                                        value: '住院科别',
+                                    },
+                                    {
+                                        label: '出院科别',
+                                        value: '出院科别',
+                                    },
+                                    {
+                                        label: '病历号',
+                                        value: '病历号',
+                                    },
+                                    {
+                                        label: '住院日期时间',
+                                        value: '住院日期时间',
+                                    },
+                                    {
+                                        label: '转出日期',
+                                        value: '转出日期',
+                                    },
+                                    {
+                                        label: '出院日期时间',
+                                        value: '出院日期时间',
+                                    },
+                                    {
+                                        label: '出院类别',
+                                        value: '出院类别',
+                                    },
+                                    {
+                                        label: '出院诊断码',
+                                        value: '出院诊断码',
+                                    },
+                                    {
+                                        label: '合并症码',
+                                        value: '合并症码',
+                                    },
+                                    {
+                                        label: '死亡原因',
+                                        value: '死亡原因',
+                                    },
+                                    {
+                                        label: '手术代码',
+                                        value: '手术代码',
+                                    },
+                                    {
+                                        label: '其他',
+                                        value: '其他',
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+
+
+                        </ProForm>
+                    </div>
+                </div>
+
+                <div className='card'>
+                    <div className='cardTitle' >管理员维护信息</div>
+                    <div className='formContent'>
+                        <ProForm
+                            formRef={adminInfoformRef}
+                            layout={'vertical'}
+                            grid={true}
+                            autoFocusFirstInput={false}
+                            initialValues={renderType == 'ADD' ? { isPublic: 1 } : renderType == 'EDIT' && record ? {
+                                ...record,
+                                indicatorMenuList: setFormInit('indicatorMenuList'),
+                            } : {}}
+                            rowProps={{
+                                gutter: [16, 16],
+                            }}
+                            submitter={{
+                                render: () => null
+                            }}
+                        >
+
+                            <ProFormCascader
+                                colProps={{ md: 12, xl: 8 }}
+                                name="indicatorMenuList"
+                                label="指标目录"
+                                rules={[{ required: true, message: '这是必填项' }]}
+                                fieldProps={{
+                                    multiple: true,
+                                    fieldNames: { label: 'name', value: 'code' },
+                                    onChange(value: any, selectOptions: any) {
+                                        console.log({ value, selectOptions });
+
+                                        var nodes: any[] = [];
+
+                                        function parseTreeJson(array: any[]) {
+                                            if (!array) return [];
+                                            for (let index = 0; index < array.length; index++) {
+                                                const element = array[index];
+                                                // 判断element.children是对象
+                                                if (element.children && typeof (element.children) == 'object') {
+                                                    parseTreeJson(element.children)
+                                                } else {
+                                                    // 判断是否为子节点
+                                                    if (!(element.children || typeof (element.children) == 'object')) {
+                                                        // 获得符合的 node
+                                                        nodes.push(element);
+                                                    }
+                                                }
+                                            }
+                                        }
+
+                                        if (value.length > 0) {
+                                            for (let index = 0; index < value.length; index++) {
+
+                                                let current = value[index];
+                                                let key = current[current.length - 1];
+                                                const result = selectOptions[index].filter((t: any) => t.code == key);
+                                                // console.log({result});
+                                                if (result[0].children) {
+                                                    //非直接叶子节点
+                                                    parseTreeJson(result[0].children);
+                                                }
+                                                if (!result[0].children) {
+                                                    //直接叶子节点
+                                                    nodes.push({ code: result[0].code })
+                                                }
+
+                                            }
+                                        }
+
+
+                                        const codes = nodes.map((t) => t.code);
+                                        console.log({ codes, nodes });
+                                        adminInfoformRef.current?.setFieldsValue({ '_indicatorMenuList': codes });
+                                    },
+                                }}
+                                request={async () => {
+                                    if (location.search.length > 0) {
+                                        const id = (location.search.split('='))[1];
+                                        if (id) {
+                                            const dirData = await getIndicatorDictionary();
+                                            if (dirData) {
+                                                const result = dirData.filter(t => t.code == id);
+
+                                                if (result.length > 0) {
+                                                    return result[0].children
+                                                }
+                                            }
+                                            return []
+                                        }
+
+                                    }
+
+                                    return []
+                                }}
+                                placeholder="请选择"
+                            />
+
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="isPublic"
+                                label="是否公开"
+                                options={[
+                                    {
+                                        label: '是',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '否',
+                                        value: 0,
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+                            <ProFormSelect
+                                colProps={{ md: 12, xl: 8 }}
+                                name="version"
+                                label="版本"
+                                options={[
+                                    {
+                                        label: '版本1',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '版本2',
+                                        value: 2,
+                                    },
+                                    {
+                                        label: '版本3',
+                                        value: 3,
+                                    },
+                                ]}
+                                placeholder="请选择"
+                            />
+
+                        </ProForm>
+                    </div>
+                </div>
+            </Drawer>
+        </div>
+    )
+}
+
+export default DrawerForm

+ 20 - 0
src/pages/platform/setting/indicatorMana/DrawerForm/style.less

@@ -0,0 +1,20 @@
+
+
+
+.DrawerForm {
+      .card {
+        padding:24px;
+        margin:10px;
+        background: #FFFFFF;
+        border-radius: 4px;
+        .cardTitle {
+            height: 16px;
+            font-size: 16px;
+            font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+            font-weight: 500;
+            color: #17181A;
+            line-height: 16px;
+            margin-bottom: 24px;
+        }
+      }
+}

+ 107 - 0
src/pages/platform/setting/indicatorMana/TreeDirectory/index.tsx

@@ -0,0 +1,107 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-16 14:33:12
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-19 11:23:19
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/indicatorMana/TreeDirectory/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+import { Divider, Tree } from 'antd';
+import { DataNode, DirectoryTreeProps } from 'antd/es/tree';
+import React, { Key, useEffect, useState } from 'react'
+
+import './style.less';
+
+const { DirectoryTree } = Tree;
+
+
+
+
+
+
+
+
+
+const TreeDirectory = ({ data,onSelectChange }: { data: any[];onSelectChange?:(selectedNode:any)=>void }) => {
+
+
+    const [defaultExpandedKeys,set_defaultExpandedKeys] = useState<Key[]>([]);
+    const [defaultSelectedKeys,set_defaultSelectedKeys] = useState<string[]>([]);
+
+
+    const onSelect: DirectoryTreeProps['onSelect'] = (keys, info) => {
+        // console.log('Trigger Select', keys, info);
+        onSelectChange&&onSelectChange(info.node);
+    };
+
+    const onExpand: DirectoryTreeProps['onExpand'] = (keys, info) => {
+        // console.log('Trigger Expand', keys, info);
+        set_defaultExpandedKeys(keys)
+    };
+
+
+    useEffect(()=>{
+
+        const getName:any = (obj:any)=>{
+            let isArr = Array.isArray(obj);
+            let reslut = [];
+            if(isArr){
+                obj.forEach((item: any) => {
+                    reslut.push(...getName(item));
+                });
+            }else{
+                reslut.push(obj.code)
+                if(obj.children){
+                    reslut.push(...getName(obj.children));
+                }
+            }
+            return reslut;
+        }
+
+            
+           if(data.length>0){
+                 const keys = getName(data);               
+                 set_defaultExpandedKeys(keys);
+                 set_defaultSelectedKeys([data[0].children[0].code]);
+                 onSelectChange&&onSelectChange({code:data[0].children[0].code});
+           } 
+    },[data]);
+
+
+    useEffect(()=>{
+           console.log({defaultExpandedKeys});
+    },[defaultExpandedKeys])
+
+
+    return (
+        <div className='TreeDirectory'>
+            {
+                (data.length > 0&&defaultExpandedKeys.length>0) && (
+                    <DirectoryTree
+                        // multiple
+                        blockNode
+                        height={750}
+                        rootStyle={{overflow:'hidden',whiteSpace: 'nowrap', textOverflow: 'ellipsis',width:'100%'}}
+                        fieldNames={{ title: 'name', key: 'code' }}
+                        expandedKeys={defaultExpandedKeys}
+                        // defaultExpandedKeys={defaultExpandedKeys}
+                        defaultSelectedKeys={defaultSelectedKeys}
+                        // expandedKeys={defaultExpandedKeys}
+                        onSelect={onSelect}
+                        onExpand={onExpand}
+                        treeData={data}
+                        // titleRender={(nodeData) => {
+                        //     return (
+                        //         <span style={{ display: 'inline-block', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', width: '70%',height:30 }}>{nodeData.name}</span>
+                        //     )
+                        // }}
+                    />
+                )
+            }
+        </div>
+    )
+}
+
+export default TreeDirectory

+ 0 - 0
src/pages/platform/setting/indicatorMana/TreeDirectory/style.less


+ 453 - 0
src/pages/platform/setting/indicatorMana/index.tsx

@@ -0,0 +1,453 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-12 11:14:21
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-20 10:44:16
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/indicatorMana/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import KCTable from '@/components/kcTable';
+import { ActionType, ProColumns } from '@ant-design/pro-table';
+import React, { useEffect, useRef, useState } from 'react'
+import { Button, Drawer, Popconfirm } from 'antd'
+import Divider from '@ant-design/pro-card/lib/components/Divider';
+import DrawerForm from './DrawerForm/drawer';
+import ProForm from '@ant-design/pro-form/lib/layouts/ProForm';
+import { addIndicatorManaList, delIndicatorManaList, editIndicatorManaList, getIndicatorCateList, getIndicatorManaList, IndicatorManaItemType } from '@/service/indicator';
+import TreeDirectory from './TreeDirectory';
+
+import './style.less';
+import { getIndicatorDictionary, IndicatorDictionaryDataType } from '@/service/dictionary';
+import { useLocation } from 'umi';
+
+
+const IndicatorMana = () => {
+
+  const [reloadTable, set_reloadTable] = useState(false);
+  const [drawerVisible, set_drawerVisible] = useState(false);
+  const [indicateType, set_indicateType] = useState<IndicatorDictionaryDataType[]>([]);
+  const [currentEditRowData, set_currentEditRowData] = useState<any | undefined>(undefined);
+  const [indicatorCateTreeData, set_indicatorCateTreeData] = useState<any[]>([]);
+  const [defaultExpandedRowKeys, set_defaultExpandedRowKeys] = useState<string[]>([]);
+  const [tableData, set_tableData] = useState<any[]>([]);
+  const [cateId, set_cateId] = useState<string>();
+
+
+  const [drawerActype, set_drawerActype] = useState<'ADD' | 'EDIT'>('ADD');
+
+  const indicatorTableRef = useRef<ActionType>();
+
+
+  const columns: ProColumns<any>[] = [
+    {
+      title: '指标名称',
+      dataIndex: 'name',
+      hideInSearch: false,
+      width: '30%',
+      ellipsis: true,
+
+    },
+    // {
+    //   title: '指标编码',
+    //   dataIndex: 'code',
+    //   ellipsis: true,
+    //   render: (text, record) => {
+    //     if (record) {
+    //       const { indicatorBoolean, code } = record;
+    //       return indicatorBoolean ? code : ''
+    //     } else {
+    //       return ''
+    //     }
+
+    //   }
+    // },
+    {
+      title: '指标类别',
+      dataIndex: 'indicatorType',
+      hideInSearch:true,
+      ellipsis: true,
+      hideInTable: true,
+      valueType: 'select',
+      request: async () => {
+        const resp = await getIndicatorDictionary();
+        if (resp) {
+          const data = resp.filter(t => t.code == 'IndicatorType');
+          if (data.length > 0) {
+            return data[0].children.map(t => ({ label: t.name, value: t.code }))
+          }
+        }
+        return []
+      },
+      render: (text, record) => {
+        if (record) {
+          const { indicatorBoolean, indicatorTypeList } = record;
+          return indicatorBoolean && indicatorTypeList ? (indicatorTypeList.map((t: any) => t.name)).join('/') : ''
+        } else {
+          return ''
+        }
+
+      }
+    },
+    {
+      title: '外部指标',
+      dataIndex: 'outsideIndexes',
+      hideInSearch: true,
+      ellipsis: true,
+      hideInTable: true,
+      valueType: 'cascader',
+      fieldProps: {
+        fieldNames: { label: 'name', value: 'code' },
+        placeholder: '请选择'
+      },
+
+      request: async () => {
+        const resp = await getIndicatorDictionary();
+        if (resp) {
+          const data = resp.filter(t => t.code == 'IndicatorExternal');
+          if (data.length > 0) {
+            return data[0].children
+          }
+        }
+        return []
+      },
+      render: (text, record) => {
+        if (record) {
+          const { indicatorBoolean, indicatorExternalList } = record;
+          return indicatorBoolean ? indicatorExternalList ? (indicatorExternalList.map((t: any) => t.name)).join('/') : '-' : ''
+        } else {
+          return ''
+        }
+
+      }
+    },
+    {
+      title: '指标编码',
+      dataIndex: 'code',
+      hideInSearch:true,
+      width: '10%',
+      ellipsis: true,
+
+    },
+    {
+      title: '指标定义',
+      dataIndex: 'targetDefinition',
+      hideInSearch:true,
+      width: '30%',
+      ellipsis: true,
+
+    },
+
+    {
+      title: '操作',
+      width: 200,
+      key: 'option',
+      valueType: 'option',
+      render: (text, record) => {
+
+
+        if (record && record.indicatorBoolean) {
+          return (
+            [
+              <a key="linka" href={record.indicatorPath} target='_blank'>
+                数据展示
+              </a>,
+              <a key="link3" onClick={() => actionHandle('EDIT', record)}>
+                管理信息
+              </a>,
+              <Popconfirm
+                title="是否确定删除?"
+                onConfirm={() => delHandle(record)}
+                okText="确定"
+                cancelText="取消"
+                key="link2"
+              >
+                <a>删除</a>
+              </Popconfirm>,
+            ]
+          )
+        }
+
+        return []
+      }
+      ,
+    },
+  ];
+
+
+  const getIndicatorDir = async () => {
+    const resp = await getIndicatorDictionary();
+    if (resp) {
+      set_indicateType(resp);
+    }
+  }
+
+  const getData = async (params: any) => {
+    const { current = 1, name, indicatorType, outsideIndexes } = params;
+
+    console.log({params});
+    if(cateId){
+      const resp = await getIndicatorManaList({
+        current:1,
+        pageSize:0,
+        menuCode: cateId as string,
+        indicatorName: name,
+        indicatorType: indicatorType,
+        outsideIndexes: outsideIndexes && outsideIndexes.length > 0 ? outsideIndexes[outsideIndexes.length - 1] : ''
+      });
+  
+      if (resp&&resp[0]) {
+  
+        const getName:any = (obj:any)=>{
+
+          let isArr = Array.isArray(obj);
+          let reslut = [];
+          if(isArr){
+              obj.forEach((item: any) => {
+                  reslut.push(...getName(item));
+              });
+          }else{
+              reslut.push(obj.menuId)
+
+              if(obj.children){
+                  reslut.push(...getName(obj.children));
+              }
+          }
+          return reslut;
+        }
+  
+        set_tableData(resp[0].children as unknown as []);
+  
+  
+        set_defaultExpandedRowKeys(getName(resp[0].children));
+  
+        return {
+          data: resp[0].children as unknown as [],
+          success: true,
+          total: 1,
+        };
+      } else {
+        return {
+          data: [],
+          success: true,
+          total: 0,
+        };
+      }
+    }
+
+    return {
+          data: [],
+          success: false,
+          total: 0,
+    }
+    
+  }
+
+
+  const getIndicatorCateTree = async () => {
+    // console.log(location.search);
+    let menuId = '';
+    if (location.search.length > 0) {
+      const searchArr = location.search.split('=');
+      // console.log({ searchArr });
+      if(searchArr[1]){
+        const resp = await getIndicatorCateList({ menuCode: searchArr[1] });
+        if (resp) {
+          set_indicatorCateTreeData(resp);
+        }
+      }
+
+    }
+
+  }
+
+
+
+  const actionHandle = async (key: 'EDIT' | 'DEL', record: IndicatorDictionaryDataType) => {
+    set_currentEditRowData(record);
+    if (key == 'EDIT') {
+      set_drawerActype('EDIT');
+      set_drawerVisible(true);
+    }
+  }
+
+  const addHandle = () => {
+    set_drawerActype('ADD');
+    set_currentEditRowData(undefined);
+    set_drawerVisible(true);
+  }
+
+  const delHandle = async (record: IndicatorDictionaryDataType) => {
+
+    const resp = await delIndicatorManaList({ id: record.id });
+    if (resp) {
+      indicatorTableRef.current?.reload();
+    }
+  }
+
+  const onVisibleChangeHandle = (bool: boolean) => {
+
+    if (!bool) {
+      set_drawerVisible(false);
+    }
+    if (bool) {
+      set_drawerVisible(true);
+    }
+  }
+
+  const drawerFormCommitHanndle = async (data: any) => {
+    // const formData = Object.assign({}, data[0].baseInfoformRef, data[1].manaInfoformRef, data[2].showSetInfoformRef, data[3].adminInfoformRef);
+    //const _formData = {...data[0].baseInfoformRef,...data[1].manaInfoformRef,...data[2].showSetInfoformRef,...data[3].adminInfoformRef}
+  
+    let formData:any;
+    data.forEach((element:any) => {
+         if(element.baseInfoformRef){
+            formData = {...formData,...element.baseInfoformRef}
+         }
+         if(element.manaInfoformRef){
+          formData = {...formData,...element.manaInfoformRef}
+         }
+         if(element.showSetInfoformRef){
+          formData = {...formData,...element.showSetInfoformRef}
+         }
+         if(element.adminInfoformRef){
+          formData = {...formData,...element.adminInfoformRef}
+         }
+    });
+ 
+
+    if (drawerActype == 'ADD') {
+      const resp = await addIndicatorManaList({
+        ...formData,
+        caseBreakdown: formData.caseBreakdown ? formData.caseBreakdown.join('/') : '',
+        dataDownload: formData.dataDownload ? formData.dataDownload.join('/') : '',
+        drillLevel: formData.drillLevel ? formData.drillLevel.join('/') : '',
+        dataSum: formData.dataSum ? formData.dataSum.join('/') : '',
+        chartType: formData.chartType ? formData.chartType.join('/') : '',
+
+        indicatorMenuList: formData.indicatorMenuList ? formData.indicatorMenuList : [],
+        indicatorTypeList: formData.indicatorTypeList ? formData.indicatorTypeList : [],
+        indicatorExternalList: formData.indicatorExternalList ? formData.indicatorExternalList : [],
+        divisionId: `${formData.divisionId}`,
+
+      });
+
+      if (resp) {
+        set_drawerVisible(false);
+        indicatorTableRef.current?.reload();
+      }
+    }
+
+    if (drawerActype == 'EDIT') {
+      const resp = await editIndicatorManaList({
+        ...currentEditRowData,
+        ...formData,
+        caseBreakdown: formData.caseBreakdown ? formData.caseBreakdown.join('/') : '',
+        dataDownload: formData.dataDownload ? formData.dataDownload.join('/') : '',
+        drillLevel: formData.drillLevel ? formData.drillLevel.join('/') : '',
+        dataSum: formData.dataSum ? formData.dataSum.join('/') : '',
+        chartType: formData.chartType ? formData.chartType.join('/') : '',
+      });
+      if (resp) {
+        set_drawerVisible(false);
+        indicatorTableRef.current?.reload();
+      }
+    }
+
+  }
+
+
+  const onSelectChangehandle = (currentSelected: any) => {
+    // console.log({ currentSelected });
+    set_cateId(currentSelected.code);
+  }
+
+  useEffect(() => {
+    if (tableData) {
+      const keys = tableData.map((t: any) => t ? t.code : '');
+ 
+    }
+  }, [tableData]);
+
+
+  useEffect(() => {
+    // console.log({ cateId });
+    // set_reloadTable(true);
+    indicatorTableRef.current?.reload();
+  }, [cateId]);
+
+
+  useEffect(() => {
+    getIndicatorCateTree();
+  }, [location.search]);
+
+
+  useEffect(() => {
+    getIndicatorDir();
+    getIndicatorCateTree();
+  }, [])
+
+  return (
+    <div className='IndicatorMana'>
+      <DrawerForm actType={drawerActype} visible={drawerVisible} onVisibleChange={onVisibleChangeHandle} onFinish={data => drawerFormCommitHanndle(data)} record={currentEditRowData} />
+      <div className='content'>
+        <div className='left'>
+          <TreeDirectory data={indicatorCateTreeData} onSelectChange={(info) => onSelectChangehandle(info)} />
+        </div>
+        <div className='right'>
+          {
+            cateId && (
+              <KCTable
+                className='indicatorTable'
+                rowKey="menuId"
+                headerTitle="指标管理"
+                columns={columns}
+                actionRef={indicatorTableRef}
+                expandable={{
+                      expandedRowKeys:defaultExpandedRowKeys,
+                      onExpand:(expanded, record)=>{
+                              // console.log({expanded, record});
+                              let _expandedKeys = [...defaultExpandedRowKeys];
+                              if(expanded){
+                                _expandedKeys.push(record.menuId)
+                              }else{
+                                const index = _expandedKeys.findIndex(t=>t==`${record.menuId}`);
+                                if(index != -1){
+                                  _expandedKeys.splice(index,1);
+                                }
+                              }
+                              set_defaultExpandedRowKeys([..._expandedKeys]);
+                      }
+
+                }}
+                reload={reloadTable}
+                search={{
+                  span: 8
+                }}
+                tableStyle={{ height: 600, overflow: 'scroll' }}
+                pagination={{pageSize:100}}
+                toolBarRender={() => [
+                  // <Button key="1" onClick={addHandle}>
+                  //   上传
+                  // </Button>,
+                  // <Button key="2" onClick={addHandle}>
+                  //   下载
+                  // </Button>,
+                  <Button key="3" type="primary" onClick={addHandle}>
+                    新增
+                  </Button>,
+                ]}
+                request={(params) => getData(params)}
+              />
+            )
+          }
+        </div>
+      </div>
+
+    </div>
+  )
+}
+
+export default IndicatorMana

+ 37 - 0
src/pages/platform/setting/indicatorMana/style.less

@@ -0,0 +1,37 @@
+
+
+
+.IndicatorMana {
+     .content {
+        display: flex;
+        flex: 1;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items:flex-start;
+
+        .left {
+             position: sticky;
+             top:0px;
+             width:23%;
+             height: 785px;
+             padding: 5px;
+             padding-top: 30px;
+             background-color: #fff;
+        }
+        .right {
+            width: 76%;
+            // overflow-y: hidden;
+            .indicatorTable {
+                  td {
+                       &>span {
+                           &.kcmp-ant-typography-ellipsis {
+                                display:inline;
+                           }
+                       }
+                  }
+            }
+        }
+     }
+
+
+}

+ 106 - 38
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-28 14:49:55
+ * @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,82 @@ 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="link0" onClick={() => editHandle(record)}>
+              编辑
+            </a>,
+            <Divider key="11" 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',display:record.type != 1?'inline':'none' }}  />,
+            <a key="link3" onClick={() => addHandle(record.menuId, record)} style={{display:record.type != 1?'inline':'none'}}>
+              添加
+            </a>,
+            <Divider key="100" type="vertical" style={{ margin: '0 1px' }} />,
+             <a key="link4" onClick={() => moveAndCopy(record)}>
+               复制/移动
+             </a>,
+          ]:[
+            <a key="link12" onClick={() => editHandle(record)}>
+              编辑
+            </a>,
+            <Divider key="10" type="vertical" style={{ margin: '0 1px' }} />,
+            <Popconfirm
+              title="是否确定删除?"
+              onConfirm={() => delHandle(record)}
+              // onCancel={cancel}
+              okText="确定"
+              cancelText="取消"
+              key="link23"
+            >
+              <a>删除</a>
+            </Popconfirm>,
+            <Divider key="2" type="vertical" style={{ margin: '0 1px' }} />,
+            <a key="link5" 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();
@@ -132,24 +178,33 @@ const MenuManage: FC<PageProps> = ({ menuManageModel: state, dispatch }) => {
 
     if (name) {
       //搜索菜单
-      const deeper = (data: MenuItemDataType[], keyword: string) => {
-        let result: MenuItemDataType[] = [];
-
-        data.forEach((t, index) => {
-          if (t.name.includes(keyword)) {
-            result.push({ ...t, children: [] }); //不带出子集
+      let deeper = (data: MenuItemDataType[], keyword: string) => {
+        let newarr:MenuItemDataType[] = [];
+        data.forEach(element => {
+          if (element.name.indexOf(keyword) > -1) { // 判断条件
+            newarr.push(element);
           } else {
-            if (t.children && t.children.length > 0) {
-              result.push({ ...t, children: deeper(t.children, keyword) });
+            if (element.children && element.children.length > 0) {
+            
+            
+              let redata = deeper(element.children,keyword);
+              if (redata && redata.length > 0) {
+                let obj = {
+                  ...element,
+                  children: redata
+                };
+                newarr.push(obj);
+              }
             }
           }
         });
-        return result;
+        return newarr;
       };
+
       return {
         data: resp.list ? deeper(resp.list, name) : [],
         success: true,
-        total: resp.totalCount,
+        total: (deeper(resp.list, name)).length,
       };
     }
 
@@ -160,6 +215,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 +273,7 @@ const MenuManage: FC<PageProps> = ({ menuManageModel: state, dispatch }) => {
         reload={reloadTable}
         toolBarRender={() => [
           <Button key="3" type="primary" onClick={() => addHandle()}>
-            新增主菜单
+            新增中心
           </Button>,
         ]}
         request={(params) => getData(params)}

+ 264 - 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-21 16:56:55
+ * @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, ProFormTextArea } 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) => {
+    console.log({ currentEdit });
     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}
@@ -96,127 +138,231 @@ const ActModal: React.FC<ActModalProps> = ({
       initialValues={
         tableAct == TableActType.EDIT
           ? { ...currentEdit }
-          : { hospSign: randomString(16), isDataShare: 0 }
+          : {
+            hospSign: randomString(16), isDataShare: 0, isHomepage: 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 }) => {
+      {
+        tableAct == TableActType.SET && (
+          <>
+            <ProFormText
+              width="md"
+              name="menuName"
+              label="首页名称"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: false,
+                  message: '请输入名称(可选)',
+                },
+              ]}
+            />
+          </>
+        )
+      }
+      {
+        tableAct == TableActType.MOVEANDCOPY && (
+          <Form.Item name='treeEditer'>
+            <TreeEditer />
+          </Form.Item>
+        )
+      }
+      {
+        (tableAct == TableActType.ADD || tableAct == TableActType.EDIT) && (
+          <>
+            <ProFormText
+              width="md"
+              name="name"
+              label="名称"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: true,
+                  message: '请输入名称!',
+                },
+              ]}
+            />
+            <KCProSelect
+              label="类型"
+              width="md"
+              name="type"
+              options={menuTypeOptionFiler()}
+              rules={[
+                {
+                  required: true,
+                  message: '请选择!',
+                },
+              ]}
+            />
+            <ProFormText
+              width="md"
+              name="url"
+              label="URL"
+              placeholder="请输入"
+              rules={[
+                {
+                  required: false,
+                  message: '请输入!',
+                },
+              ]}
+            />
+
+            <ProFormDependency name={['type', 'contentType']}>
+              {
+                ({ type, contentType }) => {
+                  if (type == 1 && contentType != 4) {
+                    return (
+                      <ProFormText
+                        width="md"
+                        name="path"
+                        label="PATH"
+                        placeholder="请输入"
+                        rules={[
+                          {
+                            required: true,
+                            message: '请输入!',
+                          },
+                        ]}
+                      />
+                    )
+                  } else {
                     return (
-                      contentType &&
-                      contentType != 0 && (
-                        //页面内容为非一般时,填写对应有数Id
-                        <ProFormDigit
-                          label="报告Id"
-                          name="reportId"
-                          min={1}
-                          fieldProps={{ precision: 0 }}
-                          rules={[
-                            {
-                              required: true,
-                              message: '请填写id!',
-                            },
-                          ]}
-                        />
-                      )
-                    );
-                  }}
-                </ProFormDependency>
-              </>
-            )
-          );
-        }}
-      </ProFormDependency>
+                      <ProFormText
+                        width="md"
+                        name="path"
+                        label="PATH"
+                        initialValue={tableAct == TableActType.ADD ? '/platform' : ''}
+                        placeholder="请输入"
+                        rules={[
+                          {
+                            required: false,
+                            message: '请输入!',
+                          },
+                        ]}
+                      />
+                    )
+                  }
+                }
+              }
+            </ProFormDependency>
+            <ProFormDigit
+              label="排序号"
+              name="orderNum"
+              min={0}
+              width="md"
+              max={1000}
+              fieldProps={{ precision: 0 }}
+            />
+            <ProFormText width="md" name="icon" label="icon" placeholder="请输入" />
+            <ProFormDependency name={['type']}>
+              {({ type }) => {
+                return (
+                  type == 1 && (
+                    //类型时菜单时
+                    <>
+                      <KCProSelect
+                        label="内容类型"
+                        width="md"
+                        name="contentType"
+                        initialValue={0}
+                        options={[
+                          {
+                            label: '一般',
+                            value: 0, //普通页面,默认值
+                          },
+                          {
+                            label: '报告',
+                            value: 1,
+                          },
+                          {
+                            label: '大屏',
+                            value: 2,
+                          },
+                          {
+                            label: '填报',
+                            value: 3,
+                          },
+                          {
+                            label: '空白',
+                            value: 4,
+                          },
+                        ]}
+                        rules={[
+                          {
+                            required: true,
+                            message: '请选择!',
+                          },
+                        ]}
+                      />
+                      <ProFormRadio.Group
+                        name="isHomepage"
+                        label="是否为首页"
+                        options={[
+                          {
+                            label: '是',
+                            value: 1,
+                          },
+                          {
+                            label: '否',
+                            value: 0,
+                          },
+                        ]}
+                      />
+
+                      <ProFormDependency name={['contentType']}>
+                        {({ contentType }) => {
+                          return (
+                            contentType &&
+                            contentType != 0 && contentType != 4 && (
+                              //页面内容为非一般时,填写对应有数Id
+                              <ProFormDigit
+                                label="报告Id"
+                                name="reportId"
+                                min={1}
+                                fieldProps={{ precision: 0 }}
+                                rules={[
+                                  {
+                                    required: true,
+                                    message: '请填写id!',
+                                  },
+                                ]}
+                              />
+                            )
+                          );
+                        }}
+                      </ProFormDependency>
+                    </>
+                  )
+                );
+              }}
+            </ProFormDependency>
+            <ProFormDependency name={['contentType']}>
+              {
+                ({ contentType }) => {
+                  if (contentType == 4) {
+                    return (
+                      <ProFormTextArea
+                        name="description"
+                        label="空白页描述"
+                        placeholder="请输入"
+                        fieldProps={{}}
+                      />
+                    )
+                  }
+                }
+              }
+            </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-07 16:23:55
+ * @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});
       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


+ 5 - 4
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-14 08:59:21
+ * @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
  */
@@ -180,7 +180,8 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
 
   return (
     <div className="UserManage">
-      <ActModal {...state} dispatch={dispatch} />
+      <ActModal  {...state} dispatch={dispatch} />
+
       <KCTable
         rowKey="id"
         headerTitle="查询表格"
@@ -190,7 +191,7 @@ const UserManage: FC<PageProps> = ({ userManageModel: state, dispatch }) => {
           <KCUpload
             title="导入数据"
             fieldProps={{
-              onChange: ({ file, fileList }) => {
+              onChange: ({ file, fileList }:{file:any,fileList:any}) => {
                 if (file.status == 'done') {
                   importUserHandle(file.originFileObj);
                 }

+ 262 - 84
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-14 16:27:52
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/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 { getHospList } from '@/service/hospList';
-import type { AddUsersDataType } from '@/service/user';
+import { ProFormDateTimePicker, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+import { getShareHospList } from '@/service/hospList';
+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,231 @@ 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) => {
+    let result = dirData.filter((t: any) => (t.code == key));
+
+    if (result.length > 0) {
+      
+      let dataArr = result[0].dataVoList;
+
+      let defaultValue = dataArr.filter(t=>t.defaultValue == 1);
+
+      dataArr.sort((prev:UserRelaSeletDataListType,next:UserRelaSeletDataListType)=>{
+        return prev.sort - next.sort;
+      });
+
+      // console.log({dataArr,defaultValue});
+
+      return {
+           defaultvalue:defaultValue[0]?defaultValue[0].value:'',
+           list:dataArr.map(t=>({label:t.code,value:t.value}))
+      }
+    }
+    return {
+      defaultvalue:'',
+      list:[]
+    };
+  }
+
+  useEffect(() => {
+    getDirecData();
+  }, [])
 
   return (
     <KCModal
       visible={isShowModal}
       onVisibleChange={onVisibleChangeHandle}
       layout="horizontal"
+      className='ProfileModal'
       initialValues={
-        tableAct == TableActType.EDIT ? { ...currentEditUser } : undefined
+        tableAct == TableActType.EDIT ? { ...currentEditUser } : {
+               //设置当新增时的默认值
+               major:(setSelectorData('PROFESSIONAL_TYPE')).defaultvalue,
+               jobTitle:(setSelectorData('POSITION_TYPE')).defaultvalue,
+               doctorLevel:(setSelectorData('PHYSICIAN_TYPE')).defaultvalue,
+               practiceSubject:setSelectorData('PROCESSIONAL_SUBJECTS_TYPE').defaultvalue,
+               title:setSelectorData('TITLE_TYPE').defaultvalue,
+               practiceCate:setSelectorData('JOB_TYPE').defaultvalue,
+               practiceStatus:setSelectorData('PROFESSIONAL_STATUS_TYPE').defaultvalue
+        }
       }
       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 />}>上传照片</Button>
+                  </Upload>
+                </div>
+                <div className='formItem'>
+                  <KCProSelect
+                    label="院区"
+                    width="md"
+                    name="hospId"
+                    request={async () => {
+                      const hospList = await getShareHospList();
+                      if (hospList) {
+                        return hospList.map((t) => ({
+                          label: t.name,
+                          value: t.id,
+                        }));
+                      }
+                      return [];
+                    }}
+                    rules={[
+                      {
+                        required: true,
+                        message: '请选择院区!',
+                      },
+                    ]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="major"
+                    label="所学专业:"
+                    
+                    options={(setSelectorData('PROFESSIONAL_TYPE')).list}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择专业!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="jobTitle"
+                    label="职务:"
+                    options={setSelectorData('POSITION_TYPE').list}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择职务!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="idCardNum" label="身份证号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="phoneNumber" label="手机号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="qualificationCertificateNo" label="资格证号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="doctorLevel"
+                    label="医师级别:"
+                    options={setSelectorData('PHYSICIAN_TYPE').list}
+                    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="gender"
+                    label="性别:"
+                    options={[
+                      { label: '男', value: 1 },
+                      { label: '女', value: 2 },
+                    ]}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择性别!' }]}
+                  />
+                </div>
+                {/* <div className='formItem'>
+                  <ProFormText name="departmentId" label="科室:" placeholder="请输入" rules={[{ required: true, message: '请选择!' }]} />
+                </div> */}
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="title"
+                    label="职称:"
+                    options={setSelectorData('TITLE_TYPE').list}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择职称!' }]}
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormDateTimePicker name="entryTime" width={282} label="入职时间" placeholder={'请选择日期'} />
+                </div>
+                <div className='formItem'>
+                  <ProFormText name="practiceCertificateNo" label="执业证号:" placeholder="请输入" />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="practiceCate"
+                    label="执业类别:"
+                    options={setSelectorData('JOB_TYPE').list}
+                    placeholder="请选择"
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="practiceStatus"
+                    label="执业状态:"
+                    options={setSelectorData('PROFESSIONAL_STATUS_TYPE').list}
+                    placeholder="请选择"
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="departmentId"
+                    label="科室:"
+                    options={setSelectorData('PRACTICE_DEPARTMENT_TYPE').list}
+                    placeholder="请选择"
+                  />
+                </div>
+                <div className='formItem'>
+                  <ProFormSelect
+                    name="practiceSubject"
+                    label="执业科目:"
+                    options={setSelectorData('PROCESSIONAL_SUBJECTS_TYPE').list}
+                    placeholder="请选择"
+                  />
+                </div>
+              </div>
+            </div>
+
+            <div style={{display:'flex',flexDirection:'row',width:'100%'}}>
+              <div style={{paddingLeft:36,whiteSpace:'nowrap'}}>备注:</div>
+              <ProFormTextArea
+                name="remark"
+                width={877}
+                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%;
+    }
+  }
+}

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

@@ -0,0 +1,98 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-06 15:29:43
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-08 10:25:02
+ * @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, { useRef, useState } from 'react'
+import Editor, { useMonaco } from "@monaco-editor/react";
+
+
+function SQLEditer() {
+
+  const editorRef = useRef(null);
+  const monaco = useMonaco();
+  const [suggestions, set_suggestions] = useState([]);
+  const [currentText, set_currentText] = useState('');
+
+  // const changeModelContent = (e:any) => {
+  //   console.log('内容改变', editorRef.current.getValue());
+
+  // };
+
+  const handleEditorDidMount = (editor: any, monaco: any) => {
+    console.log({ editor, monaco })
+    editorRef.current = editor;
+
+    // editor.onDidChangeModelContent(changeModelContent);
+
+    // this.editor = editor;
+    // this.monaco = monaco;
+    // 注册自定义语言
+    // monaco.languages.register({ id: 'mylan' });
+
+    // 为该语言注册一个语言提示器--联想
+    monaco.languages.registerCompletionItemProvider('sql', {
+      provideCompletionItems: () => {
+        // this.suggestions 根据输入内容的不同发生变化
+        return { suggestions: suggestions };
+      },
+    });
+
+
+  }
+
+  const onChangeHandle = (value: string | undefined, ev: any) => {
+    // console.log({ value, ev });
+    monaco.caretOffset = ev.changes[0].rangeOffset; //获取光标位置
+    fetchSuggestions();
+  }
+
+  const fetchSuggestions = () => {
+
+    let str = currentText.substr(0, monaco.caretOffset + 1);
+
+    let reg = /薪资.$/;
+    if (reg.test(str)) {
+      const suggestions = [{
+        label: '一月工资',
+        insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
+        kind: monaco.languages.CompletionItemKind.Function,
+        insertText: '一月工资',
+        detail: '一月工资',
+      }];
+
+    } else {
+      const suggestions = [
+        {
+          label: 'sum',
+          kind: monaco.languages.CompletionItemKind.Function,
+          insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
+          insertText: 'sum(${1:})',
+          detail: '计算所有参数数值的和',
+        }];
+    }
+    if(editorRef.current){
+      console.log('editorRef.current',editorRef.current)
+      // editorRef.current.trigger('提示', 'editor.action.triggerSuggest', {});
+    }
+    
+  }
+
+  return (
+    <Editor
+      height="60vh"
+      defaultLanguage="sql"
+      defaultValue="// some comment"
+      onChange={onChangeHandle}
+      onMount={handleEditorDidMount}
+    />
+  );
+}
+
+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;
   };
 }

+ 31 - 0
src/service/department.ts

@@ -0,0 +1,31 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-16 10:01:55
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-16 10:12:03
+ * @FilePath: /KC-MiddlePlatform/src/service/department.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+//科室相关
+
+import { request } from 'umi';
+
+//获取医院科室
+
+export type DepartmentItemType = {
+      id:number;
+      hospId:string;
+      code:string;//科室代码
+      name:string;
+      parentId:number;
+      computeId:number;
+      delFlag:number;
+}
+export const getHospDepartment = async () => {
+    return request<DepartmentItemType[]>('/master/centerSys/sysdepartment/getDepartmentUser', {
+      method: 'GET',
+    });
+};

+ 41 - 0
src/service/dictionary.ts

@@ -0,0 +1,41 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-06 11:46:24
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-15 16:13:42
+ * @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 type PlatformPubDirDataType = { code: string; value: string | number; dataVoList: { code: string; value: string | number; sort: number; defaultValue: number }[] }
+
+export const getPlatformDictionary = async (key?: string) => {
+  return request<PlatformPubDirDataType[]>('/master/centerSys/sysdictdata/getDictData', {
+    method: 'GET',
+    params: { dictType: key },
+  });
+};
+
+
+//获取指标相关字典
+export type IndicatorDictionaryDataType = {
+  type:number;
+  status:string;
+  parentId:number;
+  name:string;
+  id:number;
+  dictSort:number;
+  code:string;
+  children:IndicatorDictionaryDataType[]
+}
+export const getIndicatorDictionary = async () => {
+  return request<IndicatorDictionaryDataType[]>('/master/centerSys/indicator/getDict', {
+    method: 'GET',
+  });
+};

+ 26 - 4
src/service/hospList.ts

@@ -1,16 +1,17 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 09:15:59
- * @LastEditTime: 2022-03-02 17:16:06
- * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-07-08 18:11:11
+ * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/service/hospList.ts
  */
 
+import { Key } from 'react';
 import { request } from 'umi';
 
 //获取当前登陆院区以及互通的院区列表
-export const getHospList = async () => {
+export const getShareHospList = async () => {
   return request<
     {
       id: number;
@@ -21,12 +22,25 @@ export const getHospList = async () => {
   });
 };
 
+
+//获取所有院区
+export const getHospList = async () => {
+  return request<
+    {
+      id: number;
+      name: string;
+    }[]
+  >('/master/centerSys/hospital/getAllMainList', {
+    method: 'GET',
+  });
+};
+
 //获取主院
 export const getMainHosp = async () => {
   return request<{
     id: number;
     name: string;
-  }>('/master/centerSys/hospital/getMainList', {
+  }[]>('/master/centerSys/hospital/getMainList', {
     method: 'GET',
   });
 };
@@ -153,3 +167,11 @@ export const hospBindYoushuAccount = async (data: HospBindYoushuAccountReqBodyTy
     data: data,
   });
 };
+
+//院区初始化
+export const hospInit = async (hospId:Key) => {
+  return request('/master/centerSys/role/init', {
+    method: 'POST',
+    params:{hospId},
+  });
+};

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

+ 67 - 0
src/service/indicator.ts

@@ -0,0 +1,67 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-07-15 10:13:10
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2022-07-18 22:13:36
+ * @FilePath: /KC-MiddlePlatform/src/service/indicator.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+import { request } from 'umi';
+
+//获取指标列表
+
+export type IndicatorManaItemType = {
+    [x: string]: any;
+    current: number;
+    pageSize: number;
+    totalCount: number;
+    totalPage: number;
+    list?: any[];
+}
+export const getIndicatorManaList = async (params: {
+    current: number;
+    pageSize: number;
+    menuCode:string;
+    [key:string]:any;
+  }) => {
+    return request<IndicatorManaItemType>('/master/centerSys/indicator/getIndicatorList', {
+      method: 'GET',
+      params:{...params,pageSize:100}
+    });
+};
+
+//添加指标信息
+export const addIndicatorManaList = async (data:any) => {
+  return request('/master/centerSys/indicator/addIndicator', {
+    method: 'POST',
+    data:data
+  });
+};
+
+//编辑指标信息
+export const editIndicatorManaList = async (data:any) => {
+  return request('/master/centerSys/indicator/editIndicator', {
+    method: 'POST',
+    data:data
+  });
+};
+
+
+//删除指标
+export const delIndicatorManaList = async (params:{id:number}) => {
+  return request('/master/centerSys/indicator/deleteIndicator', {
+    method: 'POST',
+    params:params
+  });
+};
+
+//获取指标目录
+
+export const getIndicatorCateList = async (params?:{menuCode:string}) => {
+  return request<any[]>('/master/centerSys/indicator/getIndicatorMenu', {
+    method: 'GET',
+    params:params
+  });
+};

+ 105 - 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-11 16:59:28
+ * @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?:Key) => {
   return request('/master/centerSys/user/getMenuNav', {
     method: 'GET',
     params: { systemId },
@@ -30,7 +31,13 @@ export interface MenuItemDataType {
   softUrl?: string;
   type: number;
   url?: string;
+  key?:string;
+  contentType:string;
+  systemId?:string;
+  isHomepage:number;
+  description:string;
   modifyTime: string;
+  isSetupMenu?:number;
   children: MenuItemDataType[];
 }
 
@@ -48,6 +55,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 = {
@@ -59,6 +74,7 @@ export type AddMenuDataType = {
   perms?: string;
   softUrl?: string;
   type: number;
+  contentType:string;
   url?: string;
 };
 
@@ -81,6 +97,7 @@ export type EditMenuDataType = {
   perms?: string;
   softUrl?: string;
   type: number;
+  contentType:string;
   url?: string;
 };
 
@@ -109,3 +126,88 @@ export const getSpacifyHospMenu = async (data: { hospId: number }) => {
     params: data,
   });
 };
+
+
+//获取用户在平台中所拥有的导航菜单
+
+export type UserPlatformNav = {
+  menuId:string|number;
+  name:string;
+  type:number;
+  path:string;
+  systemId:string;
+  contentType: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},
+    });   
+  }
+
+}
+
+//通过ID获取指定菜单的详情
+
+export const getSpecifyMenuDetail = async (menuId:Key) => {
+  return request<MenuItemDataType>('/master/centerSys/menu/getMenuDetail', {
+    method: 'GET',
+    params:{menuId}
+  });   
+
+}

+ 1 - 0
src/service/role.ts

@@ -13,6 +13,7 @@ import { request } from 'umi';
 //获取所有角色
 
 export type RoleItemType = {
+  allUsers: any;
   roleId: number;
   roleName: string;
   hospName: string;

+ 36 - 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-21 16:11:55
+ * @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
  */
@@ -74,6 +74,17 @@ export const delUsers = async (data: number[]) => {
   });
 };
 
+
+//修改用户密码
+export const editUsersPsd = async (params:{id:number,password:string}) => {
+  return request('/master/centerSys/user/updatePassword', {
+    method: 'POST',
+    params:params
+  });
+};
+
+
+//获取用户模板
 export const getUsertemplate = async () => {
   return request<string>('/master/centerSys/pfmfiledata/getUserTemplateFileUrl', {
     method: 'GET',
@@ -110,3 +121,26 @@ export const getYoushuUsers = async () => {
     method: 'GET',
   });
 };
+
+
+//获取用户相关的字典表
+
+export type UserRelaSeletDataListType = {
+      code:string;
+      value:string;
+      sort:number;
+      defaultValue:number;
+}
+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;
 };