diff --git a/package.json b/package.json index d4c2dd3c4f..32dc84a6a1 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "officeparser": "^4.1.1", "os-proxy-config": "^1.1.2", "proxy-agent": "^6.5.0", + "react-query": "^3.39.3", "tar": "^7.4.3", "turndown": "^7.2.0", "turndown-plugin-gfm": "^1.0.2", diff --git a/src/renderer/src/pages/home/Messages/ChatFlowHistory.tsx b/src/renderer/src/pages/home/Messages/ChatFlowHistory.tsx index 7c9b536ae6..73a3208ca2 100644 --- a/src/renderer/src/pages/home/Messages/ChatFlowHistory.tsx +++ b/src/renderer/src/pages/home/Messages/ChatFlowHistory.tsx @@ -167,7 +167,7 @@ interface ChatFlowHistoryProps { } // 定义节点和边的类型 -type FlowNode = Node +type FlowNode = Node type FlowEdge = Edge // 统一的边样式 diff --git a/src/renderer/src/pages/home/Messages/CitationsList.tsx b/src/renderer/src/pages/home/Messages/CitationsList.tsx index 01798c62ca..de8ae5e2e6 100644 --- a/src/renderer/src/pages/home/Messages/CitationsList.tsx +++ b/src/renderer/src/pages/home/Messages/CitationsList.tsx @@ -5,6 +5,7 @@ import { Button, Drawer } from 'antd' import { FileSearch } from 'lucide-react' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' +import { QueryClient, QueryClientProvider } from 'react-query' import styled from 'styled-components' export interface Citation { @@ -21,6 +22,17 @@ interface CitationsListProps { citations: Citation[] } +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: Infinity, + cacheTime: Infinity, + refetchOnWindowFocus: false, + retry: false + } + } +}) + /** * 限制文本长度 * @param text @@ -50,61 +62,49 @@ const CitationsList: React.FC = ({ citations }) => { const { t } = useTranslation() const [open, setOpen] = useState(false) - const hasCitations = citations.length > 0 - const count = citations.length const previewItems = citations.slice(0, 3) - - if (!hasCitations) return null - - const handleOpen = () => { - setOpen(true) - } - - const handleClose = () => { - setOpen(false) - } + const count = citations.length + if (!count) return null return ( - <> - - - {previewItems.map((c, i) => ( - - {c.type === 'websearch' && c.url ? ( - - ) : ( - - )} - - ))} - - {t('message.citation', { count: count })} - + + <> + setOpen(true)}> + + {previewItems.map((c, i) => ( + + {c.type === 'websearch' && c.url ? ( + + ) : ( + + )} + + ))} + + {t('message.citation', { count })} + - - {citations.map((citation) => ( - - {citation.type === 'websearch' ? ( - - ) : ( - - )} - - ))} - - + setOpen(false)} + open={open} + width={680} + destroyOnClose={true} // unmount on close + > + {open && + citations.map((citation) => ( + + {citation.type === 'websearch' ? ( + + ) : ( + + )} + + ))} + + + ) } @@ -212,14 +212,14 @@ const WebSearchCard = styled.div` padding: 12px; margin-bottom: 8px; border-radius: 8px; - border: 1px solid var(--color-border); - background-color: var(--color-bg-2); + border: 1px solid #e5e6eb; + background-color: #f8f9fa; transition: all 0.3s ease; &:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); - background-color: var(--color-bg-3); - border-color: var(--color-primary-light); + background-color: #f1f3f5; + border-color: rgba(24, 144, 255, 0.1); transform: translateY(-2px); } ` diff --git a/src/renderer/src/pages/home/Tabs/TopicsTab.tsx b/src/renderer/src/pages/home/Tabs/TopicsTab.tsx index 59cca8d739..8970c64397 100644 --- a/src/renderer/src/pages/home/Tabs/TopicsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/TopicsTab.tsx @@ -264,22 +264,22 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic key: 'export', icon: , children: [ - exportMenuOptions.image !== false && { + exportMenuOptions.image && { label: t('chat.topics.export.image'), key: 'image', onClick: () => EventEmitter.emit(EVENT_NAMES.EXPORT_TOPIC_IMAGE, topic) }, - exportMenuOptions.markdown !== false && { + exportMenuOptions.markdown && { label: t('chat.topics.export.md'), key: 'markdown', onClick: () => exportTopicAsMarkdown(topic) }, - exportMenuOptions.markdown_reason !== false && { + exportMenuOptions.markdown_reason && { label: t('chat.topics.export.md.reason'), key: 'markdown_reason', onClick: () => exportTopicAsMarkdown(topic, true) }, - exportMenuOptions.docx !== false && { + exportMenuOptions.docx && { label: t('chat.topics.export.word'), key: 'word', onClick: async () => { @@ -287,14 +287,14 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic window.api.export.toWord(markdown, removeSpecialCharactersForFileName(topic.name)) } }, - exportMenuOptions.notion !== false && { + exportMenuOptions.notion && { label: t('chat.topics.export.notion'), key: 'notion', onClick: async () => { exportTopicToNotion(topic) } }, - exportMenuOptions.yuque !== false && { + exportMenuOptions.yuque && { label: t('chat.topics.export.yuque'), key: 'yuque', onClick: async () => { @@ -302,7 +302,7 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic exportMarkdownToYuque(topic.name, markdown) } }, - exportMenuOptions.obsidian !== false && { + exportMenuOptions.obsidian && { label: t('chat.topics.export.obsidian'), key: 'obsidian', onClick: async () => { @@ -310,7 +310,7 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic await ObsidianExportPopup.show({ title: topic.name, markdown, processingMethod: '3' }) } }, - exportMenuOptions.joplin !== false && { + exportMenuOptions.joplin && { label: t('chat.topics.export.joplin'), key: 'joplin', onClick: async () => { @@ -318,7 +318,7 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic exportMarkdownToJoplin(topic.name, markdown) } }, - exportMenuOptions.siyuan !== false && { + exportMenuOptions.siyuan && { label: t('chat.topics.export.siyuan'), key: 'siyuan', onClick: async () => { diff --git a/src/renderer/src/store/messageBlock.ts b/src/renderer/src/store/messageBlock.ts index 561396fa43..db5ec338f8 100644 --- a/src/renderer/src/store/messageBlock.ts +++ b/src/renderer/src/store/messageBlock.ts @@ -193,7 +193,7 @@ const formatCitationsFromBlock = (block: CitationMessageBlock | undefined): Cita let url = result.sourceUrl let title = result.sourceUrl - let showFavicon = true + const showFavicon = true // 如果匹配文件链接格式 [filename](http://file/xxx) if (fileMatch) { diff --git a/yarn.lock b/yarn.lock index b2bb107c51..854ed8e275 100644 --- a/yarn.lock +++ b/yarn.lock @@ -383,6 +383,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2": + version: 7.27.1 + resolution: "@babel/runtime@npm:7.27.1" + checksum: 10c0/530a7332f86ac5a7442250456823a930906911d895c0b743bf1852efc88a20a016ed4cd26d442d0ca40ae6d5448111e02a08dd638a4f1064b47d080e2875dc05 + languageName: node + linkType: hard + "@babel/template@npm:^7.26.9, @babel/template@npm:^7.27.0": version: 7.27.0 resolution: "@babel/template@npm:7.27.0" @@ -4418,6 +4425,7 @@ __metadata: react-i18next: "npm:^14.1.2" react-infinite-scroll-component: "npm:^6.1.0" react-markdown: "npm:^9.0.1" + react-query: "npm:^3.39.3" react-redux: "npm:^9.1.2" react-router: "npm:6" react-router-dom: "npm:6" @@ -5066,6 +5074,13 @@ __metadata: languageName: node linkType: hard +"big-integer@npm:^1.6.16": + version: 1.6.52 + resolution: "big-integer@npm:1.6.52" + checksum: 10c0/9604224b4c2ab3c43c075d92da15863077a9f59e5d4205f4e7e76acd0cd47e8d469ec5e5dba8d9b32aa233951893b29329ca56ac80c20ce094b4a647a66abae0 + languageName: node + linkType: hard + "bignumber.js@npm:^9.0.0": version: 9.2.1 resolution: "bignumber.js@npm:9.2.1" @@ -5183,6 +5198,22 @@ __metadata: languageName: node linkType: hard +"broadcast-channel@npm:^3.4.1": + version: 3.7.0 + resolution: "broadcast-channel@npm:3.7.0" + dependencies: + "@babel/runtime": "npm:^7.7.2" + detect-node: "npm:^2.1.0" + js-sha3: "npm:0.8.0" + microseconds: "npm:0.2.0" + nano-time: "npm:1.0.0" + oblivious-set: "npm:1.0.0" + rimraf: "npm:3.0.2" + unload: "npm:2.2.0" + checksum: 10c0/95978446f24c685be666f5508a91350bcd4075c08feda929d26c0c678fb24bd421901f19fa8d36cb6f5ed480a334072f3bdce48fa177a8cb29793d88693911cc + languageName: node + linkType: hard + "browser-image-compression@npm:^2.0.2": version: 2.0.2 resolution: "browser-image-compression@npm:2.0.2" @@ -6636,7 +6667,7 @@ __metadata: languageName: node linkType: hard -"detect-node@npm:^2.0.4": +"detect-node@npm:^2.0.4, detect-node@npm:^2.1.0": version: 2.1.0 resolution: "detect-node@npm:2.1.0" checksum: 10c0/f039f601790f2e9d4654e499913259a798b1f5246ae24f86ab5e8bd4aaf3bce50484234c494f11fb00aecb0c6e2733aa7b1cf3f530865640b65fbbd65b2c4e09 @@ -10172,6 +10203,13 @@ __metadata: languageName: node linkType: hard +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 10c0/43a21dc7967c871bd2c46cb1c2ae97441a97169f324e509f382d43330d8f75cf2c96dba7c806ab08a425765a9c847efdd4bffbac2d99c3a4f3de6c0218f40533 + languageName: node + linkType: hard + "js-tiktoken@npm:^1.0.12, js-tiktoken@npm:^1.0.14": version: 1.0.19 resolution: "js-tiktoken@npm:1.0.19" @@ -11075,6 +11113,16 @@ __metadata: languageName: node linkType: hard +"match-sorter@npm:^6.0.2": + version: 6.3.4 + resolution: "match-sorter@npm:6.3.4" + dependencies: + "@babel/runtime": "npm:^7.23.8" + remove-accents: "npm:0.5.0" + checksum: 10c0/35d2a6b6df003c677d9ec87ecd4683657638f5bce856f43f9cf90b03e357ed2f09813ebbac759defa7e7438706936dd34dc2bfe1a18771f7d2541f14d639b4ad + languageName: node + linkType: hard + "matcher@npm:^3.0.0": version: 3.0.0 resolution: "matcher@npm:3.0.0" @@ -12010,6 +12058,13 @@ __metadata: languageName: node linkType: hard +"microseconds@npm:0.2.0": + version: 0.2.0 + resolution: "microseconds@npm:0.2.0" + checksum: 10c0/59dfae1c696c0bacd79603c4df7cd0dcc9e091b7c5556aaca9b0832017d3c0b40ad8f57ca25e0ee5709ef1973404448c4a2fea6c9c1fad7d9e197ff5c1c9c2d5 + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -12357,6 +12412,15 @@ __metadata: languageName: node linkType: hard +"nano-time@npm:1.0.0": + version: 1.0.0 + resolution: "nano-time@npm:1.0.0" + dependencies: + big-integer: "npm:^1.6.16" + checksum: 10c0/3bd12e0bcd30867178afdbe8053b3dde5fdd1c665ecd348bf879863049344fbaf05cbb1d7806a825b91efbca011ee115eee52e76fb38b7da9c97931cd9e61f15 + languageName: node + linkType: hard + "nanoid@npm:^3.3.7, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" @@ -12696,6 +12760,13 @@ __metadata: languageName: node linkType: hard +"oblivious-set@npm:1.0.0": + version: 1.0.0 + resolution: "oblivious-set@npm:1.0.0" + checksum: 10c0/ca8640474ea1e1feb3b5c98d42f5649f114ac4513ef84774e724f22fc7e529f1de3e7f26a0d9593097ab8942ca0bb8c241f7c1bd63c3e33047dd49de3aca9805 + languageName: node + linkType: hard + "office-text-extractor@npm:^3.0.3": version: 3.0.3 resolution: "office-text-extractor@npm:3.0.3" @@ -14503,6 +14574,24 @@ __metadata: languageName: node linkType: hard +"react-query@npm:^3.39.3": + version: 3.39.3 + resolution: "react-query@npm:3.39.3" + dependencies: + "@babel/runtime": "npm:^7.5.5" + broadcast-channel: "npm:^3.4.1" + match-sorter: "npm:^6.0.2" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + checksum: 10c0/319045ef31b9b02aa9b5446169a8c6f95cfe49406466b819cc85e41c29bfe5032d3732577efe56511278db41514772375d416a3e3976e8967c6e0972ff04dd2e + languageName: node + linkType: hard + "react-redux@npm:^8.1.3": version: 8.1.3 resolution: "react-redux@npm:8.1.3" @@ -14923,6 +15012,13 @@ __metadata: languageName: node linkType: hard +"remove-accents@npm:0.5.0": + version: 0.5.0 + resolution: "remove-accents@npm:0.5.0" + checksum: 10c0/a75321aa1b53d9abe82637115a492770bfe42bb38ed258be748bf6795871202bc8b4badff22013494a7029f5a241057ad8d3f72adf67884dbe15a9e37e87adc4 + languageName: node + linkType: hard + "repeat-string@npm:^1.0.0": version: 1.6.1 resolution: "repeat-string@npm:1.6.1" @@ -15124,7 +15220,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.2": +"rimraf@npm:3.0.2, rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -17032,6 +17128,16 @@ __metadata: languageName: node linkType: hard +"unload@npm:2.2.0": + version: 2.2.0 + resolution: "unload@npm:2.2.0" + dependencies: + "@babel/runtime": "npm:^7.6.2" + detect-node: "npm:^2.0.4" + checksum: 10c0/0a4f86b502e7aa35d39c27373ebeaad4f2b7da793fb3d6308e5337aab541885cfe7b339ea4a1963477bf73fddabd5d69f4f47023dad71224b4b4a25611ef7dd8 + languageName: node + linkType: hard + "unpipe@npm:1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0"