@gientech/modual 1.3.2 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. package/.editorconfig +38 -0
  2. package/.prettierignore +16 -0
  3. package/.prettierrc +17 -0
  4. package/README.md +129 -129
  5. package/USAGE.md +191 -0
  6. package/bash.exe.stackdump +40 -0
  7. package/components.json +21 -0
  8. package/dist/README.md +129 -0
  9. package/{assets → dist/assets}/database.svg +11 -11
  10. package/{assets → dist/assets}/database_add.svg +53 -53
  11. package/{assets → dist/assets}/database_connect.svg +66 -66
  12. package/{assets → dist/assets}/database_upload.svg +29 -29
  13. package/{assets → dist/assets}/defaultWeLogo.svg +14 -14
  14. package/{assets/index-ldqIbm0x.js → dist/assets/index-XvC_4jDB.js} +106 -101
  15. package/{assets/index-D-dGaGjW.js → dist/assets/index-mPgEc8KC.js} +288 -102
  16. package/{assets/MySQL.svg → dist/assets/mysql.svg} +14 -14
  17. package/dist/assets/style.css +1 -0
  18. package/dist/assets/style3.css +1 -0
  19. package/{chat.js → dist/chat.js} +78 -78
  20. package/dist/database.js +20 -0
  21. package/{databaseId.js → dist/databaseId.js} +1 -1
  22. package/{databaseTable.js → dist/databaseTable.js} +1 -1
  23. package/{modelManage.js → dist/modelManage.js} +1 -1
  24. package/dist/package.json +56 -0
  25. package/{sensitive.js → dist/sensitive.js} +1 -1
  26. package/{streamFilesReader.js → dist/streamFilesReader.js} +11 -11
  27. package/{worker → dist/worker}/pdf.worker.min.js +21 -21
  28. package/doc_assets/2.png +0 -0
  29. package/doc_assets/demo.md +27 -0
  30. package/doc_assets/demos/dist-app/assets/index.Dh-ZAS9Z.css +2 -0
  31. package/doc_assets/demos/dist-app/assets/index.Dv8KVW18.js +23699 -0
  32. package/doc_assets/demos/dist-app/assets/index.Dv8KVW18.js.map +1 -0
  33. package/doc_assets/demos/dist-app/index.html +14 -0
  34. package/doc_assets/demos/dist-app/vite.svg +1 -0
  35. package/doc_assets/images/1.png +0 -0
  36. package/doc_assets/images/3.png +0 -0
  37. package/doc_assets/images/component-screenshot.png +1 -0
  38. package/doc_assets/install.md +5 -0
  39. package/eslint.config.js +92 -0
  40. package/index.html +13 -0
  41. package/package.json +83 -39
  42. package/postcss.config.cjs +19 -0
  43. package/public/vite.svg +1 -0
  44. package/public/worker/pdf.worker.min.js +22 -0
  45. package/scripts/README.md +133 -0
  46. package/scripts/build-demo.js +88 -0
  47. package/scripts/demo-selector.js +216 -0
  48. package/scripts/dev-demo.js +76 -0
  49. package/scripts/preview-demo.js +130 -0
  50. package/scripts/run-demo.bat +34 -0
  51. package/src/assets/img/downArrow.png +0 -0
  52. package/src/assets/img/excel.png +0 -0
  53. package/src/assets/img/img.png +0 -0
  54. package/src/assets/img/pdf.png +0 -0
  55. package/src/assets/img/ppt.png +0 -0
  56. package/src/assets/img/txt.png +0 -0
  57. package/src/assets/img/word.png +0 -0
  58. package/src/assets/login/homeBg.png +0 -0
  59. package/src/assets/login/left.jpg +0 -0
  60. package/src/assets/login/logoImg.png +0 -0
  61. package/src/examples/LoginPage/index.tsx +18 -0
  62. package/src/examples/aaa/index.tsx +3758 -0
  63. package/src/examples/chat/components/DrawerGraphPreview.tsx +78 -0
  64. package/src/examples/chat/index.tsx +190 -0
  65. package/src/examples/gientechStreamFilesReader/index.tsx +1016 -0
  66. package/src/examples/ragDatabaseDataPage/index.tsx +36 -0
  67. package/src/examples/ragDatabaseIdPage/index.tsx +44 -0
  68. package/src/examples/ragDatabasePage/index.tsx +36 -0
  69. package/src/examples/ragModelManagePage/index.tsx +37 -0
  70. package/src/examples/ragSearchPage/index.tsx +0 -0
  71. package/src/examples/ragSensitiveWordsPage/index.tsx +32 -0
  72. package/src/examples/streamFiles/index.tsx +384 -0
  73. package/src/lib_enter.ts +38 -0
  74. package/src/main.tsx +5 -0
  75. package/src/main.tsx.backup +5 -0
  76. package/src/modules/chat/Conversations/Item.tsx +167 -0
  77. package/src/modules/chat/Conversations/List.tsx +143 -0
  78. package/src/modules/chat/Conversations/groupByTime.ts +39 -0
  79. package/src/modules/chat/Conversations/index.tsx +212 -0
  80. package/src/modules/chat/constants.tsx +33 -0
  81. package/src/modules/chat/data.txt +82 -0
  82. package/src/modules/chat/index.tsx +1908 -0
  83. package/src/modules/chat/types.ts +17 -0
  84. package/src/modules/database/CreateModal.tsx +398 -0
  85. package/src/modules/database/assets/Doris.png +0 -0
  86. package/src/modules/database/assets/PostgreSQL.png +0 -0
  87. package/src/modules/database/assets/SQLServer.png +0 -0
  88. package/src/modules/database/assets/database.svg +11 -0
  89. package/src/modules/database/assets/database_add.svg +53 -0
  90. package/src/modules/database/assets/database_connect.svg +66 -0
  91. package/src/modules/database/assets/database_upload.svg +29 -0
  92. package/src/modules/database/assets/empty.png +0 -0
  93. package/src/modules/database/assets/mysql.svg +14 -0
  94. package/src/modules/database/index.tsx +466 -0
  95. package/src/modules/database/server.ts +196 -0
  96. package/src/modules/databaseId/CustomCom.tsx +156 -0
  97. package/src/modules/databaseId/EditConfig.tsx +268 -0
  98. package/src/modules/databaseId/UploadDrawer.tsx +520 -0
  99. package/src/modules/databaseId/assets/aiOptimize.svg +10 -0
  100. package/src/modules/databaseId/assets/empty.png +0 -0
  101. package/src/modules/databaseId/assets/template.svg +6 -0
  102. package/src/modules/databaseId/assets/upload.svg +9 -0
  103. package/src/modules/databaseId/assets/useTemp.svg +6 -0
  104. package/src/modules/databaseId/index.tsx +734 -0
  105. package/src/modules/databaseId/server.ts +286 -0
  106. package/src/modules/databaseId/style.css +5 -0
  107. package/src/modules/databaseTable/EditRowDrawer.tsx +119 -0
  108. package/src/modules/databaseTable/index.tsx +357 -0
  109. package/src/modules/databaseTable/server.ts +180 -0
  110. package/src/modules/headlessChat/constants.tsx +32 -0
  111. package/src/modules/headlessChat/index.tsx +1065 -0
  112. package/src/modules/headlessChat/types.ts +23 -0
  113. package/src/modules/login/components/Login/LoginBox/index.tsx +102 -0
  114. package/src/modules/login/components/Login/RegisterBox/index.tsx +180 -0
  115. package/src/modules/login/components/Login/index.tsx +100 -0
  116. package/src/modules/login/index.tsx +106 -0
  117. package/src/modules/login/style.css +3 -0
  118. package/src/modules/login/useServices.ts +53 -0
  119. package/src/modules/login/utils.ts +42 -0
  120. package/src/modules/modelManage/ConfigDrawer.tsx +249 -0
  121. package/src/modules/modelManage/assets/empty.png +0 -0
  122. package/src/modules/modelManage/const.ts +50 -0
  123. package/src/modules/modelManage/index.tsx +439 -0
  124. package/src/modules/modelManage/server.ts +185 -0
  125. package/src/modules/nodegraph/index.tsx +1 -0
  126. package/src/modules/search/assets/Icon-history.svg +8 -0
  127. package/src/modules/search/assets/answerAwartar.png +0 -0
  128. package/src/modules/search/assets/doc.png +0 -0
  129. package/src/modules/search/assets/genera.gif +0 -0
  130. package/src/modules/search/assets/icon-robot.svg +9 -0
  131. package/src/modules/search/assets/icon-search-bar.svg +14 -0
  132. package/src/modules/search/assets/icon-sub-title.svg +3 -0
  133. package/src/modules/search/assets/icon-title.svg +9 -0
  134. package/src/modules/search/assets/icon-zoomOut.svg +9 -0
  135. package/src/modules/search/assets/iconAi.svg +9 -0
  136. package/src/modules/search/assets/pdf.png +0 -0
  137. package/src/modules/search/assets/ppt.png +0 -0
  138. package/src/modules/search/assets/search.svg +3 -0
  139. package/src/modules/search/assets/selected.svg +4 -0
  140. package/src/modules/search/assets/txt.png +0 -0
  141. package/src/modules/search/assets/xls.png +0 -0
  142. package/src/modules/search/components/AssisSelect.tsx +137 -0
  143. package/src/modules/search/components/Editor/ChatViewEditor.tsx +261 -0
  144. package/src/modules/search/components/Editor/aichat.css +1 -0
  145. package/src/modules/search/components/Editor/constant.ts +13 -0
  146. package/src/modules/search/components/Editor/index.tsx +113 -0
  147. package/src/modules/search/components/Editor/plugins/autofomatRules.ts +332 -0
  148. package/src/modules/search/components/Editor/plugins/convertImgPlugins.tsx +20 -0
  149. package/src/modules/search/components/Editor/plugins/createIndexes.tsx +38 -0
  150. package/src/modules/search/components/Editor/plugins/displayer.ts +298 -0
  151. package/src/modules/search/components/Editor/plugins/imageClick.tsx +32 -0
  152. package/src/modules/search/components/Editor/plugins/myplugin.tsx +98 -0
  153. package/src/modules/search/components/Editor/ui/avatar.tsx +19 -0
  154. package/src/modules/search/components/Editor/ui/blockquote-element.tsx +21 -0
  155. package/src/modules/search/components/Editor/ui/button.tsx +58 -0
  156. package/src/modules/search/components/Editor/ui/calendar.tsx +68 -0
  157. package/src/modules/search/components/Editor/ui/caption.tsx +46 -0
  158. package/src/modules/search/components/Editor/ui/checkbox.tsx +27 -0
  159. package/src/modules/search/components/Editor/ui/code-block-combobox.tsx +188 -0
  160. package/src/modules/search/components/Editor/ui/code-block-element.css +434 -0
  161. package/src/modules/search/components/Editor/ui/code-block-element.tsx +39 -0
  162. package/src/modules/search/components/Editor/ui/code-leaf.tsx +24 -0
  163. package/src/modules/search/components/Editor/ui/code-line-element.tsx +10 -0
  164. package/src/modules/search/components/Editor/ui/code-syntax-leaf.tsx +21 -0
  165. package/src/modules/search/components/Editor/ui/column-element.tsx +30 -0
  166. package/src/modules/search/components/Editor/ui/column-group-element.tsx +94 -0
  167. package/src/modules/search/components/Editor/ui/command.tsx +75 -0
  168. package/src/modules/search/components/Editor/ui/comment-avatar.tsx +22 -0
  169. package/src/modules/search/components/Editor/ui/comment-create-form.tsx +37 -0
  170. package/src/modules/search/components/Editor/ui/comment-item.tsx +74 -0
  171. package/src/modules/search/components/Editor/ui/comment-leaf.tsx +49 -0
  172. package/src/modules/search/components/Editor/ui/comment-more-dropdown.tsx +42 -0
  173. package/src/modules/search/components/Editor/ui/comment-reply-items.tsx +22 -0
  174. package/src/modules/search/components/Editor/ui/comment-resolve-button.tsx +32 -0
  175. package/src/modules/search/components/Editor/ui/comment-value.tsx +34 -0
  176. package/src/modules/search/components/Editor/ui/comments-popover.tsx +63 -0
  177. package/src/modules/search/components/Editor/ui/date-element.tsx +83 -0
  178. package/src/modules/search/components/Editor/ui/dialog.tsx +63 -0
  179. package/src/modules/search/components/Editor/ui/draggable.tsx +177 -0
  180. package/src/modules/search/components/Editor/ui/dropdown-menu.tsx +180 -0
  181. package/src/modules/search/components/Editor/ui/emoji-input-element.tsx +85 -0
  182. package/src/modules/search/components/Editor/ui/excalidraw-element.tsx +28 -0
  183. package/src/modules/search/components/Editor/ui/fixed-toolbar-buttons.tsx +76 -0
  184. package/src/modules/search/components/Editor/ui/fixed-toolbar.tsx +8 -0
  185. package/src/modules/search/components/Editor/ui/floating-toolbar-buttons.tsx +51 -0
  186. package/src/modules/search/components/Editor/ui/floating-toolbar.tsx +77 -0
  187. package/src/modules/search/components/Editor/ui/heading-element.tsx +48 -0
  188. package/src/modules/search/components/Editor/ui/highlight-leaf.tsx +17 -0
  189. package/src/modules/search/components/Editor/ui/hr-element.tsx +30 -0
  190. package/src/modules/search/components/Editor/ui/icons.tsx +267 -0
  191. package/src/modules/search/components/Editor/ui/image-element.tsx +74 -0
  192. package/src/modules/search/components/Editor/ui/inline-combobox.tsx +368 -0
  193. package/src/modules/search/components/Editor/ui/input.tsx +25 -0
  194. package/src/modules/search/components/Editor/ui/insert-dropdown-menu.tsx +218 -0
  195. package/src/modules/search/components/Editor/ui/kbd-leaf.tsx +20 -0
  196. package/src/modules/search/components/Editor/ui/link-element.tsx +29 -0
  197. package/src/modules/search/components/Editor/ui/link-floating-toolbar.tsx +161 -0
  198. package/src/modules/search/components/Editor/ui/list-element.tsx +30 -0
  199. package/src/modules/search/components/Editor/ui/mark-toolbar-button.tsx +24 -0
  200. package/src/modules/search/components/Editor/ui/media-embed-element.tsx +133 -0
  201. package/src/modules/search/components/Editor/ui/media-popover.tsx +97 -0
  202. package/src/modules/search/components/Editor/ui/mention-element.tsx +43 -0
  203. package/src/modules/search/components/Editor/ui/mention-input-element.tsx +141 -0
  204. package/src/modules/search/components/Editor/ui/mode-dropdown-menu.tsx +93 -0
  205. package/src/modules/search/components/Editor/ui/more-dropdown-menu.tsx +67 -0
  206. package/src/modules/search/components/Editor/ui/paragraph-element.tsx +4 -0
  207. package/src/modules/search/components/Editor/ui/placeholder.tsx +52 -0
  208. package/src/modules/search/components/Editor/ui/popover.tsx +32 -0
  209. package/src/modules/search/components/Editor/ui/resizable.tsx +66 -0
  210. package/src/modules/search/components/Editor/ui/separator.tsx +25 -0
  211. package/src/modules/search/components/Editor/ui/style.less +12 -0
  212. package/src/modules/search/components/Editor/ui/table-cell-element.tsx +143 -0
  213. package/src/modules/search/components/Editor/ui/table-element.tsx +243 -0
  214. package/src/modules/search/components/Editor/ui/table-row-element.tsx +22 -0
  215. package/src/modules/search/components/Editor/ui/tableValue.tsx +135 -0
  216. package/src/modules/search/components/Editor/ui/todo-list-element.tsx +43 -0
  217. package/src/modules/search/components/Editor/ui/toggle-element.tsx +31 -0
  218. package/src/modules/search/components/Editor/ui/toolbar.tsx +157 -0
  219. package/src/modules/search/components/Editor/ui/tooltip.tsx +65 -0
  220. package/src/modules/search/components/Editor/ui/turn-into-dropdown-menu.tsx +160 -0
  221. package/src/modules/search/components/Editor/ui/with-draggables.tsx +175 -0
  222. package/src/modules/search/components/FileList.tsx +287 -0
  223. package/src/modules/search/components/ImageGroupView/index.tsx +85 -0
  224. package/src/modules/search/components/ResultContent.tsx +232 -0
  225. package/src/modules/search/components/SearchInput.tsx +232 -0
  226. package/src/modules/search/components/SearchLanding.tsx +74 -0
  227. package/src/modules/search/components/SearchView.tsx +563 -0
  228. package/src/modules/search/components/SimpleEditor.tsx +158 -0
  229. package/src/modules/search/components/SimpleFileList.tsx +215 -0
  230. package/src/modules/search/index.tsx +10 -0
  231. package/src/modules/search/reademe.md +1 -0
  232. package/src/modules/search/servers/apis.tsx +19 -0
  233. package/src/modules/search/servers/index.ts +184 -0
  234. package/src/modules/search/style.less +503 -0
  235. package/src/modules/search/type.ts +22 -0
  236. package/src/modules/search/utils.ts +34 -0
  237. package/src/modules/sensitive/index.tsx +313 -0
  238. package/src/modules/sensitive/server.ts +122 -0
  239. package/src/modules/streamFilesReader/GientechStreamReader.tsx +1555 -0
  240. package/src/modules/streamFilesReader/components/Header/Toolbar.tsx +0 -0
  241. package/src/modules/streamFilesReader/components/Header/index.tsx +297 -0
  242. package/src/modules/streamFilesReader/index.tsx +3 -0
  243. package/src/style.css +6 -0
  244. package/src/type.d.ts +0 -0
  245. package/src/utils/commonFn.tsx +111 -0
  246. package/src/utils/gientechCommon/components/AppError.tsx +32 -0
  247. package/src/utils/gientechCommon/components/AppLoading.tsx +75 -0
  248. package/src/utils/gientechCommon/components/DeleteModal.tsx +75 -0
  249. package/src/utils/gientechCommon/components/DisplayError.tsx +33 -0
  250. package/src/utils/gientechCommon/components/DisplayLoading.tsx +38 -0
  251. package/src/utils/gientechCommon/components/FeedBackModal.tsx +310 -0
  252. package/src/utils/gientechCommon/components/FileCardCommon.tsx +82 -0
  253. package/src/utils/gientechCommon/components/FileManager/index.tsx +390 -0
  254. package/src/utils/gientechCommon/components/FileManager/style.css +5 -0
  255. package/src/utils/gientechCommon/components/Messages/GientechNewChatWelcome.tsx +296 -0
  256. package/src/utils/gientechCommon/components/Messages/ReferenceCard.tsx +339 -0
  257. package/src/utils/gientechCommon/components/Messages/RetriveItem.tsx +245 -0
  258. package/src/utils/gientechCommon/components/Messages/WebRetriveItem.tsx +209 -0
  259. package/src/utils/gientechCommon/components/Messages/defaultBot.png +0 -0
  260. package/src/utils/gientechCommon/components/Messages/defaultStyleSet.tsx +148 -0
  261. package/src/utils/gientechCommon/components/Messages/defaultWeLogo.svg +14 -0
  262. package/src/utils/gientechCommon/components/RenameModal.tsx +86 -0
  263. package/src/utils/gientechCommon/components/style.less +11 -0
  264. package/src/utils/gientechCommon/configs/commonConfig.ts +2 -0
  265. package/src/utils/gientechCommon/configs/senderConfig.ts +0 -0
  266. package/src/utils/gientechCommon/configs/stylesConfig.ts +142 -0
  267. package/src/utils/gientechCommon/hooks/AichatUseController.tsx +345 -0
  268. package/src/utils/gientechCommon/slate/converters/deserializers.ts +763 -0
  269. package/src/utils/gientechCommon/slate/converters/mockData.ts +232 -0
  270. package/src/utils/gientechCommon/slate/converters/slateConverters.ts +258 -0
  271. package/src/utils/gientechCommon/slate/richElements/index.tsx +499 -0
  272. package/src/utils/gientechCommon/utils/request.ts +37 -0
  273. package/src/utils/gientechCommon/utils/serverFn.ts +172 -0
  274. package/src/utils/index.tsx +126 -0
  275. package/src/utils/testconfigs/demologin/index.tsx +32 -0
  276. package/src/utils/testconfigs/index.ts +53 -0
  277. package/src/vite-env.d.ts +11 -0
  278. package/stats.html +4949 -0
  279. package/tailwind.config.js +170 -0
  280. package/tsconfig.app.json +30 -0
  281. package/tsconfig.app.tsbuildinfo +11 -0
  282. package/tsconfig.json +13 -0
  283. package/tsconfig.node.json +22 -0
  284. package/tsconfig.node.tsbuildinfo +1 -0
  285. package/vite.config.ts +177 -0
  286. package/workflows/release.yml +60 -0
  287. package/assets/style.css +0 -1
  288. package/assets/style3.css +0 -1
  289. package/database.js +0 -20
  290. /package/{assets → dist/assets}/Doris.png +0 -0
  291. /package/{assets → dist/assets}/PostgreSQL.png +0 -0
  292. /package/{assets → dist/assets}/SQLServer.png +0 -0
  293. /package/{assets → dist/assets}/_commonjsHelpers-gnU0ypJ3.js +0 -0
  294. /package/{assets → dist/assets}/circle-alert-g2Y6zAjt.js +0 -0
  295. /package/{assets → dist/assets}/empty.png +0 -0
  296. /package/{assets → dist/assets}/index-CEK88UzR.js +0 -0
  297. /package/{assets → dist/assets}/index-CpW6Dhpp.js +0 -0
  298. /package/{assets → dist/assets}/plus-omCUN0e3.js +0 -0
  299. /package/{assets → dist/assets}/style2.css +0 -0
  300. /package/{assets → dist/assets}/styled-components.browser.esm-DPkS13KC.js +0 -0
  301. /package/{assets → dist/assets}/x-vPcWt3fC.js +0 -0
  302. /package/{chat.d.ts → dist/chat.d.ts} +0 -0
  303. /package/{database.d.ts → dist/database.d.ts} +0 -0
  304. /package/{databaseId.d.ts → dist/databaseId.d.ts} +0 -0
  305. /package/{databaseTable.d.ts → dist/databaseTable.d.ts} +0 -0
  306. /package/{modelManage.d.ts → dist/modelManage.d.ts} +0 -0
  307. /package/{sensitive.d.ts → dist/sensitive.d.ts} +0 -0
  308. /package/{streamFilesReader.d.ts → dist/streamFilesReader.d.ts} +0 -0
  309. /package/{vite.svg → dist/vite.svg} +0 -0
