From 94be64311c6335b5b0b0f05a4074d58cead943eb Mon Sep 17 00:00:00 2001 From: zhangkai <17600160566@163.com> Date: Tue, 3 Sep 2024 11:12:51 +0800 Subject: [PATCH] 1 --- .DS_Store | Bin 10244 -> 10244 bytes build/index.html | 2 +- build/locales/en/bs.json | 10 +- build/locales/zh/bs.json | 27 +- public/locales/en/bs.json | 10 +- public/locales/zh/bs.json | 27 +- src/.DS_Store | Bin 10244 -> 10244 bytes src/assets/.DS_Store | Bin 10244 -> 10244 bytes src/assets/chat/.DS_Store | Bin 8196 -> 8196 bytes src/assets/chat/biaoqian-paixu.png | Bin 0 -> 2112 bytes src/assets/chat/shengQue.png | Bin 0 -> 60763 bytes src/assets/npc/.DS_Store | Bin 12292 -> 12292 bytes src/assets/npc/biaoqian-bian.png | Bin 0 -> 1319 bytes src/assets/npc/biaoqian-del.png | Bin 0 -> 1223 bytes src/assets/npc/tianjiabiaoqian.png | Bin 0 -> 1092 bytes src/components/.DS_Store | Bin 10244 -> 10244 bytes .../bs-comp/cardComponent/LabelShow.tsx | 110 +++++++++ .../bs-comp/chatComponent/ChatInput.tsx | 6 +- .../bs-comp/chatComponent/MessageBs.tsx | 1 + .../bs-comp/chatComponent/MessageUser.tsx | 3 +- .../bs-comp/selectComponent/LabelSelect.tsx | 200 +++++++++++++++ .../bs-comp/sheets/SkillChatSheet.tsx | 98 ++++++-- src/components/bs-icons/office/index.tsx | 2 +- src/components/bs-icons/prompt/Prompt.svg | 2 + src/components/bs-icons/prompt/index.tsx | 10 + src/components/bs-ui/alertDialog/index.tsx | 13 +- src/components/bs-ui/input/index.tsx | 2 +- src/controllers/API/assistant.ts | 12 +- src/controllers/API/flow.ts | 9 +- src/controllers/API/label.ts | 61 +++++ src/layout/MainLayout.tsx | 2 +- src/pages/ChatAppPage/components/ChatHome.tsx | 158 ++++++++++++ .../ChatAppPage/components/ChatPanne.tsx | 1 + .../ChatAppPage/components/MarkLabel.tsx | 146 +++++++++++ .../ChatAppPage/components/ResouceModal.tsx | 231 +++++++++++------- src/pages/ChatAppPage/index.tsx | 91 ++++--- .../ChatAppPage/mobile/chatAssitantShare.tsx | 1 - src/pages/FileLibPage/files.tsx | 28 ++- src/pages/LogPage/utils/index.ts | 4 +- src/pages/SkillPage/tabAssistant.tsx | 48 +++- src/pages/SkillPage/tabSkills.tsx | 59 ++++- src/style/zk.scss | 78 +++++- src/util/hook.ts | 3 +- 43 files changed, 1255 insertions(+), 200 deletions(-) create mode 100644 src/assets/chat/biaoqian-paixu.png create mode 100644 src/assets/chat/shengQue.png create mode 100644 src/assets/npc/biaoqian-bian.png create mode 100644 src/assets/npc/biaoqian-del.png create mode 100644 src/assets/npc/tianjiabiaoqian.png create mode 100644 src/components/bs-comp/cardComponent/LabelShow.tsx create mode 100644 src/components/bs-comp/selectComponent/LabelSelect.tsx create mode 100644 src/components/bs-icons/prompt/Prompt.svg create mode 100644 src/components/bs-icons/prompt/index.tsx create mode 100644 src/controllers/API/label.ts create mode 100644 src/pages/ChatAppPage/components/ChatHome.tsx create mode 100644 src/pages/ChatAppPage/components/MarkLabel.tsx diff --git a/.DS_Store b/.DS_Store index f166eaf1c756b88474336f7165e3700501fc3320..21301a494d2140afc7359fa29dbbb83082d51b12 100644 GIT binary patch delta 65 zcmZn(XbIThFEIJ0cqxamshN&~p@qfdvjQ@czl*7C<`r~g#}u6=QOLfTP2o4oW+qW) FW&pIF6c7La delta 70 zcmZn(XbIThFTl8Ka)3Y~k5qNFsiA?6g07*l(d07%GK@WwUkb=G_HO1BbYbVPG%(Up ZFfug*$~bJEDpAP3nO)%*%O+7~W&rmY6uAHZ diff --git a/build/index.html b/build/index.html index 1846e8f..f3fc146 100644 --- a/build/index.html +++ b/build/index.html @@ -1 +1 @@ -NPCs
\ No newline at end of file +NPCs
\ No newline at end of file diff --git a/build/locales/en/bs.json b/build/locales/en/bs.json index 56ad2eb..52066a4 100644 --- a/build/locales/en/bs.json +++ b/build/locales/en/bs.json @@ -356,22 +356,22 @@ "evaluation": { "id": "任务ID", "filename": "测试文件名称", - "skillAssistant": "技能助手", + "skillAssistant": "能力NPC", "status": "状态", "score": "评测分数", "createDate": "创建日期", "download": "下载", "confirmDeleteEvaluation": "确认删除该评测任务?", "createTitle": "新建任务", - "selectLabel": "选择要评测的技能或者助手:", + "selectLabel": "选择要评测的能力或者NPC:", "selectPlaceholder": "请选择", "dataLabel": "测试集数据:", "fileExpandName": "支持扩展名:", "downloadTemplate": "下载模板文件", "promptLabel": "评测指令文本:", - "enterExecType": "请选择要评测的技能或助手", - "enterUniqueId": "请选择技能或助手ID", - "enterVersion": "请选择技能的版本", + "enterExecType": "请选择要评测的能力或NPC", + "enterUniqueId": "请选择能力或NPCID", + "enterVersion": "请选择能力的版本", "enterFile": "请选择测试集数据", "enterPrompt": "评测指令不能为空", "fileSizeLimit": "文件大小限制在10M以内", diff --git a/build/locales/zh/bs.json b/build/locales/zh/bs.json index 00a08d8..735204d 100644 --- a/build/locales/zh/bs.json +++ b/build/locales/zh/bs.json @@ -186,7 +186,21 @@ "fileStorageFailure": " 文件地址失效!", "confirmDeleteChat": "确认删除该会话?", "roundOver": "本轮结束", - "chatDialogTip": "设置提示模板中定义的输入变量。与代理和链互动" + "chatDialogTip": "设置提示模板中定义的输入变量。与代理和链互动", + "feedback": "反馈", + "feedbackRequired": "反馈信息不能为空", + "dialogueSelection": "对话选择", + "chooseSkillOrAssistant": "选择一个您想使用的线上能力或NPC", + "search": "搜索", + "recommendationQuestions": "推荐问题", + "historicalMessages": "以上为历史消息", + "clickDownload": "点击下载", + "searchAssistantOrSkill": "搜索NPC或者能力", + "operationTips": "操作提示:在左侧选择要展示的标签,在右侧拖拽进行排序", + "selected": "已选", + "pleaseSelectAnApp": "请选择一个应用", + "allLabels": "全部标签", + "searchLabels": "搜索标签" }, "model": { "modelConfiguration": "模型配置", @@ -515,6 +529,11 @@ "cancle": "取消", "tip": "提示", "deleteAssistant": "确认删除该NPC?", + "chatTipsTitle": "使用提示", + "updateSuccess": "修改成功", + "createSuccess": "创建成功", + "confirm": "确认", + "required": "不可为空", "build": { "create": "创建", "assistant": "NPC", @@ -679,6 +698,12 @@ "endDate": "结束日期", "actionBehavior": "操作行为" }, + "tag": { + "labelMaxLength": "标签名不能超过10个字符", + "confirmDeleteLabel": "标签【{{label}}】正在使用中,确认删除?", + "createNewLabel": "创建“新标签”", + "addLabel": "添加标签" + }, "agents": { "AgentInitializer": { "display_name": "AgentInitializer", diff --git a/public/locales/en/bs.json b/public/locales/en/bs.json index 56ad2eb..52066a4 100644 --- a/public/locales/en/bs.json +++ b/public/locales/en/bs.json @@ -356,22 +356,22 @@ "evaluation": { "id": "任务ID", "filename": "测试文件名称", - "skillAssistant": "技能助手", + "skillAssistant": "能力NPC", "status": "状态", "score": "评测分数", "createDate": "创建日期", "download": "下载", "confirmDeleteEvaluation": "确认删除该评测任务?", "createTitle": "新建任务", - "selectLabel": "选择要评测的技能或者助手:", + "selectLabel": "选择要评测的能力或者NPC:", "selectPlaceholder": "请选择", "dataLabel": "测试集数据:", "fileExpandName": "支持扩展名:", "downloadTemplate": "下载模板文件", "promptLabel": "评测指令文本:", - "enterExecType": "请选择要评测的技能或助手", - "enterUniqueId": "请选择技能或助手ID", - "enterVersion": "请选择技能的版本", + "enterExecType": "请选择要评测的能力或NPC", + "enterUniqueId": "请选择能力或NPCID", + "enterVersion": "请选择能力的版本", "enterFile": "请选择测试集数据", "enterPrompt": "评测指令不能为空", "fileSizeLimit": "文件大小限制在10M以内", diff --git a/public/locales/zh/bs.json b/public/locales/zh/bs.json index 00a08d8..735204d 100644 --- a/public/locales/zh/bs.json +++ b/public/locales/zh/bs.json @@ -186,7 +186,21 @@ "fileStorageFailure": " 文件地址失效!", "confirmDeleteChat": "确认删除该会话?", "roundOver": "本轮结束", - "chatDialogTip": "设置提示模板中定义的输入变量。与代理和链互动" + "chatDialogTip": "设置提示模板中定义的输入变量。与代理和链互动", + "feedback": "反馈", + "feedbackRequired": "反馈信息不能为空", + "dialogueSelection": "对话选择", + "chooseSkillOrAssistant": "选择一个您想使用的线上能力或NPC", + "search": "搜索", + "recommendationQuestions": "推荐问题", + "historicalMessages": "以上为历史消息", + "clickDownload": "点击下载", + "searchAssistantOrSkill": "搜索NPC或者能力", + "operationTips": "操作提示:在左侧选择要展示的标签,在右侧拖拽进行排序", + "selected": "已选", + "pleaseSelectAnApp": "请选择一个应用", + "allLabels": "全部标签", + "searchLabels": "搜索标签" }, "model": { "modelConfiguration": "模型配置", @@ -515,6 +529,11 @@ "cancle": "取消", "tip": "提示", "deleteAssistant": "确认删除该NPC?", + "chatTipsTitle": "使用提示", + "updateSuccess": "修改成功", + "createSuccess": "创建成功", + "confirm": "确认", + "required": "不可为空", "build": { "create": "创建", "assistant": "NPC", @@ -679,6 +698,12 @@ "endDate": "结束日期", "actionBehavior": "操作行为" }, + "tag": { + "labelMaxLength": "标签名不能超过10个字符", + "confirmDeleteLabel": "标签【{{label}}】正在使用中,确认删除?", + "createNewLabel": "创建“新标签”", + "addLabel": "添加标签" + }, "agents": { "AgentInitializer": { "display_name": "AgentInitializer", diff --git a/src/.DS_Store b/src/.DS_Store index c128842d0e92bd754ecf8fdd5a56a5afe4b03252..e9a3a46b9590c57c396078c9e720cd2ed03a2786 100644 GIT binary patch delta 29 kcmZn(XbIThD8ylGYNn%LXkjr~P{LudfFR4}UZHYP0DD;n(EtDd delta 29 kcmZn(XbIThD8ylDV5Fm9WNJ29P{LudfFR4}UZHYP0DA5R$^ZZW diff --git a/src/assets/.DS_Store b/src/assets/.DS_Store index 7ae5f5a99271940713c5b554315b46c118a789a6..ab780ccd3246de70910635ec98b0025383d8b6ca 100644 GIT binary patch delta 377 zcmZn(XbISGK!C&8)J#Xg(86LeucXXm1re3a9D;6)>?nfbYMZAErJ)FJRuJ)Goa`-7 zilKk9s@QcD!OaTdML3lDN*+d03bKE4gp?5D=E>Po${eC%;-V6g64H~WN!^i-7vL|> z$S?Oy&d&=dN-fJwEsw|qvV$|LQYZIHs|j-mFmi_E<>#exDmw%)fWhP&(u$6fj7p5! zj3$h>jP{HkjGm0%j6RHkj6o0;OpFkkK?X`gDaL3ZgP9?Zp@1QIvY?>w=0KTBCQPRa W$$y>LAhelXA(@r9u$ZhM{s;gO3{y4$ delta 400 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 Sn^`r!uxu_@dCmmnsQ>`}|3&fu delta 112 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 literal 0 HcmV?d00001 diff --git a/src/assets/npc/tianjiabiaoqian.png b/src/assets/npc/tianjiabiaoqian.png new file mode 100644 index 0000000000000000000000000000000000000000..71e4a3eaf2b6c6b22dfb1432ae4cd57751149209 GIT binary patch literal 1092 zcmV-K1iSl*P)Px&{z*hZR9Hvtm`#WrMHI*XuV&0avaq{oa1Tb~NAQCX@ZuqeLHxLRaxfBO;_g({ zun*QTJp2Jj1jq6h9Itcb)!St!Y^9mplc`OXWkGl=z?HgkPzn>Cc z`9J`6)TMiOC4j88EF!uokcfDy7Z`LGb4i$9X?bcN9o#{R|Pk0pLHS z)Wbm#eA_CNF{blC#+bhV40;F=ITVIrsnMlu}7s@1AL8m?%|0$NBJW6W^?8cQA_1&lGL0o;_t%ty|-$9uhG zmw*5`X0G%Us9Y}Jr<8h=i2fFlCz<(=o&vS%e8sl?{|-oNymhz|f6Y1zV zWQ_3_%P{~ird0Zsh{l|AhgwmtV?fs05fM26;D$WMMD!(qea^Y>n}IDGs8XqHj-u!Q z5p8Nk0RV4DQS{RE^z_+|26cTVYwP!XuSi}3e^x~H)DyGY0qo9ke2$1FoO6@ezLpg7 zS6gPDPsU26QlY=Uf6T`PfK^$8A~IR4)h1?VXV3XQpQa=V`a(js9Veo_&bcod9mbeh z0Na!2{Hrt(-S3?HMr*x=h+fH5C>pj7C&Bw;-co3-w-J$7)GM29pT%*!$EPGok!)8p zAQ2G{v6hIQ$}#p+GRw~wiy>d#7#tiN6A`})=kudowDopx&t@VS+GTys@oy&kOpX(M(W*P6UUj$wjkvxshGI^4y#AX@MS4;r*;SC@F delta 34 qcmZn(XbISGKydPHp}mt!1O+$u2vzcKW>@&lGC4?8YO|E+3nl>jqYWSc diff --git a/src/components/bs-comp/cardComponent/LabelShow.tsx b/src/components/bs-comp/cardComponent/LabelShow.tsx new file mode 100644 index 0000000..d68fcda --- /dev/null +++ b/src/components/bs-comp/cardComponent/LabelShow.tsx @@ -0,0 +1,110 @@ +import { LabelIcon } from "@/components/bs-icons/label"; +import LabelSelect from "../selectComponent/LabelSelect"; +import { UPDATETYPE } from "../selectComponent/LabelSelect"; +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { BookmarkFilledIcon } from "@radix-ui/react-icons"; +import tianjiabiaoqian from "../../../assets/npc/tianjiabiaoqian.png"; + +export default function LabelShow({ show, isOperator, labels, all, resource, reload, AllLabelsApi }) { + const { t } = useTranslation() + const [freshData, setFreshData] = useState(labels) + const [allData, setAllData] = useState(all) + const [isShow, setIsShow] = useState(show) + + const handleUpdate = (obj: { type: string, data: any }) => { + console.log(UPDATETYPE,obj) + switch (obj.type) { + case UPDATETYPE.DELETELINK: { + reload(); + AllLabelsApi(); + setFreshData(pre => pre.filter(l => l.value !== obj.data.value)) + break + } + case UPDATETYPE.CREATELINK: { + reload(); + AllLabelsApi(); + setFreshData(pre => [obj.data, ...pre]) + break + } + case UPDATETYPE.UPDATENAME: { + reload(); + AllLabelsApi(); + setFreshData(pre => pre.map(d => d.value === obj.data.value ? { ...d, label: obj.data.label } : d)) + break + } + case UPDATETYPE.CREATELABEL: { + // 什么也不用做 + break + } + case UPDATETYPE.DELETELABEL: { + reload(); + AllLabelsApi(); + setFreshData(pre => pre.filter(d => d.value !== obj.data.value)) + setAllData(pre => pre.filter(a => a.value !== obj.data.value)) + break + } + default: console.log('error:>>事件类型错误!!!') + } + } + + useEffect(() => { + setIsShow(freshData.length > 0) + }, [freshData]) + + return ( +

+ {isShow ? ( + isOperator ? ( + +
e.stopPropagation()} className="mb-[10px] max-w-[100%] flex place-items-center rounded-sm p-1 border border-transparent group-hover:bg-search-input group-hover:border-input"> + {/* +
+ {freshData.map((l, index) => {l.label}{index !== freshData.length - 1 && ','})} +
*/} +
+ +
+ {freshData.map((l, index) =>
{l.label}
)} + {/*
知识库
*/} + {/*
法律
*/} +
+
+
+
+ ) : ( +
+ {/* +
+ {freshData.map((l, index) => {l.label}{index !== freshData.length - 1 && ','})} +
*/} +
+ {/* */} +
+ {freshData.map((l, index) =>
{l.label}
)} + {/*
知识库
+
法律
*/} +
+
+
+ ) + ) : ( + isOperator ? ( + +
e.stopPropagation()} className=""> + {/* +
+ {t('tag.addLabel')} +
*/} +
+ +
+
+
+ ) : ( +
+ ) + )} +
+ ) +} diff --git a/src/components/bs-comp/chatComponent/ChatInput.tsx b/src/components/bs-comp/chatComponent/ChatInput.tsx index 4956ee7..0d42375 100644 --- a/src/components/bs-comp/chatComponent/ChatInput.tsx +++ b/src/components/bs-comp/chatComponent/ChatInput.tsx @@ -270,7 +270,7 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on {/* form */} { formShow &&
-
+
{inputForm}
@@ -295,7 +295,7 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on
{ form &&
(showWhenLocked || !inputLock.locked) && setFormShow(!formShow)} >
} @@ -338,7 +338,7 @@ export default function ChatInput({ clear, form, questions, inputForm, wsUrl, on disabled={inputLock.locked} onInput={handleTextAreaHeight} placeholder={inputLock.locked ? inputLock.reason : t('chat.inputPlaceholder')} - className="questionTextarea w-full resize-none border-none bg-transparent outline-none max-h-[160px]" + className="questionTextarea w-full resize-none border-none bg-transparent outline-none max-h-[160px] pr-[68px]" // className={"resize-none py-4 pr-10 text-md min-h-6 max-h-[200px] scrollbar-hide dark:bg-[#2A2B2E] text-gray-800" + (form && ' pl-10')} onKeyDown={(event) => { if (event.key === "Enter" && !event.shiftKey) { diff --git a/src/components/bs-comp/chatComponent/MessageBs.tsx b/src/components/bs-comp/chatComponent/MessageBs.tsx index 7555d31..dcea3f8 100644 --- a/src/components/bs-comp/chatComponent/MessageBs.tsx +++ b/src/components/bs-comp/chatComponent/MessageBs.tsx @@ -39,6 +39,7 @@ const colorList = [ ] export default function MessageBs({ data, onUnlike = () => { }, flow_type, onSource }: { data: ChatMessageType, flow_type: any, onUnlike?: any, onSource?: any }) { +// export default function MessageBs({ logo, data, onUnlike = () => { }, flow_type, onSource }: { logo: string, 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 ] diff --git a/src/components/bs-comp/chatComponent/MessageUser.tsx b/src/components/bs-comp/chatComponent/MessageUser.tsx index 99cb0e8..c718888 100644 --- a/src/components/bs-comp/chatComponent/MessageUser.tsx +++ b/src/components/bs-comp/chatComponent/MessageUser.tsx @@ -7,7 +7,8 @@ import robotU from "../../../assets/robotU.png"; import btnEdit from "../../../assets/chat/btn-edit.png"; import btnReSend from "../../../assets/chat/btn-reSend.png"; -export default function MessageUser({ useName, data }: { data: ChatMessageType }) { +export default function MessageUser({ useName = 'xxx', data }: {useName: string, data: ChatMessageType }) { +// export default function MessageUser({ useName, data }: { data: ChatMessageType }) { const msg = data.message[data.chatKey] const { appConfig } = useContext(locationContext) diff --git a/src/components/bs-comp/selectComponent/LabelSelect.tsx b/src/components/bs-comp/selectComponent/LabelSelect.tsx new file mode 100644 index 0000000..460b0e7 --- /dev/null +++ b/src/components/bs-comp/selectComponent/LabelSelect.tsx @@ -0,0 +1,200 @@ +import { Popover, PopoverContent, PopoverTrigger } from "@/components/bs-ui/popover"; +import { useEffect, useMemo, useRef, useState } from "react"; +import { SearchInput } from "@/components/bs-ui/input"; +import { Checkbox } from "@/components/bs-ui/checkBox"; +import { Label } from "@/components/bs-ui/label"; +import { Pencil2Icon } from "@radix-ui/react-icons"; +import { Trash2 } from "lucide-react"; +import { Input } from "@/components/bs-ui/input"; +import { useToast } from "@/components/bs-ui/toast/use-toast"; +import { useTranslation } from "react-i18next"; +import { bsConfirm } from "@/components/bs-ui/alertDialog/useConfirm"; +import { PlusIcon } from "@radix-ui/react-icons"; +import { useContext } from "react"; +import { userContext } from "@/contexts/userContext"; +import { + createLabelApi, updateLabelApi, + createLinkApi, deleteLinkApi, + deleteLabelApi +} from "@/controllers/API/label"; +import { captureAndAlertRequestErrorHoc } from "@/controllers/request"; +import biaoqianBian from "../../../assets/npc/biaoqian-bian.png" +import biaoqianDel from "../../../assets/npc/biaoqian-del.png" + +export enum UPDATETYPE { + DELETELINK = 'deleteLink', + CREATELINK = 'createLink', + UPDATENAME = 'updateName', + CREATELABEL = 'createLabel', + DELETELABEL = 'deleteLabel' +} + +export default function LabelSelect({ labels, all, children, resource, onUpdate }) { + const [open, setOpen] = useState(false) + const [data, setData] = useState([]) + const { user } = useContext(userContext) + const dataRef = useRef([]) + const { message } = useToast() + const { t } = useTranslation() + + useEffect(() => { + const newData = all.map(d => { + const res = labels.find(l => l.value === d.value) + return res ? { ...d, selected: true } : d + }) + dataRef.current = newData + setData(newData) + }, [all]) + + const handleEdit = (id) => { + setData(pre => pre.map(d => ({ ...d, edit: d.value === id }))) + } + + const handleChecked = (id) => { + const type = resource.type === 'assist' ? 3 : 2 + setData(pre => { + const newData = pre.map(d => d.value === id ? { ...d, selected: !d.selected } : d) + const cur = newData.find(d => d.value === id) + captureAndAlertRequestErrorHoc( + (cur.selected ? createLinkApi(id, resource.id, type) : deleteLinkApi(id, resource.id, type)).then(() => { + onUpdate({ + type: cur.selected ? UPDATETYPE.CREATELINK : UPDATETYPE.DELETELINK, + data: cur + }) + }) + ) + return newData + }) + } + + const nameRef = useRef('') + const handleChange = (e, id) => { + nameRef.current = id ? dataRef.current.find(d => d.value === id).label : '' + setData(pre => pre.map(d => d.value === id ? { ...d, label: e.target.value } : d)) + } + + const errorRestName = (preName, id) => { //错误发生回退初值 + preName + ? setData(pre => pre.map(d => d.value === id ? { ...d, label: nameRef.current } : d)) + : setData(pre => pre.filter(d => d.value)) + } + + const handleSave = async (e, id) => { + if (e.key === 'Enter') { + setData(pre => pre.map(d => d.value === id ? { ...d, edit: false } : d)) + const label = data.find(d => d.value === id) + if (label.label.length > 10) { + errorRestName(nameRef.current, id) + return message({ title: t('prompt'), variant: 'warning', description: t('tag.labelMaxLength') }) + } + const err = await captureAndAlertRequestErrorHoc(updateLabelApi(id, label.label).then((res: any) => { + setData(pre => { + const newData = pre.map(d => d.value ? d : { ...d, label: res.name, value: res.id }) + dataRef.current = newData + return newData + }) + onUpdate({ + type: UPDATETYPE.UPDATENAME, + data: label + }) + return message({ title: t('prompt'), variant: 'success', description: id ? t('updateSuccess') : t('createSuccess') }) + })) + if (!err) { + errorRestName(nameRef.current, id) + } + } + } + + const handleDelete = (label) => { + bsConfirm({ + title: t('prompt'), + desc: t('tag.confirmDeleteLabel', { label: label.label }), + okTxt: "确认", + onOk(next) { + captureAndAlertRequestErrorHoc(deleteLabelApi(label.value).then(() => { + onUpdate({ + type: UPDATETYPE.DELETELABEL, + data: label + }) + message({ title: t('prompt'), variant: 'success', description: t('deleteSuccess') }) + })) + next() + } + }) + } + + const handleOpenChange = (b) => { // 可用于整体保存 + setOpen(b) + setData(pre => pre.map(d => ({ ...d, edit: false }))) + } + + const [keyword, setKeyword] = useState('') + const handleSearch = (e) => { + const key = e.target.value + setKeyword(key) + const newData = dataRef.current.filter(d => d.label.toUpperCase().includes(key.toUpperCase())) + setData(newData) + } + + const handleAdd = () => { + if (keyword.length > 10) { + return message({ title: t('prompt'), variant: 'warning', description: t('tag.labelMaxLength') }) + } + createLabelApi(keyword).then((res: any) => { + const addItem = { label: res.name, value: res.id, edit: false, selected: false } + dataRef.current = [addItem, ...dataRef.current] + setData([addItem]) + onUpdate({ + type: UPDATETYPE.CREATELABEL, + data: res.name + }) + }) + } + + const showAdd = useMemo(() => { + if (data.length === 1 && data[0].label === keyword) { + return false + } + return true + }, [data]) + + return + + {children} + + e.stopPropagation()}> +
+ { + if (e.key === 'Enter') { + (!data.length && user.role === 'admin') ? handleAdd() : null + } + }} /> +
+
+ {data.map(d =>
+
+ handleChecked(d.value)} /> + { + d.edit + ? handleChange(e, d.value)} + onKeyDown={(e) => handleSave(e, d.value)} /> + : + } +
+ {user.role === 'admin' &&
+ handleEdit(d.value)} className="w-[14px] cursor-pointer"/> + handleDelete(d)} className="w-[14px] ml-[14px] cursor-pointer"/> + {/* handleEdit(d.value)} /> */} + {/* handleDelete(d)} className="text-gray-600 cursor-pointer" /> */} +
} +
)} + {(showAdd && keyword != '' && user.role === 'admin') &&
+ 创建标签 +
} +
+
+
+} diff --git a/src/components/bs-comp/sheets/SkillChatSheet.tsx b/src/components/bs-comp/sheets/SkillChatSheet.tsx index cf14c32..3477069 100644 --- a/src/components/bs-comp/sheets/SkillChatSheet.tsx +++ b/src/components/bs-comp/sheets/SkillChatSheet.tsx @@ -1,7 +1,7 @@ import { Badge } from "@/components/bs-ui/badge"; import { Button } from "@/components/bs-ui/button"; import { getChatOnlineApi } from "@/controllers/API/assistant"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useContext, useEffect, useMemo, useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; import { SearchInput } from "../../bs-ui/input"; import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from "../../bs-ui/sheet"; @@ -19,40 +19,57 @@ import zidingyi1 from "../../../assets/npc/zidingyi1.png"; import zidingyi2 from "../../../assets/npc/zidingyi2.png"; import npcIcon from "../../../assets/npc/npcIcon.png"; import nengliIcon from "../../../assets/npc/nengliIcon.png"; +import biaoqianPaixu from "../../../assets/chat/biaoqian-paixu.png"; import { useDebounce } from "@/util/hook"; import LoadMore from "../loadMore"; +import { userContext } from "@/contexts/userContext"; +import { getHomeLabelApi } from "@/controllers/API/label"; +import MarkLabel from "@/pages/ChatAppPage/components/MarkLabel"; export default function SkillChatSheet({ children, onSelect }) { - const [open, setOpen] = useState(false) - const { t } = useTranslation() - + const { user } = useContext(userContext) + const chatListRef = useRef([]) const navigate = useNavigate() + const [labels, setLabels] = useState([]) + const [open, setOpen] = useState(false) + const pageRef = useRef(1) + const [options, setOptions] = useState([]) + const searchRef = useRef('') + const [flag, setFlag] = useState(null) // 解决筛选之后再次发起请求覆盖筛选数据 + const [keyword, setKeyword] = useState(' ') const allDataRef = useRef([]) + const [markLabelOpen, setMarkLabelOpen] = useState(false) - const pageRef = useRef(1) - const searchRef = useRef('') - const [options, setOptions] = useState([]) const loadData = (more = false) => { - open && getChatOnlineApi(pageRef.current, searchRef.current).then(res => { - setOptions(opts => more ? [...opts, ...res] : res) + getChatOnlineApi(pageRef.current, searchRef.current, -1).then((res: any) => { + setFlag(true) + chatListRef.current = res + setOptions(more ? [...options, ...res] : res) }) } - const debounceLoad = useDebounce(loadData, 600, false) + // useEffect(() => { + // // open && getChatOnlineApi().then(res => { + // // allDataRef.current = res + // // setKeyword('') + // // }) + // // setKeyword(' ') + // pageRef.current = 1 + // searchRef.current = '' + // loadData() + // }, [open]) useEffect(() => { - // open && getChatOnlineApi().then(res => { - // allDataRef.current = res - // setKeyword('') - // }) - // setKeyword(' ') - pageRef.current = 1 - searchRef.current = '' - loadData() - }, [open]) + debounceLoad() + getHomeLabelApi().then((res: any) => { + setLabels(res.map(d => ({ label: d.name, value: d.id, selected: true }))) + }) + }, []) + + const debounceLoad = useDebounce(loadData, 600, false) // const options = useMemo(() => { // return allDataRef.current.filter(el => el.name.toLowerCase().includes(keyword.toLowerCase())) @@ -64,9 +81,26 @@ export default function SkillChatSheet({ children, onSelect }) { debounceLoad() } - const handleLoadMore = () => { + const handleClose = async (bool) => { + const newHome = await getHomeLabelApi() + // @ts-ignore + setLabels(newHome.map(d => ({ label: d.name, value: d.id, selected: true }))) + setMarkLabelOpen(bool) + } + + const [chooseId, setChooseId] = useState() // 筛选项样式变化 + const handleTagSearch = (id) => { + setChooseId(id) + setFlag(false) + pageRef.current = 1 + getChatOnlineApi(pageRef.current, '', id).then((res: any) => { + setOptions(res) + }) + } + + const handleLoadMore = async () => { pageRef.current++ - loadData(true) + await debounceLoad(true) } const render = (item: any) => ( @@ -109,13 +143,31 @@ export default function SkillChatSheet({ children, onSelect }) { 选择对话 选择一个您想使用的上线NPC或能力 {/* setKeyword(e.target.value)} /> */} - + +
+ {/* @ts-ignore */} + {user.role === 'admin' && setMarkLabelOpen(true)} />} + {/* */} +
{ setChooseId(null); loadData(false) }}>全部
+ { + labels.map((l, index) => index <= 11 && + // +
handleTagSearch(l.value)}>{l.label}
) + } + +
- + {flag && }
+ }; diff --git a/src/components/bs-icons/office/index.tsx b/src/components/bs-icons/office/index.tsx index 10e6163..60a88a8 100644 --- a/src/components/bs-icons/office/index.tsx +++ b/src/components/bs-icons/office/index.tsx @@ -5,6 +5,6 @@ export const WordIcon = forwardRef< SVGSVGElement & { className: any }, React.PropsWithChildren<{ className?: string }> >(({ className, ...props }, ref) => { - const _className = 'transition text-gray-950 ' + (className || '') + const _className = 'transition text-[#43AFD2] ' + (className || '') return ; }); diff --git a/src/components/bs-icons/prompt/Prompt.svg b/src/components/bs-icons/prompt/Prompt.svg new file mode 100644 index 0000000..e1442f0 --- /dev/null +++ b/src/components/bs-icons/prompt/Prompt.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/components/bs-icons/prompt/index.tsx b/src/components/bs-icons/prompt/index.tsx new file mode 100644 index 0000000..61d56b8 --- /dev/null +++ b/src/components/bs-icons/prompt/index.tsx @@ -0,0 +1,10 @@ +import React, { forwardRef } from "react"; +import { ReactComponent as Prompt } from "./Prompt.svg"; + +export const PromptIcon = forwardRef< + SVGSVGElement & { className: any }, + React.PropsWithChildren<{ className?: string }> +>(({ className, ...props }, ref) => { + const _className = 'transition text-[#999] ' + (className || '') + return ; +}); \ No newline at end of file diff --git a/src/components/bs-ui/alertDialog/index.tsx b/src/components/bs-ui/alertDialog/index.tsx index 9473388..dbd86e6 100644 --- a/src/components/bs-ui/alertDialog/index.tsx +++ b/src/components/bs-ui/alertDialog/index.tsx @@ -35,7 +35,7 @@ const AlertDialogContent = React.forwardRef< ) => (
(({ className, ...props }, ref) => ( )) @@ -90,7 +90,7 @@ const AlertDialogDescription = React.forwardRef< >(({ className, ...props }, ref) => ( )) @@ -103,7 +103,7 @@ const AlertDialogAction = React.forwardRef< >(({ className, ...props }, ref) => ( )) @@ -118,7 +118,8 @@ const AlertDialogCancel = React.forwardRef< className={cname( buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", - className + className, + "baogao-btn" )} {...props} /> diff --git a/src/components/bs-ui/input/index.tsx b/src/components/bs-ui/input/index.tsx index e5b8e43..9f9c90f 100644 --- a/src/components/bs-ui/input/index.tsx +++ b/src/components/bs-ui/input/index.tsx @@ -6,7 +6,7 @@ import { MinusCircledIcon } from "@radix-ui/react-icons" import { EyeOpenIcon, EyeNoneIcon } from "@radix-ui/react-icons" import { useState } from "react" -import sousuo from "../../../assets/npc/sousuo1.png" +import sousuo from "../../../assets/npc/sousuo.png" export interface InputProps extends React.InputHTMLAttributes { } diff --git a/src/controllers/API/assistant.ts b/src/controllers/API/assistant.ts index b77211e..1c963c5 100644 --- a/src/controllers/API/assistant.ts +++ b/src/controllers/API/assistant.ts @@ -13,10 +13,18 @@ export interface AssistantItemDB { status: number; } // 获取助手列表 -export const getAssistantsApi = async (page, limit, name): Promise => { +// export const getAssistantsApi = async (page, limit, name): Promise => { +// return await axios.get(`/api/v1/assistant`, { +// params: { +// page, limit, name +// } +// }); +// }; +export const getAssistantsApi = async (page, limit, name, tag_id): Promise => { return await axios.get(`/api/v1/assistant`, { params: { - page, limit, name + page, limit, name, + tag_id: tag_id === -1 ? null : tag_id } }); }; diff --git a/src/controllers/API/flow.ts b/src/controllers/API/flow.ts index 9514143..75f480f 100644 --- a/src/controllers/API/flow.ts +++ b/src/controllers/API/flow.ts @@ -148,8 +148,13 @@ export async function saveFlowToDatabase(newFlow: { * @returns {Promise} The flows data. * @throws Will throw an error if reading fails. */ -export async function readFlowsFromDatabase(page: number = 1, pageSize: number = 20, search: string) { - const { data, total }: { data: any[], total: number } = await axios.get(`/api/v1/flows/?page_num=${page}&page_size=${pageSize}&name=${search}`); +// export async function readFlowsFromDatabase(page: number = 1, pageSize: number = 20, search: string) { +// const { data, total }: { data: any[], total: number } = await axios.get(`/api/v1/flows/?page_num=${page}&page_size=${pageSize}&name=${search}`); +// return { data, total }; +// } +export async function readFlowsFromDatabase(page: number = 1, pageSize: number = 20, search: string, tag_id = -1) { + const tagIdStr = tag_id === -1 ? '' : `&tag_id=${tag_id}` + const { data, total }: { data: any[], total: number } = await axios.get(`/api/v1/flows/?page_num=${page}&page_size=${pageSize}&name=${search}${tagIdStr}`); return { data, total }; } diff --git a/src/controllers/API/label.ts b/src/controllers/API/label.ts new file mode 100644 index 0000000..aa03adb --- /dev/null +++ b/src/controllers/API/label.ts @@ -0,0 +1,61 @@ +import axios from "../request"; + +export async function getAllLabelsApi() { + return await axios.get('/api/v1/tag') +} + +// admin全局创建一个标签 +export async function createLabelApi(name:string) { + return await axios.post('/api/v1/tag', { + name + }) +} + +// admin修改标签 +export async function updateLabelApi(id:number, name:string) { + return await axios.put('/api/v1/tag', { + tag_id: id, + name + }) +} + +// admin删除标签 +export async function deleteLabelApi(id:number) { + return await axios.delete('/api/v1/tag', { + data: { + tag_id: id + } + }) +} + +// 建立助手或技能和标签的关系,即选择标签 +export async function createLinkApi(tag_id:number, resource_id:string, resource_type:number) { + return await axios.post('/api/v1/tag/link', { + tag_id, + resource_id, + resource_type + }) +} + +// 删除助手或技能和标签的关系,即不选标签 +export async function deleteLinkApi(tag_id:number, resource_id:string, resource_type:number) { + return await axios.delete('/api/v1/tag/link', { + data: { + tag_id, + resource_id, + resource_type + } + }) +} + +// 获取首页展示的标签列表 +export async function getHomeLabelApi() { + return await axios.get('/api/v1/tag/home') +} + +// 更新首页展示的标签列表 +export async function updateHomeLabelApi(tag_ids) { + return await axios.post('/api/v1/tag/home', { + tag_ids + }) +} \ No newline at end of file diff --git a/src/layout/MainLayout.tsx b/src/layout/MainLayout.tsx index 0ce29fc..e9a0b79 100755 --- a/src/layout/MainLayout.tsx +++ b/src/layout/MainLayout.tsx @@ -99,7 +99,7 @@ export default function MainLayout() { } { - isMenu('filelib') && + isMenu('knowledge') && {/* */} {t('menu.knowledge')} diff --git a/src/pages/ChatAppPage/components/ChatHome.tsx b/src/pages/ChatAppPage/components/ChatHome.tsx new file mode 100644 index 0000000..86c56ed --- /dev/null +++ b/src/pages/ChatAppPage/components/ChatHome.tsx @@ -0,0 +1,158 @@ +import { Badge } from "@/components/bs-ui/badge"; +import { Button } from "@/components/bs-ui/button"; +import { getChatOnlineApi } from "@/controllers/API/assistant"; +import { useContext, useEffect, useMemo, useRef, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { SearchInput } from "@/components/bs-ui/input"; +import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from "@/components/bs-ui/sheet"; +import CardComponent, { TitleIconBg } from "@/components/bs-comp/cardComponent"; +import { SkillIcon } from "@/components/bs-icons/skill"; +import { AssistantIcon } from "@/components/bs-icons/assistant"; +import { useTranslation } from "react-i18next"; +import borderR from "../../../assets/npc/border-r.png"; +import { SpotlightCard } from "@lobehub/ui"; +import { Flexbox } from 'react-layout-kit'; +import robot from "../../../assets/robot.png"; +import robot2 from "../../../assets/robot2.png"; +import robot3 from "../../../assets/robot3.png"; +import zidingyi1 from "../../../assets/npc/zidingyi1.png"; +import zidingyi2 from "../../../assets/npc/zidingyi2.png"; +import npcIcon from "../../../assets/npc/npcIcon.png"; +import nengliIcon from "../../../assets/npc/nengliIcon.png"; +import biaoqianPaixu from "../../../assets/chat/biaoqian-paixu.png"; +import sousuo from "../../../assets/npc/sousuo.png"; +import shengQue from "../../../assets/chat/shengQue.png"; +import { useDebounce } from "@/util/hook"; +import LoadMore from "@/components/bs-comp/loadMore"; +import { userContext } from "@/contexts/userContext"; +import { getHomeLabelApi } from "@/controllers/API/label"; +import MarkLabel from "@/pages/ChatAppPage/components/MarkLabel"; + +export default function HomePage({ onSelect }) { + const { t } = useTranslation() + const { user } = useContext(userContext) + const chatListRef = useRef([]) + const navigate = useNavigate() + + const [labels, setLabels] = useState([]) + const [open, setOpen] = useState(false) + const pageRef = useRef(1) + const [options, setOptions] = useState([]) + const searchRef = useRef('') + const [flag, setFlag] = useState(null) // 解决筛选之后再次发起请求覆盖筛选数据 + + const [keyword, setKeyword] = useState(' ') + const allDataRef = useRef([]) + const [markLabelOpen, setMarkLabelOpen] = useState(false) + + + const loadData = (more = false) => { + getChatOnlineApi(pageRef.current, searchRef.current, -1).then((res: any) => { + setFlag(true) + chatListRef.current = res + setOptions(more ? [...options, ...res] : res) + }) + } + + useEffect(() => { + debounceLoad() + getHomeLabelApi().then((res: any) => { + setLabels(res.map(d => ({ label: d.name, value: d.id, selected: true }))) + }) + }, []) + + const debounceLoad = useDebounce(loadData, 600, false) + + const handleSearch = (e) => { + pageRef.current = 1 + searchRef.current = e.target.value + debounceLoad() + } + + const handleClose = async (bool) => { + const newHome = await getHomeLabelApi() + // @ts-ignore + setLabels(newHome.map(d => ({ label: d.name, value: d.id, selected: true }))) + setMarkLabelOpen(bool) + } + + const [chooseId, setChooseId] = useState() // 筛选项样式变化 + const handleTagSearch = (id) => { + setChooseId(id) + setFlag(false) + pageRef.current = 1 + getChatOnlineApi(pageRef.current, '', id).then((res: any) => { + setOptions(res) + }) + } + + const handleLoadMore = async () => { + pageRef.current++ + await debounceLoad(true) + } + + const render = (item: any) => ( + { onSelect(item); setOpen(false) }}> +
+ + +
+ +
+
+
+
+
+ +
+

{item.name}

+
+ +
+
+
+

{item.desc}

+
+ {item.flow_type === 'flow' ? '能力' : 'NPC'} +
+
+ ); + + return
+
e.stopPropagation()}> + {/*
+
*/} +
+ {/* 选择对话 + 选择一个您想使用的上线NPC或能力 */} + {/* setKeyword(e.target.value)} /> */} +

选择对话

+

选择一个您想使用的上线NPC或能力

+
+ +
+
+
+ {/* @ts-ignore */} + {user.role === 'admin' && setMarkLabelOpen(true)} />} + {/* */} +
{ setChooseId(null); loadData(false) }}>全部
+ { + labels.map((l, index) => index <= 11 && +
handleTagSearch(l.value)}>{l.label}
) + } +
+
+
+ {options.length ? + :
+ +

未找到您搜索的「NPC」或「能力」

+
} + {flag && } +
+ +
+
+} \ No newline at end of file diff --git a/src/pages/ChatAppPage/components/ChatPanne.tsx b/src/pages/ChatAppPage/components/ChatPanne.tsx index d2e5423..35fd636 100644 --- a/src/pages/ChatAppPage/components/ChatPanne.tsx +++ b/src/pages/ChatAppPage/components/ChatPanne.tsx @@ -184,6 +184,7 @@ export default function ChatPanne({ customWsHost = '', appendHistory = false, da }); document.dispatchEvent(myEvent); } + if(!appConfig.websocketHost) return // // ws通信 // const { stop, connectWS, begin: chating, checkReLinkWs, sendAll } = useWebsocket(chatId, flow, setChatHistory, queryString, version) // // 停止状态 diff --git a/src/pages/ChatAppPage/components/MarkLabel.tsx b/src/pages/ChatAppPage/components/MarkLabel.tsx new file mode 100644 index 0000000..290ae58 --- /dev/null +++ b/src/pages/ChatAppPage/components/MarkLabel.tsx @@ -0,0 +1,146 @@ +import { PromptIcon } from '@/components/bs-icons/prompt'; +import { Button } from '@/components/bs-ui/button'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/bs-ui/dialog"; +import { useTranslation } from 'react-i18next'; +import { CrossCircledIcon } from '@radix-ui/react-icons'; +import { cname } from '@/components/bs-ui/utils'; +import { useEffect, useState } from 'react'; +import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'; +import { updateHomeLabelApi, getAllLabelsApi } from "@/controllers/API/label"; +import { captureAndAlertRequestErrorHoc } from '@/controllers/request'; +import { useToast } from '@/components/bs-ui/toast/use-toast'; + +function DragItem({className = '', data, children, onCancel}) { + return
+ {e.stopPropagation(); onCancel(data.id)}} + className='text-[#999] absolute top-[-6px] right-[-6px] cursor-pointer'/> +
+ {data.index} +
+
+ {children} +
+
+} + +export default function MarkLabel({open, home, onClose}) { + const { t } = useTranslation() + const [labels, setLabels] = useState([]) + const [selected, setSelected] = useState([]) + const { message } = useToast() + + useEffect(() => { + async function init() { + const all = await getAllLabelsApi() + const newData = all.data.map(d => { + const res = home.find(h => h.value === d.id) + return res ? {label:d.name, value:d.id, selected:true} : {label:d.name, value:d.id, selected:false} + }) + setLabels(newData) + setSelected(home) + } + init() + }, [home]) + + const handleCancel = () => { + onClose(false) + } + + const handleConfirm = async () => { + await captureAndAlertRequestErrorHoc(updateHomeLabelApi(selected.map(s => s.value))) + onClose(false) + } + + const handleSelect = (id) => { + setLabels(pre => { + const newData = pre.map(l => l.value === id ? {...l, selected:!l.selected} : l) + if(newData.filter(d => d.selected).length > 10) { + message({ + title: t('prompt'), + variant: 'warning', + description: '最多选择10个标签' + }) + return pre + } + const select = newData.find(d => d.value === id && d.selected) + setSelected(select ? [...selected, select] : pre => pre.filter(d => d.value !== id)) + return newData + }) + } + + const handleDelete = (id) => { + setSelected(pre => pre.filter(d => d.value !== id)) + setLabels(pre => pre.map(d => d.value === id ? {...d, selected:!d.selected} : d)) + } + + const handleDragEnd = (result) => { + if(!result.destination) return + const newData = selected + const [moveItem] = newData.splice(result.source.index, 1) + newData.splice(result.destination.index, 0, moveItem) + setSelected(newData) + setFlag(false) + } + + const [flag, setFlag] = useState(false) // 解决拖拽映射位置错位 + + return + + + + + {t('chat.operationTips')} + + +
+
+
+ {/*
*/} + { + labels.map(l => + + //
handleSelect(l.value)} style={{borderRadius:"4px"}} className={`ml-[14px] w-[108px] h-[22px] flex justify-center items-center cursor-pointer ${!l.selected ? 'text-[#999999] bg-[#333333]' : 'text-[#333333] bg-[#FFD54C]'} w-[120px]`}> + // {l.label} + //
+ ) + } +
+
+
+
+ {t('chat.selected')}:{selected.length}/10 + setFlag(true)} onDragUpdate={() => setFlag(true)}> + + {(provided) => ( +
+ {selected.map((b,index) => ( + + {(provided) => ( +
+ + {b.label} + +
+ )} +
+ ))} + {provided.placeholder} +
+ )} +
+
+
+
+
+ + + + + +
+} \ No newline at end of file diff --git a/src/pages/ChatAppPage/components/ResouceModal.tsx b/src/pages/ChatAppPage/components/ResouceModal.tsx index a4c302a..8099668 100644 --- a/src/pages/ChatAppPage/components/ResouceModal.tsx +++ b/src/pages/ChatAppPage/components/ResouceModal.tsx @@ -1,10 +1,12 @@ +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/bs-ui/dialog"; import { Download, Import } from "lucide-react"; -import React, { useEffect, useRef, useState } from "react"; +import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { getSourceChunksApi, splitWordApi } from "../../../controllers/API"; -import { ChatMessageType } from "../../../types/chat"; -import FileView, { checkSassUrl } from "./FileView"; import { downloadFile } from "../../../util/utils"; +import FileView, { checkSassUrl } from "./FileView"; +import { QuestionMarkCircledIcon } from "@radix-ui/react-icons"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/bs-ui/tooltip"; // 顶部答案区 const Anwser = ({ id, msg, onInit, onAdd }) => { @@ -14,12 +16,20 @@ const Anwser = ({ id, msg, onInit, onAdd }) => { // init useEffect(() => { onInit([]) - msg && splitWordApi(msg, id).then((res) => { - // 匹配 - const reg = new RegExp(`(${res.join('|')})`, 'g') - setHtml(msg.replace(reg, '$1')) - onInit(res) - }) + const loadData = () => { + splitWordApi(msg, id).then((res) => { + // 匹配 + const reg = new RegExp(`(${res.join('|')})`, 'g') + setHtml(msg.replace(reg, '$1')) + onInit(res) + }).catch(e => { + // 自动重试 + e === '后台处理中,稍后再试' && setTimeout(() => { + loadData() + }, 1800); + }) + } + msg && loadData() }, []) // add @@ -33,18 +43,43 @@ const Anwser = ({ id, msg, onInit, onAdd }) => { return () => pRef.current?.removeEventListener('click', handleclick) }, []) - return
+ return

} // let timer = null -const ResultPanne = ({ chatId, words, data, onClose, onAdd, children }: { chatId: string, words: string[], data: ChatMessageType, onClose: any, onAdd: any, children: any }) => { +const ResultPanne = ({ chatId, words, data, onClose, onAdd, children, closeDialog }: { chatId: string, words: string[], data: any, onClose: any, onAdd: any, children: any, closeDialog: () => void }) => { const { t } = useTranslation() const [editCustomKey, setEditCustomKey] = useState(false) const inputRef = useRef(null) + // 移动端 + const [collapse, setCollapse] = useState(true) + const [isMobile, setIsMobile] = useState(true) + const [width, setWidth] = useState(window.innerWidth); + const [height, setHeight] = useState(window.innerHeight); + const checkIsMobile = () => { + if (width < 640) { + setIsMobile(true) + } else { + setIsMobile(false) + } + } + useEffect(() => { + const handleResize = () => { + setWidth(window.innerWidth); + setHeight(window.innerHeight); + }; + window.addEventListener("resize", handleResize); + checkIsMobile() + return () => { + window.removeEventListener("resize", handleResize); + } + }, [width]) + // 移动端 e + const handleAddKeyword = (str: string) => { setEditCustomKey(false) if (!str) return @@ -59,7 +94,7 @@ const ResultPanne = ({ chatId, words, data, onClose, onAdd, children }: { chatId // if (!words.length) return setFiles([]) clearTimeout(timer) // 简单防抖 timer = setTimeout(() => { - getSourceChunksApi(chatId, data.id, words.join(';')).then((_files) => { + getSourceChunksApi(chatId, data.messageId, words.join(';')).then((_files) => { setFiles(_files) // 默认打开第一个文件 _files && setFile(_files[0]) @@ -78,70 +113,95 @@ const ResultPanne = ({ chatId, words, data, onClose, onAdd, children }: { chatId setTimeout(() => document.getElementById('taginput')?.focus(), 0); } - return
+ return
+ { + isMobile &&
+ {!collapse && { setCollapse(true) }} className="">收起} + {collapse && { setCollapse(false) }} className="">展开} +
+ } + { + isMobile &&
+ 关闭 +
+ } {/* left */} -
- {/* label */} -
- {t('chat.filterLabel')} -
?
-
-
- {words.map((str, i) =>
{str} onClose(i)}>x
)} - {/* 自定义 */} - { - editCustomKey ?
{ - if (event.key === "Enter" && !event.shiftKey) { + { + (!isMobile || !collapse) &&
+ {/* label */} +
+
+ {t('chat.filterLabel')} + + + + + + +

{t('chat.tooltipText')}

+
+
+
+
+
+
+ {words.map((str, i) =>
{str} onClose(i)}>x
)} + { + editCustomKey ?
{ + if (event.key === "Enter" && !event.shiftKey) { + handleAddKeyword(inputRef.current.value); + } + }} + onBlur={() => { handleAddKeyword(inputRef.current.value); - } - }} - onBlur={() => { - handleAddKeyword(inputRef.current.value); - }}>
: -
{t('chat.addCustomLabel')}
- } -
- {/* files */} -
-

{t('chat.sourceDocumentsLabel')}

- {files.map(_file => - _file.right ?
setFile(_file)} className={`group rounded-xl bg-[#fff] hover-bg-gray-200 flex items-center px-4 mb-2 relative min-h-16 cursor-pointer ${file?.id === _file.id && 'bg-gray-200'}`}> -

{_file.fileName}

- - {_file.score} -
: -
-

是真的马赛克.msk

+ }}>
: +
{t('chat.addCustomLabel')}
+ } +
+ {/* files */} +
+

