import {useContext, useEffect, useRef, useState} from "react"; import {GlobalContext} from "../../context/GlobalContext.ts"; import {get, post, put, WebSocketBaseUrl} 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"; type PropsType = { projId: string; projIntroduction?: string; projDesc?: string; projMods?: ProjModType[]; } 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 ping = () => { clearTimeout(pingTimeout.current); pingTimeout.current = setTimeout(() => { if (!ws.current) { return; } ws.current.send("PING"); ping(); }, 3000); } const websocket = () => { ws.current = new WebSocket(`${WebSocketBaseUrl}/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[]; 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); } }) }} /> ) }