Browse Source

再调整

sw 1 week ago
parent
commit
2b6d6fb7ee

+ 214 - 0
src/layouts/BusinessZone.tsx

@@ -0,0 +1,214 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { Space } from 'antd';
+import { FormattedMessage } from 'react-intl';
+import {
+  AlertOutlined,
+  AppstoreOutlined,
+  MailOutlined,
+  PrinterOutlined,
+  SettingOutlined,
+} from '@ant-design/icons';
+import MeButton from '../pages/security/components/MeButton';
+
+interface BusinessZoneProps {
+  onMenuClick?: (key: string) => void;
+  collapsed: boolean;
+}
+
+const BusinessZone: React.FC<BusinessZoneProps> = ({ onMenuClick, collapsed }) => {
+  const items = [
+    {
+      key: 'patient_management',
+      label: (
+        <FormattedMessage
+          id="patient"
+          defaultMessage={'语言包中没有定义patient的翻译文本'}
+        />
+      ),
+      icon: <MailOutlined />,
+      children: [
+        {
+          key: 'register',
+          label: (
+            <FormattedMessage
+              id="register"
+              defaultMessage={'语言包中没有定义patient的翻译文本'}
+            />
+          ),
+        },
+        {
+          key: 'worklist',
+          label: (
+            <FormattedMessage
+              id="tasklist"
+              defaultMessage={'语言包中没有定义patient的翻译文本'}
+            />
+          ),
+        },
+        {
+          key: 'historylist',
+          label: (
+            <FormattedMessage
+              id="historylist"
+              defaultMessage={'语言包中没有定义patient的翻译文本'}
+            />
+          ),
+        },
+        {
+          key: 'archivelist',
+          label: (
+            <FormattedMessage
+              id="archivelist"
+              defaultMessage={'语言包中没有定义patient的翻译文本'}
+            />
+          ),
+        },
+        {
+          key: 'bin',
+          label: (
+            <FormattedMessage
+              id="bin"
+              defaultMessage={'语言包中没有定义patient的翻译文本'}
+            />
+          ),
+        },
+        {
+          key: 'outputlist',
+          label: (
+            <FormattedMessage
+              id="outputlist"
+              defaultMessage={'语言包中没有定义patient的翻译文本'}
+            />
+          ),
+        },
+      ],
+    },
+    {
+      key: 'emergency',
+      icon: <AlertOutlined />,
+      label: '急诊',
+    },
+    {
+      key: 'exam',
+      label: (
+        <FormattedMessage
+          id="exam"
+          defaultMessage={'语言包中没有定义patient的翻译文本'}
+        />
+      ),
+      icon: <AppstoreOutlined />,
+    },
+    {
+      type: 'divider',
+    },
+    {
+      key: 'process',
+      label: (
+        <FormattedMessage
+          id="process"
+          defaultMessage={'语言包中没有定义patient的翻译文本'}
+        />
+      ),
+      icon: <SettingOutlined />,
+    },
+    {
+      key: 'print',
+      label: (
+        <FormattedMessage
+          id="print"
+          defaultMessage={'语言包中没有定义patient的翻译文本'}
+        />
+      ),
+      icon: <PrinterOutlined />,
+    },
+  ];
+
+  const [visibleItems, setVisibleItems] = useState(items);
+  const businessZoneRef = useRef<HTMLDivElement>(null);
+
+  useEffect(() => {
+    const handleResize = () => {
+      if (businessZoneRef.current) {
+        const businessZoneHeight = businessZoneRef.current.offsetHeight;
+        const windowHeight = window.innerHeight;
+        const systemZoneHeight = 100; // Assuming SystemZone height is fixed
+
+        if (businessZoneHeight + systemZoneHeight > windowHeight) {
+          const visibleCount = Math.floor((windowHeight - systemZoneHeight) / 50); // Assuming each button height is 50px
+          setVisibleItems(items.slice(0, visibleCount));
+        } else {
+          setVisibleItems(items);
+        }
+      }
+    };
+
+    window.addEventListener('resize', handleResize);
+    handleResize(); // Initial check
+
+    return () => {
+      window.removeEventListener('resize', handleResize);
+    };
+  }, [items]);
+
+  return (
+<div style={{ width: '100%',overflow: 'hidden' ,flex: '1 1 auto',position: 'relative' ,minHeight:'0'}}>
+  <p>1. 这里内容很多,会撑高。</p>
+    <p>2. 这里内容很多,会撑高。</p>
+    <p>3. 这里内容很多,会撑高。</p>
+    <p>4. 这里内容很多,会撑高。</p>
+    <p>5. 这里内容很多,会撑高。</p>
+    <p>6. 这里内容很多,会撑高。</p>
+    <p>7. 这里内容很多,会撑高。</p>
+    <p>8. 这里内容很多,会撑高。</p>
+    <p>9. 这里内容很多,会撑高。</p>
+    <p>10. 这里内容很多,会撑高。</p>
+    <p>11. 这里内容很多,会撑高。</p>
+    <p>12. 这里内容很多,会撑高。</p>
+    <p>13. 这里内容很多,会撑高。</p>
+    <p>14. 这里内容很多,会撑高。</p>
+    <p>15. 这里内容很多,会撑高。</p>
+        <p>12. 这里内容很多,会撑高。</p>
+    <p>13. 这里内容很多,会撑高。</p>
+    <p>14. 这里内容很多,会撑高。</p>
+    <p>15. 这里内容很多,会撑高。</p>
+        <p>12. 这里内容很多,会撑高。</p>
+    <p>13. 这里内容很多,会撑高。</p>
+    <p>14. 这里内容很多,会撑高。</p>
+    <p>15. 这里内容很多,会撑高。</p>
+        <p>12. 这里内容很多,会撑高。</p>
+    <p>13. 这里内容很多,会撑高。</p>
+    <p>14. 这里内容很多,会撑高。</p>
+    <p>15. 这里内容很多,会撑高。</p>
+        <p>12. 这里内容很多,会撑高。</p>
+    <p>13. 这里内容很多,会撑高。</p>
+    <p>14. 这里内容很多,会撑高。</p>
+    <p>1852. 这里内容很多,会撑高。</p>
+  {/* <Space direction="vertical"> */}
+        {/* {visibleItems.map((item) => (
+          <div key={item.key}>
+            <MeButton
+              icon={item.icon}
+              onClick={() => onMenuClick?.(item.key)}
+              username={typeof item.label === 'string' ? item.label : undefined}
+            />
+            {item.children && (
+              <Space direction="vertical" style={{ marginLeft: 20 }}>
+                {item.children.map((child) => (
+                  <MeButton
+                    key={child.key}
+                    onClick={() => onMenuClick?.(child.key)}
+                    username={typeof child.label === 'string' ? child.label : undefined}
+                  />
+                ))}
+              </Space>
+            )}
+          </div>
+        ))} */}
+      {/* </Space> */}
+
+</div>
+    
+  );
+};
+
+export default BusinessZone;

