import {useContext, useEffect, useRef, useState} from "react"; import {GlobalContext} from "../../context/GlobalContext.ts"; import {del, get, post, put, websocketUrl} from "../../util/AjaxUtils.ts"; import {Col, Divider, Row, Spin} from "antd"; import useMessage from "antd/es/message/useMessage"; import AiHelperText from "./text/AiHelperText.tsx"; import AiHelperMod from "./mod/AiHelperMod.tsx"; import {IProjMod} from "../../interfaces/proj/IProj.ts"; import {MAX_MOD_SIZE} from "../../route/proj/edit/ProjConfigModList.tsx"; import {useNavigate} from "react-router-dom"; import {uuid} from "../../util/CommonUtil.ts"; type PropsType = { projId: string; projIntroduction?: string; projDesc?: string; isFree: boolean; } type ProjModType = { id: string, name: string, desc: string } export default function AiHelper(props: PropsType) { const globalContext = useContext(GlobalContext); const pingTimeout = useRef(-1); const ws = useRef(null); const [messageApi, messageApiHolder] = useMessage(); const [projIntroduction, setProjIntroduction] = useState(props.projIntroduction ? props.projIntroduction : ''); const [newProjIntroduction, setNewProjIntroduction] = useState(''); const [isProjIntroductionLoading, setIsProjIntroductionLoading] = useState(false); const [projDesc, setProjDesc] = useState(props.projDesc ? props.projDesc : ''); const [newProjDesc, setNewProjDesc] = useState(''); const [isProjDescLoading, setIsProjDescLoading] = useState(false); const [projModArray, setProjModArray] = useState([]); const [newProjModArray, setNewProjModArray] = useState([]); const [isProjModArrayLoading, setIsProjModArrayLoading] = useState(false); const nav = useNavigate(); const ping = () => { clearTimeout(pingTimeout.current); pingTimeout.current = setTimeout(() => { if (!ws.current) { return; } ws.current.send("PING"); ping(); }, 3000); } const websocket = () => { ws.current = new WebSocket(`${websocketUrl()}/ws/ai/${globalContext.user.userId}`); ws.current.onopen = (event) => { console.log('打开', event); ping(); } ws.current.onmessage = (event) => { if (event.data == 'PONE') { return; } const data = JSON.parse(event.data); if (data.projId != props.projId) { return; } if (data.type == 'REFRESH_PROJ_INTRODUCTION') { setIsProjIntroductionLoading(false); setNewProjIntroduction(data.content); } else if (data.type == 'REFRESH_PROJ_DESC') { setIsProjDescLoading(false); setNewProjDesc(data.content); } else if (data.type == 'REFRESH_PROJ_MODS') { setIsProjModArrayLoading(false); const projMods = JSON.parse(data.content) as ProjModType[]; projMods.forEach(projMod => projMod.id = uuid()) setNewProjModArray(projMods); } else if (data.type == 'REFRESH_PROJ_MOD_FIELDS') { listMods(); } } ws.current.onerror = (event) => { console.log('error', event); } ws.current.onclose = (event) => { console.log('close', event); websocket() } } const listMods = () => { get({ messageApi, url: `/api/proj-mod/list/proj-id/${props.projId}`, onBefore() { setIsProjModArrayLoading(true); }, onSuccess({data}) { setProjModArray(data); }, onFinally() { setIsProjModArrayLoading(false); } }) } const generateProjIntroduction = () => { ws.current?.send(JSON.stringify({ type: 'REFRESH_PROJ_INTRODUCTION', projId: props.projId })); ping(); setIsProjIntroductionLoading(true); } const generateProjDesc = () => { ws.current?.send(JSON.stringify({ type: 'REFRESH_PROJ_DESC', projId: props.projId })); ping(); setIsProjDescLoading(true); } const generateProjModArray = () => { ws.current?.send(JSON.stringify({ type: 'REFRESH_PROJ_MODS', projId: props.projId })); ping(); setIsProjModArrayLoading(true); } /** * 保存简介 */ const updateProjIntroduction = (content: string) => { put({ messageApi, url: `/api/proj/update-introduction/${props.projId}`, body: { content: content }, onBefore() { setIsProjIntroductionLoading(true); }, onSuccess() { messageApi.success('保存成功'); setProjIntroduction(content); setNewProjIntroduction(''); }, onFinally() { setIsProjIntroductionLoading(false) } }) } /** * 保存详情 */ const updateProjDesc = (content: string) => { put({ messageApi, url: `/api/proj/update-desc/${props.projId}`, body: { content: content }, onBefore() { setIsProjDescLoading(true); }, onSuccess() { messageApi.success('保存成功').then(); setProjDesc(content); setNewProjDesc(''); }, onFinally() { setIsProjDescLoading(false) } }) } useEffect(() => { if (!props.projId) { return; } listMods(); websocket(); }, [globalContext.user.userId, props.projId]); return ( <> {messageApiHolder} { generateProjIntroduction(); }} handleSave={(text) => { updateProjIntroduction(text); }} /> { generateProjDesc(); }} handleSave={(text) => { updateProjDesc(text); }} /> { generateProjModArray(); }} handleSave={(index, mod) => { if(projModArray.length > MAX_MOD_SIZE) { messageApi.error(`模块最大数量为${MAX_MOD_SIZE}`); return; } post({ messageApi, url: `/api/proj-mod/save-ai/${props.projId}`, body: { name: mod.name, desc: mod.desc, }, onBefore() { setIsProjModArrayLoading(true); }, onSuccess() { messageApi.success('提交成功') listMods(); newProjModArray.splice(index, 1); setNewProjModArray([ ...newProjModArray ]); }, onFinally() { setIsProjModArrayLoading(false); } }) }} handleResaveField={(_index, projModId) => { post({ messageApi, url: `/api/proj-mod/resave-ai-field/${props.projId}/${projModId}`, onBefore() { setIsProjModArrayLoading(true); }, onSuccess() { messageApi.success('提交成功') listMods(); }, onFinally() { setIsProjModArrayLoading(false); } }) }} handleEdit={(_index, projModId, item) => { if(item.aiFieldStatus != 'SUCCESS') { messageApi.error('模块未处理完毕不能编辑'); return; } if(props.isFree) { nav(`/proj-edit/config-mod-fedit/${props.projId}/${projModId}`) } else { nav(`/proj-edit/config-mod-edit/${props.projId}/${projModId}`) } }} handleRemove={(_index, projModId, item) => { if(item.aiFieldStatus != 'SUCCESS') { messageApi.error('模块未处理完毕不能删除'); return; } del({ messageApi, url: `/api/proj-mod/remove/proj-id/${props.projId}/${projModId}`, onBefore() { setIsProjModArrayLoading(true); }, onSuccess() { messageApi.success('删除成功'); listMods(); }, onFinally() { setIsProjModArrayLoading(false); } }) }} /> ) }