zhangkai 1 ano atrás
pai
commit
a7677c32fb
37 arquivos alterados com 592 adições e 240 exclusões
  1. 2 2
      build/index.html
  2. 25 25
      build/locales/zh/bs.json
  3. 1 1
      public/locales/zh/bs.json
  4. 4 1
      src/App.css
  5. BIN
      src/assets/.DS_Store
  6. BIN
      src/assets/chat/.DS_Store
  7. BIN
      src/assets/chat/copy.png
  8. BIN
      src/assets/chat/xiazai.png
  9. 5 4
      src/components/bs-comp/chatComponent/ChatInput.tsx
  10. 18 8
      src/components/bs-comp/chatComponent/MessageBs.tsx
  11. 3 2
      src/components/bs-comp/chatComponent/MessagePanne.tsx
  12. 3 1
      src/components/bs-comp/chatComponent/RunLog.tsx
  13. 2 4
      src/components/bs-comp/chatComponent/messageStore.ts
  14. 5 9
      src/components/bs-comp/sheets/SkillSheet.tsx
  15. 2 2
      src/components/inputFileComponent/index.tsx
  16. 6 0
      src/controllers/API/user.ts
  17. 10 6
      src/modals/formModal/chatMessage/codeBlock/index.tsx
  18. 2 2
      src/pages/ChatAppPage/components/ChatPanne.tsx
  19. 4 2
      src/pages/ChatAppPage/index.tsx
  20. 1 0
      src/pages/ChatAppPage/mobile/ChatPanneM.tsx
  21. 1 1
      src/pages/FileLibPage/files.tsx
  22. 10 8
      src/pages/FlowPage/components/extraSidebarComponent/PersonalComponents.tsx
  23. 1 1
      src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
  24. 2 2
      src/pages/SkillPage/components/SkillTemps.tsx
  25. 3 2
      src/pages/SkillPage/components/editAssistant/Header.tsx
  26. 1 1
      src/pages/SkillPage/components/editAssistant/TestChat.tsx
  27. 4 2
      src/pages/SkillPage/editAssistant.tsx
  28. 23 8
      src/pages/SkillPage/l2Edit.tsx
  29. 23 11
      src/pages/SkillPage/tabAssistant.tsx
  30. 25 10
      src/pages/SkillPage/tabSkills.tsx
  31. 9 4
      src/pages/SkillPage/temps.tsx
  32. 225 0
      src/pages/SystemPage/components/EditRole copy.tsx
  33. 126 113
      src/pages/SystemPage/components/EditRole.tsx
  34. 1 1
      src/pages/SystemPage/components/Roles.tsx
  35. 1 1
      src/style/applies.css
  36. 41 3
      src/style/zk.scss
  37. 3 3
      src/util/hook.ts

+ 2 - 2
build/index.html

@@ -8,12 +8,12 @@
     <link rel="icon" href="/favicon.ico" />
     <script src="/node_modules/ace-builds/src-min-noconflict/ace.js" type="text/javascript"></script>
     <title>NPCs</title>
-  <script type="module" crossorigin src="/assets/index-92a8c43f.js"></script>
+  <script type="module" crossorigin src="/assets/index-7689cf6c.js"></script>
   <link rel="modulepreload" crossorigin href="/assets/acebuilds-fbc0ccc6.js">
   <link rel="modulepreload" crossorigin href="/assets/reactflow-c250d835.js">
   <link rel="modulepreload" crossorigin href="/assets/reactdrop-be699031.js">
   <link rel="modulepreload" crossorigin href="/assets/pdfjs-36654f0a.js">
-  <link rel="stylesheet" href="/assets/index-29c2092e.css">
+  <link rel="stylesheet" href="/assets/index-9b55ebe4.css">
 </head>
 
 <body id='body' style="width: 100%; height:100%">

+ 25 - 25
build/locales/zh/bs.json