{t('chat.sourceDocumentsLabel')}

+ {files.map(_file => + _file.right ?
setFile(_file)} className={`group rounded-xl bg-[#fff] dark:bg-[#303134] hover-bg-gray-200 flex items-center px-4 mb-2 relative min-h-16 cursor-pointer ${file?.id === _file.id && 'bg-gray-200'}`}> +

{_file.fileName}

+ {_file.score} -
- )} - {!files.length &&

{t('chat.noMatchedFilesMessage')}

} +
: +
+

是真的马赛克.msk

+ {_file.score} +
+ )} + {!files.length &&

{t('chat.noMatchedFilesMessage')}

} +
-
+ } {/* file pane */} {file && children(file)}
} -export default function ResouceModal({ chatId, data, open, setOpen }: { chatId: string, data: ChatMessageType, open: boolean, setOpen: (b: boolean) => void }) { +const ResouceModal = forwardRef((props, ref) => { // labels const { t } = useTranslation() + + const [open, setOpen] = useState(false) const [keywords, setKeywords] = useState([]) const handleAddWord = (word: string) => { // 去重 更新 @@ -152,38 +212,35 @@ export default function ResouceModal({ chatId, data, open, setOpen }: { chatId: setKeywords(keywords.filter((wd, i) => i !== index)) } - // 记忆 - // useEffect(() => { - // const KEYWORDS_LOCAL_KEY = 'KEYWORDS_LOCAL' - // setKeywords(JSON.parse(localStorage.getItem(KEYWORDS_LOCAL_KEY) || '[]')) + const [data, setData] = useState({}) + useImperativeHandle(ref, () => ({ + openModal: (data) => { + setOpen(true) + setData(data) + } + })); - // return () => localStorage.setItem(KEYWORDS_LOCAL_KEY, JSON.stringify(keywords)) - // }, []) const MemoizedFileView = React.memo(FileView); - return setOpen(false)}> -
e.stopPropagation()}> + return + + {/* + {t('chat.feedback')} + */} {open &&
- - + + setOpen(false)}> { (file) => file.fileUrl ? : -
+

{t('chat.fileStorageFailure')}

}
} -
-
-}; + +
+}); -// const useRefState = (state) => { -// const [data, setData] = useState(state) -// const ref = useRef(state) -// return [data, ref, (nState) => { -// setData(nState) -// ref.current = nState -// }] -// } +export default ResouceModal diff --git a/src/pages/ChatAppPage/index.tsx b/src/pages/ChatAppPage/index.tsx index c1f3618..166f579 100755 --- a/src/pages/ChatAppPage/index.tsx +++ b/src/pages/ChatAppPage/index.tsx @@ -22,8 +22,12 @@ import SkillChatSheet from "@/components/bs-comp/sheets/SkillChatSheet"; import { TitleIconBg } from "@/components/bs-comp/cardComponent"; import npcIcon from "../../assets/npc/npcIcon.png"; import nengliIcon from "../../assets/npc/nengliIcon.png"; +import xinjian1 from "../../assets/chat/xinjian1.png"; +import xinjian2 from "../../assets/chat/xinjian2.png"; import { useMessageStore } from "@/components/bs-comp/chatComponent/messageStore"; import { formatDate } from "@/util/utils"; +import { message } from "@/components/bs-ui/toast/use-toast"; +import HomePage from "./components/ChatHome"; export default function SkillChatPage() { @@ -70,30 +74,42 @@ export default function SkillChatPage() { // const { chatList, chatId, chatsRef, setChatId, addChat, deleteChat } = useChatList() const { chatList, chatId, chatsRef, setChatId, addChat, deleteChat, onScrollLoad } = useChatList() + const [location, setLocation] = useState(true) // select flow const handlerSelectFlow = async (card) => { - // 会话ID - const _chatId = generateUUID(32) - // setOpen(false) - // add list - addChat({ - "flow_name": card.name, - "flow_description": card.desc, - "flow_id": card.id, - "chat_id": _chatId, - "create_time": "-", - "update_time": "-", - "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 }) - setChatId(_chatId) + console.log(card) + if (!location) { + setLocation(true) + return + } + if (card) { + // 会话ID + const _chatId = generateUUID(32) + // setOpen(false) + // add list + addChat({ + "flow_name": card.name, + "flow_description": card.desc, + "flow_id": card.id, + "chat_id": _chatId, + "create_time": "-", + "update_time": "-", + "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 }) + setChatId(_chatId) + setLocation(false) + } else { + return message({ title: t('prompt'), variant: 'warning', description: t('chat.pleaseSelectAnApp') }) + } + } // select chat const handleSelectChat = useDebounce(async (chat) => { + setLocation(false) // console.log('chat.id :>> ', chat); if (chat.chat_id === chatId) return setSelelctChat({ id: chat.flow_id, chatId: chat.chat_id, type: chat.flow_type }) @@ -118,13 +134,12 @@ export default function SkillChatPage() { return
- -
- {/* */} - {/* */} - {t('chat.newChat')} -
-
+
handlerSelectFlow(null)} className="xinDuiHua-btn cursor-pointer"> + {t('chat.newChat')} +
+ {/* + + */} {/*
setOpen(true)}>{t('chat.newChat')}
*/} {/*
@@ -146,6 +161,7 @@ export default function SkillChatPage() {

{chat.flow_name}

{/*
离线
*/}

