PageLayout.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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 =
  65. localStorage.getItem('default_collapse_sidebar') === 'true';
  66. return (
  67. <Layout
  68. style={{
  69. height: '100vh',
  70. display: 'flex',
  71. flexDirection: 'column',
  72. overflow: styleState.isMobile ? 'visible' : 'hidden',
  73. }}
  74. >
  75. <Header
  76. style={{
  77. padding: 0,
  78. height: 'auto',
  79. lineHeight: 'normal',
  80. position: styleState.isMobile ? 'sticky' : 'fixed',
  81. width: '100%',
  82. top: 0,
  83. zIndex: 100,
  84. boxShadow: '0 1px 6px rgba(0, 0, 0, 0.08)',
  85. }}
  86. >
  87. <HeaderBar />
  88. </Header>
  89. <Layout
  90. style={{
  91. marginTop: styleState.isMobile ? '0' : '56px',
  92. height: styleState.isMobile ? 'auto' : 'calc(100vh - 56px)',
  93. overflow: styleState.isMobile ? 'visible' : 'auto',
  94. display: 'flex',
  95. flexDirection: 'column',
  96. }}
  97. >
  98. {styleState.showSider && (
  99. <Sider
  100. style={{
  101. position: 'fixed',
  102. left: 0,
  103. top: '56px',
  104. zIndex: 99,
  105. background: 'var(--semi-color-bg-1)',
  106. boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
  107. border: 'none',
  108. paddingRight: '0',
  109. height: 'calc(100vh - 56px)',
  110. }}
  111. >
  112. <SiderBar />
  113. </Sider>
  114. )}
  115. <Layout
  116. style={{
  117. marginLeft: styleState.isMobile
  118. ? '0'
  119. : styleState.showSider
  120. ? styleState.siderCollapsed
  121. ? '60px'
  122. : '200px'
  123. : '0',
  124. transition: 'margin-left 0.3s ease',
  125. flex: '1 1 auto',
  126. display: 'flex',
  127. flexDirection: 'column',
  128. }}
  129. >
  130. <Content
  131. style={{
  132. flex: '1 0 auto',
  133. overflowY: styleState.isMobile ? 'visible' : 'auto',
  134. WebkitOverflowScrolling: 'touch',
  135. padding: styleState.shouldInnerPadding ? '24px' : '0',
  136. position: 'relative',
  137. marginTop: styleState.isMobile ? '2px' : '0',
  138. }}
  139. >
  140. <App />
  141. </Content>
  142. <Layout.Footer
  143. style={{
  144. flex: '0 0 auto',
  145. width: '100%',
  146. }}
  147. >
  148. <FooterBar />
  149. </Layout.Footer>
  150. </Layout>
  151. </Layout>
  152. <ToastContainer />
  153. </Layout>
  154. );
  155. };
  156. export default PageLayout;