From 224ae55d6bd89c264cc1e9280c33b94369aedd76 Mon Sep 17 00:00:00 2001 From: zhaoweijie Date: Thu, 21 Aug 2025 14:08:07 +0800 Subject: [PATCH] =?UTF-8?q?feat/playground:=20=E9=87=8D=E6=9E=84=20playgro?= =?UTF-8?q?und=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 Data 和 History组件的样式和布局 - 添加新的功能和交互,如热门搜索和智能体选择 - 优化组件性能和可维护性 --- package.json | 4 +- src/assets/locale/zh/playground.json | 4 +- src/components/Common/DataNavigation.tsx | 15 +- src/components/Common/Playground/Data.tsx | 181 +++++------ src/components/Common/Playground/History.tsx | 231 +++++++++++-- .../Common/Playground/IodRelevant.tsx | 202 ++++++++---- src/components/Common/Playground/Message.tsx | 20 +- src/components/Common/Playground/Scene.tsx | 161 +++++----- src/components/Common/Playground/Team.tsx | 153 ++++----- src/components/Layouts/Header.tsx | 303 +++--------------- src/components/Layouts/Layout.tsx | 12 +- src/components/Layouts/_Header.tsx | 264 +++++++++++++++ .../Option/Playground/Playground.tsx | 16 +- .../Option/Playground/PlaygroundChat.tsx | 5 +- .../Option/Playground/PlaygroundEmpty.tsx | 85 +---- .../Option/Playground/PlaygroundForm.tsx | 1 + src/components/Option/Sidebar.tsx | 8 +- src/libs/playground.tsx | 51 +++ wxt.config.ts | 2 +- 19 files changed, 1009 insertions(+), 709 deletions(-) create mode 100644 src/components/Layouts/_Header.tsx create mode 100644 src/libs/playground.tsx diff --git a/package.json b/package.json index 712b58f..5f6dec1 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,8 @@ "rehype-mathjax": "4.0.3", "remark-gfm": "3.0.1", "remark-math": "5.1.1", - "segmentit":"^2.0.3", + "segmentit": "^2.0.3", + "styled-components": "^6.1.19", "tesseract.js": "^5.1.1", "turndown": "^7.1.3", "unist-util-visit": "^5.0.0", @@ -76,6 +77,7 @@ "@types/react-dom": "18.2.18", "@types/react-speech-recognition": "^3.9.5", "@types/react-syntax-highlighter": "^15.5.11", + "@types/styled-components": "^5.1.34", "@types/turndown": "^5.0.4", "autoprefixer": "^10.4.17", "cross-env": "^7.0.3", diff --git a/src/assets/locale/zh/playground.json b/src/assets/locale/zh/playground.json index 9f57bb4..598941f 100644 --- a/src/assets/locale/zh/playground.json +++ b/src/assets/locale/zh/playground.json @@ -19,7 +19,7 @@ } }, "tooltip": { - "searchInternet": "搜索中...", + "searchInternet": "深度搜索", "searchIod": "搜索数联网", "speechToText": "语音到文本", "uploadImage": "上传图片", @@ -29,4 +29,4 @@ "sendWhenEnter": "按Enter发送", "welcome": "你好!今天我能帮你什么?", "useOCR": "从图片中提取文字(OCR)" -} \ No newline at end of file +} diff --git a/src/components/Common/DataNavigation.tsx b/src/components/Common/DataNavigation.tsx index 7e1f48d..bcb7e58 100644 --- a/src/components/Common/DataNavigation.tsx +++ b/src/components/Common/DataNavigation.tsx @@ -16,22 +16,19 @@ export const DataNavigation: React.FC = ({ Header, showButton = true, onC {/* 左侧部分 */}
+ level={3} + className="flex items-center" + style={{ marginBottom: 0, color: "#1F2937", fontSize: "18px" }}> {Header}
{/* 右侧部分 */} {showButton && ( - + )} ) diff --git a/src/components/Common/Playground/Data.tsx b/src/components/Common/Playground/Data.tsx index 98e6ece..4078b67 100644 --- a/src/components/Common/Playground/Data.tsx +++ b/src/components/Common/Playground/Data.tsx @@ -16,28 +16,28 @@ export const PlaygroundData = () => { description: "数字对象标识: CSTR:13452.11.01.11.2021.242 国家海洋科学数据中心", time: "包括2019年8月,2021年8月和2024年6月", - metadata: "热 榜 第" + metadata: "热 榜 第2" }, { title: "祁连山老虎沟大本营10米气象每日值数据集(V1.0)(2018-2023)", description: "中国科学院西北生态环境资源研究院,2021年8月3日发布,2021年8月3日20:48更新", time: "包括2019年8月,2021年8月和2024年6月", - metadata: "热 榜 第" + metadata: "热 榜 第2" }, { title: "李嘉图为研究老虎沟大本营2014-2018年...", description: "中国科学院西北生态环境资源研究院,2021年8月3日发布,2021年8月3日20:48更新", time: "包括2019年8月,2021年8月和2024年6月", - metadata: "热 榜 第" + metadata: "热 榜 第2" }, { title: "青海玉树B1区俄日矿勘探数据2017-2023", description: "数字中国集团,CSTR:3260.11.1528414774204895456,DT2023年地质勘探补充调查", time: "包括2019年8月,2021年8月和2024年6月", - metadata: "热 榜 第" + metadata: "热 榜 第2" } ] @@ -60,67 +60,58 @@ export const PlaygroundData = () => { } return ( -
- {/* 数据导航 */} - - - - - + +
+ {/* 数据导航 */} + + - - - - 相关数据 -
- } - onClick={showDrawer} - /> - - {/* 数据列表 */} -
- {data.slice(0, 3).map((item, index) => ( - -
-

- {item.title} -

-

- {item.description} -

-

{item.time}

- {item.metadata && ( -
- - - - - - - {item.metadata} -
- )} + d="M877.714286 54.857143H754.285714V9.142857c0-5.028571-4.114286-9.142857-9.142857-9.142857h-64c-5.028571 0-9.142857 4.114286-9.142857 9.142857v45.714286H498.285714V9.142857c0-5.028571-4.114286-9.142857-9.142857-9.142857h-64c-5.028571 0-9.142857 4.114286-9.142857 9.142857v45.714286H292.571429c-20.228571 0-36.571429 16.342857-36.571429 36.571428v137.142858h-109.714286c-20.228571 0-36.571429 16.342857-36.571428 36.571428v722.285714c0 20.228571 16.342857 36.571429 36.571428 36.571429h585.142857c20.228571 0 36.571429-16.342857 36.571429-36.571429v-109.714285h109.714286c20.228571 0 36.571429-16.342857 36.571428-36.571429V91.428571c0-20.228571-16.342857-36.571429-36.571428-36.571428zM685.714286 941.714286H192V310.857143h249.142857v198.857143c0 25.257143 20.457143 45.714286 45.714286 45.714285h198.857143v386.285715z m0-459.428572H514.285714V310.857143h0.228572L685.714286 482.057143v0.228571z m146.285714 313.142857h-64V448L548.571429 228.571429H338.285714v-91.428572h77.714286v36.571429c0 5.028571 4.114286 9.142857 9.142857 9.142857h64c5.028571 0 9.142857-4.114286 9.142857-9.142857v-36.571429h173.714286v36.571429c0 5.028571 4.114286 9.142857 9.142857 9.142857h64c5.028571 0 9.142857-4.114286 9.142857-9.142857v-36.571429h77.714286v658.285714z" + p-id="3573" + fill="#3480e3"> + + 相关数据
-
- ))} + } + onClick={showDrawer} + /> + + {/* 数据列表 */} +
+ {data.slice(0, 3).map((item, index) => ( + +
+

+ {item.title} +

+

+ {item.description} +

+

{item.time}

+ {item.metadata && ( +
+ + {item.metadata} + +
+ )} +
+
+ ))} +
{/* 抽屉 */} @@ -129,47 +120,31 @@ export const PlaygroundData = () => { closable={{ "aria-label": "Close Button" }} onClose={onClose} open={open} - width={600}> - ( - - - {item.title} - - } - description={ -
-

{item.description}

-

{item.time}

- {item.metadata && ( -
- - - - - - - {item.metadata} -
- )} + width="33.33%"> +
+ {data.slice(0, 3).map((item, index) => ( + +
+

+ {item.title} +

+

{item.description}

+

{item.time}

+ {item.metadata && ( +
+ + {item.metadata} +
- } - /> - - )} - /> + )} +
+
+ ))} +
-
+ ) } diff --git a/src/components/Common/Playground/History.tsx b/src/components/Common/Playground/History.tsx index ed19284..bf49e40 100644 --- a/src/components/Common/Playground/History.tsx +++ b/src/components/Common/Playground/History.tsx @@ -1,13 +1,45 @@ import { Sidebar } from "@/components/Option/Sidebar.tsx" -import React, { useContext, useState } from "react" +import React, { useContext, useMemo, useState } from "react" import { useMessageOption } from "@/hooks/useMessageOption.tsx" import { useStoreChatModelSettings } from "@/store/model.tsx" -import { Card, Tooltip } from "antd" +import { + Button, + Card, + Divider, + List, + Menu, + MenuProps, + Popover, + Select, + Tooltip +} from "antd" import { PageAssitDatabase } from "@/db" -import { EraserIcon } from "lucide-react" +import { EraserIcon, PanelLeftIcon } from "lucide-react" import { useTranslation } from "react-i18next" -import { useQueryClient } from "@tanstack/react-query" +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { HistoryContext } from "@/components/Layouts/Layout.tsx" +import { PlusOutlined, RightOutlined } from "@ant-design/icons" +import { qaPrompt } from "@/libs/playground.tsx" +import { ProviderIcons } from "@/components/Common/ProviderIcon.tsx" +import { fetchChatModels } from "@/services/ollama.ts" + +const ModelIcon = () => { + return ( + + + + ) +} export const PlaygroundHistory = () => { const { setSystemPrompt } = useStoreChatModelSettings() @@ -20,6 +52,7 @@ export const PlaygroundHistory = () => { setHistoryId, historyId, clearChat, + selectedModel, setSelectedModel, temporaryChat, setSelectedSystemPrompt @@ -29,13 +62,163 @@ export const PlaygroundHistory = () => { const queryClient = useQueryClient() + type MenuItem = Required["items"][number] + const qaPromptItems = useMemo(() => { + return [ + { + key: "qaPrompt", + label: "热门搜索", + type: "group" as const, + children: qaPrompt.map((item) => { + return { + key: item.id, + label: {item.title}, + icon:

{item.icon}

+ } + }) + } + ] + }, []) + + const { onSubmit } = useMessageOption() + + const { mutateAsync: sendMessage } = useMutation({ + mutationFn: onSubmit, + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: ["fetchChatHistory"] + }) + } + }) + + const onClickQaPromptItem: MenuProps["onClick"] = (e) => { + const record = qaPrompt.find((item) => item.id === e.key) + void sendMessage({ message: record.title, image: "" }) + } + + // 大模型 + const { + data: models, + isLoading: isModelsLoading, + refetch + } = useQuery({ + queryKey: ["fetchModel"], + queryFn: () => fetchChatModels({ returnEmpty: true }), + refetchIntervalInBackground: false, + placeholderData: (prev) => prev + }) + return ( :nth-child(2)]:flex-1 [&>:nth-child(2)]:overflow-y-auto w-[300px] h-full pt-16 pb-5 transition-all duration-300 ease-in-out`} - style={{ paddingTop: "4rem", width: show ? "300px" : "0" }} - title={ -
- {t("sidebarTitle")} + className={`flex flex-col [&_.ant-card-body]:h-full w-[300px] overflow-hidden h-full pb-5 transition-all duration-300 ease-in-out !bg-[#f3f4f6]`} + style={{ width: show ? "300px" : "0" }}> + {/*Header*/} +
+
+

