PageLayout.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import HeaderBar from './HeaderBar.js';
  2. import { Layout } from '@douyinfe/semi-ui';
  3. import SiderBar from './SiderBar.js';
  4. import App from '../App.js';
  5. import FooterBar from './Footer.js';
  6. import { ToastContainer } from 'react-toastify';
  7. import React, { useContext, useEffect } from 'react';
  8. import { StyleContext } from '../context/Style/index.js';
  9. import { useTranslation } from 'react-i18next';
  10. import { API, getLogo, getSystemName, showError } from '../helpers/index.js';
  11. import { setStatusData } from '../helpers/data.js';
  12. import { UserContext } from '../context/User/index.js';
  13. import { StatusContext } from '../context/Status/index.js';
  14. const { Sider, Content, Header, Footer } = Layout;
  15. const PageLayout = () => {
  16. const [userState, userDispatch] = useContext(UserContext);
  17. const [statusState, statusDispatch] = useContext(StatusContext);
  18. const [styleState, styleDispatch] = useContext(StyleContext);
  19. const { i18n } = useTranslation();
  20. const loadUser = () => {
  21. let user = localStorage.getItem('user');
  22. if (user) {
  23. let data = JSON.parse(user);
  24. userDispatch({ type: 'login', payload: data });
  25. }
  26. };
  27. const loadStatus = async () => {
  28. try {
  29. const res = await API.get('/api/status');
  30. const { success, data } = res.data;
  31. if (success) {
  32. statusDispatch({ type: 'set', payload: data });
  33. setStatusData(data);
  34. } else {
  35. showError('Unable to connect to server');
  36. }
  37. } catch (error) {
  38. showError('Failed to load status');
  39. }
  40. };
  41. useEffect(() => {
  42. loadUser();
  43. loadStatus().catch(console.error);
  44. let systemName = getSystemName();
  45. if (systemName) {
  46. document.title = systemName;
  47. }
  48. let logo = getLogo();
  49. if (logo) {
  50. let linkElement = document.querySelector("link[rel~='icon']");
  51. if (linkElement) {
  52. linkElement.href = logo;
  53. }
  54. }
  55. // 从localStorage获取上次使用的语言
  56. const savedLang = localStorage.getItem('i18nextLng');
  57. if (savedLang) {
  58. i18n.changeLanguage(savedLang);
  59. }
  60. // 默认显示侧边栏
  61. styleDispatch({ type: 'SET_SIDER', payload: true });
  62. }, [i18n]);
  63. // 获取侧边栏折叠状态
  64. const isSidebarCollapsed = localStorage.getItem('default_collapse_sidebar') === 'true';
  65. return (
  66. <Layout style={{
  67. height: '100vh',
  68. display: 'flex',
  69. flexDirection: 'column',
  70. overflow: styleState.isMobile ? 'visible' : 'hidden'
  71. }}>
  72. <Header style={{
  73. padding: 0,
  74. height: 'auto',
  75. lineHeight: 'normal',
  76. position: styleState.isMobile ? 'sticky' : 'fixed',
  77. width: '100%',
  78. top: 0,
  79. zIndex: 100,
  80. boxShadow: '0 1px 6px rgba(0, 0, 0, 0.08)'
  81. }}>
  82. <HeaderBar />
  83. </Header>
  84. <Layout style={{
  85. marginTop: styleState.isMobile ? '0' : '56px',
  86. height: styleState.isMobile ? 'auto' : 'calc(100vh - 56px)',
  87. overflow: styleState.isMobile ? 'visible' : 'auto',
  88. display: 'flex',
  89. flexDirection: 'column'
  90. }}>
  91. {styleState.showSider && (
  92. <Sider style={{
  93. position: 'fixed',
  94. left: 0,
  95. top: '56px',
  96. zIndex: 99,
  97. background: 'var(--semi-color-bg-1)',
  98. boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
  99. border: 'none',
  100. paddingRight: '0',
  101. height: 'calc(100vh - 56px)',
  102. }}>
  103. <SiderBar />
  104. </Sider>
  105. )}
  106. <Layout style={{
  107. marginLeft: styleState.isMobile ? '0' : (styleState.showSider ? (styleState.siderCollapsed ? '60px' : '200px') : '0'),
  108. transition: 'margin-left 0.3s ease',
  109. flex: '1 1 auto',
  110. display: 'flex',
  111. flexDirection: 'column'
  112. }}>
  113. <Content
  114. style={{
  115. flex: '1 0 auto',
  116. overflowY: styleState.isMobile ? 'visible' : 'auto',
  117. WebkitOverflowScrolling: 'touch',
  118. padding: styleState.shouldInnerPadding? '24px': '0',
  119. position: 'relative',
  120. marginTop: styleState.isMobile ? '2px' : '0',
  121. }}
  122. >
  123. <App />
  124. </Content>
  125. <Layout.Footer style={{
  126. flex: '0 0 auto',
  127. width: '100%'
  128. }}>
  129. <FooterBar />
  130. </Layout.Footer>
  131. </Layout>
  132. </Layout>
  133. <ToastContainer />
  134. </Layout>
  135. )
  136. }
  137. export default PageLayout;