SiderBar.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 { useTranslation } from 'react-i18next';
  6. import {
  7. API,
  8. getLogo,
  9. getSystemName,
  10. isAdmin,
  11. isMobile,
  12. showError,
  13. } from '../helpers';
  14. import '../index.css';
  15. import {
  16. IconCalendarClock, IconChecklistStroked,
  17. IconComment, IconCommentStroked,
  18. IconCreditCard,
  19. IconGift, IconHelpCircle,
  20. IconHistogram,
  21. IconHome,
  22. IconImage,
  23. IconKey,
  24. IconLayers,
  25. IconPriceTag,
  26. IconSetting,
  27. IconUser
  28. } from '@douyinfe/semi-icons';
  29. import { Avatar, Dropdown, Layout, Nav, Switch } from '@douyinfe/semi-ui';
  30. import { setStatusData } from '../helpers/data.js';
  31. import { stringToColor } from '../helpers/render.js';
  32. import { useSetTheme, useTheme } from '../context/Theme/index.js';
  33. import { StyleContext } from '../context/Style/index.js';
  34. // HeaderBar Buttons
  35. const SiderBar = () => {
  36. const { t } = useTranslation();
  37. const [styleState, styleDispatch] = useContext(StyleContext);
  38. const [statusState, statusDispatch] = useContext(StatusContext);
  39. const defaultIsCollapsed =
  40. localStorage.getItem('default_collapse_sidebar') === 'true';
  41. const [selectedKeys, setSelectedKeys] = useState(['home']);
  42. const [isCollapsed, setIsCollapsed] = useState(defaultIsCollapsed);
  43. const [chatItems, setChatItems] = useState([]);
  44. const theme = useTheme();
  45. const setTheme = useSetTheme();
  46. const routerMap = {
  47. home: '/',
  48. channel: '/channel',
  49. token: '/token',
  50. redemption: '/redemption',
  51. topup: '/topup',
  52. user: '/user',
  53. log: '/log',
  54. midjourney: '/midjourney',
  55. setting: '/setting',
  56. about: '/about',
  57. chat: '/chat',
  58. detail: '/detail',
  59. pricing: '/pricing',
  60. task: '/task',
  61. playground: '/playground',
  62. };
  63. const headerButtons = useMemo(
  64. () => [
  65. {
  66. text: 'Playground',
  67. itemKey: 'playground',
  68. to: '/playground',
  69. icon: <IconCommentStroked />,
  70. },
  71. {
  72. text: t('渠道'),
  73. itemKey: 'channel',
  74. to: '/channel',
  75. icon: <IconLayers />,
  76. className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle',
  77. },
  78. {
  79. text: t('聊天'),
  80. itemKey: 'chat',
  81. items: chatItems,
  82. icon: <IconComment />,
  83. },
  84. {
  85. text: t('令牌'),
  86. itemKey: 'token',
  87. to: '/token',
  88. icon: <IconKey />,
  89. },
  90. {
  91. text: t('数据看板'),
  92. itemKey: 'detail',
  93. to: '/detail',
  94. icon: <IconCalendarClock />,
  95. className:
  96. localStorage.getItem('enable_data_export') === 'true'
  97. ? 'semi-navigation-item-normal'
  98. : 'tableHiddle',
  99. },
  100. {
  101. text: t('兑换码'),
  102. itemKey: 'redemption',
  103. to: '/redemption',
  104. icon: <IconGift />,
  105. className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle',
  106. },
  107. {
  108. text: t('钱包'),
  109. itemKey: 'topup',
  110. to: '/topup',
  111. icon: <IconCreditCard />,
  112. },
  113. {
  114. text: t('用户管理'),
  115. itemKey: 'user',
  116. to: '/user',
  117. icon: <IconUser />,
  118. className: isAdmin() ? 'semi-navigation-item-normal' : 'tableHiddle',
  119. },
  120. {
  121. text: t('日志'),
  122. itemKey: 'log',
  123. to: '/log',
  124. icon: <IconHistogram />,
  125. },
  126. {
  127. text: t('绘图'),
  128. itemKey: 'midjourney',
  129. to: '/midjourney',
  130. icon: <IconImage />,
  131. className:
  132. localStorage.getItem('enable_drawing') === 'true'
  133. ? 'semi-navigation-item-normal'
  134. : 'tableHiddle',
  135. },
  136. {
  137. text: t('异步任务'),
  138. itemKey: 'task',
  139. to: '/task',
  140. icon: <IconChecklistStroked />,
  141. className:
  142. localStorage.getItem('enable_task') === 'true'
  143. ? 'semi-navigation-item-normal'
  144. : 'tableHiddle',
  145. },
  146. {
  147. text: t('设置'),
  148. itemKey: 'setting',
  149. to: '/setting',
  150. icon: <IconSetting />,
  151. },
  152. ],
  153. [
  154. localStorage.getItem('enable_data_export'),
  155. localStorage.getItem('enable_drawing'),
  156. localStorage.getItem('enable_task'),
  157. localStorage.getItem('chat_link'),
  158. chatItems,
  159. isAdmin(),
  160. t,
  161. ],
  162. );
  163. useEffect(() => {
  164. let localKey = window.location.pathname.split('/')[1];
  165. if (localKey === '') {
  166. localKey = 'home';
  167. }
  168. setSelectedKeys([localKey]);
  169. let chatLink = localStorage.getItem('chat_link');
  170. if (!chatLink) {
  171. let chats = localStorage.getItem('chats');
  172. if (chats) {
  173. // console.log(chats);
  174. try {
  175. chats = JSON.parse(chats);
  176. if (Array.isArray(chats)) {
  177. let chatItems = [];
  178. for (let i = 0; i < chats.length; i++) {
  179. let chat = {};
  180. for (let key in chats[i]) {
  181. chat.text = key;
  182. chat.itemKey = 'chat' + i;
  183. chat.to = '/chat/' + i;
  184. }
  185. // setRouterMap({ ...routerMap, chat: '/chat/' + i })
  186. chatItems.push(chat);
  187. }
  188. setChatItems(chatItems);
  189. }
  190. } catch (e) {
  191. console.error(e);
  192. showError('聊天数据解析失败')
  193. }
  194. }
  195. }
  196. setIsCollapsed(localStorage.getItem('default_collapse_sidebar') === 'true');
  197. }, []);
  198. return (
  199. <>
  200. <Nav
  201. style={{ maxWidth: 220, height: '100%' }}
  202. defaultIsCollapsed={
  203. localStorage.getItem('default_collapse_sidebar') === 'true'
  204. }
  205. isCollapsed={isCollapsed}
  206. onCollapseChange={(collapsed) => {
  207. setIsCollapsed(collapsed);
  208. }}
  209. selectedKeys={selectedKeys}
  210. renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
  211. let chatLink = localStorage.getItem('chat_link');
  212. if (!chatLink) {
  213. let chats = localStorage.getItem('chats');
  214. if (chats) {
  215. chats = JSON.parse(chats);
  216. if (Array.isArray(chats) && chats.length > 0) {
  217. for (let i = 0; i < chats.length; i++) {
  218. routerMap['chat' + i] = '/chat/' + i;
  219. }
  220. if (chats.length > 1) {
  221. // delete /chat
  222. if (routerMap['chat']) {
  223. delete routerMap['chat'];
  224. }
  225. } else {
  226. // rename /chat to /chat/0
  227. routerMap['chat'] = '/chat/0';
  228. }
  229. }
  230. }
  231. }
  232. return (
  233. <Link
  234. style={{ textDecoration: 'none' }}
  235. to={routerMap[props.itemKey]}
  236. >
  237. {itemElement}
  238. </Link>
  239. );
  240. }}
  241. items={headerButtons}
  242. onSelect={(key) => {
  243. if (key.itemKey.toString().startsWith('chat')) {
  244. styleDispatch({ type: 'SET_INNER_PADDING', payload: false });
  245. } else {
  246. styleDispatch({ type: 'SET_INNER_PADDING', payload: true });
  247. }
  248. setSelectedKeys([key.itemKey]);
  249. }}
  250. footer={
  251. <>
  252. </>
  253. }
  254. >
  255. <Nav.Footer collapseButton={true}></Nav.Footer>
  256. </Nav>
  257. </>
  258. );
  259. };
  260. export default SiderBar;