diff --git a/src/backend/bisheng/api/v1/chat.py b/src/backend/bisheng/api/v1/chat.py index 92af9006e..718da042f 100644 --- a/src/backend/bisheng/api/v1/chat.py +++ b/src/backend/bisheng/api/v1/chat.py @@ -211,8 +211,8 @@ def get_chatlist_list(*, create_time=message.create_time, update_time=message.update_time)) else: - # 通过接口创建的会话记录,不关联技能或者助手 - logger.debug(f'unknown message.flow_id={message.flow_id}') + # 通过接口创建的会话记录,不关联技能或者助手, 或者技能和助手已被删除 + pass res = chat_list[(page - 1) * limit:page * limit] chat_ids = [one.chat_id for one in res] latest_messages = ChatMessageDao.get_latest_message_by_chat_ids(chat_ids, 'answer') diff --git a/src/backend/bisheng/chat/manager.py b/src/backend/bisheng/chat/manager.py index c154e75a9..47229ac1c 100644 --- a/src/backend/bisheng/chat/manager.py +++ b/src/backend/bisheng/chat/manager.py @@ -13,7 +13,7 @@ from bisheng.api.services.audit_log import AuditLogService from bisheng.api.services.user_service import UserPayload -from bisheng.api.utils import build_flow_no_yield +from bisheng.api.utils import build_flow_no_yield, get_request_ip from bisheng.api.v1.schemas import ChatMessage, ChatResponse, FileResponse from bisheng.cache import cache_manager from bisheng.cache.flow import InMemoryCache @@ -410,7 +410,7 @@ async def _process_when_payload(self, flow_id: str, chat_id: str, "user_id": user_id, "user_name": UserDao.get_user(user_id).user_name, }) - AuditLogService.create_chat_flow(login_user, websocket.client.host, flow_id) + AuditLogService.create_chat_flow(login_user, get_request_ip(websocket), flow_id) start_resp.type = 'start' # should input data diff --git a/src/frontend/index.html b/src/frontend/index.html index 0402eee16..2937ac62d 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -8,6 +8,22 @@ <%- aceScriptSrc %> BISHENG + + diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 086b8b054..403ffdbe0 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "bisheng", - "version": "0.3.1.4", + "version": "0.3.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bisheng", - "version": "0.3.1.4", + "version": "0.3.3", "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", @@ -61,6 +61,7 @@ "react": "^18.2.0", "react-ace": "^10.1.0", "react-beautiful-dnd": "^13.1.1", + "react-color": "^2.19.3", "react-cookie": "^4.1.1", "react-day-picker": "^8.10.1", "react-dom": "^18.2.0", @@ -1075,6 +1076,14 @@ "react": ">= 16" } }, + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -7951,6 +7960,11 @@ "resolved": "https://registry.npmmirror.com/markdown-table/-/markdown-table-3.0.3.tgz", "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==" }, + "node_modules/material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "node_modules/mathjax-full": { "version": "3.2.2", "resolved": "https://registry.npmmirror.com/mathjax-full/-/mathjax-full-3.2.2.tgz", @@ -9583,6 +9597,23 @@ "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "dependencies": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-cookie": { "version": "4.1.1", "resolved": "https://registry.npmmirror.com/react-cookie/-/react-cookie-4.1.1.tgz", @@ -9931,6 +9962,14 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "dependencies": { + "lodash": "^4.0.1" + } + }, "node_modules/reactflow": { "version": "11.10.4", "resolved": "https://registry.npmmirror.com/reactflow/-/reactflow-11.10.4.tgz", @@ -11310,6 +11349,11 @@ "resolved": "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/src/frontend/package.json b/src/frontend/package.json index ccdee428e..3028cf76a 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -56,6 +56,7 @@ "react": "^18.2.0", "react-ace": "^10.1.0", "react-beautiful-dnd": "^13.1.1", + "react-color": "^2.19.3", "react-cookie": "^4.1.1", "react-day-picker": "^8.10.1", "react-dom": "^18.2.0", diff --git a/src/frontend/src/App.css b/src/frontend/src/App.css index 6bf4ee4f6..01bc8a843 100644 --- a/src/frontend/src/App.css +++ b/src/frontend/src/App.css @@ -189,7 +189,6 @@ .build-tab {} .build-tab a.active { - color: #024FE5; background: #fff; box-shadow: 1px 1px 2px 0 #e9e9e9 /* background: #F4F5F8; @@ -197,25 +196,16 @@ } .build-tab a.active>svg { - color: #024FE5 !important; + color: hsl(var(--primary)) !important; } - -.build-tab a { - color: #666; - /* background: #F4F5F8; - padding: 10px 40px; */ -} - -.build-tab a>svg { - color: #666; +.build-tab a.active>span { + color: hsl(var(--primary)) !important; } - -.build-tab a:hover { - color: #024FE5; +:is(.dark .build-tab a.active>svg){ + color: #fff !important; } - -.build-tab a:hover>svg { - color: #024FE5; +:is(.dark .build-tab a.active>span){ + color: #fff !important; } .bs-chat-bg { diff --git a/src/frontend/src/components/bs-comp/cardComponent/index.tsx b/src/frontend/src/components/bs-comp/cardComponent/index.tsx index 396c12d4f..4bafed4f2 100644 --- a/src/frontend/src/components/bs-comp/cardComponent/index.tsx +++ b/src/frontend/src/components/bs-comp/cardComponent/index.tsx @@ -148,7 +148,7 @@ export default function CardComponent({ // 技能组件 - return edit && onClick()}> + return edit && onClick()}>
diff --git a/src/frontend/src/components/bs-comp/chatComponent/ChatInput.tsx b/src/frontend/src/components/bs-comp/chatComponent/ChatInput.tsx index 6d52cfafb..802337dde 100644 --- a/src/frontend/src/components/bs-comp/chatComponent/ChatInput.tsx +++ b/src/frontend/src/components/bs-comp/chatComponent/ChatInput.tsx @@ -1,15 +1,17 @@ +import { ClearIcon } from "@/components/bs-icons/clear"; import { FormIcon } from "@/components/bs-icons/form"; import { SendIcon } from "@/components/bs-icons/send"; +import { Button } from "@/components/bs-ui/button"; import { Textarea } from "@/components/bs-ui/input"; import { useToast } from "@/components/bs-ui/toast/use-toast"; import { locationContext } from "@/contexts/locationContext"; +import { PauseIcon } from "@radix-ui/react-icons"; import { useContext, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useMessageStore } from "./messageStore"; import GuideQuestions from "./GuideQuestions"; -import { ClearIcon } from "@/components/bs-icons/clear"; -import { Button } from "@/components/bs-ui/button"; -import { PauseIcon, StopIcon } from "@radix-ui/react-icons"; +import { useMessageStore } from "./messageStore"; +import { formatDate } from "@/util/utils"; +import { StopIcon } from "@radix-ui/react-icons"; export default function ChatInput({ clear, form, stop, questions, inputForm, wsUrl, onBeforSend }) { const { toast } = useToast() @@ -198,6 +200,7 @@ export default function ChatInput({ clear, form, stop, questions, inputForm, wsU const handleWsMessage = (data) => { if (Array.isArray(data) && data.length) return if (data.type === 'start') { + setStoped(false) createWsMsg(data) } else if (data.type === 'stream') { //@ts-ignore @@ -213,13 +216,12 @@ export default function ChatInput({ clear, form, stop, questions, inputForm, wsU thought: data.intermediate_steps || '', messageId: data.message_id, noAccess: false, - liked: 0 + liked: 0, + update_time: formatDate(new Date(), 'yyyy-MM-ddTHH:mm:ss') }, data.type === 'end_cover') } else if (data.type === "close") { setStoped(true) setInputLock({ locked: false, reason: '' }) - } else if (data.type === 'begin') { - setStoped(false) } } @@ -289,11 +291,14 @@ export default function ChatInput({ clear, form, stop, questions, inputForm, wsU
{/* send */}
-
{ !inputLock.locked && handleSendClick() }} - >
+ onClick={() => { !inputLock.locked && handleSendClick() }}> + +
} + {!stoped && { setStoped(true); sendWsMsg({ "action": "stop" }); }}/>} {/* question */} - {/* stop */} - { - stop &&
- -
- }

{appConfig.dialogTips}

diff --git a/src/frontend/src/components/bs-comp/chatComponent/MessageBs.tsx b/src/frontend/src/components/bs-comp/chatComponent/MessageBs.tsx index 67346538a..2899e453c 100644 --- a/src/frontend/src/components/bs-comp/chatComponent/MessageBs.tsx +++ b/src/frontend/src/components/bs-comp/chatComponent/MessageBs.tsx @@ -79,8 +79,8 @@ export default function MessageBs({ data, onUnlike = () => { }, onSource }: { da const chatId = useMessageStore(state => state.chatId) return
-
-
+
+
{formatStrTime(data.update_time, 'MM 月 dd 日 HH:mm')}
{data.sender &&

{data.sender}

} diff --git a/src/frontend/src/components/bs-comp/chatComponent/MessagePanne.tsx b/src/frontend/src/components/bs-comp/chatComponent/MessagePanne.tsx index 45ff786fc..a9fc12a9f 100644 --- a/src/frontend/src/components/bs-comp/chatComponent/MessagePanne.tsx +++ b/src/frontend/src/components/bs-comp/chatComponent/MessagePanne.tsx @@ -71,7 +71,7 @@ export default function MessagePanne({ useName, guideWord, loadMore }) { } else if (msg.files?.length) { type = 'file' } else if (['tool', 'flow', 'knowledge'].includes(msg.category) - || (msg.category === 'processing' && msg.thought.indexOf(`status_code`) === -1) + // || (msg.category === 'processing' && msg.thought.indexOf(`status_code`) === -1) ) { // 项目演示? type = 'runLog' } else if (msg.thought) { diff --git a/src/frontend/src/components/bs-comp/chatComponent/MessageUser.tsx b/src/frontend/src/components/bs-comp/chatComponent/MessageUser.tsx index 51ac9480d..81ef6c47f 100644 --- a/src/frontend/src/components/bs-comp/chatComponent/MessageUser.tsx +++ b/src/frontend/src/components/bs-comp/chatComponent/MessageUser.tsx @@ -1,9 +1,9 @@ import { locationContext } from "@/contexts/locationContext"; import { ChatMessageType } from "@/types/chat"; +import { formatStrTime } from "@/util/utils"; import { MagnifyingGlassIcon, Pencil2Icon, ReloadIcon } from "@radix-ui/react-icons"; -import { useContext, useState } from "react"; +import { useContext } from "react"; import { useMessageStore } from "./messageStore"; -import { formatStrTime } from "@/util/utils"; export default function MessageUser({ useName = 'xxx', data }: { data: ChatMessageType }) { const msg = data.message[data.chatKey] @@ -26,8 +26,8 @@ export default function MessageUser({ useName = 'xxx', data }: { data: ChatMessa } return
-
-
+
+
{formatStrTime(data.update_time, 'MM 月 dd 日 HH:mm')}
{useName &&

{useName}

} diff --git a/src/frontend/src/components/bs-comp/chatComponent/messageStore.ts b/src/frontend/src/components/bs-comp/chatComponent/messageStore.ts index 61184ab2a..a0d0d3e00 100644 --- a/src/frontend/src/components/bs-comp/chatComponent/messageStore.ts +++ b/src/frontend/src/components/bs-comp/chatComponent/messageStore.ts @@ -1,9 +1,8 @@ -import { message } from '@/components/bs-ui/toast/use-toast'; -import { generateUUID } from '@/components/bs-ui/utils' -import { MessageDB, getChatHistory } from '@/controllers/API' -import { ChatMessageType } from '@/types/chat' -import { cloneDeep } from 'lodash' -import { create } from 'zustand' +import { getChatHistory } from '@/controllers/API'; +import { ChatMessageType } from '@/types/chat'; +import { cloneDeep } from 'lodash'; +import { create } from 'zustand'; +import { formatDate } from '@/util/utils'; /** * 会话消息管理 @@ -138,7 +137,8 @@ export const useMessageStore = create((set, get) => ({ category: '', files: [], end: false, - user_name: "" + user_name: "", + update_time: formatDate(new Date(), 'yyyy-MM-ddTHH:mm:ss') }] })) }, diff --git a/src/frontend/src/components/bs-icons/plusBox/PlusBox.svg b/src/frontend/src/components/bs-icons/plusBox/PlusBox.svg index bbf3b3ecd..117bfcc41 100644 --- a/src/frontend/src/components/bs-icons/plusBox/PlusBox.svg +++ b/src/frontend/src/components/bs-icons/plusBox/PlusBox.svg @@ -1,10 +1,13 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/src/frontend/src/components/bs-ui/alertDialog/useConfirm.tsx b/src/frontend/src/components/bs-ui/alertDialog/useConfirm.tsx index e5aef806e..7b8563fd6 100644 --- a/src/frontend/src/components/bs-ui/alertDialog/useConfirm.tsx +++ b/src/frontend/src/components/bs-ui/alertDialog/useConfirm.tsx @@ -55,7 +55,7 @@ function ConfirmWrapper() {
{showClose && } {title} - + {desc} diff --git a/src/frontend/src/components/bs-ui/button/index.tsx b/src/frontend/src/components/bs-ui/button/index.tsx index 1009eb65b..47fa46e54 100644 --- a/src/frontend/src/components/bs-ui/button/index.tsx +++ b/src/frontend/src/components/bs-ui/button/index.tsx @@ -12,12 +12,12 @@ const buttonVariants = cva( destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + "border border-input shadow-sm hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary no-underline hover:underline", - black: "bg-[#111] text-primary-foreground shadow hover:bg-[#48494d]" + black: "bg-black-button text-primary-foreground shadow hover:bg-black-button/85" }, size: { default: "h-9 px-4 py-2", diff --git a/src/frontend/src/components/bs-ui/select/hover.tsx b/src/frontend/src/components/bs-ui/select/hover.tsx index b13398fdd..0c6bd85a3 100644 --- a/src/frontend/src/components/bs-ui/select/hover.tsx +++ b/src/frontend/src/components/bs-ui/select/hover.tsx @@ -3,7 +3,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../too export function SelectHoverItem({ children, ...props }) { - return
+ return
{children}
} @@ -15,7 +15,7 @@ export function SelectHover({ triagger, children }) { {triagger} - + {children} diff --git a/src/frontend/src/controllers/API/assistant.ts b/src/frontend/src/controllers/API/assistant.ts index b2f98eb06..b80400520 100644 --- a/src/frontend/src/controllers/API/assistant.ts +++ b/src/frontend/src/controllers/API/assistant.ts @@ -27,8 +27,8 @@ export const createAssistantsApi = async (name, prompt) => { }; // 获取助手详情 -export const getAssistantDetailApi = async (id): Promise => { - return await axios.get(`/api/v1/assistant/info/${id}`) +export const getAssistantDetailApi = async (id, version): Promise => { + return await axios.get(`/api/${version}/assistant/info/${id}`) }; // 获取助手系统模型 diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index bb83bc058..3cd15cd71 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -62,7 +62,12 @@ export async function delComponentApi(name): Promise { export async function getAppConfig(): Promise { return await axios.get(`/api/v1/env`); } - +/** + * 获取平台配置 + */ +export async function saveThemeApi(data: string): Promise { + return await axios.post(`/api/v1/web/config`, { value: data }); +} /** * Reads all templates from the database. * diff --git a/src/frontend/src/layout/BuildLayout.tsx b/src/frontend/src/layout/BuildLayout.tsx index 0128e0956..d5164f404 100755 --- a/src/frontend/src/layout/BuildLayout.tsx +++ b/src/frontend/src/layout/BuildLayout.tsx @@ -9,21 +9,21 @@ export default function BuildLayout(params) { return
- - - {t('build.assistant')} + + + {t('build.assistant')}
- - - {t('build.skill')} + + + {t('build.skill')}
- - - {t('build.tools')} + + + {t('build.tools')}
diff --git a/src/frontend/src/pages/ChatAppPage/chatAssitantShare.tsx b/src/frontend/src/pages/ChatAppPage/chatAssitantShare.tsx new file mode 100644 index 000000000..79ca70db9 --- /dev/null +++ b/src/frontend/src/pages/ChatAppPage/chatAssitantShare.tsx @@ -0,0 +1,17 @@ +// 支持嵌iframe、适配移动端 +import { useMemo, useState } from "react"; +import { useLocation, useParams } from "react-router-dom"; +import { generateUUID } from "../../utils"; +import ChatPanne from "./components/ChatPanne"; + +export default function chatAssitantShare() { + const { id: assitId } = useParams() + + const wsUrl = `/api/v2/assistant/chat/${assitId}` + + const [data] = useState({ id: assitId, chatId: generateUUID(32), type: 'assistant' }) + + if (!assitId) return
请选择会话
+ + return +}; diff --git a/src/frontend/src/pages/ChatAppPage/chatShare.tsx b/src/frontend/src/pages/ChatAppPage/chatShare.tsx index 3ab41cc60..bbd2ba568 100644 --- a/src/frontend/src/pages/ChatAppPage/chatShare.tsx +++ b/src/frontend/src/pages/ChatAppPage/chatShare.tsx @@ -24,7 +24,7 @@ export default function chatShare() { const [data] = useState({ id: flowId, chatId: generateUUID(32), type: 'flow' }) - if (!flowId) return
请选择技能
+ if (!flowId) return
请选择会话
return }; diff --git a/src/frontend/src/pages/ChatAppPage/components/ChatPanne.tsx b/src/frontend/src/pages/ChatAppPage/components/ChatPanne.tsx index 675f91fac..d3a049378 100644 --- a/src/frontend/src/pages/ChatAppPage/components/ChatPanne.tsx +++ b/src/frontend/src/pages/ChatAppPage/components/ChatPanne.tsx @@ -47,7 +47,7 @@ export default function ChatPanne({ customWsHost = '', appendHistory = false, da } else { flowRef.current = null setFlow(null) - const _assistant = await loadAssistantState(id) + const _assistant = await loadAssistantState(id, version) loadHistoryMsg(_assistant.id, chatId, { appendHistory, lastMsg: t('historicalMessages') @@ -159,12 +159,12 @@ export default function ChatPanne({ customWsHost = '', appendHistory = false, da if (!(flow || assistant)) return
-

- {t('chat.chooseOne')}{t('chat.dialogue')}
{t('chat.start')}{t('chat.wenqingruijian')} +

+ {t('chat.chooseOne')}{t('chat.dialogue')}
{t('chat.start')}{t('chat.wenqingruijian')}

{ !customWsHost &&
{ document.getElementById('newchat')?.click() }}> diff --git a/src/frontend/src/pages/ChatAppPage/index.tsx b/src/frontend/src/pages/ChatAppPage/index.tsx index 19aa5c5b2..c0ab48952 100755 --- a/src/frontend/src/pages/ChatAppPage/index.tsx +++ b/src/frontend/src/pages/ChatAppPage/index.tsx @@ -9,7 +9,7 @@ import { captureAndAlertRequestErrorHoc } from "../../controllers/request"; import { useDebounce } from "../../util/hook"; import { generateUUID } from "../../utils"; import ChatPanne from "./components/ChatPanne"; -import { formatStrTime } from "@/util/utils"; +import { formatStrTime, formatDate } from "@/util/utils"; import { SkillIcon, AssistantIcon } from "@/components/bs-icons"; import { useMessageStore } from "@/components/bs-comp/chatComponent/messageStore"; @@ -102,11 +102,11 @@ export default function SkillChatPage() {
{chat.flow_type === 'assistant' ? : }
-

{chat.flow_name}

+

{chat.flow_name}

{chat.latest_message?.message || ''}
- {formatStrTime(chat.update_time, 'MM 月 dd 日')} + {formatStrTime(chat.update_time, 'MM 月 dd 日')} handleDeleteChat(e, chat.chat_id)}>
@@ -133,9 +133,11 @@ const useChatList = () => { const latest:any = messages[messages.length - 1] setChatList(chats => chats.map(chat => (chat.chat_id === chatId && chat.latest_message) ? { - ...chat, latest_message: { - ...chat.latest_message, - message: latest.message[latest.chatKey] || latest.message + ...chat, + update_time: latest.update_time || formatDate(new Date(), 'yyyy-MM-ddTHH:mm:ss'), + latest_message: { + ...chat.latest_message, + message: latest.message[latest.chatKey] || latest.message } } : chat) diff --git a/src/frontend/src/pages/FileLibPage/index.tsx b/src/frontend/src/pages/FileLibPage/index.tsx index 7c19c2f44..b99738b58 100755 --- a/src/frontend/src/pages/FileLibPage/index.tsx +++ b/src/frontend/src/pages/FileLibPage/index.tsx @@ -203,7 +203,7 @@ export default function FileLibPage() { // @ts-ignore window.libname = el.name; }}> - {t('lib.details')} + {t('lib.details')} {user.role === 'admin' || user.user_id === el.user_id ? : diff --git a/src/frontend/src/pages/SkillPage/editAssistant.tsx b/src/frontend/src/pages/SkillPage/editAssistant.tsx index 2b5b68d7c..424fb07aa 100644 --- a/src/frontend/src/pages/SkillPage/editAssistant.tsx +++ b/src/frontend/src/pages/SkillPage/editAssistant.tsx @@ -21,7 +21,7 @@ export default function editAssistant() { const { startNewRound, insetSystemMsg, insetBsMsg, setShowGuideQuestion } = useMessageStore() useEffect(() => { - loadAssistantState(assisId).then((res) => { + loadAssistantState(assisId, 'v1').then((res) => { setShowGuideQuestion(true) setGuideQuestion(res.guide_question?.filter((item) => item) || []) res.guide_word && insetBsMsg(res.guide_word) diff --git a/src/frontend/src/pages/SystemPage/index.tsx b/src/frontend/src/pages/SystemPage/index.tsx index 7f11d6812..a58c001e7 100644 --- a/src/frontend/src/pages/SystemPage/index.tsx +++ b/src/frontend/src/pages/SystemPage/index.tsx @@ -1,16 +1,17 @@ +import { userContext } from "@/contexts/userContext"; +import { useContext } from "react"; +import { useTranslation } from "react-i18next"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "../../components/bs-ui/tabs"; -import Roles from "./components/Roles"; import Config from "./components/Config"; -import Users from "./components/Users"; -import { useTranslation } from "react-i18next"; +import Roles from "./components/Roles"; +import Theme from "./theme"; import UserGroups from "./components/UserGroup"; -import { userContext } from "@/contexts/userContext"; -import { useContext } from "react"; +import Users from "./components/Users"; export default function FileLibPage() { const { user } = useContext(userContext); @@ -24,9 +25,9 @@ export default function FileLibPage() { {user.role === 'admin' && {t('system.userGroupsM')}} {t('system.roleManagement')} {user.role === 'admin' && {t('system.systemConfiguration')}} + 主题配置 - @@ -38,6 +39,9 @@ export default function FileLibPage() { + + +
}; diff --git a/src/frontend/src/pages/SystemPage/theme/Example.tsx b/src/frontend/src/pages/SystemPage/theme/Example.tsx new file mode 100644 index 000000000..563168303 --- /dev/null +++ b/src/frontend/src/pages/SystemPage/theme/Example.tsx @@ -0,0 +1,185 @@ +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/bs-ui/accordion"; +import { Badge } from "@/components/bs-ui/badge"; +import { Button } from "@/components/bs-ui/button"; +import { Calendar } from "@/components/bs-ui/calendar"; +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/bs-ui/card"; +import { Checkbox } from "@/components/bs-ui/checkBox"; +import { SearchInput, Textarea } from "@/components/bs-ui/input"; +import { Label } from "@/components/bs-ui/label"; +import AutoPagination from "@/components/bs-ui/pagination/autoPagination"; +import { RadioGroup, RadioGroupItem } from "@/components/bs-ui/radio"; +import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/bs-ui/select"; +import { Slider } from "@/components/bs-ui/slider"; +import { Switch } from "@/components/bs-ui/switch"; +import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/bs-ui/table"; + +const invoices = [ + { + invoice: "INV001", + paymentStatus: "Paid", + totalAmount: "$250.00", + paymentMethod: "Credit Card", + }, + { + invoice: "INV002", + paymentStatus: "Pending", + totalAmount: "$150.00", + paymentMethod: "PayPal", + }, + { + invoice: "INV003", + paymentStatus: "Unpaid", + totalAmount: "$350.00", + paymentMethod: "Bank Transfer", + }, +] + +export default function Example(params) { + + return
+ +
+ + + + + + +
+ +
+ Badge + Badge + Badge + Badge +
+ +
+ +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+ + +
+
+ + +
+
+
+ +
+ + A list of your recent invoices. + + + Invoice + Status + Method + Amount + + + + {invoices.map((invoice) => ( + + {invoice.invoice} + {invoice.paymentStatus} + {invoice.paymentMethod} + {invoice.totalAmount} + + ))} + + + + Total + $2,500.00 + + +
+ +
+ +
+ +
+ +
+ + + Create project + Deploy your new project in one-click. + + + 内容 + + + + + + +
+ +
+ + + Is it accessible? + + Yes. It adheres to the WAI-ARIA design pattern. + + + + Is it styled? + + Yes. It comes with default styles that matches the other + components' aesthetic. + + + + Is it animated? + + Yes. It's animated by default, but you can disable it if you prefer. + + + +
+
+}; diff --git a/src/frontend/src/pages/SystemPage/theme/HSLitem.tsx b/src/frontend/src/pages/SystemPage/theme/HSLitem.tsx new file mode 100644 index 000000000..91a2b152e --- /dev/null +++ b/src/frontend/src/pages/SystemPage/theme/HSLitem.tsx @@ -0,0 +1,21 @@ +import { Button } from "@/components/bs-ui/button"; +import { Label } from "@/components/bs-ui/label"; +import { useState } from "react"; +import { BlockPicker } from 'react-color'; + +export default function HSLitem({ label, name, value, onChange }) { + const [show, setShow] = useState(false) + + return
+ +
+ + {show &&
+
setShow(false)}>
+ { onChange(name, e.hsl), setShow(false) }} /> +
} +
+
+}; diff --git a/src/frontend/src/pages/SystemPage/theme/index.tsx b/src/frontend/src/pages/SystemPage/theme/index.tsx new file mode 100644 index 000000000..0a43b673e --- /dev/null +++ b/src/frontend/src/pages/SystemPage/theme/index.tsx @@ -0,0 +1,109 @@ +import { useState } from "react"; +import HSLitem from "./HSLitem"; +import Example from "./Example"; +import { Button } from "@/components/bs-ui/button"; +import { LoadIcon } from "@/components/bs-icons"; +import { ReloadIcon } from "@radix-ui/react-icons"; +import { saveThemeApi } from "@/controllers/API"; + +const defaultTheme = { + '--background': { h: 0, s: 0, l: 1 }, + '--foreground': { h: 222.2, s: 0.474, l: 0.112 }, + '--muted': { h: 210, s: 0.4, l: 0.98 }, + '--muted-foreground': { h: 215.4, s: 0.163, l: 0.469 }, + '--popover': { h: 0, s: 0, l: 1 }, + '--popover-foreground': { h: 222.2, s: 0.474, l: 0.112 }, + '--card': { h: 0, s: 0, l: 1 }, + '--card-foreground': { h: 222.2, s: 0.474, l: 0.112 }, + '--border': { h: 214.3, s: 0.218, l: 0.914 }, + '--input': { h: 223, s: 0.48, l: 0.44 }, + '--primary': { h: 220, s: 0.98, l: 0.45 }, + '--primary-foreground': { h: 210, s: 0.4, l: 0.98 }, + '--secondary': { h: 210, s: 0.4, l: 0.961 }, + '--secondary-foreground': { h: 222.2, s: 0.474, l: 0.112 }, + '--accent': { h: 210, s: 0.3, l: 0.961 }, + '--accent-foreground': { h: 222.2, s: 0.474, l: 0.112 }, + '--destructive': { h: 0, s: 1, l: 0.5 }, + '--destructive-foreground': { h: 210, s: 0.4, l: 0.98 }, + '--black-button': { h: 0, s: 0, l: 0.07 }, +}; + +const themeKeys = { + "--primary": "主题色", + "--primary-foreground": "主题前景色", + "--background": "背景色", + "--foreground": "前景色", + "--muted": "柔和背景色", + "--muted-foreground": "柔和前景色", + "--card": "卡片背景色", + "--card-foreground": "卡片前景色", + "--popover": "弹出框背景色", + "--popover-foreground": "弹出框前景色", + "--border": "边框色", + "--input": "输入框边框色", + "--secondary": "次要按钮背景色", + "--secondary-foreground": "次要按钮前景色", + "--accent": "强调色", + "--accent-foreground": "强调前景色", + "--destructive": "警告按钮背景色", + "--destructive-foreground": "警告按钮前景色", + "--ring": "聚焦边框色", + "--radius": "圆角半径", + "--warning": "警告色", + "--warning-foreground": "警告前景色", + '--black-button': '黑按钮', +}; + +export default function Theme() { + const [theme, setTheme] = useState(Object.keys(window.ThemeStyle.comp).length ? window.ThemeStyle.comp : { ...defaultTheme }); + + const applyTheme = (theme) => { + Object.keys(theme).forEach(key => { + document.documentElement.style.setProperty(key, handleHSLtoStr(theme[key])); + }); + setTheme(theme); + window.ThemeStyle = { comp: theme } + saveThemeApi(JSON.stringify({ comp: theme })) + }; + + // hsl -> '220 98% 95%' + const handleHSLtoStr = (hsl) => { + return `${hsl.h} ${hsl.s * 100}% ${hsl.l * 100}%` + } + + const handleHSLChange = (name, hsl) => { + const newTheme = { + ...theme, + [name]: hsl, + }; + setTheme(newTheme); + document.documentElement.style.setProperty(name, handleHSLtoStr(hsl)); + // save + window.ThemeStyle = { comp: newTheme } + saveThemeApi(JSON.stringify({ comp: newTheme })) + }; + + + return
+
+

+ 颜色配置 + +

+
+ { + Object.keys(theme).map(key => { + return + }) + } +
+
+
+

组件预览

+
+ {/* 组件列表 */} + +
+
+
+}; diff --git a/src/frontend/src/routes.tsx b/src/frontend/src/routes.tsx index dfec19baf..6dcf0cfc4 100755 --- a/src/frontend/src/routes.tsx +++ b/src/frontend/src/routes.tsx @@ -5,6 +5,7 @@ import BuildLayout from "./layout/BuildLayout"; import MainLayout from "./layout/MainLayout"; import SkillChatPage from "./pages/ChatAppPage"; import ChatShare from "./pages/ChatAppPage/chatShare"; +import ChatAssitantShare from "./pages/ChatAppPage/chatAssitantShare"; import ChatPro from "./pages/ChatAppPage/chatWebview"; import DiffFlowPage from "./pages/DiffFlowPage"; import FileLibPage from "./pages/FileLibPage"; @@ -98,6 +99,7 @@ const privateRouter = [ // 独立会话页 { path: "/chat", element: }, { path: "/chat/:id/", element: }, + { path: "/chat/assitant/:id/", element: }, { path: "/chatpro/:id", element: }, { path: "/report/:id/", element: }, { path: "/diff/:id/:vid/:cid", element: }, @@ -139,6 +141,7 @@ export const publicRouter = createBrowserRouter([ { path: "/", element: }, { path: "/reset", element: }, { path: "/chat/:id/", element: }, + { path: "/chat/assitant/:id/", element: }, { path: "*", element: } ], baseConfig) diff --git a/src/frontend/src/store/assistantStore.tsx b/src/frontend/src/store/assistantStore.tsx index 75129ca87..2ed583cf3 100644 --- a/src/frontend/src/store/assistantStore.tsx +++ b/src/frontend/src/store/assistantStore.tsx @@ -13,7 +13,7 @@ type State = { type Actions = { dispatchAssistant: (action: Action, assistantState: Partial) => void, - loadAssistantState: (id: string) => Promise + loadAssistantState: (id: string, version: string) => Promise saveAfter: () => void destroy: () => void } @@ -56,8 +56,8 @@ export const useAssistantStore = create((set) => ({ assistantState: { ...assistantTemp }, dispatchAssistant: (action: Action, data: Partial) => set((state) => assistantReducer(state, action, data)), // 加载助手状态 - loadAssistantState: (id) => { - return getAssistantDetailApi(id).then(data => { + loadAssistantState: (id, version) => { + return getAssistantDetailApi(id, version).then(data => { set({ assistantState: { ...data, diff --git a/src/frontend/src/style/applies.css b/src/frontend/src/style/applies.css index 97f0265a9..bdfb5eccc 100644 --- a/src/frontend/src/style/applies.css +++ b/src/frontend/src/style/applies.css @@ -981,16 +981,12 @@ } .navlink.active{ - @apply bg-[#fff] text-[#0055e3] shadow-sm - } - - .navlink.active{ - @apply dark:bg-[#34353A] dark:text-[#FFFFFF] dark:shadow-sm + @apply bg-[#fff] text-primary shadow-sm dark:bg-[#34353A] dark:text-[#FFFFFF] dark:shadow-sm } /* new ui */ .bisheng-label { - @apply text-sm text-[#67728F] font-medium leading-none + @apply text-sm text-muted-foreground font-medium leading-none } .bisheng-tip { diff --git a/src/frontend/src/style/index.css b/src/frontend/src/style/index.css index 07473d0fd..50803d12a 100644 --- a/src/frontend/src/style/index.css +++ b/src/frontend/src/style/index.css @@ -22,10 +22,6 @@ --background-new: hsla(240, 14%, 99%, 1); - --background-hoverAssistant: hsla(0, 0%, 100%, 1); - - --background-Assistant: hsla(0, 0%, 100%, 1); - --nav-hover: white; --header-icon: white; @@ -71,10 +67,10 @@ --destructive: 0 100% 50%; /* hsl(0 100% 50%) */ --destructive-foreground: 210 40% 98%; - /* hsl(210 40% 98%) */ - --radius: .58rem; - --ring: 223, 48%, 44%, 0.35; + --black-button: 0 0% 7%; /* hsl(215 20% 65%) */ + --ring: 223, 48%, 44%, 0.35; + --radius: .58rem; --round-btn-shadow: #00000063; --error-background: #fef2f2; @@ -124,10 +120,6 @@ --background-new: hsla(0, 0%, 9%, 1); - --background-hoverAssistant: hsla(240, 1%, 16%, 1); - - --background-Assistant: hsla(240, 1%, 13%, 1); - --nav-hover: rgba(52, 53, 58, 1); --header-icon: rgba(33, 33, 34, 1); @@ -157,7 +149,7 @@ --popover-foreground: 215 20.2% 65.1%; /* hsl(215 20% 65%) */ - --card: 224 25% 15.5%; + --card: 240 1% 13%; /* hsl(224 71% 4%) */ --card-foreground: 213 31% 80%; /* hsl(213 31% 91%) */ @@ -186,6 +178,7 @@ /* hsl(0 63% 31%) */ --destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */ + --black-button: 0 0% 7%; --ring: 216 24% 30%; /* hsl(216 24% 30%) */ diff --git a/src/frontend/tailwind.config.js b/src/frontend/tailwind.config.js index 85ee3273d..b6445d011 100644 --- a/src/frontend/tailwind.config.js +++ b/src/frontend/tailwind.config.js @@ -30,8 +30,6 @@ module.exports = { extend: { colors: { "search-input": "var(--search-input)", - "background-Assistant": "var(--background-Assistant)", - "background-hoverAssistant": "var(--background-hoverAssistant)", "background-new": "var(--background-new)", "prompt-description": "var(--text-prompt)", "background-prompt": "var(--background-prompt)", @@ -95,7 +93,7 @@ module.exports = { "beta-foreground": "var(--beta-foreground)", "chat-bot-icon": "var(--chat-bot-icon)", "chat-user-icon": "var(--chat-user-icon)", - + "black-button": "hsl(var(--black-button))", white: "var(--white)", border: "hsl(var(--border))", input: "hsl(var(--input)/0.15)",