@@ -0,0 +1,390 @@
1
+ import { Modal, Button, Upload, Popconfirm } from "antd";
2
+ import { FileText, FileImage, FileSpreadsheet, File, Plus, X } from 'lucide-react';
3
+ import { Icon } from '@mxmweb/zui';
4
+ import { useEffect, useState } from "react";
5
+ import './style.css';
6
+ import { type Styles } from '@mxmweb/zui';
7
+ import ReferenceCard from '../Messages/ReferenceCard';
8
+ type ThemeColors = any;
9
+ import { getTypeByName } from "../../../../utils";
10
+ import FileCardCommon from "../FileCardCommon";
11
+
12
+ // 文件类型icon获取函数,优先用用户传入styles.theme.icons
13
+ export function getFileTypeIcon(type: string, styles?: any) {
14
+ const icons = styles?.theme?.icons || {};
15
+ //console.log('type``````````', type,icons)
16
+ switch (type.toLowerCase()) {
17
+ case 'docx':
18
+ case 'doc':
19
+ return icons.docx ? (
20
+ <img src={icons.docx} alt="docx" style={{ width: 20, height: 20 }} />
21
+ ) : (
22
+ <Icon type='rag/word' size={18} />
23
+ );
24
+ case 'image':
25
+ case 'jpg':
26
+ case 'jpeg':
27
+ case 'png':
28
+ case 'gif':
29
+ case 'bmp':
30
+ case 'webp':
31
+ case 'svg':
32
+ case 'ico':
33
+ return icons.image ? (
34
+ <img src={icons.image} alt="image" style={{ width: 20, height: 20 }} />
35
+ ) : (
36
+ <Icon type='rag/pic' size={18} />
37
+ );
38
+ case 'pptx':
39
+ case 'ppt':
40
+ return icons.pptx ? (
41
+ <img src={icons.pptx} alt="pptx" style={{ width: 20, height: 20 }} />
42
+ ) : (
43
+ <Icon type='rag/ppt' size={18} />
44
+ );
45
+ case 'sheets':
46
+ case 'excel':
47
+ case 'xls':
48
+ case 'csv':
49
+ case 'xlsx':
50
+ case 'xlsm':
51
+ case 'xlsb':
52
+ case 'xltx':
53
+ case 'xltm':
54
+ case 'xlt':
55
+ case 'xlam':
56
+ return icons.sheets ? (
57
+ <img src={icons.sheets} alt="sheets" style={{ width: 20, height: 20 }} />
58
+ ) : (
59
+ <Icon type='rag/excel' size={18} />
60
+ );
61
+ case 'pdf':
62
+ return icons.pdf ? (
63
+ <img src={icons.pdf} alt="pdf" style={{ width: 20, height: 20 }} />
64
+ ) : (
65
+ <Icon type='rag/pdf' size={18} />
66
+ );
67
+ case 'txt':
68
+ return icons.txt ? (
69
+ <img src={icons.txt} alt="txt" style={{ width: 20, height: 20 }} />
70
+ ) : (
71
+ <Icon type='rag/txt' size={18} />
72
+ );
73
+ case 'md':
74
+ return icons.md ? (
75
+ <img src={icons.md} alt="txt" style={{ width: 20, height: 20 }} />
76
+ ) : (
77
+ <Icon type='rag/document' size={18} />
78
+ );
79
+ case 'json':
80
+ return icons.json ? (
81
+ <img src={icons.json} alt="json" style={{ width: 20, height: 20 }} />
82
+ ) : (
83
+ <Icon type='rag/json' size={18} />
84
+ );
85
+ case 'html':
86
+ case 'htm':
87
+ return icons.html ? (
88
+ <img src={icons.html} alt="html" style={{ width: 20, height: 20 }} />
89
+ ) : (
90
+ <Icon type='rag/url' size={18} />
91
+ );
92
+ case 'xml':
93
+ default:
94
+ return <Icon type='rag/file' size={18} />;
95
+ }
96
+ }
97
+ interface FileItem {
98
+ file: File;
99
+ preview?: string;
100
+ type: string;
101
+ status?: 'pending' | 'uploading' | 'uploaded' | 'error';
102
+ url?: string;
103
+ error?: string;
104
+ }
105
+
106
+ // Mock数据
107
+ const mockFiles: FileItem[] = [
108
+ {
109
+ file: {
110
+ name: '产品需求文档.pdf',
111
+ size: 1024 * 1024 * 2.5, // 2.5MB
112
+ type: 'application/pdf',
113
+ } as File,
114
+ type: 'pdf',
115
+ status: 'uploaded',
116
+ url: 'https://example.com/file1.pdf',
117
+ },
118
+ {
119
+ file: {
120
+ name: '数据分析报告.xlsx',
121
+ size: 1024 * 1024 * 1.2, // 1.2MB
122
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
123
+ } as File,
124
+ type: 'excel',
125
+ status: 'uploaded',
126
+ url: 'https://example.com/file3.xlsx',
127
+ },
128
+ {
129
+ file: {
130
+ name: '系统架构图.png',
131
+ size: 1024 * 512, // 512KB
132
+ type: 'image/png',
133
+ } as File,
134
+ type: 'image',
135
+ status: 'uploaded',
136
+ url: 'https://example.com/file2.png',
137
+ },
138
+ ];
139
+
140
+ const formatFileSize = (bytes: number) => {
141
+ if (bytes < 1024) return bytes + ' B';
142
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
143
+ return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
144
+ };
145
+
146
+ export default function FileManager({
147
+ open,
148
+ onCancel,
149
+ files = mockFiles,
150
+ currentFiles = [],
151
+ onUpload,
152
+ onRemoveFile,
153
+ styles,
154
+ eventsEmit
155
+ }: {
156
+ open: boolean;
157
+ onCancel: () => void;
158
+ files: FileItem[];
159
+ styles: Styles;
160
+ currentFiles: FileItem[];
161
+ onUpload?: (files: FileList) => void;
162
+ onRemoveFile?: (file: FileItem, idx: number, type: 'uploaded' | 'pending') => void;
163
+ eventsEmit?: (eventName: string, payload?: any) => void;
164
+ }) {
165
+
166
+
167
+ // 状态映射
168
+ const statusMap = {
169
+ pending: '待上传',
170
+ uploading: '上传中',
171
+ uploaded: '已上传',
172
+ analyzing: '解析中',
173
+ analyze_failed: '解析失败',
174
+ error: '失败',
175
+ };
176
+
177
+ // 选中状态
178
+ const [selectedFiles, setSelectedFiles] = useState<number[]>([]);
179
+
180
+ const handleSelect = (idx: number) => {
181
+ setSelectedFiles(prev => prev.includes(idx) ? prev.filter(i => i !== idx) : [...prev, idx]);
182
+ };
183
+
184
+ // 已上传文件删除事件抛出
185
+ const handleRemove = (file: FileItem, idx: number) => {
186
+ eventsEmit && eventsEmit('uploaded_file:removeFromTemp', { file, idx });
187
+ };
188
+
189
+
190
+ // 主题色,提前定义,避免未初始化访问
191
+ const themeColors: ThemeColors = (styles && styles.theme && styles.theme.colors) ? styles.theme.colors : {
192
+ primary: '#007bff',
193
+ secondary: '#6c757d',
194
+ success: '#008000',
195
+ warning: '#FFA500',
196
+ error: '#FF0000',
197
+ info: '#0000FF',
198
+ background: '#f8f9fa',
199
+ text: '#343a40',
200
+ border: '#dee2e6',
201
+ disabled: '#808080',
202
+ disabledBackground: '#F5F5F5',
203
+ disabledText: '#808080',
204
+ shadow: '#000000',
205
+ appBackground: '#fff',
206
+ };
207
+
208
+ // 拆分文件
209
+ const uploadedFileCards = files.map((f:any, idx) => {
210
+ // console.log(f,'fffffffff')
211
+ return (
212
+ <div key={f.file.name + idx} className="relative flex flex-col gap-2.5 items-center justify-center">
213
+ <div className="absolute right-1 top-1 z-10">
214
+ <Popconfirm
215
+ title="确认从临时对话知识库移除该文件?"
216
+ onConfirm={() => handleRemove(f, idx)}
217
+ okText="确认"
218
+ cancelText="取消"
219
+ >
220
+ <button
221
+ className="bg-white cursor-pointer rounded-full p-0.5"
222
+ style={{
223
+ lineHeight: 0,
224
+ color: themeColors && themeColors.text ? themeColors.text : '#FF0000',
225
+ transition: 'background 0.2s, color 0.2s',
226
+ }}
227
+ onMouseOver={e => {
228
+ (e.currentTarget as HTMLElement).style.color = themeColors && themeColors.error ? themeColors.error : '#FF0000';
229
+ }}
230
+ onMouseOut={e => {
231
+ (e.currentTarget as HTMLElement).style.color = themeColors.text!;
232
+ }}
233
+ title="移除"
234
+ >
235
+ <X className="w-3 h-3" />
236
+ </button>
237
+ </Popconfirm>
238
+ </div>
239
+ <ReferenceCard
240
+ file_type={getTypeByName(f.file.name||f.name)}
241
+ file_name={f.name || f.file.name}
242
+ url={f.url}
243
+ retrieve_tags={[]}
244
+ styles={styles}
245
+ isUploadFile={true}
246
+ eventsEmit={eventsEmit}
247
+ parse_url={f.convertedFilePath}
248
+ pdfPages={f.pdfPages || 0}
249
+ />
250
+ </div>
251
+ )});
252
+ const pendingFileCards = currentFiles.map((f, idx) => {
253
+ const fileType = f.file.name.split('.').pop() || '';
254
+ const icon = getFileTypeIcon(fileType, styles);
255
+ return (
256
+ <FileCardCommon
257
+ key={f.file.name + idx}
258
+ cardId={`pending-file-card-${idx}`}
259
+ fileName={f.file.name}
260
+ fileSize={f.file.size}
261
+ icon={icon}
262
+ statusText={statusMap[f.status || 'pending']}
263
+ statusColor="text-gray-400"
264
+ showRemove={true}
265
+ onRemove={() => onRemoveFile && onRemoveFile(f, idx, 'pending')}
266
+ themeColors={themeColors}
267
+ style={{ boxShadow: 'none', height: 55, background: '#f8fafc' }}
268
+ />
269
+ );
270
+ });
271
+
272
+ // 多选删除
273
+ const handleBatchRemove = () => {
274
+ if (eventsEmit) {
275
+ const filesToRemove = selectedFiles.map(idx => ({ file: files[idx], idx })).filter(f => f.file);
276
+ eventsEmit('uploaded_file:remove_batch', filesToRemove);
277
+ }
278
+ setSelectedFiles([]);
279
+ };
280
+
281
+ // 主题色
282
+ const batchDeleteBtnStyle = selectedFiles.length > 0
283
+ ? {
284
+ borderColor: themeColors && themeColors.error ? themeColors.error : '#FF0000',
285
+ background: themeColors && themeColors.error ? themeColors.error + '22' : '#FF000022',
286
+ color: themeColors && themeColors.error ? themeColors.error : '#FF0000',
287
+ }
288
+ : {
289
+ borderColor: themeColors && themeColors.disabledText ? themeColors.disabledText : '#808080',
290
+ background: themeColors && themeColors.disabledBackground ? themeColors.disabledBackground : '#F5F5F5',
291
+ color: themeColors && themeColors.disabledText ? themeColors.disabledText : '#808080',
292
+ cursor: 'not-allowed',
293
+ };
294
+
295
+ //console.log(files,'weljkfewoifho23hf8h3289fh8923hf982h389fh2389fh8923h89')
296
+ return (
297
+ <Modal
298
+ open={open}
299
+ onCancel={onCancel}
300
+ footer={null}
301
+ title={'对话临时文件知识库'}
302
+ closable={false}
303
+ width={800}
304
+ styles={{
305
+ body: {
306
+ padding: '0',
307
+ maxHeight: '70vh',
308
+ overflow: 'auto',
309
+ },
310
+ }}
311
+ >
312
+ <div className="file-manager-modal space-y-6 px-4 py-4">
313
+ {/* 已上传文件区域 */}
314
+ <div className="">
315
+ <div className="flex items-center mb-2 justify-between">
316
+ <div className="flex items-center">
317
+ <span className="text-xs font-semibold text-gray-700">已上传文件</span>
318
+ <span className="ml-2 text-xs text-gray-400">{files.length} 个</span>
319
+ </div>
320
+ {/* <button
321
+ className="ml-4 px-2 cursor-pointer py-1 text-xs rounded border"
322
+ disabled={selectedFiles.length === 0}
323
+ onClick={handleBatchRemove}
324
+ style={batchDeleteBtnStyle}
325
+ >
326
+ 删除知识文档
327
+ </button> */}
328
+ </div>
329
+ <div
330
+ className="w-full relative min-h-[200px] max-h-[260px] p-2 overflow-y-auto"
331
+ style={{ overflowX: 'hidden' }}
332
+ >
333
+ <div className="flex flex-wrap gap-1">
334
+ {uploadedFileCards.length > 0 ? (
335
+ uploadedFileCards
336
+ ) : (
337
+ <div className="flex items-center w-full h-full py-10 justify-center text-gray-400 text-sm">
338
+ 暂无已上传文件
339
+ </div>
340
+ )}
341
+ </div>
342
+ </div>
343
+ </div>
344
+ {/* 待上传文件区域 */}
345
+ <div>
346
+ <div className="flex items-center mb-2">
347
+ <span className="text-xs font-semibold text-gray-700">待上传文件</span>
348
+ <span className="ml-2 text-xs text-gray-400">{currentFiles.length} 个</span>
349
+ </div>
350
+ <div className="flex gap-2 overflow-x-auto pb-2">
351
+ {pendingFileCards}
352
+ {/* 上传卡片 */}
353
+ <Upload.Dragger
354
+ multiple
355
+ showUploadList={false}
356
+ beforeUpload={(file, fileList) => {
357
+ if (file === fileList[0]) {
358
+ onUpload?.(fileList as unknown as FileList);
359
+ }
360
+ return false;
361
+ }}
362
+ className="!bg-gray-50 !border-dashed !border-gray-300 hover:!border-blue-400 cursor-pointer min-w-[160px] max-w-[220px] flex flex-row items-center justify-center border-2 rounded-lg transition-all"
363
+ style={{ height: 45, boxShadow: 'none', padding: 0 }}
364
+ >
365
+ <div className="flex flex-row items-center pb-8 justify-center">
366
+ <Plus size={20} className="text-blue-400 mr-2" />
367
+ <div className="text-xs text-gray-500">上传文件</div>
368
+ </div>
369
+ </Upload.Dragger>
370
+ </div>
371
+ </div>
372
+ <div className="flex justify-end gap-2">
373
+ <Button type="primary" onClick={onCancel}>
374
+ 确认
375
+ </Button>
376
+ {/* <Button onClick={onCancel}>取消</Button> */}
377
+ </div>
378
+ </div>
379
+ <style>{`
380
+ .file-manager-modal .ant-upload-wrapper,
381
+ .file-manager-modal .ant-upload-drag,
382
+ .file-manager-modal .ant-upload-drag-container {
383
+ min-height: 55px !important;
384
+ height: 55px !important;
385
+ padding: 0 !important;
386
+ }
387
+ `}</style>
388
+ </Modal>
389
+ );
390
+ }
@@ -0,0 +1,5 @@
1
+ .ant-upload-drag-container {
2
+ height: 45px !important;
3
+ min-height: 45px !important;
4
+ padding: 0 !important;
5
+ }
@@ -0,0 +1,296 @@
1
+ import React, { useEffect, useMemo, useState, useRef } from 'react';
2
+ import { Popover } from 'antd';
3
+ import { type Styles, defaultTheme } from '@mxmweb/zui';
4
+ import { uid } from 'uid';
5
+ import defaultWeLogo from './defaultWeLogo.svg';
6
+ import defaultBot from './defaultBot.png';
7
+
8
+ const createWelcomeStyles = (colors: any, classId: string) => {
9
+ const c = { ...defaultTheme.colors, ...colors };
10
+ return `
11
+ .g-welcome-${classId} .g-welcome-title {
12
+ background-image: linear-gradient(90deg, #3262FA 0%, #6C18FF 100%);
13
+ -webkit-background-clip: text;
14
+ background-clip: text;
15
+ color: transparent;
16
+ -webkit-text-fill-color: transparent;
17
+ }
18
+ .g-welcome-${classId} .g-welcome-subtitle {
19
+ color: ${c.disabled};
20
+ }
21
+ .g-welcome-${classId} .g-welcome-btn {
22
+ background-color: #ffffff;
23
+ border-color: ${c.border};
24
+ color: ${c.text};
25
+ height: 36px;
26
+ border-width: 1px;
27
+ box-shadow: 0 1px 2px rgba(31,35,41,0.04);
28
+ }
29
+ .g-welcome-${classId} .g-welcome-btn:hover {
30
+ border-color: ${c.primary};
31
+ color: ${c.primary};
32
+ background-color: #ffffff;
33
+ box-shadow: 0 2px 6px rgba(31,35,41,0.08);
34
+ }
35
+ .g-welcome-${classId} .g-welcome-btn.active {
36
+ background-image: linear-gradient(90deg, #F1F8FF 0%, #F9F4FF 100%);
37
+ border-color: ${c.primary};
38
+ box-shadow: 0 4px 10px rgba(24, 144, 255, 0.25);
39
+ }
40
+ .g-welcome-${classId} .g-welcome-btn .icon-badge {
41
+ width: 24px;
42
+ height: 24px;
43
+ border-radius: 9999px;
44
+ display: inline-flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ background: radial-gradient(100% 100% at 50% 0%, #F2F3F5 0%, #FFFFFF 100%);
48
+ box-shadow: inset 0 0 0 1px ${c.border};
49
+ }
50
+ .g-welcome-${classId} .g-welcome-pagination-btn {
51
+ color: ${c.primary};
52
+ }
53
+ .g-welcome-${classId} .g-welcome-pagination-btn:disabled {
54
+ color: ${c.disabled};
55
+ cursor: not-allowed;
56
+ }
57
+ .g-welcome-${classId} .g-welcome-pagination-text {
58
+ color: ${c.text};
59
+ }
60
+ `;
61
+ }
62
+
63
+ function AssistantConfigCard({ config, styles }: { config: any, styles?: Styles }) {
64
+ if (!config) return null;
65
+ const parseConfig = JSON.parse(config.configJson);
66
+ //console.log('parseConfig',parseConfig);
67
+
68
+ const colors = useMemo(() => ({
69
+ ...defaultTheme.colors,
70
+ ...styles?.theme?.colors
71
+ }), [styles]);
72
+
73
+ return (
74
+ <div className="w-[340px] rounded-xl p-4 animate-fade-in bg-white">
75
+ {/* 标题区 */}
76
+ <div className="flex items-center mb-2">
77
+ <span className="text-md font-bold truncate mr-2" style={{ color: colors.primary }}>{parseConfig.config_name || '助手配置'}</span>
78
+ <span
79
+ className="text-xs truncate rounded px-2 py-0.5"
80
+ style={{
81
+ backgroundColor: `${colors.primary}1A`,
82
+ color: colors.disabled
83
+ }}
84
+ >{parseConfig.model_name}</span>
85
+ </div>
86
+ {/* 默认回复 */}
87
+ {/* <div className="text-xs text-gray-500 mb-2 break-all whitespace-pre-line">{parseConfig.defaultAnswer}</div> */}
88
+ <div className="border-b my-2" style={{ borderColor: colors.border }} />
89
+ {/* 基础参数 */}
90
+ <div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-700 mb-2" style={{ color: colors.text }}>
91
+ <div>上下文最大轮数:<span className="font-semibold">{parseConfig.max_round}</span></div>
92
+ <div>最大令牌数:<span className="font-semibold">{parseConfig.max_tokens}</span></div>
93
+ <div>温度:<span className="font-semibold">{parseConfig.temperature}</span></div>
94
+ <div>召回数:<span className="font-semibold">{parseConfig.top_k}</span></div>
95
+ <div>多样性:<span className="font-semibold">{parseConfig.top_p}</span></div>
96
+ <div>相似度阈值:<span className="font-semibold">{parseConfig.score_threshold}</span></div>
97
+ </div>
98
+ {/* 知识库 */}
99
+ <div className="mb-2">
100
+ <div className="text-xs text-gray-400 mb-1" style={{ color: colors.disabled }}>关联知识库:</div>
101
+ <div className="flex flex-wrap gap-1">
102
+ {parseConfig.knowledge_base_name ? parseConfig.knowledge_base_name.split(';').map((kb: any,index:number) => (
103
+ <span
104
+ key={index}
105
+ className="px-2 py-0.5 rounded-full text-xs"
106
+ style={{
107
+ backgroundColor: `${colors.primary}1A`,
108
+ color: colors.primary
109
+ }}
110
+ >{kb}</span>
111
+ )) : <span className="text-gray-300" style={{ color: colors.disabled }}>无</span>}
112
+ </div>
113
+ </div>
114
+ {/* 其他开关 */}
115
+ <div className='mb-2'>
116
+ <div className="text-xs text-gray-400 mb-1" style={{ color: colors.disabled }}>开启功能:</div>
117
+ <div className="flex flex-wrap gap-2 text-xs mt-2">
118
+ {!!parseConfig.enabled_faq && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>FAQ</span>}
119
+ {!!parseConfig.enabled_graph && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>图谱</span>}
120
+ {!!parseConfig.dependOnKb && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>强知识依赖</span>}
121
+ {!!parseConfig.enabled_table_select && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>表格筛选</span>}
122
+ {!!parseConfig.enabled_rerank && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>精排模式</span>}
123
+ {!!parseConfig.need_trace_source && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>溯源</span>}
124
+ {!!parseConfig.is_download && <span className="px-2 py-0.5 rounded" style={{ backgroundColor: `${colors.success}1A`, color: colors.success }}>下载溯源</span>}
125
+ </div>
126
+ </div>
127
+ </div>
128
+ );
129
+ }
130
+
131
+ function useTypewriter(text: string, deps: any[] = [], speed = 60) {
132
+ const [displayed, setDisplayed] = useState('');
133
+ useEffect(() => {
134
+ setDisplayed('');
135
+ if (!text) return;
136
+ let i = 0;
137
+ const timer = setInterval(() => {
138
+ setDisplayed(prev => {
139
+ if (i >= text.length) {
140
+ clearInterval(timer);
141
+ return prev;
142
+ }
143
+ i++;
144
+ return text.slice(0, i);
145
+ });
146
+ }, speed);
147
+ return () => clearInterval(timer);
148
+ }, [text, ...deps]);
149
+ return displayed;
150
+ }
151
+
152
+ // 添加类型定义,支持 selectedId 和 onSelectAssistant
153
+ interface GientechNewChatWelcomeProps {
154
+ assistantList: any[];
155
+ eventsEmit?: (type: string, data?: any) => void;
156
+ styles?: Styles;
157
+ selectedId?: string;
158
+ onSelectAssistant?: (id: string) => void;
159
+ productLogo?: string; // 外部传入的产品logo
160
+ }
161
+
162
+ function GientechNewChatWelcome(props: GientechNewChatWelcomeProps) {
163
+ const { assistantList, eventsEmit, styles, selectedId, onSelectAssistant, productLogo } = props;
164
+ const [currentPage, setCurrentPage] = useState(1);
165
+ const pageSize = 12;
166
+
167
+ // 只在 selectedId 变化时触发事件,且去重
168
+ const prevSelectedId = useRef<string | undefined>();
169
+ useEffect(() => {
170
+ if (selectedId && prevSelectedId.current !== selectedId) {
171
+ eventsEmit?.('conversation:new_assistant_change', { assistantId: selectedId });
172
+ prevSelectedId.current = selectedId;
173
+ }
174
+ }, [selectedId, eventsEmit]);
175
+
176
+ const classId = useMemo(() => uid(), []);
177
+
178
+ useEffect(() => {
179
+ if (styles?.theme?.colors) {
180
+ const styleTag = document.createElement('style');
181
+ styleTag.innerHTML = createWelcomeStyles(styles.theme.colors, classId);
182
+ styleTag.id = `g-welcome-styles-${classId}`;
183
+ document.head.appendChild(styleTag);
184
+
185
+ return () => {
186
+ const el = document.getElementById(styleTag.id);
187
+ if (el) {
188
+ el.remove();
189
+ }
190
+ };
191
+ }
192
+ }, [styles, classId]);
193
+
194
+ const selectAssistant = useMemo(() => {
195
+ return assistantList.find(assistant => assistant.id === selectedId);
196
+ }, [assistantList, selectedId]);
197
+
198
+ const selectAssistantConfig = useMemo(() => {
199
+ return JSON.parse(selectAssistant?.configJson || '{}');
200
+ }, [selectAssistant]);
201
+
202
+ // 分页逻辑
203
+ const totalPages = Math.ceil((assistantList?.length || 0) / pageSize);
204
+ const currentAssistants = assistantList?.slice((currentPage - 1) * pageSize, currentPage * pageSize) || [];
205
+
206
+ // 当选中助手时,自动跳转到对应页面
207
+ useEffect(() => {
208
+ if (selectedId && assistantList) {
209
+ const selectedIndex = assistantList.findIndex(a => a.id === selectedId);
210
+ if (selectedIndex !== -1) {
211
+ const targetPage = Math.floor(selectedIndex / pageSize) + 1;
212
+ setCurrentPage(targetPage);
213
+ }
214
+ }
215
+ }, [selectedId, assistantList, pageSize]);
216
+
217
+ const prologue = selectAssistantConfig.prologue || '您好,欢迎使用小鲸智能问答';
218
+ const prologueTypewriter = useTypewriter(prologue, [selectedId], 30);
219
+
220
+ return (
221
+ <div className={`flex flex-col items-center justify-center h-full w-full g-welcome-${classId}`}>
222
+ {/* 产品Logo */}
223
+ <img
224
+ src={productLogo || (defaultWeLogo as unknown as string)}
225
+ alt="logo"
226
+ className="mb-4"
227
+ style={{ width: 100, height: 100 }}
228
+ />
229
+ <div className="text-3xl font-bold mb-2 g-welcome-title">{prologueTypewriter}</div>
230
+ <div className="text-sm text-gray-500 mb-20">请选择一个智能助手,开始你的智能问答之旅</div>
231
+ {!selectedId && <div className="flex mb-2 g-welcome-subtitle">请选择一个智能助手</div>}
232
+ <div className="flex flex-wrap gap-3 px-5 justify-center mb-4">
233
+ {currentAssistants && currentAssistants.length > 0 ? (
234
+ currentAssistants.map(assistant => {
235
+ const isActive = selectedId === assistant.id;
236
+ // 图标解析:优先 assistant.icon,其次配置中的 icon/avatar/logo,最后使用默认
237
+ let iconSrc: string | undefined = assistant.icon;
238
+ try {
239
+ const cfg = JSON.parse(assistant.configJson || '{}');
240
+ iconSrc = iconSrc || cfg.icon || cfg.avatar || cfg.logo;
241
+ } catch (e) {
242
+ // ignore json parse error
243
+ }
244
+ iconSrc = iconSrc || (defaultBot as unknown as string);
245
+ return (
246
+ <Popover
247
+ key={assistant.id}
248
+ content={() => <AssistantConfigCard config={assistantList.find(item => item.id === assistant.id)} styles={styles} />}
249
+ trigger="hover"
250
+ placement="bottom"
251
+ >
252
+ <button
253
+ className={`g-welcome-btn px-3 cursor-pointer rounded-full border font-medium min-w-[160px] text-sm transition-all flex items-center gap-2 ${isActive ? 'active' : ''}`}
254
+ onClick={() => onSelectAssistant?.(assistant.id)}
255
+ title={assistant.name}
256
+ >
257
+ <span className="icon-badge">
258
+ <img src={iconSrc} alt="icon" style={{ width: 16, height: 16, borderRadius: 4 }} />
259
+ </span>
260
+ <span className="truncate max-w-[180px]">{assistant.name}</span>
261
+ </button>
262
+ </Popover>
263
+ );
264
+ })
265
+ ) : (
266
+ <div className="g-welcome-subtitle">暂无可用助手</div>
267
+ )}
268
+ </div>
269
+ {/* 分页控制 */}
270
+ {totalPages > 1 && (
271
+ <div className="flex items-center gap-3 text-sm">
272
+ <button
273
+ className="g-welcome-pagination-btn px-3 py-1 rounded transition-colors"
274
+ onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
275
+ disabled={currentPage === 1}
276
+ >
277
+ 上一页
278
+ </button>
279
+ <span className="g-welcome-pagination-text">
280
+ {currentPage} / {totalPages}
281
+ </span>
282
+ <button
283
+ className="g-welcome-pagination-btn px-3 py-1 rounded transition-colors"
284
+ onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
285
+ disabled={currentPage === totalPages}
286
+ >
287
+ 下一页
288
+ </button>
289
+ </div>
290
+ )}
291
+ </div>
292
+ );
293
+ }
294
+
295
+ // 只在assistantList、defaultSelect、styles变化时才重渲染
296
+ export default GientechNewChatWelcome;