{chat.latest_message?.message || ''}

+ {/* {!location &&

{chat.latest_message?.message || ''}

} */}
@@ -163,19 +179,34 @@ export default function SkillChatPage() {
{/* chat */} {/* */} - - {/* { + {/* */} + {/* {location ?
+ +

选择一个 NPC 或 能力,开始对话吧 ~

+
{ + document.getElementById('newchat')?.click() + }}> + + {t('chat.newChat')} +
+
+ : + } */} + { location ? : - } */} + } {/* 选择对话技能 */} - + onSelect={handlerSelectFlow}> */}
}; /** diff --git a/src/pages/ChatAppPage/mobile/chatAssitantShare.tsx b/src/pages/ChatAppPage/mobile/chatAssitantShare.tsx index c17e4c8..67d6e8a 100644 --- a/src/pages/ChatAppPage/mobile/chatAssitantShare.tsx +++ b/src/pages/ChatAppPage/mobile/chatAssitantShare.tsx @@ -11,7 +11,6 @@ export default function chatAssitantShare() { const wsUrl = `/api/v2/assistant/chat/${assitId}` const [data] = useState({ id: assitId, chatId: generateUUID(32), type: 'assistant' }) - if (!assitId) return
请选择会话
// return
diff --git a/src/pages/FileLibPage/files.tsx b/src/pages/FileLibPage/files.tsx index c4d55c3..7482f28 100755 --- a/src/pages/FileLibPage/files.tsx +++ b/src/pages/FileLibPage/files.tsx @@ -39,7 +39,7 @@ export default function FilesPage() { const [open, setOpen] = useState(false) const [title, setTitle] = useState('') - const { page, pageSize, data: datalist, total, loading, setPage, search, reload, filterData, refreshData,loadData } = useTable({}, (param) => + const { page, pageSize, data: datalist, total, setPage, search, reload, filterData, refreshData,loadData } = useTable({}, (param) => readFileByLibDatabase({ ...param, id, name: param.keyword }).then(res => { setHasPermission(res.writeable) return res @@ -123,13 +123,15 @@ export default function FilesPage() { } return
- {loading &&
+ {/* {loading &&
-
} +
} */} - + + + {/* @@ -138,9 +140,9 @@ export default function FilesPage() { */}

