hts/apps/staffai/app/[locale]/manage/new/create-form.tsx

566 lines
16 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.

"use client";
import React, { useEffect, useState } from 'react';
import { Button, Form, GetProp, Input, InputNumber, Modal, Select, Upload, UploadFile, UploadProps, message } from 'antd';
import { Loading } from "@/components/dashboard/loading";
import service, { UserDataStorageName } from '@/lib/http/service';
import toast from 'react-hot-toast';
import { StaffsInfo, addStaff } from '@/lib/http/staff';
import { useRouter } from 'next/navigation';
import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { useLocalStorage } from '@/lib/hooks/use-local-storage';
import { UserData } from '@/components/user-menu';
export interface CreateFormProps {
onCancel?: () => void;
onSubmit?: (values: StaffsInfo) => void;
createModalVisible?: boolean;
}
const FormItem = Form.Item;
const formLayout = {
labelCol: { span: 7 },
wrapperCol: { span: 13 },
};
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
const getBase64 = (file: FileType): Promise<string> =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = (error) => reject(error);
});
/**
* 添加节点
* @param fields
*/
const handleAdd = async (fields: StaffsInfo) => {
const hide = message.loading('正在添加');
try {
// fields.password = md5(fields.password)
// fields.user_alias = fields.user_name
console.log("----------:", fields)
let result = await addStaff({ ...fields });
console.log("---handleAdd-result------:", result)
hide();
message.success('添加成功');
return true;
} catch (error) {
hide();
message.error('添加失败请重试!');
return false;
}
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
const [form] = Form.useForm();
const [initLoading, setInitLoading] = useState(false);
const {
onSubmit,
onCancel,
createModalVisible,
} = props;
useEffect(() => {
if (form && !createModalVisible) {
form.resetFields();
}
}, [props.createModalVisible]);
const handleSubmit = () => {
if (!form) return;
form.submit();
};
// const handleFinish = (values: JobListItem) => {
// if (onSubmit) {
// onSubmit(values);
// }
// };
const [previewOpen, setPreviewOpen] = useState(false);
const [previewImage, setPreviewImage] = useState('');
const [urlImage, setURLImage] = useState('');
const [uploading, setUploading] = useState(false);
const [fileList, setFileList] = useState<UploadFile[]>([
// {
// uid: '-1',
// name: 'image.png',
// status: 'done',
// url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
// },
// {
// uid: '-xxx',
// percent: 50,
// name: 'image.png',
// status: 'uploading',
// url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
// },
// {
// uid: '-5',
// name: 'image.png',
// status: 'error',
// },
]);
const handleFinish = async (value: StaffsInfo) => {
console.log("onFinish ---", value);
await service.post('/api/v1/customer/create/staff', {
// "name":"我的AI员工1号", //员工名称(必填)
// "org_name":"主板销售部", //组织名称(必填)
// "tone":"亲切且专业", //语气
// "output_length":"简短", //回复长度
// "description":"销冠的潜质", //员工描述
// "avatar_url":"https://www.pic.com/avatar001.jpg" //头像URL
name: value.name,
org_name: value.org_name,
tone: value.tone,
output_length: value.output_length,
description: value.description,
avatar_url: value.avatar_url,
}, {
headers: {
// 'Authorization': token
}
}).then(function (result: any) {
console.log("result:", result)
if (result && result.header.code != 0) {
toast.error(result.header.message)
return
}
// setInitLoading(false);
// categoriesRef.current.values
const tags = result.data.list
// getNewListFunc(1)
}).catch((err) => {
// setInitLoading(false);
});
};
const handlePreview = async (file: UploadFile) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj as FileType);
}
setPreviewImage(file.url || (file.preview as string));
setPreviewOpen(true);
};
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
setFileList(newFileList);
console.log("=---handleChange----", newFileList)
// const formData = new FormData();
// fileList.forEach((file) => {
// formData.append('files[]', file as FileType);
// });
// setUploading(true);
// // You can use any AJAX library you like
// fetch(process.env.NEXT_PUBLIC_FILE_BASE + "/api/v1/customer/upload/file", {
// method: 'POST',
// body: formData,
// })
// .then((res) => res.json())
// .then(() => {
// setFileList([]);
// message.success('upload successfully.');
// })
// .catch(() => {
// message.error('upload failed.');
// })
// .finally(() => {
// setUploading(false);
// });
}
const uploadButton = (
<button style={{ border: 0, background: 'none' }} type="button">
<PlusOutlined />
<div style={{ marginTop: 8 }}>Upload</div>
</button>
);
const [userData, setUserData] = useLocalStorage(
UserDataStorageName,
{
auth_token: "",
id: 1,
login_ip: "",
login_time: 0,
role: "",
user_name: "",
first_name: "",
version: ""
} as UserData
)
const renderContent = () => {
return (
<>
<Form.Item label="版本">
<Select defaultValue="demo" disabled>
<Select.Option value="demo"></Select.Option>
<Select.Option value="demo2"></Select.Option>
</Select>
</Form.Item>
<Form.Item
label="设置组织名称"
name="org_name"
rules={[{ required: true }]}
>
<Input
// variant="borderless"
// className="placeholder:text-[#808080] "
// style={{
// background: "#F5F5F5",
// borderRadius: "0",
// // width: 360
// }}
placeholder="设置名称"
/>
</Form.Item>
<Form.Item
label="员工名称(必填)"
name="name"
rules={[{ required: true }]}
>
<Input
// variant="borderless"
// className="placeholder:text-[#808080] "
// style={{
// background: "#F5F5F5",
// borderRadius: "0",
// // width: 360
// }}
placeholder="设置名称"
/>
</Form.Item>
<Form.Item
label="语言模式"
name="language_mode"
// rules={[{ required: true }]}
>
<Select id="language_mode" placeholder={'请选择语言模式'}>
<Select.Option value="spoken language"></Select.Option>
</Select>
</Form.Item>
<Form.Item
label="回复语言类型"
name="language_response"
// rules={[{ required: true }]}
>
<Select id="language_response" placeholder={'请选择回复语言类型'}>
<Select.Option value="chinese"></Select.Option>
</Select>
</Form.Item>
<Form.Item
label="客服语气"
name="tone"
// rules={[{ required: true }]}
>
{/* communication tones交流语气友好且真诚friendly and sincere, 专业且稳重professional and cautious, 清晰且直接clear and direct */}
{/* defaultValue="friendly and sincere" */}
<Select id="tone" placeholder={'请选择语气'}>
<Select.Option value="friendly and sincere"></Select.Option>
<Select.Option value="professional and cautious"></Select.Option>
<Select.Option value="clear and direct"></Select.Option>
</Select>
</Form.Item>
<Form.Item
label="回答长度"
name="output_length"
// rules={[{ required: true }]}
>
<Select id="output_length" placeholder={'请选择回答长度'}>
<Select.Option value="short">()</Select.Option>
<Select.Option value="medium"></Select.Option>
<Select.Option value="longer"></Select.Option>
</Select>
</Form.Item>
<Form.Item
label="上传LOGO"
name="avatar_url"
// valuePropName="fileList"
// getValueFromEvent={(e) => {
// if (Array.isArray(e)) {
// return e;
// }
// return e && e.fileList;
// }}
// rules={[{ required: true }]}
>
{/* <Input
// variant="borderless"
// className="placeholder:text-[#808080] "
// style={{
// background: "#F5F5F5",
// borderRadius: "0",
// // width: 360
// }}
placeholder="设置Logo"
/> */}
<Upload
action={process.env.NEXT_PUBLIC_FILE_BASE + "/api/v1/customer/upload/file"}
// action="//jsonplaceholder.typicode.com/posts/"
accept='*'
listType="picture"
// headers={{"Authorization": 'Bearer ' + localStorage.getItem(UserDataStorageName)}}
// headers={{ "Authorization": localStorage.getItem(UserDataStorageName) }}
maxCount={1}
headers={{
"Authorization": userData.auth_token,
}}
data={(file) => {
// const formData = new FormData()
// formData.append('files[]', file as FileType)
return {
file_data: file,
file_name: file.name,
}
}}
defaultFileList={[...fileList]}
// name='file_data'
onPreview={handlePreview}
// onChange={handleChange}
onChange={(info) => {
console.log("-------info----", info)
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
message.success(`${info.file.name} file uploaded successfully`);
if (info.file.response.header.code === 0) {
setURLImage(info.file.response.data.file_url)
} else {
message.error(`${info.file.response.header.message}.`);
}
} else if (info.file.status === 'error') {
message.error(`${info.file.name} file upload failed.`);
}
setFileList(info.fileList);
// setFileList([
// ...fileList,
// ...info.fileList,
// {
// uid: info.file.originFileObj?.uid || "",
// name: info.file.name,
// status: 'done',
// url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
// }
// ]);
}}
// previewFile={(file) => {
// console.log('Your upload file:', file);
// // Your process logic. Here we just mock to the same file
// const formData = new FormData();
// // fileList.forEach((file) => {
// // formData.append('files[]', file as FileType);
// // });
// formData.append('files[]', file as FileType);
// return fetch(process.env.NEXT_PUBLIC_FILE_BASE + "/api/v1/customer/upload/file", {
// method: 'POST',
// body: formData,
// })
// .then((res) => res.json())
// .then(({ thumbnail }) => thumbnail);
// }}
beforeUpload={(file) => {
// setFileList([...fileList, file]);
return true;
}}
>
<Button icon={<UploadOutlined />}>Upload</Button>
</Upload>
<br />
</Form.Item >
<Form.Item label="问候语"
name="greetings"
>
<Input.TextArea
maxLength={512}
className=""
/>
</Form.Item>
<Form.Item label="员工描述"
name="description"
// wrapperCol={{
// offset: 2,
// span: 16
// }}
// validateStatus="error"
// hasFeedback
// help="Should have something"
>
<Input.TextArea
maxLength={1024}
// allowClear
// showCount
// style={{
// background: "#fff",
// borderRadius: "0",
// border: "none",
// height: "100px",
// }}
className=""
/>
</Form.Item>
{/* <Button type="primary" htmlType="submit" className="bg-[#000] w-full rounded">
创建AI客服
</Button> */}
<Form.Item wrapperCol={{ span: 12, offset: 12 }}>
<Button
// disabled={initLoading || !form.formState.isValid}
disabled={
initLoading
// ||
// !form.isFieldsTouched(true) ||
// !!form.getFieldsError().filter(({ errors }) => errors.length).length
}
className="mt-4 bg-[#000] text-[#fff]"
htmlType="submit"
>
{initLoading ? <Loading /> : "创建AI客服"}
</Button>
</Form.Item>
</>
);
};
const modalFooter = { okText: '保存', onOk: handleSubmit, onCancel };
const router = useRouter();
return (
// <Modal
// forceRender
// destroyOnClose
// title="新建职位信息"
// open={createModalVisible}
// {...modalFooter}
// >
// <Form
// {...formLayout}
// form={form}
// onFinish={handleFinish}
// >
// {renderContent()}
// </Form>
// </Modal>
<div>
<Form
{...formLayout}
form={form}
initialValues={{
tone: 'friendly and sincere',
output_length: 'short',
language_mode: 'spoken language',
language_response: 'chinese',
}}
onFinish={async (e: StaffsInfo) => {
// "name":"我的AI员工1号", //员工名称(必填)
// "org_name":"主板销售部", //组织名称(必填)
// "tone":"亲切且专业", //语气
// "language_mode":"口语", //语言模式
// "language_response":"中文", //回复语言类型
// "output_length":"简短", //回复长度
// "description":"销冠的潜质", //员工描述
// "avatar_url":"https://www.pic.com/avatar001.jpg" //头像URL
e.avatar_url = urlImage
console.log("-----onFinish--------", e)
if (await handleAdd(e)) {
// router.push("/manage/staffs")
window.location.href = `/manage/staffs`
}
}}
>
{renderContent()}
</Form>
</div>
);
};
export default CreateForm;