+ 47 - 191
src/layouts/NavMenu.tsx

@@ -1,213 +1,69 @@
-import React, { useState } from 'react';
-import {
-  AlertOutlined,
-  AppstoreOutlined,
-  MailOutlined,
-  PrinterOutlined,
-  SettingOutlined,
-} from '@ant-design/icons';
-import type { MenuProps } from 'antd';
-import { Menu } from 'antd';
-import { FormattedMessage } from 'react-intl';
-import { Space, Button, Row } from 'antd';
-import { ToolOutlined } from '@ant-design/icons';
-import MeButton from '../pages/security/components/MeButton';
+import React, { useState, useEffect, useRef } from 'react';
+import { Button, Tooltip } from 'antd';
+import { EllipsisOutlined } from '@ant-design/icons';
+import BusinessZone from './BusinessZone';
+import SystemZone from './SystemZone';
 import { useSelector, useDispatch } from 'react-redux';
 import { useSelector, useDispatch } from 'react-redux';
-import { RootState } from '@/states/store'; // 使用路径别名@指向src
-import { isLoggedIn } from '../states/user_info'; // 根据你的实际路径调整
+import { RootState } from '@/states/store';
 import { setBusinessFlow } from '@/states/BusinessFlowSlice';
 import { setBusinessFlow } from '@/states/BusinessFlowSlice';
 
 