+ 数联网科创智能体 +

+ + +
+
+ {/*新建对话*/} + + {/*选择智能体*/} + { + setSelectedModel(e) + localStorage.setItem("selectedModel", e) + }} + filterOption={(input, option) => { + //@ts-ignore + return ( + option?.label?.props["data-title"] + ?.toLowerCase() + ?.indexOf(input.toLowerCase()) >= 0 + ) + }} + showSearch + loading={isModelsLoading} + options={models?.map((model) => ({ + label: ( + + + {model.name} + + ), + value: model.model + }))} + size="large" + // onRefresh={() => { + // refetch() + // }} + /> + }> + + + + {/*热门搜索*/} + +
+ +
+ 最近对话 @@ -59,21 +242,21 @@ export const PlaygroundHistory = () => {
- }> -
- setShow(true)} - setMessages={setMessages} - setHistory={setHistory} - setHistoryId={setHistoryId} - setSelectedModel={setSelectedModel} - setSelectedSystemPrompt={setSelectedSystemPrompt} - clearChat={clearChat} - historyId={historyId} - setSystemPrompt={setSystemPrompt} - temporaryChat={temporaryChat} - history={history} - /> +
+ setShow(true)} + setMessages={setMessages} + setHistory={setHistory} + setHistoryId={setHistoryId} + setSelectedModel={setSelectedModel} + setSelectedSystemPrompt={setSelectedSystemPrompt} + clearChat={clearChat} + historyId={historyId} + setSystemPrompt={setSystemPrompt} + temporaryChat={temporaryChat} + history={history} + /> +
) diff --git a/src/components/Common/Playground/IodRelevant.tsx b/src/components/Common/Playground/IodRelevant.tsx index 648e3a8..287673c 100644 --- a/src/components/Common/Playground/IodRelevant.tsx +++ b/src/components/Common/Playground/IodRelevant.tsx @@ -1,61 +1,119 @@ -import React from 'react'; +import React from "react" +import { Button, Card } from "antd" + +// 使用 CSS-in-JS 方式 +import styled, { keyframes } from 'styled-components' + +const rotate = keyframes` + 0% { + transform: translate(-50%, -50%) rotate(0deg); + } + 100% { + transform: translate(-50%, -50%) rotate(360deg); + } +` + +const breathe = keyframes` + 0% { + box-shadow: 0 0 5px rgba(37, 231, 232, 0.3); + } + 50% { + box-shadow: 0 0 20px rgba(37, 231, 232, 0.8); + } + 100% { + box-shadow: 0 0 5px rgba(37, 231, 232, 0.3); + } +` + +const CircleElement = styled.div<{ delay: number }>` + position: absolute; + width: 300px; + height: 160px; + background: #3b82f6; // blue-500 + opacity: 0.2; + border-radius: 50%; + top: 55%; + left: 50%; + animation: ${rotate} 6s linear infinite, ${breathe} 2s infinite alternate; + animation-delay: ${props => props.delay}s; +` + const SuccessIcon = () => { - return ( - - ) + return ( + + + + ) } const LoadingIcon = () => { return ( - - - - + ) } +const SearchIcon = () => { + return ( + + + + ) +} export const PlaygroundIodRelevant: React.FC = () => { const data = [ { - title: "已在29个科学数据中心的50万个科学数据集中进行搜索", + title:

