Files
bishengWeb/src/pages/SkillPage/components/CreateAssistant.tsx
zhangkai 1c07d4b9df 1
2024-06-22 18:34:39 +08:00

175 lines
7.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { LoadIcon } from "../../../components/bs-icons/loading";
import { Button } from "../../../components/bs-ui/button";
import { DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "../../../components/bs-ui/dialog";
import { Input, Textarea } from "../../../components/bs-ui/input";
import { createAssistantsApi } from "../../../controllers/API/assistant";
import { captureAndAlertRequestErrorHoc } from "../../../controllers/request";
import { useTranslation } from "react-i18next";
import { TitleIconBg } from "@/components/bs-comp/cardComponent";
import { uploadFileWithProgress, uploadNpcHeaderLibFileWithProgress } from "../../../modals/UploadModal/upload";
import huifumoren from "../../../assets/npc/huifumoren.png";
import npcIcon from "../../../assets/npc/npcIcon.png";
export default function CreateAssistant() {
const { t } = useTranslation()
// State for form fields
const [formData, setFormData] = useState({
name: '',
roleAndTasks: `示例:
示例一
示例二
1. XX
2. XX
3. …`
});
const [loading, setLoading] = useState(false);
// State for errors
const [errors, setErrors] = useState<any>({});
// Validate form fields
const validateField = (name, value) => {
switch (name) {
case 'name':
if (!value) return t('build.nameRequired');
if (value.length > 50) return t('build.nameMaxLength');
return '';
case 'roleAndTasks':
if (value.length < 20) return t('build.forBetter');
return '';
default:
return '';
}
};
// Handle field change
const handleChange = (e) => {
const { name, value } = e.target;
const error = validateField(name, value);
setFormData(prev => ({ ...prev, [name]: value }));
setErrors(prev => ({ ...prev, [name]: error }));
};
// Validate entire form
const validateForm = () => {
const formErrors = {};
let isValid = true;
Object.keys(formData).forEach(key => {
const error = validateField(key, formData[key]);
if (error) {
formErrors[key] = error;
isValid = false;
}
});
setErrors(formErrors);
return isValid;
};
const [avatar_img, setAvatar_img] = useState("")
const [avatar_color, setAvatar_color] = useState("")
const randomNum = Math.floor(Math.random()*(4-0+1)+0).toString();
useEffect(() => {
if (avatar_color != "") return
setAvatar_color(randomNum);
}, [avatar_color]);
// Handle form submission
const navigate = useNavigate()
const handleSubmit = async (e) => {
e.preventDefault();
const isValid = validateForm();
if (isValid) {
console.log('Form data:', formData);
setLoading(true)
const res = await captureAndAlertRequestErrorHoc(createAssistantsApi(formData.name, formData.roleAndTasks, avatar_img, avatar_color))
if (res) {
window.assistantCreate = true // 标记新建助手
navigate('/assistant/' + res.id)
}
setLoading(false)
}
};
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
// Upload the file
uploadNpcHeaderLibFileWithProgress(file, (progress) => { }).then(res => {
setLoading(false);
setAvatar_img(res);
})
};
// Trigger the file selection dialog
input.click();
};
return <DialogContent className="sm:max-w-[625px] bg-[#262626]">
<DialogHeader>
<DialogTitle className="text-[#fff]">NPC</DialogTitle>
</DialogHeader>
<div className="flex flex-col gap-8 py-6">
<div>
<label htmlFor="name" className="bisheng-label text-[#999999]"><span className="bisheng-tip text-[#FF6060]">* </span>NPC头像</label>
{/* <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 : npcIcon} alt="" /></TitleIconBg> */}
<div className="flex items-center ml-[7px] mt-[6px]">
<TitleIconBg className="w-[41px] h-[41px] min-w-[41px]" img={avatar_img} id={avatar_color} ><img onClick={handleButtonClick} src={avatar_img ? avatar_img : npcIcon} alt="" /></TitleIconBg>
<div className="flex items-center justify-center ml-[20px] w-[95px] h-[27px] bg-[#333333] cursor-pointer" style={{borderRadius:"14px"}} onClick={() => setAvatar_img("")}>
<img src={huifumoren} className="w-[12px] h-[11px]" alt="" />
<span className="ml-[5px] text-[#999999] text-[12px] mt-[1px]"></span>
</div>
</div>
</div>
<div className="">
<label htmlFor="name" className="bisheng-label text-[#999999]"><span className="bisheng-tip text-[#FF6060]">* </span>NPC名称</label>
<Input id="name" name="name" placeholder="给NPC取一个名字" className="mt-2 npcInput" value={formData.name} onChange={handleChange} />
{errors.name && <p className="bisheng-tip mt-1 text-[#999999]"></p>}
</div>
<div className="">
<label htmlFor="roleAndTasks" className="bisheng-label text-[#999999]">NPC的角色是什么</label>
<Textarea
id="roleAndTasks"
name="roleAndTasks"
placeholder=""
maxLength={1000}
className="mt-2 min-h-32 npcInput overflow-auto scrollbar-hide"
value={formData.roleAndTasks}
onChange={handleChange}
/>
{errors.roleAndTasks && <p className="bisheng-tip mt-1">{errors.roleAndTasks}</p>}
</div>
</div>
{/* <DialogFooter>
<DialogClose>
<Button variant="outline" className="px-11 baogao-btn baogao-btn2" type="button" onClick={() => setFormData({ name: '', roleAndTasks: '' })}>取 消</Button>
</DialogClose>
<Button disabled={loading} type="submit" className="px-11 baogao-btn baogao-btn2" onClick={handleSubmit}>
{loading && <LoadIcon className="mr-2" />}
创 建</Button>
</DialogFooter> */}
<div className="flex justify-center ">
<DialogClose>
<Button variant="outline" className="px-11 baogao-btn baogao-btn2" type="button" onClick={() => setFormData({ name: '', roleAndTasks: '' })}> </Button>
</DialogClose>
<Button disabled={loading} type="submit" className="px-11 baogao-btn baogao-btn2" onClick={handleSubmit}>
{loading && <LoadIcon className="mr-2" />}
</Button>
</div>
</DialogContent>
};