-type MenuItem = Required<MenuProps>['items'][number];
-
-const items: MenuItem[] = [
-  {
-    key: 'patient_management',
-    label: (
-      <FormattedMessage
-        id="patient"
-        defaultMessage={'语言包中没有定义patient的翻译文本'}
-      />
-    ),
-    icon: <MailOutlined />,
-    children: [
-      {
-        key: 'register',
-        label: (
-          <FormattedMessage
-            id="register"
-            defaultMessage={'语言包中没有定义patient的翻译文本'}
-          />
-        ),
-      },
-      {
-        key: 'worklist',
-        label: (
-          <FormattedMessage
-            id="tasklist"
-            defaultMessage={'语言包中没有定义patient的翻译文本'}
-          />
-        ),
-      },
-      {
-        key: 'historylist',
-        label: (
-          <FormattedMessage
-            id="historylist"
-            defaultMessage={'语言包中没有定义patient的翻译文本'}
-          />
-        ),
-      },
-      {
-        key: 'archivelist',
-        label: (
-          <FormattedMessage
-            id="archivelist"
-            defaultMessage={'语言包中没有定义patient的翻译文本'}
-          />
-        ),
-      },
-      {
-        key: 'bin',
-        label: (
-          <FormattedMessage
-            id="bin"
-            defaultMessage={'语言包中没有定义patient的翻译文本'}
-          />
-        ),
-      },
-      {
-        key: 'outputlist',
-        label: (
-          <FormattedMessage
-            id="outputlist"
-            defaultMessage={'语言包中没有定义patient的翻译文本'}
-          />
-        ),
-      },
-    ],
-  },
-  {
-    key: 'emergency',
-    icon: <AlertOutlined />,
-    label: '急诊',
-  },
-  {
-    key: 'exam',
-    label: (
-      <FormattedMessage
-        id="exam"
-        defaultMessage={'语言包中没有定义patient的翻译文本'}
-      />
-    ),
-    icon: <AppstoreOutlined />,
-  },
-  {
-    type: 'divider',
-  },
-  {
-    key: 'process',
-    label: (
-      <FormattedMessage
-        id="process"
-        defaultMessage={'语言包中没有定义patient的翻译文本'}
-      />
-    ),
-    icon: <SettingOutlined />,
-  },
-  {
-    key: 'print',
-    label: (
-      <FormattedMessage
-        id="print"
-        defaultMessage={'语言包中没有定义patient的翻译文本'}
-      />
-    ),
-    icon: <PrinterOutlined />,
-  },
-];
-
 interface NavMenuProps {
 interface NavMenuProps {
   onMenuClick?: (key: string) => void;
   onMenuClick?: (key: string) => void;
 }
 }
 
 
 const NavMenu: React.FC<NavMenuProps> = ({ onMenuClick }) => {
 const NavMenu: React.FC<NavMenuProps> = ({ onMenuClick }) => {
   const dispatch = useDispatch();
   const dispatch = useDispatch();
+  const [collapsed, setCollapsed] = useState(false);
+  const businessZoneRef = useRef<HTMLDivElement>(null);
+  const systemZoneRef = useRef<HTMLDivElement>(null);
 
 
-  const onClick: MenuProps['onClick'] = (e) => {
-    console.log('click ', e);
-    dispatch(setBusinessFlow(e.key));
-    onMenuClick?.(e.key);
+  const onClick = (key: string) => {
+    dispatch(setBusinessFlow(key));
+    onMenuClick?.(key);
   };
   };
 
 
-  // 从items得到所有key
-  const allKeys = items.map((item) => item?.key as string);
-  const [openKeys, setOpenKeys] = useState(allKeys); // 初始展开的 key
-
-  // 阻止默认的折叠行为
-  const onOpenChange = (keys: string[]) => {
-    // 如果当前的 key 在 openKeys 中,说明用户试图关闭它,我们忽略这个操作
-    if (openKeys.includes(keys[0])) {
-      return;
-    }
-    // 如果用户试图展开其他子菜单,我们也可以选择忽略,或者更新 openKeys
-    setOpenKeys([...openKeys, keys[0]]);
+  const toggleCollapse = () => {
+    setCollapsed(!collapsed);
   };
   };
 
 
-  const login = useSelector((state: RootState) => isLoggedIn(state.userInfo));
-  const username = useSelector((state: RootState) => state.userInfo.name);
-  const avatarUrl = useSelector((state: RootState) => state.userInfo.avatar);
+  useEffect(() => {
+    const handleResize = () => {
+      if (businessZoneRef.current && systemZoneRef.current) {
+        const businessZoneHeight = businessZoneRef.current.offsetHeight;
+        const systemZoneHeight = systemZoneRef.current.offsetHeight;
+        const windowHeight = window.innerHeight;
+
+        if (businessZoneHeight + systemZoneHeight > windowHeight) {
+          setCollapsed(true);
+        } else {
+          setCollapsed(false);
+        }
+      }
+    };
+
+    window.addEventListener('resize', handleResize);
+    handleResize(); // Initial check
+
+    return () => {
+      window.removeEventListener('resize', handleResize);
+    };
+  }, []);
 
 
   return (
   return (
-    <>
-      <Menu
-        openKeys={openKeys}
-        onOpenChange={onOpenChange}
-        onClick={onClick}
-        defaultSelectedKeys={['1']}
-        defaultOpenKeys={['sub1']}
-        mode="inline"
-        items={items}
-      />
-      {/* 底部按钮区域 */}
-      <Row
-        style={{
-          position: 'absolute',
-          bottom: 32,
-          left: 0,
-          width: '100%',
-          justifyContent: 'center',
-        }}
-      >
-        <Space
-          direction="vertical"
-          align="start"
-          style={{ width: '100%', paddingLeft: 20 }}
-        >
-          <Space>
+    <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
+        <BusinessZone onMenuClick={onClick} collapsed={collapsed} />
+        {/* {collapsed && (
+          <Tooltip title="更多">
             <Button
             <Button
               shape="circle"
               shape="circle"
-              size="large"
-              icon={<ToolOutlined />}
-              style={{
-                display: 'flex',
-                alignItems: 'center',
-                justifyContent: 'center',
-                userSelect: 'none',
-              }}
-              onClick={() => onMenuClick?.('settings')}
+              icon={<EllipsisOutlined />}
+              onClick={toggleCollapse}
+              style={{ margin: '10px 0' }}
             />
             />
-            <span>配置</span>
-          </Space>
-          <MeButton
-            size="large"
-            isLogin={login}
-            avatarUrl={avatarUrl || undefined}
-            username={login ? username : '未登录'}
-            onClick={() => onMenuClick?.('me')}
-          />
-        </Space>
-      </Row>
-    </>
+          </Tooltip>
+        )} */}
+      <SystemZone ref={systemZoneRef} onMenuClick={onClick} />
+    </div>
   );
   );
 };
 };
 
 

