1
This commit is contained in:
@@ -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%">
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -2411,7 +2411,7 @@
|
||||
},
|
||||
"NPCsChatLLM": {
|
||||
"display_name": "NPCsChatLLM",
|
||||
"description": "`OpenAI`聊天大型语言模型API。",
|
||||
"description": "无缝切换支持的大语言模型",
|
||||
"description_url": "",
|
||||
"template": {
|
||||
"api_base": {
|
||||
|
||||
@@ -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
vendored
BIN
src/assets/.DS_Store
vendored
Binary file not shown.
BIN
src/assets/chat/.DS_Store
vendored
BIN
src/assets/chat/.DS_Store
vendored
Binary file not shown.
BIN
src/assets/chat/copy.png
Normal file
BIN
src/assets/chat/copy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 915 B |
BIN
src/assets/chat/xiazai.png
Normal file
BIN
src/assets/chat/xiazai.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 936 B |
@@ -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>
|
||||
|
||||
@@ -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 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.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> */}
|
||||
{data.message.toString() ?
|
||||
<div className="chat-start-zk relative">
|
||||
{data.message.toString() ? mkdown : <span className="loading loading-ring loading-md"></span>}
|
||||
{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
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -56,6 +56,12 @@ export async function setSysConfigApi(data) {
|
||||
export async function getRoleSkillsApi(params): Promise<{ data: any[], total: number }> {
|
||||
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 });
|
||||
}
|
||||
/**
|
||||
* 根据角色获取知识库列表
|
||||
*/
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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> */}
|
||||
|
||||
@@ -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'}`}>
|
||||
|
||||
@@ -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,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 className="z-[10]">
|
||||
<div>
|
||||
<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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
if(state && state.avatar_img){
|
||||
setAvatar_img(state.avatar_img);
|
||||
}else{
|
||||
setAvatar_img(flow.avatar_img);
|
||||
if(flow.avatar_color){
|
||||
}
|
||||
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
|
||||
if(state && state.avatar_img){
|
||||
setAvatar_img(state.avatar_img);
|
||||
}else{
|
||||
setAvatar_img(_flow.avatar_img);
|
||||
if(_flow.avatar_color){
|
||||
}
|
||||
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>
|
||||
|
||||
@@ -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";
|
||||
@@ -45,12 +45,23 @@ export default function Assistants() {
|
||||
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 */}
|
||||
|
||||
@@ -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 */}
|
||||
|
||||
@@ -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
src/pages/SystemPage/components/EditRole copy.tsx
Normal file
225
src/pages/SystemPage/components/EditRole copy.tsx
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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}
|
||||
{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>
|
||||
<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>
|
||||
: 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,13 +138,44 @@ 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={t('system.skillAuthorization')} total={skillData.total} onChange={handleSkillChange}>
|
||||
<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')} role_id={roleId} type={'skill'}>
|
||||
{(data) => (
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@@ -152,7 +185,7 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{skillData.data.map((el) => (
|
||||
{data.map((el) => (
|
||||
<TableRow key={el.id}>
|
||||
<TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
|
||||
<TableCell className="text-[#fff]">{el.user_name}</TableCell>
|
||||
@@ -163,21 +196,24 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</SearchPanne>
|
||||
</div>
|
||||
{/* 知识库 */}
|
||||
<div className="">
|
||||
<SearchPanne title={t('system.knowledgeAuthorization')} total={libData.total} onChange={handleLibChange}>
|
||||
<SearchPanne title={t('system.knowledgeAuthorization')} role_id={roleId} type={'lib'}>
|
||||
{(data) => (
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className=" text-[#fff]">{t('system.skillName')}</TableHead>
|
||||
<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>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{libData.data.map((el) => (
|
||||
{data.map((el) => (
|
||||
<TableRow key={el.id}>
|
||||
<TableCell className="font-medium text-[#fff]">{el.name}</TableCell>
|
||||
<TableCell className="text-[#fff]">{el.user_name}</TableCell>
|
||||
@@ -191,6 +227,7 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</SearchPanne>
|
||||
</div>
|
||||
<div className="flex justify-center gap-4 mt-16">
|
||||
@@ -199,27 +236,3 @@ export default function EditRole({ id, name, onChange, onBeforeChange }) {
|
||||
</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
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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{
|
||||
@@ -4177,3 +4186,32 @@
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user