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

调整院区管理的菜单及权限绑定

code4eat 2 éve
szülő
commit
9094955045

+ 3 - 2
config/config.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:04:20
- * @LastEditTime: 2023-06-13 14:39:01
+ * @LastEditTime: 2023-07-10 13:44:38
  * @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
@@ -31,7 +31,8 @@ export default defineConfig({
   },
   lessLoader: {
     modifyVars: { '@ant-prefix': 'kcmp-ant', 'root-entry-name': 'default' },
-  }, //
+  }, 
+ 
   theme: {
     '@primary-color': '#3376FE',
     '@primary-color-hover': '#3376FE',

+ 1 - 1
config/proxy.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-07 10:00:52
- * @LastEditTime: 2023-06-25 10:45:30
+ * @LastEditTime: 2023-08-17 18:36:44
  * @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

+ 4 - 5
src/app.tsx

@@ -255,13 +255,13 @@ export const qiankun = fetch('/config').then(() => ({
     // },
     {
       name: 'reviewMana', // 唯一 id
-      //entry: '//120.27.235.181:5000/pfmview/',
-      entry: '//localhost:8804',  //本地调试
+      entry: '//120.27.235.181:5000/pfmview/',
+      //entry: '//localhost:8804',  //本地调试
     },
     {
       name: 'budgetManaSystem', // 唯一 id
-      entry: '//localhost:8001',
-      //entry: '//120.27.235.181:5000/perform/',  //开发
+      //entry: '//localhost:8001',
+      entry: '//120.27.235.181:5000/perform/',  //开发
       //entry: '//47.96.149.190:5000/perform/', //演示
     },
     {
@@ -334,7 +334,6 @@ export function patchRoutes({ routes }: { routes: any }) {
 
 
 
-
 export const layout = ({ initialState: { userData } }: { initialState: InitialStateType }): BasicLayoutProps => {
   return {
     headerRender: false,

+ 58 - 18
src/components/NavSelecter/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-06-29 11:05:04
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2022-07-14 15:37:31
+ * @LastEditTime: 2023-08-17 09:39:08
  * @FilePath: /KC-MiddlePlatform/src/components/NavSelecter/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -11,8 +11,9 @@
 
 
 import { Tabs, Checkbox, Button } from 'antd';
-import React, { useEffect, useState } from 'react';
+import React, { Key, useEffect, useState } from 'react';
 import './style.less';
+import { findNodesBySomes, getLeafNodes } from '@/utils';
 
 const { TabPane } = Tabs;
 
@@ -39,23 +40,25 @@ export type NavSelecterData = {
 export interface NavSelecter {
     onVisibleChange?: (t: boolean) => void;
     onChecked?: (t: NavSelecterItemType[]) => void;
-    value?: NavSelecterItemType[];
+    value?: Key[];
     data?: NavSelecterData[];
+    title?: string,
 }
 
 const NavSelecter = (props: NavSelecter) => {
 
-    const { onVisibleChange, data, value = [], onChecked } = props;
+    const { onVisibleChange, data, value = [], onChecked, title } = props;
     const [checkedIds, set_checkedIds] = useState<(string | number)[]>([]);
     const [checkedItems, set_checkedItems] = useState<NavSelecterItemType[]>([]);
 
 
     const onChange = (tab: NavSelecterItemType) => {
-
-        let _checkedIds = checkedIds;
+        
+        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]);
@@ -70,7 +73,6 @@ const NavSelecter = (props: NavSelecter) => {
     };
 
     const onMaskClick = (e: React.MouseEvent) => {
-
         onVisibleChange && onVisibleChange(false);
     }
 
@@ -84,17 +86,52 @@ const NavSelecter = (props: NavSelecter) => {
         set_checkedIds([]);
     }
 
+    const checkAllHandle = (e: any) => {
+
+        let all: any[] = [];
+
+        if (e.target.checked) {
+            data?.forEach((item) => {
+                const _result = getLeafNodes({ child: item.child });
+                all = [...all, ..._result]
+            });
+            set_checkedItems([...all]);
+            set_checkedIds(all.map(a => a.menuId));
+        } else {
+            set_checkedItems([]);
+            set_checkedIds([]);
+        }
+
+    }
+
     useEffect(() => {
+        if (data) {
+          
+            let result: any[] = [];
+
+            for (let tree of data) {
+                const node = findNodesBySomes(tree,new Set(checkedIds),'menuId');
+                if (node) {
+                    result = result.concat([...node]);
+                }
+            }
+            set_checkedItems(result);
+    
+        }
+    }, [checkedIds]);
 
-        set_checkedIds(value?.map(t => t.menuId));
-        set_checkedItems(value);
+    useEffect(() => {
 
+        set_checkedIds(value);
+        
     }, [value]);
 
 
+
     return (
         <div className="navSelecter" onClick={(e) => onMaskClick(e)}>
             <div className='container'>
+                <div className='selecterTitle'>{title}</div>
                 <div className='closeBtn' onClick={(e) => onMaskClick(e)}>
                     <img src={require('./images/close.png')} />
                 </div>
@@ -104,9 +141,9 @@ const NavSelecter = (props: NavSelecter) => {
 
                             {
                                 data?.map((val) => (
-                                    
-                                        <TabPane tab={val.name} key={val.menuId}>
-                                            <div className='contentInner'>
+
+                                    <TabPane tab={`${val.name}(${(getLeafNodes({ child: val.child })).length})`} key={val.menuId}>
+                                        <div className='contentInner'>
                                             {
                                                 val.child?.map((item) => (
                                                     <div className='row' key={item.menuId}>
@@ -134,9 +171,9 @@ const NavSelecter = (props: NavSelecter) => {
                                                     </div>
                                                 ))
                                             }
-                                            </div>
-                                        </TabPane>
-                                    
+                                        </div>
+                                    </TabPane>
+
                                 ))
                             }
 
@@ -144,10 +181,13 @@ const NavSelecter = (props: NavSelecter) => {
                     </div>
                 </div>
                 <div className='footer' onClick={e => e.stopPropagation()}>
-                    <span className='count'>{`已选中${checkedIds.length}项`}</span>
+                    <span className='count'>
+                        <Checkbox onChange={(e) => checkAllHandle(e)}>全部开启 </Checkbox>
+                        {`已选中${checkedItems.length}项`}
+                    </span>
                     <div className='btnGroup'>
-                        <Button style={{ marginRight: 8 }} onClick={onReset}>重置</Button>
-                        <Button type="primary" onClick={onCommit}>确定</Button>
+                        <Button className='resetBtn btn' style={{ marginRight: 8 }} onClick={onReset}>重置</Button>
+                        <Button className='confirmBtn btn' type="primary" onClick={onCommit}>确定</Button>
                     </div>
                 </div>
             </div>

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

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

+ 5 - 1
src/global.less

@@ -3,7 +3,11 @@
   padding: 0;
 }
 
-
+body {
+  margin: 0;
+  height: 100%;
+  zoom: unset !important;
+}
 
 input {
   outline: none !important;

+ 3 - 6
src/pages/index/components/FastEntry/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-05-27 14:17:59
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-07 15:56:31
+ * @LastEditTime: 2023-08-16 16:15:34
  * @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
  */
@@ -46,13 +46,10 @@ export const FastEntry = (props: FastEntryType) => {
         history.push(tab.path)
     }
 
-    
-
     const getNavData =async () => {
           
         const navData = await getUserPlatformNav();
-        
-        set_navSelecterData(navData)
+        set_navSelecterData(navData);
     }
 
     const onCheckedHandle = async (data:NavSelecterItemType[])=>{
@@ -166,7 +163,7 @@ export const FastEntry = (props: FastEntryType) => {
             
             {
                 open&&(
-                     <NavSelecter data={navSelecterData} onVisibleChange={(bool)=>set_open(bool)} value={tabs} onChecked={onCheckedHandle} />
+                     <NavSelecter title='选择应用' data={navSelecterData} onVisibleChange={(bool)=>set_open(bool)} value={tabs.map((a)=>a.menuId)} onChecked={onCheckedHandle} />
                 )
             }
 

+ 36 - 24
src/pages/platform/_layout.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-06 15:25:39
- * @LastEditTime: 2023-06-27 13:53:57
+ * @LastEditTime: 2023-08-07 13:26:58
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/_layout.tsx
@@ -13,11 +13,10 @@ import ProLayout, { PageContainer } from '@ant-design/pro-layout';
 import { getPlatformMenu, getSpecifyMenuDetail } from '@/service/menu';
 import './index.less';
 import { TreeItemType } from '@/utils';
-import { Iframe, SpacicalPageParamsType } from '@/typings';
+import { SpacicalPageParamsType } from '@/typings';
 import { Key, useEffect, useState } from 'react';
-import IconFont from '@ant-design/icons/lib/components/IconFont';
-import { FileOutlined, FolderOutlined, SmileOutlined } from '@ant-design/icons';
-import { getParamsManaTableData } from './setting/paramsMana/service';
+
+import { FileOutlined, FolderOutlined } from '@ant-design/icons';
 import { getAllParams } from '@/service';
 
 export default function Layout({ children, location, route, history, match, ...rest }: IRouteComponentProps) {
@@ -29,9 +28,7 @@ export default function Layout({ children, location, route, history, match, ...r
   const [isEmpty, set_isEmpty] = useState(false);
 
   const [pageUrl, set_pageUrl] = useState<string | undefined>(undefined);
-
-
-
+  
   const { pathname } = location;
 
   const setEmptyPageContent = async (menuId: Key) => {
@@ -53,7 +50,6 @@ export default function Layout({ children, location, route, history, match, ...r
     if (location.query.menuId) {
       setEmptyPageContent(location.query.menuId as string);
     }
-
     set_isEmpty(location.query.isEmpty == 'true');
   }, [location]);
 
@@ -67,7 +63,7 @@ export default function Layout({ children, location, route, history, match, ...r
   }
 
   //临时演示处理
-  console.log('location.pathname',location.pathname);
+  
   if (location.pathname == '/platform/costMana') {
 
     //临时解决未嵌入成本核算,而实现访问的效果
@@ -92,27 +88,43 @@ export default function Layout({ children, location, route, history, match, ...r
       </>
     )
   }
-  if (location.pathname == '/platform/baokangCostApp') {
 
-    //临时解决未嵌入成本核算,而实现访问的效果
+  if (location.pathname == '/platform/Budget') {
 
-    // const getToken = async () => {
-    //   // const resp = await getAllParams();
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=budget/index`;
 
-    //   // if (resp) {
-    //   //   const needItem = resp.filter((a: any) => a.code == '1647777324889935872');
+    return (
+      <>
+        {pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()} ></iframe>};
+      </>
+    )
+  }
 
-    //   //   if (needItem.length > 0) {
-    //   //     set_pageUrl(`http://47.96.149.190:8000/platformMana/roleManage?hospSign=dOBHdoPmJgPGnMSH&token=${needItem[0].value}`)
-    //   //   }
-    //   // }
+  if (location.pathname == '/platform/DRG') {
 
-    //   set_pageUrl(`http://www.baidu.com`)
-    // }
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=drgs/index`;
+
+    return (
+      <>
+        {pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()} ></iframe>};
+      </>
+    )
+  }
+
+  if (location.pathname == '/platform/DIP') {
+
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=dips/index`;
 
-    // getToken();
+    return (
+      <>
+        {pageUrl && <iframe id={'bi_iframe'} style={{ width: '100%', height: '100%', border: 'none' }} src={pageUrl} onLoad={() => adjustIframe()} ></iframe>};
+      </>
+    )
+  }
+  
+  if (location.pathname == '/platform/baokangCostApp') {
 
-    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=cost/index`;
+    const pageUrl = `https://test.baokangyiguan.com/index/apiLogin?username=admin&url=cost/index `;
 
     return (
       <>

+ 2 - 3
src/pages/platform/components/TreeEditer/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-07-06 09:31:32
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-01-05 09:19:27
+ * @LastEditTime: 2023-08-10 15:21:18
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/components/TreeEditer/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -61,9 +61,7 @@ function TreeEditer(props: TreeEditerPropsType) {
 
     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[]) => {
@@ -118,6 +116,7 @@ function TreeEditer(props: TreeEditerPropsType) {
             convertData(data)
             setExpandedKeys(Array.from(new Set(expandedKeys)));
             set_treeData(data);
+            console.log({resp});
         }
 
     }

+ 229 - 61
src/pages/platform/setting/hospManage/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 15:22:48
- * @LastEditTime: 2023-06-08 14:20:08
+ * @LastEditTime: 2023-08-18 19:06:08
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/hospManage/index.tsx
@@ -9,7 +9,7 @@
 
 import { FC, Key, useEffect, useMemo, useState } from 'react';
 import { hospManageModelState, ConnectProps, Loading, connect } from 'umi';
-import { Button, Checkbox, Divider, Drawer, Dropdown, Input, Popconfirm, Switch, Table, Tree, TreeProps } from 'antd';
+import { Button, Checkbox, Divider, Drawer, Dropdown, Input, Popconfirm, Switch, Table, Tree, TreeProps, message } from 'antd';
 import KCTable from '@/components/kcTable';
 import type { ProColumns } from '@ant-design/pro-table';
 import { getAllHosp, getHospOwnSys, getHospYoushuAccounts, getMenuRelaPerm, hospInit, saveHospMenuApiPerm, setReadOnly } from '@/service/hospList';
@@ -22,12 +22,14 @@ import { KCInput } from '@/components/KCInput';
 import { createFromIconfontCN, DownOutlined } from '@ant-design/icons';
 import { DrawerForm } from '@ant-design/pro-form';
 import { DataNode } from 'antd/es/tree';
-import { getTreeDataRespType } from '../systemNavMana/service';
+import { getTableDataRequest, getTreeDataRespType } from '../systemNavMana/service';
 
 import expandedIcon from '../../../../../public/images/treenode_open.png';
 import closeIcon from '../../../../../public/images/treenode_collapse.png';
 import { getDeepestTreeData, uniqueFunc } from '@/utils';
 import { CheckboxValueType } from 'antd/lib/checkbox/Group';
+import NavSelecter, { NavSelecterData, NavSelecterItemType } from '@/components/NavSelecter';
+import { FastEntryTabType } from '@/pages/index/components/FastEntry';
 
 export enum TableActType {
   NOACT,
@@ -50,6 +52,47 @@ interface PageProps extends ConnectProps {
 }
 
 
+interface TreeNode {
+  [key:string]:any;
+  children?: TreeNode[];
+}
+
+function findParents(
+  nodes: TreeNode[], 
+  targetId: string, 
+  path: TreeNode[] = []
+): TreeNode[] | null {
+  for (const node of nodes) {
+    if (node.menuId === targetId) {
+      return path;
+    }
+
+    if (node.children) {
+      const result = findParents(node.children, targetId, [...path, node]);
+      if (result) return result;
+    }
+  }
+
+  return null;
+}
+
+function extractAttributeValues(tree: TreeNode, attributeName: keyof TreeNode): any[] {
+  let values: any[] = [];
+
+  // 提取当前节点的属性值
+  values.push(tree[attributeName]);
+
+  // 如果当前节点有子节点,递归处理每个子节点
+  if (tree.children) {
+    for (const child of tree.children) {
+      values = values.concat(extractAttributeValues(child, attributeName));
+    }
+  }
+
+  return values;
+}
+
+
 
 const DrawerActBtn = ({ record }: { record: any }) => {
 
@@ -68,8 +111,14 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
   const [oldSelectedMenuIds, set_oldSelectedMenuIds] = useState<any[]>([]);
 
+  const [checkedMenuParentsIds,set_checkedMenuParentsIds] = useState<Key[]>([]);  //所有需要保存的菜单id
+
   const [drawerVisible, set_drawerVisible] = useState(false);
 
+  const [ifFrozze, set_ifFrozze] = useState(false); //冻结勾选菜单及功能操作
+
+  const [hospAllMenuTree,set_hospAllMenuTree] = useState<any[]>([]);  //医院全量菜单
+
   const columnsData: ProColumns<TableListItem>[] = [
     {
       title: '名称',
@@ -116,16 +165,15 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           const options = record.functionList.map((item: any, index: number) => ({ label: item.name, value: item.code }))
 
           const needItem = checkBoxCodes.filter(a => a.menuId == record.menuId);
-
-          const codes = needItem && needItem.length > 0 ? needItem[0].function.map((a: any) => a.code) : [];
+          
+          const codes = (needItem && needItem.length > 0 && needItem[0].function) ? needItem[0].function.map((a: any) => a.code) : [];
 
           const onCheckGroupChange = (checkedValue: CheckboxValueType[]) => {
 
             if (checkedValue.length > 0) {
-              const _temp = checkBoxCodes;
-              const index = checkBoxCodes.findIndex((item) => item.menuId == record.menuId);
-
 
+              const _temp = [...checkBoxCodes];
+              const index = checkBoxCodes.findIndex((item) => item.menuId == record.menuId);
               const needed = options.filter((item: any) => checkedValue.includes(item.value));
               const transfered = needed.map((item: any) => ({ name: item.label, code: item.value }));
 
@@ -151,8 +199,8 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
               _temp.splice(index, 1);
 
-              const menuIdsArr = _temp.map((item: any) => item.menuId);
-              set_checkedTableMenuIds([...menuIdsArr])
+              // const menuIdsArr = _temp.map((item: any) => item.menuId);
+              // set_checkedTableMenuIds([...menuIdsArr])
               set_checkBoxCodes([..._temp]);
 
             }
@@ -164,6 +212,7 @@ const DrawerActBtn = ({ record }: { record: any }) => {
             <Checkbox.Group
               options={options}
               value={codes}
+              disabled={ifFrozze}
               onChange={checkedValue => onCheckGroupChange(checkedValue)}
             />
           )
@@ -175,7 +224,7 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   ];
 
   const getTreeReqFunc = async (hospId: string) => {
-    if(hospId){
+    if (hospId) {
       const resp = await getHospOwnSys(hospId);
       set_treeData(resp);
     }
@@ -242,18 +291,18 @@ const DrawerActBtn = ({ record }: { record: any }) => {
   generateList(treeData as any);
 
 
-  const getTableData = async (params: any, sort: any, filter: any) => {
+  const setInitCheckData = async () => {
 
     set_drawerTablereload(false);
     if (currentSelectedTreeNode) {
-      const resp = await getMenuRelaPerm({ ...params, hospId: record.id });
+      const resp = await getMenuRelaPerm({hospId: record.id,systemId:currentSelectedTreeNode.code});
       if (resp) {
         let temp: { menuId: any; function: any; }[] = [];
         const setTreeRecursion = (data: any) => {
           data.map((item: any, index: number) => {
 
 
-            if (item.type == 1 && item.functionCheckList) {
+            if (item.type == 1) {
               //菜单
               temp.push({
                 menuId: item.menuId,
@@ -268,6 +317,15 @@ const DrawerActBtn = ({ record }: { record: any }) => {
           });
 
         }
+         
+        let initCheckedMenuIds:any[] = [];
+
+        resp.forEach((item:any) => {
+          const ids = extractAttributeValues(item,'menuId');
+          initCheckedMenuIds = initCheckedMenuIds.concat(ids);
+        });
+
+        set_checkedMenuParentsIds(initCheckedMenuIds);
 
         setTreeRecursion(resp);
 
@@ -289,22 +347,49 @@ const DrawerActBtn = ({ record }: { record: any }) => {
     return []
   }
 
+  const getTableData = async (params: any, sort: any, filter: any) => {
+
+    set_drawerTablereload(false);
+    if (currentSelectedTreeNode) {
+      const resp = await getTableDataRequest({...params,systemId:currentSelectedTreeNode.code});
+      if (resp) {
+
+        set_hospAllMenuTree(resp);
+        return {
+          data: resp,
+          success: true,
+        }
+      }
+      return {
+        data: [],
+        success: true
+      }
+    }
+
+    return []
+  }
+
   const saveResult = async () => {
 
-    let old = oldSelectedMenuIds;
-    
+    let old = [...oldSelectedMenuIds];
+
     const result = checkBoxCodes.map((item: any) => {
-     
-      old.splice(old.findIndex(a=>a == item.menuId),1);
 
-      return { ...item, hospId: record.id, systemId: currentSelectedTreeNode.code }
+      old.splice(old.findIndex(a => a == item.menuId), 1);
 
+      return { ...item, hospId: record.id, systemId: currentSelectedTreeNode.code }
+      
     });
 
     const needCancelMenus = old.map(a => ({ hospId: record.id, systemId: currentSelectedTreeNode.code, function: [], menuId: a }));
 
-    const data = [...result, ...needCancelMenus];
-    
+    const data = {
+      hospId:record.id,
+      systemId: currentSelectedTreeNode.code,
+      menuIds:[...new Set(checkedMenuParentsIds)],
+      functionRequestList:[...result,...needCancelMenus]
+    };
+
     const resp = await saveHospMenuApiPerm(result.length == 0 ? [{ hospId: record.id, systemId: currentSelectedTreeNode.code }] : data);
 
     if (resp) {
@@ -328,30 +413,32 @@ const DrawerActBtn = ({ record }: { record: any }) => {
     })
   }
 
+  const clearFunction = () => {
+    if (ifFrozze) return;
+    let emptyFunc = checkBoxCodes.map((a) => ({ ...a, function: [] }));
+    set_checkBoxCodes(emptyFunc);
+  }
 
-  // const oneKeySetReadOnly = (bool: boolean) => {
-
-  //   if (bool) {
-  //     const _temp = checkBoxCodes.map((item: any) => {
-  //       const needed = item.function.filter((a: any) => a.code == 'search');
-  //       return { ...item, function: needed }
-  //     })
-  //     set_checkBoxCodes([..._temp]);
-  //   }
 
-  // }
+  const oneKeySetAll = async (bool: boolean) => {
+    set_ifFrozze(bool);
+    const resp = await saveHospMenuApiPerm([{ hospId: record.id, systemId: currentSelectedTreeNode.code, checkAll: bool ? 1 : 0 }]);
+    // if (resp) {
+    //   set_drawerTablereload(true);
+    //   set_checkBoxCodes([]);
+    //   set_checkedTableMenuIds([]);
+    // }
+  }
 
 
   useEffect(() => {
-    if (currentSelectedTreeNode) {
-      set_drawerTableDataFilterParams({ ...drawerTableDataFilterParams, systemId: currentSelectedTreeNode.code })
+    if (currentSelectedTreeNode && !currentSelectedTreeNode.children) {
+      set_drawerTableDataFilterParams({ ...drawerTableDataFilterParams, systemId: currentSelectedTreeNode.code });
+      //切换系统清空数据
+      set_checkBoxCodes([]);
+      set_checkedTableMenuIds([]);
     }
 
-    //切换系统清空数据
-    set_checkBoxCodes([]);
-    set_checkedTableMenuIds([]);
-
-
   }, [currentSelectedTreeNode]);
 
   useEffect(() => {
@@ -371,15 +458,16 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
 
   useEffect(() => {
-    getTreeReqFunc(record.id);
-
-  }, []);
+    if (drawerVisible) {
+      getTreeReqFunc(record.id);
+    }
+  }, [drawerVisible]);
 
 
   return (
     <DrawerForm
       trigger={
-        <a key="link3" onClick={(e) => { set_drawerVisible(true); }}>功能</a>
+        <a key="link3" onClick={(e) => { set_drawerVisible(true); }}>菜单</a>
       }
       width={908}
       // visible={drawerVisible}
@@ -395,6 +483,7 @@ const DrawerActBtn = ({ record }: { record: any }) => {
         <div className='topbar'>
           <div className='title'>{`院区功能权限设置(${record.hospName})`}</div>
           <div className='btnGroup'>
+            <span className={ifFrozze ? 'clearBtn disabled' : 'clearBtn'} onClick={() => clearFunction()}>清除功能权限</span>
             <span className='cancel' onClick={() => onCancel()}>取消</span>
             <span className='save' onClick={() => saveResult()}>保存</span>
           </div>
@@ -491,16 +580,19 @@ const DrawerActBtn = ({ record }: { record: any }) => {
               </div>
 
               <div className={'btnGroup'}>
-                {/* <a style={{color: '#17181A'}}><Switch style={{position:'relative',marginRight:4}} size='small'  onChange={(bool)=>oneKeySetReadOnly(bool)} />只读</a> */}
+                <a style={{ color: '#17181A' }}><Switch style={{ position: 'relative', marginRight: 4 }} size='small' onChange={(bool) => oneKeySetAll(bool)} />全部</a>
                 {/* <UpDataActBtn key={'act'} record={undefined} type='ADD' /> */}
               </div>
 
             </div>
             {currentSelectedTreeNode && <KCTable
+              tableAlertRender={false}
+              onLoad={()=>setInitCheckData()}
               rowSelection={{
                 // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
                 // 注释该行则默认不显示下拉选项
                 checkStrictly: false,
+
                 onChange(selectedRowKeys, selectedRows, info) {
                   //console.log({selectedRowKeys, selectedRows, info});
                   if (selectedRowKeys.length == 0) {
@@ -511,22 +603,42 @@ const DrawerActBtn = ({ record }: { record: any }) => {
                   }
                 },
                 selectedRowKeys: checkedTableMenuIds,
-                selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
                 onSelect: (record, selected, selectedRows, nativeEvent) => {
-                  //console.log({ record, selected, selectedRows, nativeEvent });
-                  let checkedData = checkBoxCodes;
+                  // console.log({ record, selected, selectedRows, nativeEvent });
+
+                  if (ifFrozze) return;
+
+                  let checkedData = [...checkBoxCodes];
 
                   if (selected) {
                     //选中
+
+                    const parents = findParents(hospAllMenuTree,record.menuId);
+                    const ids = (parents as TreeNode[]).map((a)=>a.menuId);
+                    
+
+                    if(record.children){
+                      const childIds = extractAttributeValues(record,'menuId');
+                      set_checkedMenuParentsIds([...checkedMenuParentsIds,...ids,...childIds,record.menuId]);
+                    }else{
+                      set_checkedMenuParentsIds([...checkedMenuParentsIds,...ids,record.menuId]);
+                    }
+
                     selectedRows.forEach(a => {
                       if (a.functionList) {
                         checkedData.push({
                           menuId: a.menuId,
                           function: a.functionList
                         });
+                      } else {
+                        checkedData.push({
+                          menuId: a.menuId,
+                          function: []
+                        });
                       }
 
                     });
+
                     //更新表格row选中状态
                     if (record.type == 0) {
                       //选中的是目录
@@ -541,18 +653,22 @@ const DrawerActBtn = ({ record }: { record: any }) => {
 
                     }
 
-                    set_checkBoxCodes([...uniqueFunc(checkedData,'menuId')]);
+                    set_checkBoxCodes([...uniqueFunc(checkedData, 'menuId')]);
 
                   } else {
 
-                    let _tempCheckedCodes = checkBoxCodes;
+                    const ids = extractAttributeValues(record,'menuId');
+
+                    const filtedMenuIds = checkedMenuParentsIds.filter((a)=>!ids.includes(a));
+                    set_checkedMenuParentsIds(filtedMenuIds);
+
+                    let _tempCheckedCodes = [...checkBoxCodes];
 
                     const leftCheckedMenuIds = selectedRows.map(a => a.menuId);
 
                     const filtedCheckCodes = _tempCheckedCodes.filter(a => (leftCheckedMenuIds.includes(a.menuId)));
 
                     set_checkedTableMenuIds([...leftCheckedMenuIds]);
-
                     set_checkBoxCodes([...uniqueFunc(filtedCheckCodes, 'menuId')]);
 
                   }
@@ -576,8 +692,11 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
 
   const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
   const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+  const [tabIds, set_tabIds] = useState<Key[]>([]);
+  const [open, set_open] = useState(false);
+  const [navSelecterData, set_navSelecterData] = useState<NavSelecterData[]>([]);
+
 
-  
 
 
 
@@ -645,10 +764,24 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
       key: 'option',
       valueType: 'option',
       render: (text, record) => [
-        <a key="link" onClick={() => editHandle(record)}>
-          编辑
-        </a>,
-        <Divider key="1" type="vertical" style={{ margin: '0 1px' }} />,
+        // <a key="link" onClick={() => editHandle(record)}>
+        //   编辑
+        // </a>,
+        // <Divider key="1" type="vertical" style={{ margin: '0 1px' }} />,
+        // <Popconfirm
+        //   title="是否确定删除?"
+        //   onConfirm={() => delHandle(record)}
+        //   // onCancel={cancel}
+        //   okText="确定"
+        //   cancelText="取消"
+        //   key="link2"
+        // >
+        //   <a>删除</a>
+        // </Popconfirm>,
+        <a onClick={() => { editHospSystemPermissions(record); set_open(true); }}>系统</a>,
+        <Divider key="2" type="vertical" style={{ margin: '0 1px' }} />,
+        <DrawerActBtn record={record} />,
+        <Divider key="3" type="vertical" style={{ margin: '0 1px' }} />,
         <Popconfirm
           title="是否确定删除?"
           onConfirm={() => delHandle(record)}
@@ -659,17 +792,19 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
         >
           <a>删除</a>
         </Popconfirm>,
-        <Divider key="2" type="vertical" style={{ margin: '0 1px' }} />,
-        <a key="link3" onClick={() => editMenuBind(record)}>
-          菜单
-        </a>,
-        <Divider key="3" type="vertical" style={{ margin: '0 1px' }} />,
+        <Divider key="10" type="vertical" style={{ margin: '0 1px' }} />,
         <Dropdown key='4' menu={{
           items: [
             { key: '1', label: <a key="link4" onClick={() => youshuAccountBind(record)}>报告</a> },
-            { key: '2', label: <DrawerActBtn record={record} /> },
-            { key: '3', label: <a key="link5" onClick={() => initHospData(record)}>初始化</a> },
+            // { key: '2', label: <DrawerActBtn record={record} /> },
+            // { key: '3', label: <a key="link5" onClick={() => initHospData(record)}>初始化</a> },
             { key: '4', label: <a key="link6" onClick={() => setOnlyRead(record)}>初始化只读</a> },
+            {
+              key: '6', label: <a key="link5" onClick={() => initHospData(record)}>初始化</a>,
+            },
+            {
+              key: '5', label: <a key="link7" onClick={() => editHandle(record)}>编辑</a>,
+            },
           ]
         }}>
           <a>
@@ -743,6 +878,24 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
       });
   };
 
+
+  //编辑系统权限
+  const editHospSystemPermissions = async (record: TableListItem) => {
+    const { selectedMenuIds, allMenuVO } = await getSpacifyHospMenu({ hospId: record.id });
+    set_navSelecterData(allMenuVO);
+    set_tabIds(selectedMenuIds);
+
+    dispatch &&
+      dispatch({
+        type: 'hospManageModel/edit',
+        payload: {
+          data: { ...record, bindMenuIds: selectedMenuIds },
+          act: TableActType.EDITMENU,
+        },
+      });
+
+  }
+
   const editMenuBind = async (record: TableListItem) => {
     //编辑菜单绑定关系
     const { selectedMenuIds } = await getSpacifyHospMenu({ hospId: record.id });
@@ -801,9 +954,24 @@ const HospManage: FC<PageProps> = ({ hospManageModel: state, dispatch }) => {
     })
   }
 
+  const onCheckedHandle = async (data: NavSelecterItemType[]) => {
+
+    dispatch &&
+      dispatch({
+        type: 'hospManageModel/postEditData',
+        payload: { bindMenuIds: data.map(a => a.menuId) },
+      });
+
+  }
+
   return (
     <div className="HospManage">
       <ActModal {...state} dispatch={dispatch} />
+      {
+        open && (
+          <NavSelecter title='系统权限设置' data={navSelecterData} onVisibleChange={(bool) => set_open(bool)} value={tabIds} onChecked={onCheckedHandle} />
+        )
+      }
       <div className='toolBar'>
         <div className='filter'>
           <div className='filterItem'>

+ 7 - 21
src/pages/platform/setting/hospManage/modals/modal.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-06-20 18:01:40
+ * @LastEditTime: 2023-08-16 17:02:37
  * @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
@@ -105,9 +105,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     }
 
     if (
-      tableAct == TableActType.EDIT ||
-      tableAct == TableActType.EDITMENU ||
-      tableAct == TableActType.BINDACCOUNT
+      tableAct == TableActType.EDIT ||tableAct == TableActType.BINDACCOUNT
     ) {
       dispatch &&
         dispatch({
@@ -125,9 +123,6 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
     if (tableAct == TableActType.ADD) {
       return '新增院区';
     }
-    if (tableAct == TableActType.EDITMENU) {
-      return '绑定菜单';
-    }
     if (tableAct == TableActType.BINDACCOUNT) {
       return '院区报告设置';
     }
@@ -149,10 +144,6 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
         hospitalNature:setSelectorData('HOSPITAL_NATURE').defaultvalue
       };
     }
-    if (tableAct == TableActType.EDITMENU) {
-      return { ...currentEdit };
-    }
-
     if (tableAct == TableActType.BINDACCOUNT) {
       if (currentEdit?.reportId) {
         return { ...currentEdit, reportId: parseInt(currentEdit.reportId) };
@@ -215,7 +206,7 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
       visible={isShowModal}
       onVisibleChange={onVisibleChangeHandle}
       layout="horizontal"
-      width={tableAct == TableActType.EDITMENU?800:800}
+      width={800}
       initialValues={setInitialValues()}
       title={setModalTitle()}
       labelCol={{ 
@@ -226,13 +217,8 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
         onFinishHandle(tableAct == TableActType.BINDACCOUNT ? { ...data, dataSource } : data)
       }
     >
-      {tableAct == TableActType.EDITMENU && (
-        <Form.Item name="bindMenuIds">
-          <MenuEditer />
-        </Form.Item>
-      )}
-
-      {tableAct != TableActType.EDITMENU && tableAct != TableActType.BINDACCOUNT && (
+     
+      {tableAct != TableActType.BINDACCOUNT && (
         <>
           <ProFormText
             width="md"
@@ -276,9 +262,9 @@ const ActModal: React.FC<ActModalProps> = ({ dispatch, isShowModal, tableAct, cu
                     width="md"
                     name="mainHospId"
                     request={async () => {
-                      const hospList = await getHospList();
+                      const hospList:any[] = await getHospList();
                       if (hospList) {
-                        return hospList.map((t) => ({
+                        return hospList.map((t:any) => ({
                           label: t.name,
                           value: t.id,
                         }));

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

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 10:12:55
- * @LastEditTime: 2023-06-20 14:58:27
+ * @LastEditTime: 2023-08-18 17:24:40
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/model.ts

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

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

+ 1 - 3
src/pages/platform/setting/static/index.tsx

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-03-03 18:04:40
- * @LastEditTime: 2023-05-10 16:58:38
+ * @LastEditTime: 2023-08-08 14:45:58
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/reports/index.tsx
@@ -38,8 +38,6 @@ export default () => {
       const { pathname } = location;
       const spacialPage = spacicalPageParamsType.filter((t) => t.path == pathname);
 
-      //console.log({pathname,spacialPage,spacicalPageParamsType,initialState});
-
       if (spacialPage.length > 0) {
         //当前页面属于有数数据展示页面
         console.log(`${spacialPage[0].url}`);

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

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-12 17:11:11
- * @LastEditTime: 2023-04-13 11:11:15
+ * @LastEditTime: 2023-06-30 18:29:30
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/userManage/modal.tsx
@@ -85,6 +85,7 @@ const ActModal: React.FC<ActModalProps> = ({
   };
 
   const onFinishHandle = (data: any & AddUsersDataType) => {
+    console.log({data});
     if (tableAct == TableActType.ADD) {
       dispatch &&
         dispatch({

+ 2 - 2
src/service/hospList.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 09:15:59
- * @LastEditTime: 2023-03-23 18:20:48
+ * @LastEditTime: 2023-08-18 17:26:26
  * @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
@@ -189,7 +189,7 @@ export const getMenuRelaPerm = async (params:{systemId:string;hospId:string;name
 
 //保存院区菜单绑定的api权限
 export const saveHospMenuApiPerm = async (data:any) => {
-  return request('/centerSys/navigation/addBatchFunction', {
+  return request('/centerSys/hospital/addBatchFunction', {
     method: 'POST',
     data
   });

+ 40 - 1
src/utils.ts

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2022-01-13 17:09:05
- * @LastEditTime: 2023-06-09 10:57:13
+ * @LastEditTime: 2023-08-16 16:39:42
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/utils.js
@@ -101,6 +101,45 @@ export const  uniqueFunc = (arr:any[], uniId:string) => {
 }
 
 
+//获取树结构的所有叶子节点
+
+interface TreeNode {
+  [key:string]:any
+  child?: TreeNode[];
+}
+
+
+export const  getLeafNodes = (node: TreeNode, leaves: TreeNode[] = []): TreeNode[] => {
+  if (!node.child || node.child.length === 0) {
+    leaves.push(node);
+  } else {
+    for (const child of node.child) {
+      getLeafNodes(child, leaves);
+    }
+  }
+  return leaves;
+}
+
+
+
+//根据树结构中的某个属性的集合,获取对应的节点,返回一个集合
+
+export const findNodesBySomes = (node: TreeNode, keys: Set<string|number>,str:string): TreeNode[] => {
+  let results: TreeNode[] = [];
+
+  if (keys.has(node[`${str}`])) {
+      results.push(node);
+  }
+
+  if (node.child) {
+      for (let child of node.child) {
+          results = results.concat(findNodesBySomes(child,keys,str));
+      }
+  }
+
+  return results;
+}
+