+ 65 - 0
src/layouts/SystemZone.tsx

@@ -0,0 +1,65 @@
+import React, { forwardRef } from 'react';
+import { Space, Button, Row } from 'antd';
+import { ToolOutlined } from '@ant-design/icons';
+import MeButton from '../pages/security/components/MeButton';
+import { useSelector } from 'react-redux';
+import { RootState } from '@/states/store';
+import { isLoggedIn } from '../states/user_info';
+
+interface SystemZoneProps {
+  onMenuClick?: (key: string) => void;
+}
+
+const SystemZone = forwardRef<HTMLDivElement, SystemZoneProps>(({ onMenuClick }, ref) => {
+  const login = useSelector((state: RootState) => isLoggedIn(state.userInfo));
+  const username = useSelector((state: RootState) => state.userInfo.name);
+  const avatarUrl = useSelector((state: RootState) => state.userInfo.avatar);
+
+  return (
+    <Row
+      ref={ref}
+      style={{
+        position: 'sticky',
+        flex: '0 0 auto',
+        bottom: 0,
+        left: 0,
+        width: '100%',
+        justifyContent: 'center',
+        backgroundColor: '#fff',
+        padding: '16px 0',
+        boxShadow: '0 -2px 5px rgba(0,0,0,0.1)',
+      }}
+    >
+      <Space
+        direction="vertical"
+        align="start"
+        style={{ width: '100%', paddingLeft: 20 }}
+      >
+        <Space>
+          <Button
+            shape="circle"
+            size="large"
+            icon={<ToolOutlined />}
+            style={{
+              display: 'flex',
+              alignItems: 'center',
+              justifyContent: 'center',
+              userSelect: 'none',
+            }}
+            onClick={() => onMenuClick?.('settings')}
+          />
+          <span>配置</span>
+        </Space>
+        <MeButton
+          size="large"
+          isLogin={login}
+          avatarUrl={avatarUrl || undefined}
+          username={login ? username : '未登录'}
+          onClick={() => onMenuClick?.('me')}
+        />
+      </Space>
+    </Row>
+  );
+});
+
+export default SystemZone;

+ 4 - 2
src/pages/security/components/MeButton.tsx

@@ -5,7 +5,8 @@ import { UserOutlined } from '@ant-design/icons';
 interface MeButtonProps extends AvatarProps {
 interface MeButtonProps extends AvatarProps {
   isLogin?: boolean;
   isLogin?: boolean;
   avatarUrl?: string;
   avatarUrl?: string;
-  username?: string;
+  username?: React.ReactNode;
+  icon?: React.ReactNode;
 }
 }
 
 
 const MeButton: React.FC<MeButtonProps> = ({
 const MeButton: React.FC<MeButtonProps> = ({
@@ -13,6 +14,7 @@ const MeButton: React.FC<MeButtonProps> = ({
   avatarUrl,
   avatarUrl,
   onClick,
   onClick,
   username,
   username,
+  icon,
   ...props
   ...props
 }) => {
 }) => {
   return (
   return (
@@ -35,7 +37,7 @@ const MeButton: React.FC<MeButtonProps> = ({
         />
         />
       ) : (
       ) : (
         <Avatar
         <Avatar
-          icon={<UserOutlined />}
+          icon={icon || <UserOutlined />}
           size={props.size}
           size={props.size}
           style={{ marginRight: username ? 8 : 0 }}
           style={{ marginRight: username ? 8 : 0 }}
         />
         />