{t('lib.fileData')}

-
+
setOpen(true)} style={{background: "#FFD025",borderRadius: "7px"}}> {/* */} - setOpen(true)}>上 传 + 上 传
@@ -225,11 +227,11 @@ export default function FilesPage() { {/* 重复文件提醒 */} -
-

文件重复提示 - setRepeatFiles([])}> +
+

文件重复提示 + setRepeatFiles([])}>

-

以下文件在知识库中已存在,继续上传将会覆盖原有文件以及处理策略,是否覆盖?

+

以下文件在知识库中已存在,继续上传将会覆盖原有文件以及处理策略,是否覆盖?

    {repeatFiles.map(el => (
  • {el.remark}
  • @@ -237,7 +239,7 @@ export default function FilesPage() {
-
diff --git a/src/pages/LogPage/utils/index.ts b/src/pages/LogPage/utils/index.ts index 32c511d..c55978a 100644 --- a/src/pages/LogPage/utils/index.ts +++ b/src/pages/LogPage/utils/index.ts @@ -36,8 +36,8 @@ export function transformEvent(event: string): string { export function transformObjectType(object: string): string { switch(object) { case 'none': return '无' - case 'flow': return '技能' - case 'assistant': return '助手' + case 'flow': return '能力' + case 'assistant': return 'NPC' case 'knowledge': return '知识库' case 'file': return '文件' case 'user_conf': return '用户配置' diff --git a/src/pages/SkillPage/tabAssistant.tsx b/src/pages/SkillPage/tabAssistant.tsx index 68a17e3..202c1aa 100644 --- a/src/pages/SkillPage/tabAssistant.tsx +++ b/src/pages/SkillPage/tabAssistant.tsx @@ -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, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useMemo, useRef, useState } from "react"; import { SpotlightCard } from "@lobehub/ui"; import { Flexbox } from 'react-layout-kit'; import { updataOnlineState } from "@/controllers/API/flow"; @@ -32,17 +32,35 @@ import { userContext } from "@/contexts/userContext"; import ShareLink from "./externalUse/shareLink"; import npcIcon from "../../assets/npc/npcIcon.png"; import { Button } from "@/components/ui/button"; +import LabelShow from "@/components/bs-comp/cardComponent/LabelShow"; +import { SkillIcon } from "@/components/bs-icons/skill"; +import { getAllLabelsApi } from "@/controllers/API/label"; export default function Assistants() { const { t } = useTranslation() const { user } = useContext(userContext); const navigate = useNavigate() const { message } = useToast() + const [labels, setLabels] = useState([]) + const labelsRef = useRef([]) const [open, setOpen] = useState(false); const [isShareLink, setIsShareLink] = useState(false) const [isShareLinkData, setIsShareLinkData] = useState("Any"); + + const AllLabelsApi = () =>{ + getAllLabelsApi().then(res => { + const newData = res.data.map(d => ({ label: d.name, value: d.id, edit: false, selected: false })) + const topData = { label: t('all'), value: -1, edit: false, selected: false } + labelsRef.current = [topData, ...newData] + setLabels(labelsRef.current) + }) + } + useEffect(() => { + AllLabelsApi(); + }, []) + const { page, pageSize, data: dataSource, total, loading, setPage, search, reload, refreshData } = useTable({ pageSize: 15 }, (param) => - getAssistantsApi(param.page, param.pageSize, param.keyword) + getAssistantsApi(param.page, param.pageSize, param.keyword, param.tag_id) ) if(dataSource == "" || dataSource[0].type != 0){ @@ -106,11 +124,25 @@ export default function Assistants() { // })) return captureAndAlertRequestErrorHoc(changeAssistantStatusApi(item.id, bln ? 1 : 0)).then(res => { if (res === null) { + reload(); refreshData((item1) => item1.id === item.id, { status: bln ? 1 : 0 }) } return res }) }; + + const isOperator = useMemo(() => { + if(item && user) { + if(user.role === 'admin') return true + if(item.group_ids == undefined) return true + item.group_ids.forEach(element => { + if(user.admin_groups.includes(element)) return true + }) + if(item.user_id === user.user_id) return true + } + return false + },[item, user]) + return( {item.type == 0 ? @@ -156,6 +188,15 @@ export default function Assistants() {

{item.name}

{item.desc}

+
+ 0} isOperator={isOperator} + resource={{id:item.id, type:"assist"}} + labels={item.tags.map(d => ({label:d.name, value:d.id, selected:true, edit:false}))} + reload={reload} + AllLabelsApi={AllLabelsApi} + all={labels.filter(a => a.value !== -1)}> + +
{!openSwitch &&
item.status !== 1 && navigate('/assistant/' + item.id,{state: { value:inputRef.current.value, page:page}})}> @@ -170,6 +211,9 @@ export default function Assistants() { {item.write &&
delConfirm(item)}>
} +
+ {item.user_name}创建 +
{/* */} !item.write && item.status !== 1 && message({ title: t('prompt'), description: t('skills.contactAdmin'), variant: 'warning' })} onCheckedChange={item.write && handleChange} /> diff --git a/src/pages/SkillPage/tabSkills.tsx b/src/pages/SkillPage/tabSkills.tsx index d06c765..90850f0 100644 --- a/src/pages/SkillPage/tabSkills.tsx +++ b/src/pages/SkillPage/tabSkills.tsx @@ -1,7 +1,7 @@ import SkillTempSheet from "@/components/bs-comp/sheets/SkillTempSheet"; 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 { useContext, useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useLocation, useNavigate } from "react-router-dom"; import CardComponent, { TitleIconBg } from "../../components/bs-comp/cardComponent"; @@ -37,6 +37,8 @@ import Templates from "./temps"; import { Size } from "recharts/types/util/types"; import SkillTemps from "./components/SkillTemps"; import nengliIcon from "../../assets/npc/nengliIcon.png"; +import LabelShow from "@/components/bs-comp/cardComponent/LabelShow"; +import { getAllLabelsApi } from "@/controllers/API/label"; export default function Skills() { const { t } = useTranslation() @@ -45,7 +47,7 @@ export default function Skills() { const navigate = useNavigate() const { page, pageSize, data: dataSource, total, loading, setPage, search, reload, refreshData } = useTable({ pageSize: 14 }, (param) => - readFlowsFromDatabase(param.page, param.pageSize, param.keyword) + readFlowsFromDatabase(param.page, param.pageSize, param.keyword, param.tag_id) ) if(dataSource == "" || dataSource[0].type != 0){ @@ -118,6 +120,22 @@ export default function Skills() { })) } + const [labels, setLabels] = useState([]) + const [selectLabel, setSelectLabel] = useState({ label: '', value: null }) + const labelsRef = useRef([]) + + const AllLabelsApi = () =>{ + getAllLabelsApi().then(res => { + const newData = res.data.map(d => ({ label: d.name, value: d.id, edit: false, selected: false })) + const topData = { label: t('all'), value: -1, edit: false, selected: false } + labelsRef.current = [topData, ...newData] + setLabels(labelsRef.current) + }) + } + useEffect(() => { + AllLabelsApi(); + }, []) + const nvaigate = useNavigate() const handleEdit = (id,pageNo) => { // onBeforeEdit?.() @@ -134,15 +152,33 @@ export default function Skills() { const [openSwitch, setOpenSwitch] = useState(item.status === 2); const handleChange = (bln) => { captureAndAlertRequestErrorHoc(updataOnlineState(item.id, item, bln).then(res => { - setOpenSwitch(bln); + // setOpenSwitch(bln); if (res) { + reload(); refreshData((item1) => item1.id === item.id, { status: bln ? 2 : 1 }) } return res - // loadPage(page.pageNo); - // itema.status = bln ? 2 : 1 })) }; + + const isOperator = useMemo(() => { + if(item && user) { + // if(user.role === 'admin') { + // item.group_ids.forEach(element => { + // if(user.admin_groups.includes(element)) return true + // }) + // } + if(user.role === 'admin') return true + if(item.group_ids){ + item.group_ids.forEach(element => { + if(user.admin_groups.includes(element)) return true + }) + } + if(item.user_id === user.user_id) return true + } + return false + },[item, user]) + return( {item.type == 0 ? @@ -172,6 +208,15 @@ export default function Skills() {

{item.name}

{item.description}

+
+ 0} isOperator={isOperator} + resource={{id:item.id, type:"skill"}} + labels={item.tags.map(d => ({label:d.name, value:d.id, selected:true, edit:false}))} + reload={reload} + AllLabelsApi={AllLabelsApi} + all={labels.filter(a => a.value !== -1)}> + +
{!openSwitch &&
handleSetting(item)}> @@ -190,6 +235,10 @@ export default function Skills() { {item.write &&
delConfirm(item)}>
} + +
+ {item.user_name}创建 +
{/* */} !item.write && item.status !== 2 && message({ title: t('prompt'), description: "请联系管理员上线能力", variant: 'warning' })} onCheckedChange={item.write && handleChange} /> diff --git a/src/style/zk.scss b/src/style/zk.scss index 5661490..94250ce 100644 --- a/src/style/zk.scss +++ b/src/style/zk.scss @@ -2712,7 +2712,7 @@ // justify-content:space-between; /* padding: 14px; */ // position: relative; - padding-bottom: 55px; + padding-bottom: 50px; >div:nth-of-type(2){ display: flex; align-items: center; @@ -2733,6 +2733,33 @@ margin-top: 8px; } >div:nth-of-type(3){ + + } + .biaoqian{ + width: 100%; + display: flex; + align-items: center; + padding-left: 14px; + margin-top: 14px; + // position: absolute; + // bottom: 55px; + >div{ + display: flex; + align-items: center; + >div{ + padding: 2px 6px; + // height: 16px; + margin-right: 7px; + background: rgba(255, 213, 76, 0.15); + border-radius: 8px; + font-family: PingFang SC; + font-weight: 400; + font-size: 9px; + color: #CCA31B; + } + } + } + >div:nth-of-type(4){ width: 100%; display: flex; justify-content: space-between; @@ -3845,7 +3872,16 @@ height: 15px!important; border: 1px solid #ffd025!important; } - + .biaoqianTab .data-\[state\=checked\]\:bg-primary[data-state=checked]{ + width: 15px!important; + height: 15px!important; + background: #ffd025!important; + } + .biaoqianTab button{ + width: 15px!important; + height: 15px!important; + border: 1px solid #ffd025!important; + } .build-tab{ display: flex; @@ -4009,6 +4045,24 @@ // border: none!important; outline: 1px solid #997e1f!important; } + .npcInput2{ + background: #0F0F0F!important; + border-radius: 17px!important; + outline: none!important; + --tw-ring-color:none!important; + border: none!important; + --tw-ring-offset-color:none!important; + color: #fff!important; + + &::-webkit-input-placeholder{ + color: #666!important; + } + // outline: #997e1f; + &:focus{ + // border: none!important; + outline: 1px solid #997e1f!important; + } + } } .npcInput4{ background: #000000!important; @@ -4194,16 +4248,23 @@ } } } + + /* 修改垂直滚动条的颜色 */ ::-webkit-scrollbar { - width: 0; + width: 10px; /* 设置滚动条的宽度 */ + height: 10px; } - ::-webkit-scrollbar-horizontal { + + ::-webkit-scrollbar-track { + // background-color: #666; /* 设置滚动条的背景颜色 */ display: none; } + ::-webkit-scrollbar-thumb { - display: none; + background-color: #333; /* 设置滚动条的颜色 */ + border-radius: 20px; } - + .SelectTrigger{ background: rgba(255, 255, 255, 0.05); border-radius: 14px!important; @@ -4257,4 +4318,9 @@ } .bg-reset{ box-shadow: 0px 3px 14px 0px rgba(255,255,255,0.2)!important; + } + .chatHomeInput{ + input{ + width: 100%!important; + } } \ No newline at end of file diff --git a/src/util/hook.ts b/src/util/hook.ts index 7d13f96..b7d1f07 100644 --- a/src/util/hook.ts +++ b/src/util/hook.ts @@ -109,7 +109,8 @@ export function useTable(param, apiFun) { // 数据过滤 filterData: (p) => { paramRef.current = { ...paramRef.current, ...p }; - setPage({ ...page, page: 1 }); + // setPage({ ...page, page: 1 }); + page.page === 1 ? loadData() : setPage({ ...page, page: 1 }); }, // 更新数据 refreshData: (compareFn, data) => {