已在29个科学数据中心50万个科学数据集中进行搜索

, + description:

已发现 4个 数据集

, + status: "success" + }, + { + title:

已在100万篇论文2800个科创场景中进行搜索

, description: "已发现4个数据集", status: "success" }, { - title: "已在100万篇论文、2800个科创场景中进行搜索", - description: "已发现4个数据集", - status: "success" - }, - { - title: "正在1000位智库专家、12万个创新机构中进行搜索", + title:

正在1000位智库专家12万个创新机构中进行搜索

, status: "loading" - }, + } ] for (let i = 0; i < 10; i++) { data.push({ - title: "已在29个科学数据中心的50万个科学数据集中进行搜索" + i, + title:

正在1000位智库专家12万个创新机构中进行搜索{i}

, description: "已发现4个数据集", status: "success" }) @@ -63,33 +121,65 @@ export const PlaygroundIodRelevant: React.FC = () => { return ( -
- {/* Header */} -
-

- 数联网搜索相关内 -

- {data.length}个结果 -
+ +
+ {/* 花瓣效果 */} +
+
+ + + +
+
- {/* Content */} -
- { - data.map((item, index) => ( -
-
- {item.status === "success" ? : } -
-
-

- {item.title} -

- {item.description &&

{item.description}

} -
+ {/* Header */} +
+

+
+ + 数联网搜索相关内容
- )) - } + +

+

+ 下面是在数联网上进行深度搜索的相关内容 +

+
+ + {/* Content */} +
+ {data.map((item, index) => ( + +
+
+ {item.status === "success" ? ( + + ) : ( + + )} +
+
+

{item.title}

+ {item.description && ( +

+ {item.description} +

+ )} +
+
+
+ ))} +
-
+ ) } diff --git a/src/components/Common/Playground/Message.tsx b/src/components/Common/Playground/Message.tsx index 7592e83..fc4c798 100644 --- a/src/components/Common/Playground/Message.tsx +++ b/src/components/Common/Playground/Message.tsx @@ -60,12 +60,12 @@ export const PlaygroundMessage = (props: Props) => { return (
{/*
*/} -
-
+
+
{props.isBot ? ( !props.botAvatar ? ( -
+
) : ( props.botAvatar ) @@ -78,13 +78,6 @@ export const PlaygroundMessage = (props: Props) => {
- {props.isBot - ? props.name === "chrome::gemini-nano::page-assist" - ? "Gemini Nano" - : removeModelSuffix( - props.name?.replaceAll(/accounts\/[^\/]+\/models\//g, "") - ) - : "You"} {props.isBot && @@ -99,7 +92,7 @@ export const PlaygroundMessage = (props: Props) => { )}
-
+
{!editMode ? ( props.isBot ? ( <> @@ -140,9 +133,10 @@ export const PlaygroundMessage = (props: Props) => {

+ "italic dark:text-gray-400" + } flex flex-row-reverse`}> {props.message} + {/*{props.message}*/}

) ) : ( diff --git a/src/components/Common/Playground/Scene.tsx b/src/components/Common/Playground/Scene.tsx index ca6a994..837ab44 100644 --- a/src/components/Common/Playground/Scene.tsx +++ b/src/components/Common/Playground/Scene.tsx @@ -47,53 +47,61 @@ export const PlaygroundScene = () => { } return ( -
- {/* 数据导航 */} - - - - + +
+ {/* 数据导航 */} + + - - - 相关场景 -
- } - onClick={showDrawer} - /> - - {/* 场景列表 */} -
- {data.slice(0,3).map((item, index) => ( - -
-

- {item.title} -

-

- - 技 术 应 - - - 制 造 - -

-

{item.demander}

- - {item.description} - + d="M980.34571 1.143792c-4.850903 0-9.824354 0.888481-14.797806 2.930966L229.773215 299.724504H20.428686c-11.233669 0-20.424853 9.446494-20.424853 21.180572V702.584302c0 11.74429 9.191184 21.180572 20.424853 21.180573h129.820365c-4.728353 14.808018-7.271248 30.51473-7.271248 46.46654 0 84.119757 68.678568 152.543014 153.176184 152.543014 70.721053 0 130.330986-47.998404 147.93721-112.847312l521.569043 209.59984c4.983664 1.919936 9.957116 2.930966 14.808019 2.930967 21.568645 0 40.839493-18.127057 40.839493-42.371358V43.525362C1021.195415 19.270849 1002.047116 1.143792 980.34571 1.143792zM296.153987 831.250663c-33.833769 0-61.274559-27.308028-61.274558-61.009035 0-14.297397 4.983664-27.951411 14.042086-38.807221l108.374269 43.525362c-2.553107 31.403211-28.972654 56.290895-61.141797 56.290894z m633.12959 74.550713L263.984844 638.501326l-16.462431-6.638077H91.915671V391.626129h155.606742l16.462431-6.638077 665.298733-267.30005v788.113374z m0 0" + fill="#52c41a" + p-id="6236"> + + 相关场景
-
- ))} + } + onClick={showDrawer} + /> + + {/* 场景列表 */} +
+ {data.slice(0, 3).map((item, index) => ( + +
+

+ {item.title} +

+ + {item.description} + +

+ {item.demander} +

+

+ + 技术应用 + + + 制造业 + +

+
+
+ ))} +
{/* 抽屉 */} @@ -102,41 +110,34 @@ export const PlaygroundScene = () => { closable={{ "aria-label": "Close Button" }} onClose={onClose} open={open} - width={600}> - ( - - - {item.title} - - } - description={ -
-

- - 技 术 应 - - - 制 造 - -

-

- {item.demander} -

- - {item.description} - -
- } - /> -
- )} - /> + width="33.33%"> +
+ {data.slice(0, 3).map((item, index) => ( + +
+

+ {item.title} +

+ + {item.description} + +

{item.demander}

+

+ + 技术应用 + + + 制造业 + +

+
+
+ ))} +
-
+ ) } diff --git a/src/components/Common/Playground/Team.tsx b/src/components/Common/Playground/Team.tsx index 7daee3e..afe2710 100644 --- a/src/components/Common/Playground/Team.tsx +++ b/src/components/Common/Playground/Team.tsx @@ -47,50 +47,62 @@ export const PlaygroundTeam = () => { } return ( -
- {/* 数据导航 */} - - - - + +
+ {/* 数据导航 */} + + - - - 相关团队 -
- } - onClick={showDrawer} - /> - - {/* 场景列表 */} -
- {data.slice(0,2).map((item, index) => ( - -
-

- {item.title} -

-

- - 技 术 应 - - - 制 造 - -

-

{item.description}

+ d="M824.2 699.9c-25.4-25.4-54.7-45.7-86.4-60.4C783.1 602.8 812 546.8 812 484c0-110.8-92.4-201.7-203.2-200-109.1 1.7-197 90.6-197 200 0 62.8 29 118.8 74.2 155.5-31.7 14.7-60.9 34.9-86.4 60.4C345 754.6 314 826.8 312 903.8c-0.1 4.5 3.5 8.2 8 8.2h56c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5C493.8 707.7 551.1 684 612 684c60.9 0 118.2 23.7 161.3 66.8C814.5 792 838 846.3 840 904.3c0.1 4.3 3.7 7.7 8 7.7h56c4.5 0 8.1-3.7 8-8.2-2-77-33-149.2-87.8-203.9zM612 612c-34.2 0-66.4-13.3-90.5-37.5-24.5-24.5-37.9-57.1-37.5-91.8 0.3-32.8 13.4-64.5 36.3-88 24-24.6 56.1-38.3 90.4-38.7 33.9-0.3 66.8 12.9 91 36.6 24.8 24.3 38.4 56.8 38.4 91.4 0 34.2-13.3 66.3-37.5 90.5-24.2 24.2-56.4 37.5-90.6 37.5z" + p-id="7273" + fill="#BE0BAC"> + + + 相关团队
-
- ))} + } + onClick={showDrawer} + /> + + {/* 场景列表 */} +
+ {data.slice(0, 5).map((item, index) => ( + +
+

+ {item.title} +

+

+ {item.description} +

+

+ + 晶体材料 + + + 中国 + +

+
+
+ ))} +
{/* 抽屉 */} @@ -99,38 +111,31 @@ export const PlaygroundTeam = () => { closable={{ "aria-label": "Close Button" }} onClose={onClose} open={open} - width={600}> - ( - - - {item.title} - - } - description={ -
-

- - 技 术 应 - - - 制 造 - -

-

- {item.description} -

-
- } - /> -
- )} - /> + width="33.33%"> +
+ {data.slice(0, 5).map((item, index) => ( + +
+

+ {item.title} +

+

{item.description}

+

+ + 晶体材料 + + + 中国 + +

+
+
+ ))} +
-
+ ) } diff --git a/src/components/Layouts/Header.tsx b/src/components/Layouts/Header.tsx index c1e5aba..27c5ef2 100644 --- a/src/components/Layouts/Header.tsx +++ b/src/components/Layouts/Header.tsx @@ -1,267 +1,66 @@ -import { useStorage } from "@plasmohq/storage/hook" -import { - BrainCog, - ChevronLeft, - ChevronRight, - CogIcon, - ComputerIcon, - GaugeCircle, - GithubIcon, - PanelLeftIcon, - ZapIcon -} from "lucide-react" -import { useTranslation } from "react-i18next" -import { useLocation, NavLink } from "react-router-dom" -import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnowledge" -import { ModelSelect } from "../Common/ModelSelect" -import { PromptSelect } from "../Common/PromptSelect" -import { useQuery } from "@tanstack/react-query" -import { fetchChatModels } from "~/services/ollama" -import { useMessageOption } from "~/hooks/useMessageOption" -import { Select, Tooltip } from "antd" -import { getAllPrompts } from "@/db" -import { ProviderIcons } from "../Common/ProviderIcon" -import { NewChat } from "./NewChat" -import { PageAssistSelect } from "../Select" -import { MoreOptions } from "./MoreOptions" -import { useContext } from "react" +import React, { useContext } from "react" import { HistoryContext } from "@/components/Layouts/Layout.tsx" -type Props = { - sidebarOpen: boolean - setSidebarOpen: () => void - setOpenModelSettings: (open: boolean) => void -} +import { PanelLeftIcon } from "lucide-react" +import { Button } from "antd" +import { PlusOutlined } from "@ant-design/icons" +import { useMessageOption } from "@/hooks/useMessageOption.tsx" +import { useTranslation } from "react-i18next" -export const Header: React.FC = ({ - setOpenModelSettings, - setSidebarOpen, - sidebarOpen -}) => { - const { t, i18n } = useTranslation(["option", "common"]) - const isRTL = i18n?.dir() === "rtl" +export const Header = () => { + const { show, setShow } = useContext(HistoryContext) + const { t } = useTranslation(["option", "common", "settings"]) - - const [shareModeEnabled] = useStorage("shareMode", false) - const [hideCurrentChatModelSettings] = useStorage( - "hideCurrentChatModelSettings", - false - ) - const { - selectedModel, - setSelectedModel, - clearChat, - selectedSystemPrompt, - setSelectedQuickPrompt, - setSelectedSystemPrompt, - messages, - streaming, - historyId, - temporaryChat - } = useMessageOption() - const { - data: models, - isLoading: isModelsLoading, - refetch - } = useQuery({ - queryKey: ["fetchModel"], - queryFn: () => fetchChatModels({ returnEmpty: true }), - refetchIntervalInBackground: false, - placeholderData: (prev) => prev - }) - - const { data: prompts, isLoading: isPromptLoading } = useQuery({ - queryKey: ["fetchAllPromptsLayout"], - queryFn: getAllPrompts - }) - - const { pathname } = useLocation() - - const getPromptInfoById = (id: string) => { - return prompts?.find((prompt) => prompt.id === id) - } - - const handlePromptChange = (value?: string) => { - if (!value) { - setSelectedSystemPrompt(undefined) - setSelectedQuickPrompt(undefined) - return - } - const prompt = getPromptInfoById(value) - if (prompt?.is_system) { - setSelectedSystemPrompt(prompt.id) - } else { - setSelectedSystemPrompt(undefined) - setSelectedQuickPrompt(prompt!.content) - } - } - + const { clearChat } = useMessageOption() return (
-
- {pathname !== "/" && ( -
- - {isRTL ? ( - - ) : ( - - )} - -
- )} -
-

- {t("projectTitle")} -

- + className={`w-full h-[60px] absolute inset-0 pl-5 z-10 flex items-center transition-all duration-300 ease-in-out ${show ? "left-[300px]" : ""}`}> + {/*控制侧边栏显示隐藏与新建对话*/} + {!show && ( +
-
- - - {"/"} - -
- - //@ts-ignore - option.label.key.toLowerCase().indexOf(input.toLowerCase()) >= 0 - } - options={prompts?.map((prompt) => ({ - label: ( - - {prompt.is_system ? ( - - ) : ( - - )} - {prompt.title} - - ), - value: prompt.id - }))} - /> -
-
- -
- -
-
-
-
- {messages.length > 0 && !streaming && ( - - )} - {!hideCurrentChatModelSettings && ( - - - - )} - - - - - - - - - - - - - - - -
+ onClick={clearChat}> +
+
+ + {t("newChat")} +
+
+
+ )} + {/* 项目标题 */} +
+

+ 数联网科创智能体 +

) diff --git a/src/components/Layouts/Layout.tsx b/src/components/Layouts/Layout.tsx index d98add0..3b45f72 100644 --- a/src/components/Layouts/Layout.tsx +++ b/src/components/Layouts/Layout.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useState } from "react" import { CurrentChatModelSettings } from "../Common/Settings/CurrentChatModelSettings" -import { Header } from "./Header" +import { Header } from "./Header.tsx" interface History { show: boolean @@ -33,15 +33,11 @@ export default function OptionLayout({ return (
-
-
-
+ {/*
*/} + {/*
*/} {/*
*/} +
{children} {/*
*/} diff --git a/src/components/Layouts/_Header.tsx b/src/components/Layouts/_Header.tsx new file mode 100644 index 0000000..24b2995 --- /dev/null +++ b/src/components/Layouts/_Header.tsx @@ -0,0 +1,264 @@ +import { useStorage } from "@plasmohq/storage/hook" +import { + BrainCog, + ChevronLeft, + ChevronRight, + CogIcon, + ComputerIcon, + GaugeCircle, + GithubIcon, + PanelLeftIcon, + ZapIcon +} from "lucide-react" +import { useTranslation } from "react-i18next" +import { useLocation, NavLink } from "react-router-dom" +import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnowledge" +import { ModelSelect } from "../Common/ModelSelect" +import { PromptSelect } from "../Common/PromptSelect" +import { useQuery } from "@tanstack/react-query" +import { fetchChatModels } from "~/services/ollama" +import { useMessageOption } from "~/hooks/useMessageOption" +import { Select, Tooltip } from "antd" +import { getAllPrompts } from "@/db" +import { ProviderIcons } from "../Common/ProviderIcon" +import { NewChat } from "./NewChat" +import { MoreOptions } from "./MoreOptions" +type Props = { + sidebarOpen: boolean + setSidebarOpen: () => void + setOpenModelSettings: (open: boolean) => void +} + +export const Header: React.FC = ({ + setOpenModelSettings, + setSidebarOpen, + sidebarOpen +}) => { + const { t, i18n } = useTranslation(["option", "common"]) + const isRTL = i18n?.dir() === "rtl" + + + + const [shareModeEnabled] = useStorage("shareMode", false) + const [hideCurrentChatModelSettings] = useStorage( + "hideCurrentChatModelSettings", + false + ) + const { + selectedModel, + setSelectedModel, + clearChat, + selectedSystemPrompt, + setSelectedQuickPrompt, + setSelectedSystemPrompt, + messages, + streaming, + historyId, + temporaryChat + } = useMessageOption() + const { + data: models, + isLoading: isModelsLoading, + } = useQuery({ + queryKey: ["fetchModel"], + queryFn: () => fetchChatModels({ returnEmpty: true }), + refetchIntervalInBackground: false, + placeholderData: (prev) => prev + }) + + const { data: prompts, isLoading: isPromptLoading } = useQuery({ + queryKey: ["fetchAllPromptsLayout"], + queryFn: getAllPrompts + }) + + const { pathname } = useLocation() + + const getPromptInfoById = (id: string) => { + return prompts?.find((prompt) => prompt.id === id) + } + + const handlePromptChange = (value?: string) => { + if (!value) { + setSelectedSystemPrompt(undefined) + setSelectedQuickPrompt(undefined) + return + } + const prompt = getPromptInfoById(value) + if (prompt?.is_system) { + setSelectedSystemPrompt(prompt.id) + } else { + setSelectedSystemPrompt(undefined) + setSelectedQuickPrompt(prompt!.content) + } + } + + return ( +
+
+ {pathname !== "/" && ( +
+ + {isRTL ? ( + + ) : ( + + )} + +
+ )} +
+

+ 数联网科创智能体 +

+ + +
+ + + {"/"} + +
+ + //@ts-ignore + option.label.key.toLowerCase().indexOf(input.toLowerCase()) >= 0 + } + options={prompts?.map((prompt) => ({ + label: ( + + {prompt.is_system ? ( + + ) : ( + + )} + {prompt.title} + + ), + value: prompt.id + }))} + /> +
+
+ +
+ +
+
+
+
+ {messages.length > 0 && !streaming && ( + + )} + {!hideCurrentChatModelSettings && ( + + + + )} + + + + + + + + + + + + + + + +
+
+
+
+ ) +} diff --git a/src/components/Option/Playground/Playground.tsx b/src/components/Option/Playground/Playground.tsx index 1893cf0..894f609 100644 --- a/src/components/Option/Playground/Playground.tsx +++ b/src/components/Option/Playground/Playground.tsx @@ -20,10 +20,8 @@ import { useStoreChatModelSettings } from "@/store/model" import { useSmartScroll } from "@/hooks/useSmartScroll" import { ChevronDown } from "lucide-react" import { PlaygroundTeam } from "@/components/Common/Playground/Team.tsx" -import { PlaygroundTokenStatistics } from "@/components/Common/Playground/TokenStatistics.tsx" import { PlaygroundHistory } from "@/components/Common/Playground/History.tsx" import { PlaygroundIodRelevant } from "@/components/Common/Playground/IodRelevant.tsx" -import { HistoryContext } from "@/components/Layouts/Layout.tsx" export const Playground = () => { @@ -148,13 +146,13 @@ export const Playground = () => { dropState === "dragging" ? "bg-gray-100 dark:bg-gray-800" : "" } bg-white dark:bg-[#171717]`}> -
+
+ className="custom-scrollbar flex h-auto w-full flex-col items-center overflow-x-hidden overflow-y-auto px-5">
-
+
{!isAtBottom && (
diff --git a/src/libs/playground.tsx b/src/libs/playground.tsx new file mode 100644 index 0000000..e0bbdc9 --- /dev/null +++ b/src/libs/playground.tsx @@ -0,0 +1,51 @@ +import RocketSvg from "@/assets/icons/rocket.svg" +import BulbSvg from "@/assets/icons/bulb.svg" +import EyeSvg from "@/assets/icons/eye.svg" +import ASvg from "@/assets/icons/a.svg" +import BSvg from "@/assets/icons/b.svg" +import CSvg from "@/assets/icons/c.svg" +import DSvg from "@/assets/icons/d.svg" +import ESvg from "@/assets/icons/e.svg" +import FSvg from "@/assets/icons/f.svg" + +export const qaPrompt = [ + { + title: "最近一年大型语言模型的技术进展有哪些?", + icon: Rocket, + }, + { + title: "生成式AI在企业中有哪些具体应用场景?", + icon: Rocket, + }, + { + title: "多模态学习技术的最新研究方向是什么?", + icon: Rocket, + }, + { + title: "当前AI芯片市场格局和未来三年发展趋势如何?", + icon: Rocket, + }, + { + title: "主流深度学习框架性能与易用性对比分析?", + icon: Rocket, + }, + { + title: "国内外AI伦理治理框架有哪些最佳实践?", + icon: Rocket, + }, + { + title: "大规模知识图谱构建与应用最新进展?", + icon: Rocket, + }, + { + title: "计算机视觉领域近期突破性技术有哪些?", + icon: Rocket, + }, + { + title: "量子计算对AI算法的影响与应用前景?", + icon: Rocket, + }, +].map((item, index) => ({ + ...item, + id: index.toString(), +})) diff --git a/wxt.config.ts b/wxt.config.ts index 82786fb..1fdeb48 100644 --- a/wxt.config.ts +++ b/wxt.config.ts @@ -97,4 +97,4 @@ export default defineConfig({ ? firefoxMV2Permissions : chromeMV3Permissions } -}) as any \ No newline at end of file +}) as any