DeekSeekHome.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import * as React from 'react';
  2. import { useNavigate } from "react-router-dom";
  3. import { Dropdown, Spin, Tooltip } from 'antd';
  4. import { Chat } from './DeepSeekHomeOnlyChat';
  5. import whiteLogo from "../icons/whiteLogo.png";
  6. import jkxz from "../icons/jkxz.png";
  7. import { useChatStore } from "../store";
  8. import { useMobileScreen } from '../utils';
  9. import api from "@/app/api/api";
  10. import './deepSeekHome.scss';
  11. const DeekSeek: React.FC = () => {
  12. const chatStore = useChatStore();
  13. const isMobileScreen = useMobileScreen();
  14. const navigate = useNavigate();
  15. const [listLoading, setListLoading] = React.useState(false);
  16. const [hideTitleOnMobile, setHideTitleOnMobile] = React.useState(false);
  17. const [activeNavIndex, setActiveNavIndex] = React.useState<number | null>(null);
  18. type List = {
  19. title: string,
  20. children: {
  21. title: string,
  22. showMenu: string,
  23. chatMode: string,
  24. appId: string,
  25. children?: List[number]['children'],
  26. }[],
  27. }[];
  28. const [list, setList] = React.useState<List>([
  29. {
  30. "children": [
  31. {
  32. "chatMode": "LOCAL",
  33. "showMenu": "false",
  34. "appId": "2935625422066814976",
  35. "title": "公司作业指导书(2023版)"
  36. },
  37. {
  38. "chatMode": "LOCAL",
  39. "showMenu": "false",
  40. "appId": "2935200536655695872",
  41. "title": "常用验收规范问答"
  42. },
  43. {
  44. "chatMode": "LOCAL",
  45. "showMenu": "false",
  46. "appId": "2942568790025965568",
  47. "title": "钢结构AI监理师"
  48. }
  49. ],
  50. "title": "专业知识"
  51. },
  52. {
  53. "children": [
  54. {
  55. "chatMode": "LOCAL",
  56. "showMenu": "false",
  57. "appId": "2919677614293913600",
  58. "title": "员工入职小百科"
  59. },
  60. {
  61. "chatMode": "LOCAL",
  62. "showMenu": "false",
  63. "appId": "2919668410128666624",
  64. "title": "数字系统答疑"
  65. },
  66. {
  67. "chatMode": "LOCAL",
  68. "showMenu": "false",
  69. "appId": "2945774476037853184",
  70. "title": "企业介绍"
  71. }
  72. ],
  73. "title": "职能管理"
  74. },
  75. {
  76. "children": [],
  77. "title": "项目级应用"
  78. }
  79. ]);
  80. const init = async () => {
  81. setListLoading(true);
  82. try {
  83. const res = await api.get('/deepseek/api/appType');
  84. setList(res.data);
  85. } catch (error) {
  86. console.error(error);
  87. } finally {
  88. setListLoading(false);
  89. }
  90. }
  91. React.useEffect(() => {
  92. chatStore.clearSessions();
  93. const userInfo = localStorage.getItem('userInfo');
  94. if (userInfo) {
  95. init();
  96. }
  97. }, []);
  98. const formatMenuTitle = React.useCallback(
  99. (title: string) => {
  100. if (isMobileScreen) {
  101. return title;
  102. }
  103. return title.length > 7 ? `${title.slice(0, 7)}...` : title;
  104. },
  105. [isMobileScreen]
  106. );
  107. const dropdownAlign = React.useMemo(() => {
  108. if (isMobileScreen) {
  109. return undefined;
  110. }
  111. return {
  112. points: ['tl', 'bl'],
  113. offset: [0, 8],
  114. overflow: {
  115. adjustY: false,
  116. adjustX: true,
  117. },
  118. };
  119. }, [isMobileScreen]);
  120. return (
  121. <Spin spinning={listLoading}>
  122. <div className='deekSeek'>
  123. <div className='deekSeek-header' style={{ justifyContent: isMobileScreen ? "space-between" : "center" }}>
  124. <div
  125. style={{
  126. display: 'flex',
  127. alignItems: 'center',
  128. margin: isMobileScreen ? 0 : '0 20px',
  129. fontSize: isMobileScreen ? undefined : 14,
  130. fontWeight: isMobileScreen ? undefined : 600,
  131. }}
  132. >
  133. <img src={whiteLogo.src} style={{ width: 20, marginRight: isMobileScreen ? 0 : 10 }} />
  134. {!isMobileScreen && (
  135. <div style={{ whiteSpace: 'nowrap' }}>
  136. 上海建科
  137. </div>
  138. )}
  139. </div>
  140. {
  141. list.map((item, index) => {
  142. return <Dropdown
  143. onOpenChange={(open) => {
  144. if (open) {
  145. setActiveNavIndex(index);
  146. }
  147. }}
  148. menu={{
  149. items: item.children.map((child, i) => {
  150. return {
  151. key: 'child' + i,
  152. label: <div
  153. className='deekSeek-menuds'
  154. onClick={() => {
  155. const search = `?showMenu=${child.showMenu}&chatMode=${child.chatMode}&appId=${child.appId}`;
  156. if (child.appId) {
  157. navigate({
  158. pathname: '/knowledgeChat',
  159. search: search,
  160. })
  161. }
  162. }}
  163. >
  164. <Tooltip placement="top" title={child.title}>
  165. {formatMenuTitle(child.title)}
  166. </Tooltip>
  167. </div>,
  168. children: child.children ? child.children.map((record, ind) => {
  169. return {
  170. key: 'record' + ind,
  171. label: (
  172. <Tooltip placement="bottom" title={record.title}>
  173. <div
  174. onClick={() => {
  175. const search = `?showMenu=${record.showMenu}&chatMode=${record.chatMode}&appId=${record.appId}`;
  176. if (record.appId) {
  177. navigate({
  178. pathname: '/knowledgeChat',
  179. search: search,
  180. })
  181. }
  182. }}
  183. >
  184. {formatMenuTitle(record.title)}
  185. </div>
  186. </Tooltip>
  187. )
  188. };
  189. }) : undefined,
  190. };
  191. })
  192. }}
  193. overlayClassName="deekSeek-dropdown"
  194. placement="bottomLeft"
  195. align={dropdownAlign}
  196. getPopupContainer={(triggerNode) => {
  197. if (isMobileScreen) {
  198. return document.body;
  199. }
  200. return triggerNode.parentElement || document.body;
  201. }}
  202. key={index}
  203. >
  204. <div
  205. className={`deekSeek-header__item ${activeNavIndex === index ? 'active' : ''}`}
  206. style={{
  207. marginRight: isMobileScreen ? 0 : 20,
  208. fontSize: isMobileScreen ? undefined : 14,
  209. fontWeight: isMobileScreen ? undefined : 600,
  210. }}
  211. title={item.title}
  212. onClick={() => setActiveNavIndex(index)}
  213. >
  214. {formatMenuTitle(item.title)}
  215. </div>
  216. </Dropdown>
  217. })
  218. }
  219. {/*<div style={{ whiteSpace: 'nowrap', marginRight: 20, color: '#98b4fa', cursor: 'pointer' }} onClick={() => {*/}
  220. {/* navigate({*/}
  221. {/* pathname: '/deepseekChat',*/}
  222. {/* })*/}
  223. {/*}}>*/}
  224. {/* DeepSeek问答*/}
  225. {/*</div>*/}
  226. {/* 右侧区域 - 开放平台按钮 */}
  227. {!isMobileScreen && (
  228. <div style={{ display: 'flex', alignItems: 'center', marginRight: 20 }}>
  229. <button
  230. className='open-platform-btn'
  231. onClick={() => {
  232. // 跳转到其他平台的逻辑,这里使用window.open举例
  233. const userInfo = localStorage.getItem('userInfo');
  234. const tokenParam = userInfo ? "?token=" + JSON.parse(userInfo).token : "";
  235. window.open('https://llm.jkec.info:11431/deepseek/questionAnswer' + tokenParam, '_blank');
  236. }}
  237. >
  238. 更多
  239. </button>
  240. </div>
  241. )}
  242. </div>
  243. <div className='deekSeek-content'>
  244. {(!isMobileScreen || !hideTitleOnMobile) && (
  245. <>
  246. <div className='deekSeek-content-title'>
  247. <img src={jkxz.src} />
  248. </div>
  249. <div className='deekSeek-content-title-sm' style={{ marginBottom: isMobileScreen ? 14 : 20 }}>
  250. 智能问答助手
  251. </div>
  252. </>
  253. )}
  254. <div
  255. className={isMobileScreen ? 'deekSeek-content-mobile' : 'deekSeek-content-pc'}
  256. style={isMobileScreen && hideTitleOnMobile ? { height: 'calc(100% - 16px)', marginTop: 16 } : undefined}
  257. >
  258. <Chat onMessageSent={() => {
  259. if (isMobileScreen) {
  260. setHideTitleOnMobile(true);
  261. }
  262. }} />
  263. </div>
  264. {isMobileScreen && (
  265. <div style={{
  266. marginTop: 8,
  267. textAlign: 'center',
  268. color: '#FFFFFF',
  269. fontSize: 12,
  270. opacity: 0.8
  271. }}>
  272. 内容由AI生成,仅供参考
  273. </div>
  274. )}
  275. </div>
  276. </div>
  277. </Spin>
  278. );
  279. };
  280. export default DeekSeek;