@@ -55,40 +55,40 @@
         "language": "语言"
     },
     "skills": {
-        "manageTemplate": "管理能模板",
-        "createNew": "新建能",
-        "customSkills": "自定义能",
+        "manageTemplate": "管理能模板",
+        "createNew": "新建能",
+        "customSkills": "自定义能",
         "chooseOnline": "选择上线版本",
-        "executionSteps": "能通过可视化的流程编排,明确任务执行步骤",
+        "executionSteps": "能通过可视化的流程编排,明确任务执行步骤",
         "sceneTemplates": "我们提供场景模板供您使用和参考",
-        "manageProjects": "在此页面管理您的能,对能上下线、编辑等等",
-        "skillSearch": "搜索您需要的能",
-        "confirmDeleteSkill": "确认删除该能?",
-        "backToSkillList": "返回能列表",
-        "skillTemplateManagement": "能模板管理,模板对所有用户可见,支持拖拽排序、删除操作",
+        "manageProjects": "在此页面管理您的能,对能上下线、编辑等等",
+        "skillSearch": "搜索您需要的能",
+        "confirmDeleteSkill": "确认删除该能?",
+        "backToSkillList": "返回能列表",
+        "skillTemplateManagement": "能模板管理,模板对所有用户可见,支持拖拽排序、删除操作",
         "templateName": "模板名称",
         "templateDescription": "模板描述",
-        "confirmText": "是否确认删除该能模板?",
-        "skillSettings": "能设置",
+        "confirmText": "是否确认删除该能模板?",
+        "skillSettings": "能设置",
         "basicInfo": "基础信息",
-        "skillName": "能名称",
+        "skillName": "能名称",
         "description": "描述",
         "parameterInfo": "参数信息",
         "advancedConfiguration": "高级配置",
         "nextStep": "下一步,高级配置",
-        "skillNameRequired": "请填写能名称",
-        "skillNameTooLong": "能名称过长,不要超过30字",
+        "skillNameRequired": "请填写能名称",
+        "skillNameTooLong": "能名称过长,不要超过30字",
         "skillNameExists": "该名称已存在",
-        "skillDescRequired": "请填写能描述",
-        "skillDescTooLong": "能描述过长,不要超过200字",
+        "skillDescRequired": "请填写能描述",
+        "skillDescTooLong": "能描述过长,不要超过200字",
         "errorTitle": "关键信息有误",
         "onlineFailure": "上线失败",
         "onlineSuccessful": "上线成功",
         "custom": "自定义",
-        "skillTemplate": "能模板",
+        "skillTemplate": "能模板",
         "skillTemplateChoose": "您可以从这里挑选一个模板开始,或者自定义高级模板",
         "createTemplate": "创建模板",
-        "createSuccessTitle": "能创建成功",
+        "createSuccessTitle": "能创建成功",
         "createFailureTitle": "创建失败",
         "createdBy": "创建用户",
         "offline": "下线",
@@ -442,7 +442,7 @@
     "build": {
         "create": "创建",
         "assistant": "NPC",
-        "skill": "能",
+        "skill": "能",
         "tools": "工具",
         "save": "保存",
         "online": "上线",
@@ -455,7 +455,7 @@
         "portraitOptimization": "NPC画像优化",
         "automaticOptimization": "自动优化",
         "createDescription": "通过描述角色和任务来创建你的NPC",
-        "nextDescription": "NPC可以调用多个能和工具",
+        "nextDescription": "NPC可以调用多个能和工具",
         "searchAssistant": "搜索您需要的NPC",
         "manageAssistant": "在此页面管理您的NPC,对NPC上下线、编辑等等",
         "establishAssistant": "创建NPC",
@@ -473,7 +473,7 @@
         "guideReplaced": "引导词已替换",
         "openingReplaced": "开场白已替换",
         "toolsReplaced": "工具已替换",
-        "skillsReplaced": "能已替换",
+        "skillsReplaced": "能已替换",
         "allReplaced": "已全部替换",
         "basicConfiguration": "基础配置",
         "modelConfiguration": "AI模型配置",
@@ -503,13 +503,13 @@
         "addTool": "添加工具",
         "search": "搜索",
         "empty": "空空如也",
-        "onlineSA": "上线能&NPC",
+        "onlineSA": "上线能&NPC",
         "params": "参数",
         "added": "已添加",
         "add": "添加",
         "configurationUpdated": "配置已更新",
-        "addSkill": "添加能",
-        "createSkill": "创建能",
+        "addSkill": "添加能",
+        "createSkill": "创建能",
         "nameRequired": "名称不可为空",
         "nameMaxLength": "名称最多50个字符",
         "descMaxLength": "最多1000个字符",
@@ -2411,7 +2411,7 @@
         },
         "NPCsChatLLM": {
             "display_name": "NPCsChatLLM",
-            "description": "`OpenAI`聊天大型语言模型API。",
+            "description": "无缝切换支持的大语言模型",
             "description_url": "",
             "template": {
                 "api_base": {

+ 1 - 1
public/locales/zh/bs.json

@@ -2411,7 +2411,7 @@
         },
         "NPCsChatLLM": {
             "display_name": "NPCsChatLLM",
-            "description": "`OpenAI`聊天大型语言模型API。",
+            "description": "无缝切换支持的大语言模型",
             "description_url": "",
             "template": {
                 "api_base": {

+ 4 - 1
src/App.css

@@ -211,6 +211,9 @@ path.react-flow__edge-interaction:hover {
 
 .bs-chat-bg {
 	width: 100%;
-	background: url(/points.png) 0 100% repeat-x;
+	/* background: url(/points.png) 0 100% repeat-x; */
 	background-size: 10px 432px;
+    /* background: rgba(0,0,0,0.9); */
+    /* background-color: #000; */
+
 }

BIN
src/assets/.DS_Store


BIN
src/assets/chat/.DS_Store


BIN
src/assets/chat/copy.png


BIN
src/assets/chat/xiazai.png


+ 5 - 4
src/components/bs-comp/chatComponent/ChatInput.tsx

@@ -91,7 +91,7 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
         // 锁定 input
         setInputLock({ locked: true, reason: '' })
         await createWebSocket(chatId)
-        console.log(wsMsg,inputKey);
+        // console.log(wsMsg,inputKey);
         sendWsMsg(wsMsg)
 
         // 滚动聊天到底
@@ -189,7 +189,7 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
 
     // 接受 ws 消息
     const handleWsMessage = (data) => {
-        console.log(data)
+        // console.log(data)
         if (Array.isArray(data) && data.length) return
         if (data.type === "begin") {
             setIsStop(false)
@@ -311,9 +311,10 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
                     }
                 }}
             ></textarea>
-            <div className=" absolute w-full flex justify-center bottom-32 pointer-events-none">
+            {!isStop && <div className=" absolute w-full flex justify-center bottom-32 pointer-events-none">
                 <Button className="rounded-full pointer-events-auto" variant="outline" disabled={isStop} onClick={() => { setIsStop(true); stop(); }}><StopCircle className="mr-2" />Stop</Button>
-            </div>
+            </div>}
+            
             {/* <p className="w-[100%] text-center text-[#666666]">内容由AI生成,仅供参考</p> */}
         </div>
         <p className="text-center text-sm pt-2 pb-4 text-gray-400">{appConfig.dialogTips}</p>

+ 18 - 8
src/components/bs-comp/chatComponent/MessageBs.tsx

@@ -38,7 +38,7 @@ const colorList = [
     "#95A5A6"
 ]
 
-export default function MessageBs({ data, onUnlike = () => { }, flow_type, onSource }: { data: ChatMessageType, flow_type: string, onUnlike?: any, onSource?: any }) {
+export default function MessageBs({ data, onUnlike = () => { }, flow_type, onSource }: { data: ChatMessageType, flow_type: any, onUnlike?: any, onSource?: any }) {
     const avatarColor = colorList[
         (data.sender?.split('').reduce((num, s) => num + s.charCodeAt(), 0) || 0) % colorList.length
     ]
@@ -88,22 +88,32 @@ export default function MessageBs({ data, onUnlike = () => { }, flow_type, onSou
 
     const chatId = useMessageStore(state => state.chatId)
     return <div className="flex w-full py-1">
-        <div className="w-fit max-w-[90%]">
+        <div className="w-[100%]">
             {data.sender && <p className="text-gray-600 text-xs mb-2">{data.sender}</p>}
             <div className="flex items-start avatarZk">
                 {/* {(data.flow_id == "06b1d374-ba97-46e6-8782-c56dec8dcc17" || data.flow_id == "ed8e21f6-9757-43d0-b076-8c6e81bb0580") && <img src={robot2} className="w-[50px]" alt=""/>}
                 {data.flow_id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[50px]" alt=""/>}
                 {(data.flow_id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && data.flow_id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && data.flow_id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[50px]" alt=""/>} */}
-                {data.flow_id && <TitleIconBg className="w-[40px] h-[40px]" img={data.avatar_img} id={data.avatar_color ? data.avatar_color : data.flow_id} ><img src={data.avatar_img ? data.avatar_img : (flow_type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>}
+                {data.flow_id && <TitleIconBg className="w-[40px] h-[40px] mr-[10px]" img={flow_type.avatar_img} id={flow_type.avatar_color ? flow_type.avatar_color : data.flow_id} ><img src={flow_type.avatar_img ? flow_type.avatar_img : (flow_type.type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>}
 
-                <div ref={messageRef} className={`min-h-8 min-w-[110px] max-w-[90%] ml-[10px] ${data.id && data.end && 'pb-8'}`}>
-                    <div className="chat-start-zk relative">
-                        {data.message.toString() ? mkdown : <span className="loading loading-ring loading-md"></span>}
+                <div ref={messageRef} className="text-sm max-w-[calc(100%-100px)]">
+                    {/* <div className="chat-start-zk relative">
+                        {data.message.toString() ? mkdown : <span className="loading loading-ring loading-md"></span>} */}
                         {/* @user */}
-                        {data.receiver && <p className="text-blue-500 text-sm">@ {data.receiver.user_name}</p>}
+                        {/* {data.receiver && <p className="text-blue-500 text-sm">@ {data.receiver.user_name}</p>} */}
                         {/* 光标 */}
                         {/* {data.message.toString() && !data.end && <div className="animate-cursor absolute w-2 h-5 ml-1 bg-gray-600" style={{ left: cursor.x, top: cursor.y }}></div>} */}
-                    </div>
+                    {/* </div> */}
+                    {data.message.toString() ?
+                        <div className="chat-start-zk relative">
+                            {mkdown}
+                            {/* @user */}
+                            {data.receiver && <p className="text-blue-500 text-sm">@ {data.receiver.user_name}</p>}
+                            {/* 光标 */}
+                            {/* {data.message.toString() && !data.end && <div className="animate-cursor absolute w-2 h-5 ml-1 bg-gray-600" style={{ left: cursor.x, top: cursor.y }}></div>} */}
+                        </div>
+                        : <div><LoadIcon className="text-gray-400" /></div>
+                    }
                     
                     {/* 赞 踩 */}
                     {!!data.id && data.end && <Thumbs

+ 3 - 2
src/components/bs-comp/chatComponent/MessagePanne.tsx

@@ -75,7 +75,7 @@ export default function MessagePanne({ useName, guideWord, loadMore, flow_type }
                 } else if (msg.thought) {
                     type = 'system'
                 }
-
+                console.log(type)
                 switch (type) {
                     case 'user':
                         return <MessageUser key={msg.id} useName={useName} data={msg} />;
@@ -88,7 +88,8 @@ export default function MessagePanne({ useName, guideWord, loadMore, flow_type }
                             onSource={(data) => { sourceRef.current?.openModal(data) }}
                         />;
                     case 'system':
-                        return <MessageSystem key={msg.id} data={msg} />;
+                        // return <MessageSystem key={msg.id} data={msg} />;
+                        return <RunLog key={msg.id} data={msg} />;
                     case 'separator':
                         return <Separator key={msg.id} text={msg.message || t('chat.roundOver')} />;
                     case 'file':

+ 3 - 1
src/components/bs-comp/chatComponent/RunLog.tsx

@@ -34,6 +34,8 @@ export default function RunLog({ data }) {
             // if (!knowledge) throw new Error('调试日志无法匹配到使用的知识库详情,id:' + data.message.tool_key)
 
             title = knowledge ? `${data.end ? '已搜索' : '正在搜索'} ${knowledge.name}` : '知识库已被删除,无法获取知识库名'
+        } else if (data.category === 'processing') {
+            title = data.thought.slice(0, 50)+"..."
         }
         return [title, lost]
     }, [assistantState, data])
@@ -46,7 +48,7 @@ export default function RunLog({ data }) {
                         data.end ? <ToastIcon type={lost ? 'error' : 'success'} /> :
                             <LoadIcon className="text-primary duration-300" />
                     }
-                    <span>{title}</span>
+                    <span className="text-[#666]">{title}</span>
                 </div>
                 <CaretDownIcon className={open && 'rotate-180'} />
             </div>

+ 2 - 4
src/components/bs-comp/chatComponent/messageStore.ts

@@ -154,7 +154,6 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
         console.log('change updateCurrentMessage');
         const messages = get().messages
         const isRunLog = runLogsTypes.includes(wsdata.category);
-        console.log(wsdata,isRunLog,messages)
         // run log类型存在嵌套情况,使用 extra 匹配 currentMessage; 否则取最近
         const currentMessageIndex = isRunLog ?
             messages.findLastIndex((msg) => msg.extra === wsdata.extra)
@@ -173,13 +172,12 @@ export const useMessageStore = create<State & Actions>((set, get) => ({
         }
 
         messages[currentMessageIndex] = newCurrentMessage
-        console.log(newCurrentMessage)
+        console.log(messages,currentMessageIndex,newCurrentMessage)
         // 会话特殊处理,兼容后端的缺陷
         if (!isRunLog) {
             // start - end 之间没有内容删除load
             if (newCurrentMessage.end && !(newCurrentMessage.files.length || newCurrentMessage.thought || newCurrentMessage.message)) {
-                // messages.pop()
-                console.log("删了")
+                messages.pop()
             }
             // 无 messageid 删除
             // if (newCurrentMessage.end && !newCurrentMessage.id) {

+ 5 - 9
src/components/bs-comp/sheets/SkillSheet.tsx

@@ -10,7 +10,7 @@ import {
   SheetTitle,
   SheetTrigger,
 } from "../../bs-ui/sheet";
-import CardComponent from "../cardComponent";
+import CardComponent, { TitleIconBg } from "../cardComponent";
 import { useTranslation } from "react-i18next";
 import { SpotlightCard } from "@lobehub/ui";
 import { Flexbox } from 'react-layout-kit';
@@ -20,6 +20,8 @@ import robot3 from "../../../assets/robot3.png";
 import zidingyi1 from "../../../assets/npc/zidingyi1.png";
 import zidingyi2 from "../../../assets/npc/zidingyi2.png";
 import borderR from "../../../assets/npc/border-r.png";
+import npcIcon from "../../../assets/npc/npcIcon.png";
+import nengliIcon from "../../../assets/npc/nengliIcon.png";
 
 export default function SkillSheet({ select, children, onSelect }) {
   const [keyword, setKeyword] = useState("");
@@ -65,19 +67,13 @@ export default function SkillSheet({ select, children, onSelect }) {
             <span>
                 <span>
                     <div>
-                        {/* <img src={robot} className="w-[160px]" alt=""/> */}
-                        {(item.id == "06b1d374-ba97-46e6-8782-c56dec8dcc17" || item.id == "ed8e21f6-9757-43d0-b076-8c6e81bb0580") && <img src={robot2} className="w-[160px]" alt=""/>}
-                        {item.id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[160px]" alt=""/>}
-                        {(item.id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && item.id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && item.id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[160px]" alt=""/>}
+                        <TitleIconBg className="w-[160px] h-[160px] min-w-[160px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.id} ><img src={item.avatar_img ? item.avatar_img : (item.flow_type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>
                     </div>
                 </span>
             </span>
         </div>
         <div>
-            {(item.id == "06b1d374-ba97-46e6-8782-c56dec8dcc17" || item.id == "ed8e21f6-9757-43d0-b076-8c6e81bb0580") && <img src={robot2} className="w-[42px]" alt=""/>}
-            {item.id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[42px]" alt=""/>}
-            {(item.id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && item.id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && item.id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[42px]" alt=""/>}
-            {/* <img src={robot} className="w-[42px]" alt=""/> */}
+            <TitleIconBg className="w-[40px] h-[40px] min-w-[40px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.id} ><img src={item.avatar_img ? item.avatar_img : (item.flow_type == "assistant" ? npcIcon : nengliIcon)} alt="" /></TitleIconBg>
             <div>
                 <p>{item.name}</p>
                 <div>

+ 2 - 2
src/components/inputFileComponent/index.tsx

@@ -107,10 +107,10 @@ export default function InputFileComponent({
           onClick={handleButtonClick}
           className={
             editNode
-              ? "input-edit-node input-dialog text-muted-foreground"
+              ? "input-edit-node input-dialog text-[#999]"
               : disabled
                 ? "input-disable input-dialog input-primary"
-                : "input-dialog input-primary text-muted-foreground"
+                : "input-dialog input-primary text-[#999]"
           }
         >
           {myValue !== "" ? myValue : placeholder}

+ 6 - 0
src/controllers/API/user.ts

@@ -57,6 +57,12 @@ export async function getRoleSkillsApi(params): Promise<{ data: any[], total: nu
     return await axios.get(`/api/v1/role_access/flow`, { params });
 }
 /**
+ * 根据角色获取技能列表
+ */
+export async function getRoleAssistApi(params): Promise<{ data: any[], total: number }> {
+    return await axios.get(`/api/v1/role_access/list_type`, { params });
+}
+/**
  * 根据角色获取知识库列表
  */
 export async function getRoleLibsApi(params): Promise<{ data: any[], total: number }> {

+ 10 - 6
src/modals/formModal/chatMessage/codeBlock/index.tsx

@@ -3,6 +3,8 @@ import { useState } from "react";
 import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
 import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
 import { copyText, programmingLanguages } from "../../../../utils";
+import copy from "../../../../assets/chat/copy.png"
+import xiazai from "../../../../assets/chat/xiazai.png"
 
 interface Props {
   language: string;
@@ -42,17 +44,19 @@ export function CodeBlock({ language, value }) {
     URL.revokeObjectURL(url);
   };
   return (
-    <div className="codeblock font-sans text-[16px]">
+    <div className="codeblock font-sans text-[16px] daimaStyle">
       <div className="code-block-modal">
-        <span className="code-block-modal-span">{language}</span>
+        <span className="code-block-modal-span text-[#999999] text-[14px]">{language}</span>
 
         <div className="flex items-center">
           <button className="code-block-modal-button" onClick={copyToClipboard}>
-            {isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
-            {isCopied ? "Copied!" : "Copy code"}
+            {/* {isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />} */}
+            <img src={copy} alt="" className="w-[14px]" />
+            {/* {isCopied ? "Copied!" : "Copy code"} */}
           </button>
-          <button className="code-block-modal-button" onClick={downloadAsFile}>
-            <IconDownload size={18} />
+          <button className="code-block-modal-button ml-[10px]" onClick={downloadAsFile}>
+            {/* <IconDownload size={18} /> */}
+            <img src={xiazai} alt="" className="w-[14px]" />
           </button>
         </div>
       </div>

+ 2 - 2
src/pages/ChatAppPage/components/ChatPanne.tsx

@@ -387,7 +387,7 @@ export default function ChatPanne({ customWsHost = '', data }) {
                         wsUrl={wsUrl}
                         onBeforSend={getWsParamData}
                         loadMore={() => loadMoreHistoryMsg(flow.id,"flow")}
-                        type={type}
+                        type={{"avatar_img":flow.avatar_img,"avatar_color":flow.avatar_color,"type":type}}
                         inputForm={flowSate.isForm ? <ChatReportForm flow={flow} onStart={sendReport} /> : null}
                     />
                      {/* <div ref={messagesRef} className={`chat-panne h-full overflow-y-scroll no-scrollbar px-[35px] ${isRoom || isReport ? 'pb-0' : 'pb-0'}`}>
@@ -426,7 +426,7 @@ export default function ChatPanne({ customWsHost = '', data }) {
                         wsUrl={wsUrl}
                         onBeforSend={getWsParamData}
                         loadMore={() => loadMoreHistoryMsg(assistant.id,"assistant")}
-                        type={type}
+                        type={{"avatar_img":assistant.avatar_img,"avatar_color":assistant.avatar_color,"type":type}}
                         inputForm={null}
                     />
                 </div>

+ 4 - 2
src/pages/ChatAppPage/index.tsx

@@ -60,7 +60,9 @@ export default function SkillChatPage() {
             "chat_id": _chatId,
             "create_time": "-",
             "update_time": "-",
-            "flow_type": card.flow_type
+            "flow_type": card.flow_type,
+            "avatar_img": card.avatar_img,
+            "avatar_color": card.avatar_color,
         })
 
         setSelelctChat({ id: card.id, chatId: _chatId, type: card.flow_type })
@@ -92,7 +94,7 @@ export default function SkillChatPage() {
 
     return <div className="flex">
         <div className="h-screen w-[288px] relative">
-            <div className="xinDuiHua absolute">
+            <div className="xinDuiHua absolute bg-[#000000] xinDuiHua-box">
                 <SkillChatSheet onSelect={handlerSelectFlow}>
                     <div id="newchat" className="xinDuiHua-btn cursor-pointer">
                         {/* <PlusBoxIcon className="dark:hidden"></PlusBoxIcon> */}

+ 1 - 0
src/pages/ChatAppPage/mobile/ChatPanneM.tsx

@@ -371,6 +371,7 @@ export default function ChatPanne({ customWsHost = '', data }) {
                         wsUrl={wsUrl}
                         onBeforSend={getWsParamData}
                         loadMore={() => loadMoreHistoryMsg(flow.id, type)}
+                        type={{"avatar_img":flow.avatar_img,"avatar_color":flow.avatar_color,"type":type}}
                         inputForm={flowSate.isForm ? <ChatReportForm flow={flow} onStart={sendReport} /> : null}
                     />
                      {/* <div ref={messagesRef} className={`chat-panne h-full overflow-y-scroll no-scrollbar px-[35px] ${isRoom || isReport ? 'pb-0' : 'pb-0'}`}>

+ 1 - 1
src/pages/FileLibPage/files.tsx

@@ -46,7 +46,7 @@ export default function FilesPage() {
         })
     )
     // loadData();
-    // setTimeout(() => reload(), 5000);
+    setTimeout(() => reload(), 5000);
 
     const [hasPermission, setHasPermission] = useState(true)
     const { appConfig } = useContext(locationContext)

+ 10 - 8
src/pages/FlowPage/components/extraSidebarComponent/PersonalComponents.tsx

@@ -10,11 +10,14 @@ import { classNames, nodeColors, nodeIconsLucide, getNodeNames, nodeIMgsLucide,
 import gengduo from "../../../../assets/npc/gengduo.png";
 import gang from "../../../../assets/npc/gang.png";
 import wenhao from "../../../../assets/npc/wenhao.png";
+import del from "../../../../assets/npc/del.png";
 import { JSX } from "react/jsx-runtime";
 import DescriptionModel from "../../../../modals/descriptionModel";
+import { typesContext } from "@/contexts/typesContext";
 
 export default function PersonalComponents({ onDragStart, launch }) {
     const { addSavedComponent, checkComponentsName, delComponent, savedComponents } = useContext(userContext)
+    const { types } = useContext(typesContext);
 
     const addComponent = (data) => {
         if (checkComponentsName(data.node.display_name)) {
@@ -126,29 +129,28 @@ export default function PersonalComponents({ onDragStart, launch }) {
                                             <CircleX className="side-bar-components-icon ml-2 cursor-pointer" onClick={(e) => handleDel(e, comp)} />
                                         </div> */}
                                         <div className="npc_zujianList_item">
-                                            <div className="npcInfoItemBg">
+                                            <div className="npcInfoItemBg z-[0]">
                                                 <span>
                                                     <span>
-                                                        <div style={{background:nodeColors["Save"] ?? nodeColors.unknown}}>
+                                                        <div style={{background:nodeColors[types[comp.data.type]] ?? nodeColors.unknown}}>
                                                         </div>
                                                     </span>
                                                 </span>
                                             </div>
-                                            <div>
+                                            <div className="z-[10]">
                                                 <div>
-                                                <img src={nodeIMgsLucide1["Save"]} className="w-[14px]" alt="" />
+                                                <img src={nodeIMgsLucide1[types[comp.data.type]]} className="w-[14px]" alt="" />
                                                 <p>{comp.name ?? ""}</p>
                                                 {/* <img src={wenhao} className="w-[14px]" alt="" /> */}
                                                 {comp.description_url && <img src={wenhao} onClick={() => {
-                                                    console.log(111)
                                                     openPopUp(<DescriptionModel data={comp.description_url} />)
                                                 }} className="w-[14px] z-[1]" alt="" />}
                                                 </div>
-                                                <div>
-                                                {/* <img src={gang} className="w-[14px]" alt="" /> */}
+                                                <div onClick={(e) => handleDel(e, comp)}>
+                                                    <img src={del} className="w-[14px] cursor-pointer z-[10]" alt="" />
                                                 </div>
                                             </div>
-                                            <p>{comp.description}</p>
+                                            <p>{comp.data.node.description}</p>
                                         </div>
                                     </div>
                                 </div>

+ 1 - 1
src/pages/FlowPage/components/nodeToolbarComponent/index.tsx

@@ -52,7 +52,7 @@ const NodeToolbarComponent = ({ data, deleteNode, openPopUp, position }) => {
     // 部分组件开放“历史/history”入口:agent、chains、retrievers 、vector store 4类组件。
     return ["chains", "agents", "vectorstores", "retrievers"].includes(types[data.type])
   }, [data, types])
-
+  
   const navigate = useNavigate()
   const { id: flowId } = useParams()
   const { addSavedComponent, checkComponentsName } = useContext(userContext)

+ 2 - 2
src/pages/SkillPage/components/SkillTemps.tsx

@@ -54,7 +54,7 @@ export default function SkillTemps({ flows, isTemp = false,
                             {/* {(item.id == "06b1d374-ba97-46e6-8782-c56dec8dcc17" || item.id == "ed8e21f6-9757-43d0-b076-8c6e81bb0580") && <img src={robot2} className="w-[160px]" alt=""/>}
                             {item.id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[160px]" alt=""/>}
                             {(item.id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && item.id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && item.id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[160px]" alt=""/>} */}
-                            <TitleIconBg className="w-[160px] h-[160px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.id} ><img src={item.avatar_img ? item.avatar_img : nengliIcon} alt="" /></TitleIconBg>
+                            <TitleIconBg className="w-[160px] h-[160px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.flow_id} ><img src={item.avatar_img ? item.avatar_img : nengliIcon} alt="" /></TitleIconBg>
                         </div>
                     </span>
                 </span>
@@ -64,7 +64,7 @@ export default function SkillTemps({ flows, isTemp = false,
                 {item.id == "ca214b41-2b73-4585-b172-bf1e546cf6ec" && <img src={robot3} className="w-[42px]" alt=""/>}
                 {(item.id != "06b1d374-ba97-46e6-8782-c56dec8dcc17" && item.id != "ed8e21f6-9757-43d0-b076-8c6e81bb0580" && item.id != "ca214b41-2b73-4585-b172-bf1e546cf6ec") && <img src={robot} className="w-[42px]" alt=""/>} */}
                 {/* <img src={robot} className="w-[42px]" alt=""/> */}
-                <TitleIconBg className="w-[40px] h-[40px] min-w-[40px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.id} ><img src={item.avatar_img ? item.avatar_img : nengliIcon} alt="" /></TitleIconBg>
+                <TitleIconBg className="w-[40px] h-[40px] min-w-[40px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.flow_id} ><img src={item.avatar_img ? item.avatar_img : nengliIcon} alt="" /></TitleIconBg>
                 <div>
                     <p>{item.name}</p>
                     <div>

+ 3 - 2
src/pages/SkillPage/components/editAssistant/Header.tsx

@@ -5,7 +5,7 @@ import { Dialog, DialogTrigger } from "@/components/bs-ui/dialog";
 import { useAssistantStore } from "@/store/assistantStore";
 import { ChevronLeftIcon, Pencil2Icon } from "@radix-ui/react-icons";
 import { useEffect, useRef, useState } from "react";
-import { useNavigate } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
 import EditAssistantDialog from "./EditAssistantDialog";
 import { useTranslation } from "react-i18next";
 import npcIcon from "../../../../assets/npc/npcIcon.png";
@@ -20,6 +20,7 @@ export default function Header({ onSave, onLine }) {
     const [editShow, setEditShow] = useState(false);
 
     const needSaveRef = useRef(false)
+    const {state} = useLocation();
     useEffect(() => {
         if (needSaveRef.current) {
             needSaveRef.current = false
@@ -33,7 +34,7 @@ export default function Header({ onSave, onLine }) {
     }
     return <div className="flex justify-between items-center border-b px-4">
         <div className="flex items-center gap-2 py-4">
-            <Button variant="outline" size="icon" onClick={() => navigate(-1)}><ChevronLeftIcon className="h-4 w-4" /></Button>
+            <Button variant="outline" size="icon" onClick={() => navigate('/build/assist',{state:state})}><ChevronLeftIcon className="h-4 w-4" /></Button>
             {/* <TitleIconBg id={assistantState.id} className="ml-4"><AssistantIcon /></TitleIconBg> */}
             <TitleIconBg className="w-[40px] h-[40px]" img={assistantState.avatar_img} id={assistantState.avatar_color ? assistantState.avatar_color : assistantState.id} ><img src={assistantState.avatar_img ? assistantState.avatar_img : npcIcon} alt="" /></TitleIconBg>
             <span className="bisheng-title text-[#fff]">{assistantState.name}</span>

+ 1 - 1
src/pages/SkillPage/components/editAssistant/TestChat.tsx

@@ -52,7 +52,7 @@ export default function TestChat({ assisId, guideQuestion }) {
             guideWord=''
             wsUrl={wsUrl}
             onBeforSend={getWsParamData}
-            type="assistant"
+            type={{"avatar_img":assistantState.avatar_img,"avatar_color":assistantState.avatar_color,"type":"assistant"}}
         ></ChatComponent>
     </div>
 };

+ 4 - 2
src/pages/SkillPage/editAssistant.tsx

@@ -5,7 +5,7 @@ import { captureAndAlertRequestErrorHoc } from "@/controllers/request";
 import { useAssistantStore } from "@/store/assistantStore";
 import { useEffect, useState } from "react";
 import { useParams } from "react-router";
-import { useNavigate } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
 import Header from "./components/editAssistant/Header";
 import Prompt from "./components/editAssistant/Prompt";
 import Setting from "./components/editAssistant/Setting";
@@ -58,6 +58,7 @@ export default function editAssistant() {
             })
         })
     }
+    const {state} = useLocation();
 
     // 上线助手
     const handleOnline = async () => {
@@ -72,7 +73,8 @@ export default function editAssistant() {
             })
         })
         setTimeout(() => {
-            navigate('/build')
+            // navigate('/build')
+            navigate('/build/assist',{state:state})
         }, 1200);
     }
 

+ 23 - 8
src/pages/SkillPage/l2Edit.tsx

@@ -1,7 +1,7 @@
 import { ArrowLeft, ChevronUp } from "lucide-react";
 import { useContext, useEffect, useMemo, useRef, useState } from "react";
 import { useTranslation } from "react-i18next";
-import { useNavigate, useParams } from "react-router-dom";
+import { useLocation, useNavigate, useParams } from "react-router-dom";
 import L2ParameterComponent from "../../CustomNodes/GenericNode/components/parameterComponent/l2Index";
 import ShadTooltip from "../../components/ShadTooltipComponent";
 import { Button } from "../../components/ui/button";
@@ -41,8 +41,9 @@ export default function l2Edit() {
     const [avatar_img, setAvatar_img] = useState("")
     const [avatar_color, setAvatar_color] = useState("")
     const randomNum = Math.floor(Math.random()*(4-0+1)+0).toString();
-
+    const {state} = useLocation();
     useEffect(() => {
+        console.log(id)
         if(!id){
             setAvatar_color(randomNum);
         }
@@ -51,11 +52,18 @@ export default function l2Edit() {
         // 已有flow 数据时,不再请求
         if (flow?.id === id) {
             setIsL2(true)
+            console.log(1)
             nameRef.current.value = flow.name
             descRef.current.value = flow.description
             guideRef.current.value = flow.guide_word
-            setAvatar_img(flow.avatar_img);
-            if(flow.avatar_color){
+            if(state && state.avatar_img){
+                setAvatar_img(state.avatar_img);
+            }else{
+                setAvatar_img(flow.avatar_img);
+            }
+            if(state && state.avatar_color){
+                setAvatar_color(state.avatar_color);
+            }else if(flow.avatar_color){
                 setAvatar_color(flow.avatar_color);
             }else{
                 setAvatar_color(id);
@@ -70,8 +78,14 @@ export default function l2Edit() {
             nameRef.current.value = _flow.name
             descRef.current.value = _flow.description
             guideRef.current.value = _flow.guide_word
-            setAvatar_img(_flow.avatar_img);
-            if(_flow.avatar_color){
+            if(state && state.avatar_img){
+                setAvatar_img(state.avatar_img);
+            }else{
+                setAvatar_img(_flow.avatar_img);
+            }
+            if(state && state.avatar_color){
+                setAvatar_color(state.avatar_color);
+            }else if(_flow.avatar_color){
                 setAvatar_color(_flow.avatar_color);
             }else{
                 setAvatar_color(id);
@@ -152,7 +166,8 @@ export default function l2Edit() {
         await saveFlow({...flow, name, description, guide_word: guideWords, avatar_img, avatar_color})
         setLoading(false)
         setSuccessData({ title: t('success') });
-        setTimeout(() => /^\/skill\/[\w\d-]+/.test(location.pathname) && navigate(-1), 2000);
+        setTimeout(() => navigate('/build/skills',{state:state}), 2000);
+        // setTimeout(() => /^\/skill\/[\w\d-]+/.test(location.pathname) && navigate(-1), 2000);
     }
 
     // 表单收缩
@@ -234,7 +249,7 @@ export default function l2Edit() {
         <div className="p-6 pb-48 h-screen overflow-y-auto">
             <div className="flex justify-between w-full">
                 <ShadTooltip content={t('back')} side="right">
-                    <button className="extra-side-bar-buttons w-[36px]" onClick={() => window.history.length < 3 ? navigate('/build/skills') : navigate(-1)}>
+                    <button className="extra-side-bar-buttons w-[36px]" onClick={() => navigate('/build/skills',{state:state})}>
                         <ArrowLeft strokeWidth={1.5} className="side-bar-button-size" />
                     </button>
                 </ShadTooltip>

+ 23 - 11
src/pages/SkillPage/tabAssistant.tsx

@@ -7,7 +7,7 @@ import { AssistantItemDB, changeAssistantStatusApi, deleteAssistantApi, getAssis
 import { FlowType } from "../../types/flow";
 import { useTable } from "../../util/hook";
 import CreateAssistant from "./components/CreateAssistant";
-import { useNavigate } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
 import { captureAndAlertRequestErrorHoc } from "@/controllers/request";
 import { useToast } from "@/components/bs-ui/toast/use-toast";
 import { bsConfirm } from "@/components/bs-ui/alertDialog/useConfirm";
@@ -23,7 +23,7 @@ import sousuo from "../../assets/npc/sousuo.png";
 import del from "../../assets/npc/del.png";
 import zidingyi1 from "../../assets/npc/zidingyi1.png";
 import zidingyijia from "../../assets/npc/zidingyijia.png";
-import { useContext, useRef, useState } from "react";
+import { useContext, useEffect, useRef, useState } from "react";
 import { SpotlightCard } from "@lobehub/ui";
 import { Flexbox } from 'react-layout-kit';
 import { updataOnlineState } from "@/controllers/API/flow";
@@ -44,13 +44,24 @@ export default function Assistants() {
     const { page, pageSize, data: dataSource, total, loading, setPage, search, reload, refreshData } = useTable<AssistantItemDB>({ pageSize: 15 }, (param) =>
         getAssistantsApi(param.page, param.pageSize, param.keyword)
     )
-    
-    if(dataSource[0] && dataSource[0].type != 0){
+
+    if(dataSource == "" || dataSource[0].type != 0){
         dataSource.unshift({"type":0})
     }
 
     const inputRef = useRef(null);
-
+    const {state} = useLocation();
+    useEffect(() => {
+        if(state){
+            if(state.page){
+                setPage(state.page)
+            }
+            if(state.value){
+                inputRef.current.value = state.value
+                search(state.value)
+            }
+        }
+    }, [])
     const handleDelete = () => {
         // bsConfirm({
         //     desc: t('确认删除该NPC?'),
@@ -147,16 +158,17 @@ export default function Assistants() {
                     <p>{item.desc}</p>
                     <div>
                         <div>
-                            {!openSwitch && <div className="w-[80px] h-[27px] bianji mr-[14px]" onClick={() => item.status !== 1 && navigate('/assistant/' + item.id)}>
+                            {!openSwitch && <div className="w-[80px] h-[27px] bianji mr-[14px]" onClick={() => item.status !== 1 && navigate('/assistant/' + item.id,{state: { value:inputRef.current.value, page:page}})}>
                                 <img src={bianji} className="w-[14px] mr-[10px]" alt=""/>
                                 编辑
                             </div>}
                             
-                            <div className="w-[27px] h-[27px] create" onClick={() => delConfirm(item)}>
+                            {item.write && <div className="w-[27px] h-[27px] create" onClick={() => delConfirm(item)}>
                                 <img src={del} className="w-[14px]" alt=""/>
-                            </div>
+                            </div>}
                         </div>
-                        <Switch checked={openSwitch} onCheckedChange={handleChange}  />
+                        {/* <Switch checked={openSwitch} onCheckedChange={handleChange}  /> */}
+                        <Switch checked={openSwitch} onClick={() => !item.write && item.status !== 1 && message({ title: t('prompt'), description: t('skills.contactAdmin'), variant: 'warning' })} onCheckedChange={item.write && handleChange}  />
                     </div>
                 </div>}
             </Flexbox>
@@ -169,8 +181,8 @@ export default function Assistants() {
             <div className="flex gap-2 absolute top-[-47px] right-[27px] btn-r">
                 <div>
 
-                    <img ref={inputRef} src={sousuo} alt="" />
-                    <input type="text" placeholder="搜索" onChange={(e) => search(e.target.value)} />
+                    <img src={sousuo} alt="" />
+                    <input ref={inputRef} type="text" placeholder="搜索" onChange={(e) => search(e.target.value)} />
                 </div>
             </div>
             {/* list */}

+ 25 - 10
src/pages/SkillPage/tabSkills.tsx

@@ -3,7 +3,7 @@ import { bsConfirm } from "@/components/bs-ui/alertDialog/useConfirm";
 import { useToast } from "@/components/bs-ui/toast/use-toast";
 import { useContext, useEffect, useRef, useState } from "react";
 import { useTranslation } from "react-i18next";
-import { useNavigate } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
 import CardComponent, { TitleIconBg } from "../../components/bs-comp/cardComponent";
 import { MoveOneIcon } from "../../components/bs-icons/moveOne";
 import { Button } from "../../components/bs-ui/button";
@@ -48,7 +48,7 @@ export default function Skills() {
         readFlowsFromDatabase(param.page, param.pageSize, param.keyword)
     )
 
-    if(dataSource[0] && dataSource[0].type != 0){
+    if(dataSource == "" || dataSource[0].type != 0){
         dataSource.unshift({"type":0})
     }
 
@@ -60,7 +60,18 @@ export default function Skills() {
     const { open: tempOpen, flowRef, toggleTempModal } = useCreateTemp()
     const [isShareLink, setIsShareLink] = useState(false)
     const [isShareLinkData, setIsShareLinkData] = useState("Any");
-
+    const {state} = useLocation();
+    useEffect(() => {
+        if(state){
+            if(state.page){
+                setPage(state.page)
+            }
+            if(state.value){
+                search(state.value)
+                inputRef.current.value = state.value
+            }
+        }
+    }, [])
     // 上下线
     const handleCheckedChange = (checked, data) => {
         // data.versionId todo
@@ -90,11 +101,12 @@ export default function Skills() {
     const handleSetting = (data) => {
         // console.log('data :>> ', data);
         const vid = data.version_list.find(item => item.is_current === 1)?.id
-        navigate(`/build/skill/${data.id}/${vid}`)
+        navigate(`/build/skill/${data.id}/${vid}`,{state: { value:inputRef.current.value, page:page}})
     }
 
     // 选模板(创建技能)
     const handldSelectTemp = async (tempId) => {
+        console.log(tempId)
         const [flow] = await readTempsDatabase(tempId.id)
 
         flow.name = `${flow.name}-${generateUUID(5)}`
@@ -102,13 +114,14 @@ export default function Skills() {
             res.user_name = user.user_name
             res.write = true
             setOpen(false)
-            navigate(`/build/skill/${res.id}/${res.version_id}`)
+            navigate(`/build/skill/${res.id}/${res.version_id}`,{state: { avatar_color:tempId.avatar_color ? tempId.avatar_color : tempId.id, avatar_img:tempId.avatar_img}})
         }))
     }
 
     const nvaigate = useNavigate()
     const handleEdit = (id,pageNo) => {
         // onBeforeEdit?.()
+        console.log()
         window.SearchSkillsPage = { no: pageNo, key: inputRef.current.value };
         nvaigate("/skill/" + id)
     }
@@ -161,7 +174,7 @@ export default function Skills() {
                     <p>{item.description}</p>
                     <div>
                         <div>
-                            {!openSwitch && <div className="w-[80px] h-[27px] bianji mr-[14px]" onClick={() => handleEdit(item.id,page.pageNo)}>
+                            {!openSwitch && <div className="w-[80px] h-[27px] bianji mr-[14px]" onClick={() => handleSetting(item)}>
                                 <img src={bianji} className="w-[14px] mr-[10px]" alt=""/>
                                 编辑
                             </div>}
@@ -174,11 +187,13 @@ export default function Skills() {
                                 <img src={share} className="w-[14px]" alt=""/>
                             </div>}
 
-                            <div className="w-[27px] h-[27px] create" onClick={() => delConfirm(item)}>
+                            {item.write && <div className="w-[27px] h-[27px] create" onClick={() => delConfirm(item)}>
                                 <img src={del} className="w-[14px]" alt=""/>
-                            </div>
+                            </div>}
                         </div>
-                        <Switch checked={openSwitch} onCheckedChange={handleChange}  />
+                        {/* <Switch checked={openSwitch} onCheckedChange={handleChange}  /> */}
+                        <Switch checked={openSwitch} onClick={() => !item.write && item.status !== 2 && message({ title: t('prompt'), description: "请联系管理员上线能力", variant: 'warning' })} onCheckedChange={item.write && handleChange}  />
+                        
                     </div>
                     <div className="absolute right-[7px] top-[7px]">
                     <CardSelectVersion
@@ -207,7 +222,7 @@ export default function Skills() {
                     <img src={sousuo} alt="" />
                     <input ref={inputRef} type="text" placeholder="搜索" onChange={(e) => search(e.target.value)} />
                 </div>
-                {user.role === 'admin' && <div onClick={() => navigate('/build/temps')}><img src={moban} className="w-[14px] mr-[5px] btn-r-d" alt=""/><span>模版管理</span></div>}
+                {user.role === 'admin' && <div onClick={() => navigate('/build/temps',{state: { value:inputRef.current.value, page:page}})}><img src={moban} className="w-[14px] mr-[5px] btn-r-d" alt=""/><span>模版管理</span></div>}
                 {/* {user.role === 'admin' && <div onClick={() => setIsTempPage(true)}><img src={moban} className="w-[14px] mr-[5px] btn-r-d" alt=""/><span>模版管理</span></div>} */}
             </div>
             {/* list */}

+ 9 - 4
src/pages/SkillPage/temps.tsx

@@ -17,10 +17,13 @@ import { SpotlightCard } from "@lobehub/ui";
 import { Flexbox } from 'react-layout-kit';
 import robot from "../../assets/robot.png";
 import del from "../../assets/npc/del.png";
-import { useNavigate } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
+import nengliIcon from "../../assets/npc/nengliIcon.png";
+import { TitleIconBg } from "@/components/bs-comp/cardComponent";
 
 export default function Templates() {
     const navigate = useNavigate()
+    const {state} = useLocation();
 
     const onChange = () => { }
     const { t } = useTranslation()
@@ -89,13 +92,15 @@ export default function Templates() {
                 <span>
                     <span>
                         <div>
-                            <img src={robot} className="w-[160px]" alt=""/>
+                            {/* <img src={robot} className="w-[160px]" alt=""/> */}
+                            <TitleIconBg className="w-[160px] h-[160px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.flow_id} ><img src={item.avatar_img ? item.avatar_img : nengliIcon} alt="" /></TitleIconBg>
                         </div>
                     </span>
                 </span>
             </div>
             <div>
-                <img src={robot} className="w-[42px]" alt=""/>
+                {/* <img src={robot} className="w-[42px]" alt=""/> */}
+                <TitleIconBg className="w-[40px] h-[40px] min-w-[40px]" img={item.avatar_img} id={item.avatar_color ? item.avatar_color : item.flow_id} ><img src={item.avatar_img ? item.avatar_img : nengliIcon} alt="" /></TitleIconBg>
                 <div>
                     <p>{item.name}</p>
                     <div>
@@ -111,7 +116,7 @@ export default function Templates() {
         </Flexbox>
       );
     return <div className="p-6 h-screen overflow-y-auto temps">
-        <div className="fanhui"  onClick={() => navigate('/build/skills')}>
+        <div className="fanhui"  onClick={() => navigate('/build/skills',{state:state})}>
             返 回
         </div>
         {/* <p className="text-gray-500">{t('skills.skillTemplateManagement')}</p> */}

+ 225 - 0
src/pages/SystemPage/components/EditRole copy.tsx

@@ -0,0 +1,225 @@
+import { Search } from "lucide-react";
+import { useContext, useEffect, useRef, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { Button } from "../../../components/ui/button";
+import { Input } from "../../../components/ui/input";
+import { Switch } from "../../../components/ui/switch";
+import {
+    Table,
+    TableBody,
+    TableCell,
+    TableHead,
+    TableHeader,
+    TableRow
+} from "../../../components/ui/table";
+import { alertContext } from "../../../contexts/alertContext";
+import { createRole, getRoleAssistApi, getRoleLibsApi, getRolePermissionsApi, getRoleSkillsApi, updateRoleNameApi, updateRolePermissionsApi } from "../../../controllers/API/user";
+import { useDebounce } from "../../../util/hook";
+import { captureAndAlertRequestErrorHoc } from "../../../controllers/request";
+
+const pageSize = 10
+const SearchPanne = ({ title, total, onChange, children }) => {
+    const [page, setPage] = useState(1)
+    const pageCount = Math.ceil(total / pageSize)
+    const searchKeyRef = useRef('')
+    const { t } = useTranslation()
+
+    const handleSearch = useDebounce((e) => {
+        searchKeyRef.current = e.target.value
+        setPage(1)
+        onChange(1, searchKeyRef.current)
+    }, 500, false)
+
+    const loadPage = (page) => {
+        setPage(page)
+        onChange(page, searchKeyRef.current)
+    }
+
+    return <>
+        <div className="mt-20 flex justify-between items-center relative">
+            <p className="font-bold">{title}</p>
+            <Input className="w-[300px] rounded-full" onChange={handleSearch}></Input>
+            <Search className="absolute right-2" color="#999" />
+        </div>
+        <div className="mt-4">
+            {children}
+        </div>
+        <div className="join grid grid-cols-2 w-[200px] mx-auto my-4">
+            <button disabled={page === 1} className="join-item btn btn-outline btn-xs" onClick={() => loadPage(page - 1)}>{t('previousPage')}</button>
+            <button disabled={page >= pageCount} className="join-item btn btn-outline btn-xs" onClick={() => loadPage(page + 1)}>{t('nextPage')}</button>
+        </div>
+    </>
+
+}
+
+
+// -1 id表示新增
+export default function EditRole({ id, name, onChange, onBeforeChange }) {
+    const { setErrorData, setSuccessData } = useContext(alertContext);
+    const { t } = useTranslation()
+
+    const [form, setForm] = useState({
+        name,
+        useSkills: [],
+        useLibs: [],
+        manageLibs: []
+    })
+    useEffect(() => {
+        if (id !== -1) {
+            // 获取详情
+            getRolePermissionsApi(id).then(res => {
+                const useSkills = [], useLibs = [], manageLibs = []
+                res.data.forEach(item => {
+                    switch (item.type) {
+                        case 1: useLibs.push(Number(item.third_id)); break;
+                        case 2: useSkills.push(item.third_id); break;
+                        case 3: manageLibs.push(Number(item.third_id)); break;
+                    }
+                })
+                setForm({ name, useSkills, useLibs, manageLibs })
+            })
+        }
+    }, [id])
+
+    const switchDataChange = (id, key, checked) => {
+        const index = form[key].findIndex(el => el === id)
+        checked && index === -1 && form[key].push(id)
+        !checked && index !== -1 && form[key].splice(index, 1)
+        setForm({ ...form, [key]: form[key] })
+    }
+
+    // 知识库管理权限switch
+    const switchLibManage = (id, checked) => {
+        switchDataChange(id, 'manageLibs', checked)
+        if (checked) switchDataChange(id, 'useLibs', checked)
+    }
+    // 知识库使用权限switch
+    const switchUseLib = (id, checked) => {
+        if (!checked && form.manageLibs.includes(id)) return
+        switchDataChange(id, 'useLibs', checked)
+    }
+
+    const { data: skillData, change: handleSkillChange } = usePageData<any>(id, 'skill')
+    const { data: libData, change: handleLibChange } = usePageData<any>(id, 'lib')
+
+    const handleSave = async () => {
+        if (!form.name.length || form.name.length > 50) {
+            return setErrorData({
+                title: t('prompt'),
+                list: [t('system.roleNameRequired'), t('system.roleNamePrompt')],
+            });
+        }
+        if (onBeforeChange(form.name)) {
+            return setErrorData({
+                title: t('prompt'),
+                list: [t('system.roleNameExists')]
+            })
+        }
+        // 新增先创建角色
+        let roleId = id
+        if (id === -1) {
+            const res = await captureAndAlertRequestErrorHoc(createRole(form.name))
+            roleId = res.id
+        } else {
+            // 更新基本信息
+            captureAndAlertRequestErrorHoc(updateRoleNameApi(roleId, form.name))
+        }
+        // 更新角色权限
+        const res = await Promise.all([
+            updateRolePermissionsApi({ role_id: roleId, access_id: form.useSkills, type: 2 }),
+            updateRolePermissionsApi({ role_id: roleId, access_id: form.useLibs, type: 1 }),
+            updateRolePermissionsApi({ role_id: roleId, access_id: form.manageLibs, type: 3 })
+        ])
+
+        console.log('form :>> ', form, res);
+        setSuccessData({ title: t('success') })
+        onChange(true)
+    }
+
+    return <div className="max-w-[600px] mx-auto pt-4">
+        <div className="font-bold mt-4">
+            <p className="mb-4 text-[#fff]">{t('system.roleName')}</p>
+            <Input placeholder={t('system.roleName')} value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} maxLength={60}></Input>
+        </div>
+        <div className="">
+            <SearchPanne title={t('system.skillAuthorization')} total={skillData.total} onChange={handleSkillChange}>
+                <Table>
+                    <TableHeader>
+                        <TableRow>
+                            <TableHead className=" text-[#fff]">{t('system.skillName')}</TableHead>
+                            <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
+                            <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
+                        </TableRow>
+                    </TableHeader>
+                    <TableBody>
+                        {skillData.data.map((el) => (
+                            <TableRow key={el.id}>
+                                <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
+                                <TableCell className=" text-[#fff]">{el.user_name}</TableCell>
+                                <TableCell className="text-right">
+                                    <Switch checked={form.useSkills.includes(el.id)} onCheckedChange={(bln) => switchDataChange(el.id, 'useSkills', bln)} />
+                                </TableCell>
+                            </TableRow>
+                        ))}
+                    </TableBody>
+                </Table>
+            </SearchPanne>
+        </div>
+        <div className="">
+            <SearchPanne title={t('system.knowledgeAuthorization')} total={libData.total} onChange={handleLibChange}>
+                <Table>
+                    <TableHeader>
+                        <TableRow>
+                            <TableHead className=" text-[#fff]">{t('system.skillName')}</TableHead>
+                            <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
+                            <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
+                            <TableHead className="text-right text-[#fff]">{t('system.managePermission')}</TableHead>
+                        </TableRow>
+                    </TableHeader>
+                    <TableBody>
+                        {libData.data.map((el) => (
+                            <TableRow key={el.id}>
+                                <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
+                                <TableCell className=" text-[#fff]">{el.user_name}</TableCell>
+                                <TableCell className="text-right">
+                                    <Switch checked={form.useLibs.includes(el.id)} onCheckedChange={(bln) => switchUseLib(el.id, bln)} />
+                                </TableCell>
+                                <TableCell className="text-right">
+                                    <Switch checked={form.manageLibs.includes(el.id)} onCheckedChange={(bln) => switchLibManage(el.id, bln)} />
+                                </TableCell>
+                            </TableRow>
+                        ))}
+                    </TableBody>
+                </Table>
+            </SearchPanne>
+        </div>
+        <div className="flex justify-center gap-4 mt-16">
+            <Button variant="outline" className="h-8 rounded-full px-16" onClick={() => onChange()}>{t('cancel')}</Button>
+            <Button className="h-8 rounded-full px-16  bg-[#FFD54C] hover:bg-[#FFD54C]" onClick={handleSave}>{t('save')}</Button>
+        </div>
+    </div>
+}
+
+const usePageData = <T,>(id: number, key: 'skill' | 'lib') => {
+    const [data, setData] = useState<{ data: T[], total: number }>({ data: [], total: 0 })
+
+    useEffect(() => {
+        loadData()
+    }, [])
+
+    const loadData = async (page = 1, keyword = '') => {
+        const param = {
+            name: keyword,
+            role_id: id === -1 ? 0 : id,
+            page_num: page,
+            page_size: pageSize
+        }
+        const data = key === 'skill' ? await getRoleSkillsApi(param) : await getRoleLibsApi(param)
+        setData(data)
+    }
+
+    return {
+        data,
+        change: loadData
+    }
+}

+ 126 - 113
src/pages/SystemPage/components/EditRole.tsx

@@ -1,8 +1,8 @@
-import { Search } from "lucide-react";
-import { useContext, useEffect, useRef, useState } from "react";
+import { useContext, useEffect, useState } from "react";
 import { useTranslation } from "react-i18next";
-import { Button } from "../../../components/ui/button";
-import { Input } from "../../../components/ui/input";
+import { Button } from "../../../components/bs-ui/button";
+import { Input, SearchInput } from "../../../components/bs-ui/input";
+import AutoPagination from "../../../components/bs-ui/pagination/autoPagination";
 import { Switch } from "../../../components/ui/switch";
 import {
     Table,
@@ -11,45 +11,40 @@ import {
     TableHead,
     TableHeader,
     TableRow
-} from "../../../components/ui/table";
+} from "../../../components/bs-ui/table";
 import { alertContext } from "../../../contexts/alertContext";
-import { createRole, getRoleLibsApi, getRolePermissionsApi, getRoleSkillsApi, updateRoleNameApi, updateRolePermissionsApi } from "../../../controllers/API/user";
-import { useDebounce } from "../../../util/hook";
+import { createRole, getRoleAssistApi, getRoleLibsApi, getRolePermissionsApi, getRoleSkillsApi, updateRoleNameApi, updateRolePermissionsApi } from "../../../controllers/API/user";
 import { captureAndAlertRequestErrorHoc } from "../../../controllers/request";
+import { useTable } from "../../../util/hook";
 
-const pageSize = 10
-const SearchPanne = ({ title, total, onChange, children }) => {
-    const [page, setPage] = useState(1)
-    const pageCount = Math.ceil(total / pageSize)
-    const searchKeyRef = useRef('')
-    const { t } = useTranslation()
-
-    const handleSearch = useDebounce((e) => {
-        searchKeyRef.current = e.target.value
-        setPage(1)
-        onChange(1, searchKeyRef.current)
-    }, 500, false)
-
-    const loadPage = (page) => {
-        setPage(page)
-        onChange(page, searchKeyRef.current)
-    }
+const SearchPanne = ({ role_id, title, type, children }) => {
+    const { page, pageSize, data, total, loading, setPage, search } = useTable({ pageSize: 10 }, (params) => {
+        const { page, pageSize, keyword } = params
+        const param = {
+            name: keyword,
+            role_id,
+            page_num: page,
+            page_size: pageSize
+        }
+        return type === 'skill' ? getRoleSkillsApi(param)
+            : (type === 'assistant' ? getRoleAssistApi({ ...param, type: 'assistant' })
+                : getRoleLibsApi(param))
+    })
 
     return <>
         <div className="mt-20 flex justify-between items-center relative">
-            <p className="font-bold">{title}</p>
-            <Input className="w-[300px] rounded-full" onChange={handleSearch}></Input>
-            <Search className="absolute right-2" color="#999" />
+            <p className="font-bold text-[#fff]">{title}</p>
+            <SearchInput onChange={(e) => search(e.target.value)}></SearchInput>
         </div>
         <div className="mt-4">
-            {children}
-        </div>
-        <div className="join grid grid-cols-2 w-[200px] mx-auto my-4">
-            <button disabled={page === 1} className="join-item btn btn-outline btn-xs" onClick={() => loadPage(page - 1)}>{t('previousPage')}</button>
-            <button disabled={page >= pageCount} className="join-item btn btn-outline btn-xs" onClick={() => loadPage(page + 1)}>{t('nextPage')}</button>
+            {loading ?
+                <div className="w-full h-[468px] flex justify-center items-center z-10 bg-[rgba(255,255,255,0.6)] dark:bg-blur-shared">
+                    <span className="loading loading-infinity loading-lg"></span>
+                </div>
+                : children(data)}
         </div>
+        <AutoPagination className="m-0 mt-4 w-auto justify-end" page={page} pageSize={pageSize} total={total} onChange={setPage}></AutoPagination>
     </>
-
 }
 
 
@@ -62,21 +57,23 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
         name,
         useSkills: [],
         useLibs: [],
+        useAssistant: [],
         manageLibs: []
     })
     useEffect(() => {
         if (id !== -1) {
-            // 获取详情
+            // 获取详情,初始化选中数据
             getRolePermissionsApi(id).then(res => {
-                const useSkills = [], useLibs = [], manageLibs = []
+                const useSkills = [], useLibs = [], manageLibs = [], useAssistant = []
                 res.data.forEach(item => {
                     switch (item.type) {
                         case 1: useLibs.push(Number(item.third_id)); break;
                         case 2: useSkills.push(item.third_id); break;
                         case 3: manageLibs.push(Number(item.third_id)); break;
+                        case 5: useAssistant.push(item.third_id); break;
                     }
                 })
-                setForm({ name, useSkills, useLibs, manageLibs })
+                setForm({ name, useSkills, useLibs, useAssistant, manageLibs })
             })
         }
     }, [id])
@@ -98,10 +95,14 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
         if (!checked && form.manageLibs.includes(id)) return
         switchDataChange(id, 'useLibs', checked)
     }
-
-    const { data: skillData, change: handleSkillChange } = usePageData<any>(id, 'skill')
-    const { data: libData, change: handleLibChange } = usePageData<any>(id, 'lib')
-
+    /**
+     * 保存权限信息
+     * 1.验证重名
+     * 2.新增时先保存基本信息 创建 ID
+     * 3.修改时先更新基本信息
+     * 4.批量 保存各个种类权限信息(助手、技能、知识库等)
+     * @returns 
+     */
     const handleSave = async () => {
         if (!form.name.length || form.name.length > 50) {
             return setErrorData({
@@ -115,7 +116,7 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
                 list: [t('system.roleNameExists')]
             })
         }
-        // 新增先创建角色
+        // 没有id时需要走创建流程,否则修改
         let roleId = id
         if (id === -1) {
             const res = await captureAndAlertRequestErrorHoc(createRole(form.name))
@@ -128,7 +129,8 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
         const res = await Promise.all([
             updateRolePermissionsApi({ role_id: roleId, access_id: form.useSkills, type: 2 }),
             updateRolePermissionsApi({ role_id: roleId, access_id: form.useLibs, type: 1 }),
-            updateRolePermissionsApi({ role_id: roleId, access_id: form.manageLibs, type: 3 })
+            updateRolePermissionsApi({ role_id: roleId, access_id: form.manageLibs, type: 3 }),
+            updateRolePermissionsApi({ role_id: roleId, access_id: form.useAssistant, type: 5 })
         ])
 
         console.log('form :>> ', form, res);
@@ -136,90 +138,101 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
         onChange(true)
     }
 
-    return <div className="max-w-[600px] mx-auto pt-4">
+    const roleId = id === -1 ? 0 : id
+
+    return <div className="max-w-[600px] mx-auto pt-4 h-[calc(100vh-136px)] overflow-y-auto pb-10 px-[3px] scrollbar-hide">
         <div className="font-bold mt-4">
             <p className="mb-4 text-[#fff]">{t('system.roleName')}</p>
-            <Input placeholder={t('system.roleName')} value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} maxLength={60}></Input>
+            <Input className="npcInput3" placeholder={t('system.roleName')} value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} maxLength={60}></Input>
+        </div>
+        {/* 助手 */}
+        <div className="">
+            <SearchPanne title={"NPC授权"} role_id={roleId} type={'assistant'}>
+                {(data) => (
+                    <Table>
+                        <TableHeader>
+                            <TableRow>
+                                <TableHead className="text-[#fff]">NPC名称</TableHead>
+                                <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
+                                <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
+                            </TableRow>
+                        </TableHeader>
+                        <TableBody>
+                            {data.map((el) => (
+                                <TableRow key={el.id}>
+                                    <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
+                                    <TableCell className="text-[#fff]">{el.user_name}</TableCell>
+                                    <TableCell className="text-right">
+                                        <Switch checked={form.useAssistant.includes(el.id)} onCheckedChange={(bln) => switchDataChange(el.id, 'useAssistant', bln)} />
+                                    </TableCell>
+                                </TableRow>
+                            ))}
+                        </TableBody>
+                    </Table>
+                )}
+            </SearchPanne>
         </div>
+        {/* 技能 */}
         <div className="">
-            <SearchPanne title={t('system.skillAuthorization')} total={skillData.total} onChange={handleSkillChange}>
-                <Table>
-                    <TableHeader>
-                        <TableRow>
-                            <TableHead className=" text-[#fff]">{t('system.skillName')}</TableHead>
-                            <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
-                            <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
-                        </TableRow>
-                    </TableHeader>
-                    <TableBody>
-                        {skillData.data.map((el) => (
-                            <TableRow key={el.id}>
-                                <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
-                                <TableCell className=" text-[#fff]">{el.user_name}</TableCell>
-                                <TableCell className="text-right">
-                                    <Switch checked={form.useSkills.includes(el.id)} onCheckedChange={(bln) => switchDataChange(el.id, 'useSkills', bln)} />
-                                </TableCell>
+            <SearchPanne title={t('system.skillAuthorization')} role_id={roleId} type={'skill'}>
+                {(data) => (
+                    <Table>
+                        <TableHeader>
+                            <TableRow>
+                                <TableHead className="text-[#fff]">{t('system.skillName')}</TableHead>
+                                <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
+                                <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
                             </TableRow>
-                        ))}
-                    </TableBody>
-                </Table>
+                        </TableHeader>
+                        <TableBody>
+                            {data.map((el) => (
+                                <TableRow key={el.id}>
+                                    <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
+                                    <TableCell className="text-[#fff]">{el.user_name}</TableCell>
+                                    <TableCell className="text-right">
+                                        <Switch checked={form.useSkills.includes(el.id)} onCheckedChange={(bln) => switchDataChange(el.id, 'useSkills', bln)} />
+                                    </TableCell>
+                                </TableRow>
+                            ))}
+                        </TableBody>
+                    </Table>
+                )}
             </SearchPanne>
         </div>
+        {/* 知识库 */}
         <div className="">
-            <SearchPanne title={t('system.knowledgeAuthorization')} total={libData.total} onChange={handleLibChange}>
-                <Table>
-                    <TableHeader>
-                        <TableRow>
-                            <TableHead className=" text-[#fff]">{t('system.skillName')}</TableHead>
-                            <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
-                            <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
-                            <TableHead className="text-right text-[#fff]">{t('system.managePermission')}</TableHead>
-                        </TableRow>
-                    </TableHeader>
-                    <TableBody>
-                        {libData.data.map((el) => (
-                            <TableRow key={el.id}>
-                                <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
-                                <TableCell className=" text-[#fff]">{el.user_name}</TableCell>
-                                <TableCell className="text-right">
-                                    <Switch checked={form.useLibs.includes(el.id)} onCheckedChange={(bln) => switchUseLib(el.id, bln)} />
-                                </TableCell>
-                                <TableCell className="text-right">
-                                    <Switch checked={form.manageLibs.includes(el.id)} onCheckedChange={(bln) => switchLibManage(el.id, bln)} />
-                                </TableCell>
+            <SearchPanne title={t('system.knowledgeAuthorization')} role_id={roleId} type={'lib'}>
+                {(data) => (
+                    <Table>
+                        <TableHeader>
+                            <TableRow>
+                                <TableHead className="text-[#fff]">{t('lib.libraryName')}</TableHead> 
+                                <TableHead className="w-[100px] text-[#fff]">{t('system.creator')}</TableHead>
+                                <TableHead className="text-right text-[#fff]">{t('system.usePermission')}</TableHead>
+                                <TableHead className="text-right text-[#fff]">{t('system.managePermission')}</TableHead>
                             </TableRow>
-                        ))}
-                    </TableBody>
-                </Table>
+                        </TableHeader>
+                        <TableBody>
+                            {data.map((el) => (
+                                <TableRow key={el.id}>
+                                    <TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
+                                    <TableCell className="text-[#fff]">{el.user_name}</TableCell>
+                                    <TableCell className="text-right">
+                                        <Switch checked={form.useLibs.includes(el.id)} onCheckedChange={(bln) => switchUseLib(el.id, bln)} />
+                                    </TableCell>
+                                    <TableCell className="text-right">
+                                        <Switch checked={form.manageLibs.includes(el.id)} onCheckedChange={(bln) => switchLibManage(el.id, bln)} />
+                                    </TableCell>
+                                </TableRow>
+                            ))}
+                        </TableBody>
+                    </Table>
+                )}
             </SearchPanne>
         </div>
         <div className="flex justify-center gap-4 mt-16">
-            <Button variant="outline" className="h-8 rounded-full px-16" onClick={() => onChange()}>{t('cancel')}</Button>
+        <Button variant="outline" className="h-8 rounded-full px-16" onClick={() => onChange()}>{t('cancel')}</Button>
             <Button className="h-8 rounded-full px-16  bg-[#FFD54C] hover:bg-[#FFD54C]" onClick={handleSave}>{t('save')}</Button>
         </div>
     </div>
-}
-
-const usePageData = <T,>(id: number, key: 'skill' | 'lib') => {
-    const [data, setData] = useState<{ data: T[], total: number }>({ data: [], total: 0 })
-
-    useEffect(() => {
-        loadData()
-    }, [])
-
-    const loadData = async (page = 1, keyword = '') => {
-        const param = {
-            name: keyword,
-            role_id: id === -1 ? 0 : id,
-            page_num: page,
-            page_size: pageSize
-        }
-        const data = key === 'skill' ? await getRoleSkillsApi(param) : await getRoleLibsApi(param)
-        setData(data)
-    }
-
-    return {
-        data,
-        change: loadData
-    }
 }

+ 1 - 1
src/pages/SystemPage/components/Roles.tsx

@@ -90,7 +90,7 @@ export default function Roles() {
                         <TableCell className="font-medium dialogueLog-body">{el.role_name}</TableCell>
                         <TableCell className="dialogueLog-body">{el.create_time.replace('T', ' ')}</TableCell>
                         <TableCell className="text-right dialogueLog-body">
-                            <Button variant="link" disabled={[1, 2].includes(el.id)} onClick={() => setRole(el)}>{t('edit')}</Button>
+                            <Button variant="link" onClick={() => setRole(el)}>{t('edit')}</Button>
                             <Button variant="link" disabled={[1, 2].includes(el.id)} onClick={() => handleDelete(el)} className="text-red-500">{t('delete')}</Button>
                         </TableCell>
                     </TableRow>

+ 1 - 1
src/style/applies.css

@@ -207,7 +207,7 @@
     @apply focus:placeholder-transparent focus:ring-ring focus:border-ring
   }
   .input-primary {
-    @apply bg-background block border-border form-input px-3 placeholder:text-muted-foreground rounded-md shadow-sm sm:text-sm truncate w-full;
+    @apply bg-background block border-border form-input px-3 placeholder:text-[#999] rounded-md shadow-sm sm:text-sm truncate w-full;
   }
 
   .input-edit-node{

+ 41 - 3
src/style/zk.scss

@@ -204,6 +204,9 @@
       width: 100%!important;
       height: 100%;
     }
+    .chata{
+      height: 96vh!important;
+    }
   }
   .chatShareM{
     .duihua-chat{
@@ -3180,7 +3183,7 @@
       justify-content: center;
       background: #0D0D0D!important;
       cursor: pointer;
-      z-index: 1;
+      z-index: 10;
       >span{
         font-family: PingFang SC;
         font-weight: 400;
@@ -3216,12 +3219,16 @@
     background: #1A1A1A;
     border-radius: 7px;
     margin: 7px;
+    position: relative;
     cursor: pointer;
     .npcInfoItemBg{
-      position: relative;
+      position: absolute;
       overflow: hidden;
+      width: 100%;
       height: 64px;
-      margin-bottom: -56px;
+      top: 0;
+      left: 0;
+      // margin-bottom: -56px;
       background: rgba(0, 0, 0, 0.06);
       -webkit-mask-image: linear-gradient(to bottom, #fff, transparent);
       mask-image: linear-gradient(to bottom, #fff, transparent);
@@ -3240,6 +3247,7 @@
       -webkit-box-align: center;
       -ms-flex-align: center;
       align-items: center;
+      z-index: -1;
       >span{
         width: 180px;
         height: 180px;
@@ -3312,6 +3320,7 @@
       }
       >div:nth-of-type(2){
         margin-right: 14px;
+        z-index: 1000;
       }
     }
     >p{
@@ -4176,4 +4185,33 @@
   }
   .input-dialog{
     color: #999999;
+  }
+  .daimaStyle{
+    background: rgba(255, 255, 255, 0.05);
+    border-radius: 14px!important;
+    border: none;
+    overflow: hidden;
+    margin: 6px 0;
+    &:focus{
+      // border: 1px solid #997e1f!important;
+      border: none!important;
+      outline: none!important;
+    }
+    .code-block-modal{
+      background: rgba(255, 213, 76, 0.04);
+    }
+    .overflow-auto{
+      background: rgba(255, 255, 255, 0.05)!important;
+      background-color: rgba(255, 255, 255, 0.05)!important;
+
+      .language-sql{
+      background-color: rgba(255, 255, 255, 0.00)!important;
+      // background: rgba(255, 255, 255, 0.05)!important;
+        // background: none;
+        span{
+        background: none;
+      // background: rgba(255, 255, 255, 0.05)!important;
+        }
+      }
+    }
   }

+ 3 - 3
src/util/hook.ts

@@ -71,7 +71,7 @@ export function useTable<T extends object>(param, apiFun) {
 
     const requestIdRef = useRef(0); // 控制请求响应顺序
     const loadData = () => {
-        setLoading(true);
+        // setLoading(true);
         const requestId = ++requestIdRef.current
         apiFun({ ...page, ...paramRef.current }).then(res => {
             if (requestId !== requestIdRef.current) return
@@ -79,9 +79,9 @@ export function useTable<T extends object>(param, apiFun) {
             // res.data.unshift({type:0})
             setData(res.data);
             setTotal(res.total);
-            setLoading(false);
+            // setLoading(false);
         }).catch(() => {
-            setLoading(false);
+            // setLoading(false);
         })
     }
     const debounceLoad = useDebounce(loadData, 600, false)