SiderBar.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. import React, { useContext, useEffect, useMemo, useState } from 'react';
  2. import { Link, useNavigate } from 'react-router-dom';
  3. import { UserContext } from '../context/User';
  4. import { StatusContext } from '../context/Status';
  5. import {
  6. API,
  7. getLogo,
  8. getSystemName,
  9. isAdmin,
  10. isMobile,
  11. showError,
  12. } from '../helpers';
  13. import '../index.css';
  14. import {
  15. IconCalendarClock,
  16. IconComment,
  17. IconCreditCard,
  18. IconGift,
  19. IconHistogram,
  20. IconHome,
  21. IconImage,
  22. IconKey,
  23. IconLayers,
  24. IconPriceTag,
  25. IconSetting,
  26. IconUser,
  27. } from '@douyinfe/semi-icons';
  28. import { Layout, Nav } from '@douyinfe/semi-ui';
  29. import { setStatusData } from '../helpers/data.js';
  30. // HeaderBar Buttons
  31. const SiderBar = () => {
  32. const [userState, userDispatch] = useContext(UserContext);
  33. const [statusState, statusDispatch] = useContext(StatusContext);
  34. const defaultIsCollapsed =
  35. isMobile() || localStorage.getItem('default_collapse_sidebar') === 'true';
  36. let navigate = useNavigate();
  37. const [selectedKeys, setSelectedKeys] = useState(['home']);
  38. const systemName = getSystemName();
  39. const logo = getLogo();
  40. const [isCollapsed, setIsCollapsed] = useState(defaultIsCollapsed);
  41. const routerMap = {
  42. home: '/',
  43. channel: '/channel',
  44. token: '/token',
  45. redemption: '/redemption',
  46. topup: '/topup',
  47. user: '/user',
  48. log: '/log',
  49. midjourney: '/midjourney',
  50. setting: '/setting',
  51. about: '/about',
  52. chat: '/chat',
  53. detail: '/detail',
  54. pricing: '/pricing',
  55. };
  56. const headerButtons = useMemo(
  57. () => [
  58. {
  59. text: '首页',
  60. itemKey: 'home',
  61. to: '/',
  62. icon: <IconHome />,
  63. },
  64. {
  65. text: '渠道',
  66. itemKey: 'channel',
  67. to: '/channel',
  68. icon: <IconLayers />,
  69. className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle',
  70. },
  71. {
  72. text: '聊天',
  73. itemKey: 'chat',
  74. to: '/chat',
  75. icon: <IconComment />,
  76. className: localStorage.getItem('chat_link')
  77. ? 'semi-navigation-item-normal'
  78. : 'tableHiddle',
  79. },
  80. {
  81. text: '令牌',
  82. itemKey: 'token',
  83. to: '/token',
  84. icon: <IconKey />,
  85. },
  86. {
  87. text: '兑换码',
  88. itemKey: 'redemption',
  89. to: '/redemption',
  90. icon: <IconGift />,
  91. className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle',
  92. },
  93. {
  94. text: '钱包',
  95. itemKey: 'topup',
  96. to: '/topup',
  97. icon: <IconCreditCard />,
  98. },
  99. {
  100. text: '模型价格',
  101. itemKey: 'pricing',
  102. to: '/pricing',
  103. icon: <IconPriceTag />,
  104. },
  105. {
  106. text: '用户管理',
  107. itemKey: 'user',
  108. to: '/user',
  109. icon: <IconUser />,
  110. className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle',
  111. },
  112. {
  113. text: '日志',
  114. itemKey: 'log',
  115. to: '/log',
  116. icon: <IconHistogram />,
  117. },
  118. {
  119. text: '数据看板',
  120. itemKey: 'detail',
  121. to: '/detail',
  122. icon: <IconCalendarClock />,
  123. className:
  124. localStorage.getItem('enable_data_export') === 'true'
  125. ? 'semi-navigation-item-normal'
  126. : 'tableHiddle',
  127. },
  128. {
  129. text: '绘图',
  130. itemKey: 'midjourney',
  131. to: '/midjourney',
  132. icon: <IconImage />,
  133. className:
  134. localStorage.getItem('enable_drawing') === 'true'
  135. ? 'semi-navigation-item-normal'
  136. : 'tableHiddle',
  137. },
  138. {
  139. text: '设置',
  140. itemKey: 'setting',
  141. to: '/setting',
  142. icon: <IconSetting />,
  143. },
  144. // {
  145. // text: '关于',
  146. // itemKey: 'about',
  147. // to: '/about',
  148. // icon: <IconAt/>
  149. // }
  150. ],
  151. [
  152. localStorage.getItem('enable_data_export'),
  153. localStorage.getItem('enable_drawing'),
  154. localStorage.getItem('chat_link'),
  155. isAdmin(),
  156. ],
  157. );
  158. const loadStatus = async () => {
  159. const res = await API.get('/api/status');
  160. if (res === undefined) {
  161. return;
  162. }
  163. const { success, data } = res.data;
  164. if (success) {
  165. statusDispatch({ type: 'set', payload: data });
  166. setStatusData(data);
  167. } else {
  168. showError('无法正常连接至服务器!');
  169. }
  170. };
  171. useEffect(() => {
  172. loadStatus().then(() => {
  173. setIsCollapsed(
  174. isMobile() ||
  175. localStorage.getItem('default_collapse_sidebar') === 'true',
  176. );
  177. });
  178. let localKey = window.location.pathname.split('/')[1];
  179. if (localKey === '') {
  180. localKey = 'home';
  181. }
  182. setSelectedKeys([localKey]);
  183. }, []);
  184. return (
  185. <>
  186. <Layout>
  187. <div style={{ height: '100%' }}>
  188. <Nav
  189. // bodyStyle={{ maxWidth: 200 }}
  190. style={{ maxWidth: 200 }}
  191. defaultIsCollapsed={
  192. isMobile() ||
  193. localStorage.getItem('default_collapse_sidebar') === 'true'
  194. }
  195. isCollapsed={isCollapsed}
  196. onCollapseChange={(collapsed) => {
  197. setIsCollapsed(collapsed);
  198. }}
  199. selectedKeys={selectedKeys}
  200. renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
  201. return (
  202. <Link
  203. style={{ textDecoration: 'none' }}
  204. to={routerMap[props.itemKey]}
  205. >
  206. {itemElement}
  207. </Link>
  208. );
  209. }}
  210. items={headerButtons}
  211. onSelect={(key) => {
  212. setSelectedKeys([key.itemKey]);
  213. }}
  214. header={{
  215. logo: (
  216. <img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
  217. ),
  218. text: systemName,
  219. }}
  220. // footer={{
  221. // text: '© 2021 NekoAPI',
  222. // }}
  223. >
  224. <Nav.Footer collapseButton={true}></Nav.Footer>
  225. </Nav>
  226. </div>
  227. </Layout>
  228. </>
  229. );
  230. };
  231. export default SiderBar;