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 L2ParameterComponent from "../../CustomNodes/GenericNode/components/parameterComponent/l2Index"; import ShadTooltip from "../../components/ShadTooltipComponent"; import { Button } from "../../components/ui/button"; import { Input } from "../../components/ui/input"; import { Label } from "../../components/ui/label"; import { Textarea } from "../../components/ui/textarea"; import { alertContext } from "../../contexts/alertContext"; import { TabsContext } from "../../contexts/tabsContext"; import { userContext } from "../../contexts/userContext"; import { createCustomFlowApi, getFlowApi } from "../../controllers/API/flow"; import { useHasForm } from "../../util/hook"; import FormSet from "./components/FormSet"; import { captureAndAlertRequestErrorHoc } from "../../controllers/request"; import shangchuan from "../../assets/npc/shangchuan.png"; import shou from "../../assets/npc/shou.png"; import huifumoren from "../../assets/npc/huifumoren.png"; import nengliIcon from "../../assets/npc/nengliIcon.png"; import robot from "../../assets/robot.png"; import { uploadFileWithProgress, uploadNpcHeaderLibFileWithProgress } from "../../modals/UploadModal/upload"; import { TitleIconBg, gradients } from "@/components/bs-comp/cardComponent"; export default function l2Edit() { const { t } = useTranslation() const { id } = useParams() const { flow: nextFlow, setFlow, saveFlow } = useContext(TabsContext); const { setErrorData, setSuccessData } = useContext(alertContext); const flow = useMemo(() => { return id ? nextFlow : null }, [nextFlow]) console.log(flow,'flow') const [isL2, setIsL2] = useState(false) const [loading, setLoading] = useState(false) const nameRef = useRef(null) const descRef = useRef(null) const guideRef = useRef(null) const [logo, setLogo] = useState("") const randomNum = Math.floor(Math.random()*(4-0+1)+0); useEffect(() => { // 无id不再请求 if (!id) return // 已有flow 数据时,不再请求 if (flow?.id === id) { setIsL2(true) nameRef.current.value = flow.name descRef.current.value = flow.description guideRef.current.value = flow.guide_word setLogo(flow.logo) return } // 无flow从db获取 getFlowApi(id).then(_flow => { // 回填flow setFlow('l2 flow init', _flow) setIsL2(true) nameRef.current.value = _flow.name descRef.current.value = _flow.description guideRef.current.value = _flow.guide_word setLogo(_flow.logo) }) }, [id]) // 校验 const { user } = useContext(userContext); const [error, setError] = useState({ name: false, desc: false }) // 表单error信息展示 const isParamError = (name, desc, showErrorConfirm = false) => { const errorlist = []; if (!name) errorlist.push(t('skills.skillNameRequired')); if (name.length > 30) errorlist.push(t('skills.skillNameTooLong')); // Duplicate name validation const nameErrors = errorlist.length; if (!desc) errorlist.push(t('skills.skillDescRequired')); if (desc.length > 200) errorlist.push(t('skills.skillDescTooLong')); if (errorlist.length && showErrorConfirm) setErrorData({ title: t('skills.errorTitle'), list: errorlist, }); setError({ name: !!nameErrors, desc: errorlist.length > nameErrors }); return !!errorlist.length; } const navigate = useNavigate() // 创建新技能 const handleCreateNewSkill = async () => { const name = nameRef.current.value const guideWords = guideRef.current.value const description = descRef.current.value const avatar_img = logo const avatar_color = gradients[randomNum] if (isParamError(name, description, true)) return setLoading(true) await captureAndAlertRequestErrorHoc(createCustomFlowApi({ name, description, guide_word: guideWords, avatar_img, avatar_color }, user.user_name).then(newFlow => { setFlow('l2 create flow', newFlow) navigate("/flow/" + newFlow.id, { replace: true }); // l3 })) setLoading(false) } const formRef = useRef(null) // 编辑回填参数 const handleJumpFlow = async () => { const name = nameRef.current.value const description = descRef.current.value const guideWords = guideRef.current.value // 高级配置信息有误直接跳转L3 if (isParamError(name, description)) return navigate('/flow/' + id, { replace: true }) // 保存在跳 setLoading(true) formRef.current?.save() await saveFlow({...flow, name, description, guide_word: guideWords}, true) setLoading(false) navigate('/flow/' + id, { replace: true }) } const handleSave = async () => { const name = nameRef.current.value const description = descRef.current.value const guideWords = guideRef.current.value const avatar_img = logo const avatar_color = gradients[randomNum] // const logo = flow.logo if (isParamError(name, description)) return setLoading(true) formRef.current?.save() console.log(flow,name,description,guideWords,logo) await saveFlow({...flow, name, description, guide_word: guideWords, avatar_img, avatar_color}, true) setLoading(false) setSuccessData({ title: t('success') }); setTimeout(() => /^\/skill\/[\w\d-]+/.test(location.pathname) && navigate(-1), 2000); } // 表单收缩 const showContent = (e) => { console.log(e,e.target.tagName) const target = e.target.tagName === 'IMG' ? e.target.parentNode : e.target const contentDom = target.nextSibling console.log(target) target.children[1].style.transform = contentDom.clientHeight ? 'rotate(180deg)' : 'rotate(0deg)' contentDom.style.display = contentDom.clientHeight ? 'none' : 'block' } // isForm const isForm = useHasForm(flow) const handleButtonClick = () => { // Create a file input element const input = document.createElement("input"); input.type = "file"; input.accept = "image/*"; input.style.display = "none"; // Hidden from view input.multiple = false; // Allow only one file selection input.onchange = (e: Event) => { setLoading(true); // Get the selected file const file = (e.target as HTMLInputElement).files?.[0]; // Check if the file type is correct // if (file && checkFileType(file.name)) { // Upload the file uploadNpcHeaderLibFileWithProgress(file, (progress) => { }).then(res => { // isSSO ? uploadFileWithProgress(file, (progress) => { }).then(res => { setLoading(false); if (typeof res === 'string') return setErrorData({ title: "Error", list: [res] }) const { file_path } = res; setLogo(file_path); // logo = file_path; // setMyValue(file.name); // onChange(file.name); // sets the value that goes to the backend // onFileChange(file_path); }) // uploadFile(file, flow.id) // .then((data) => { // console.log("File uploaded successfully"); // // Get the file name from the response // const { file_path } = data; // // Update the state and callback with the name of the file // // sets the value to the user // setMyValue(file.name); // onChange(file.name); // // sets the value that goes to the backend // onFileChange(file_path); // setLoading(false); // }) // .catch(() => { // console.error("Error occurred while uploading file"); // setLoading(false); // }); // } else { // // Show an error if the file type is not allowed // setErrorData({ // title: // "请选择有效文件。只允许使用这些文件类型:", // list: fileTypes, // }); // setLoading(false); // } }; // Trigger the file selection dialog input.click(); }; return
{t('skills.skillSettings')}
*/}基础信息
能力头像
能力名称
描述
引导词
参数信息
{t('skills.parameterInfo')}