chore: rename web_ui dir to web

This commit is contained in:
Junyan Qin
2025-04-28 21:41:03 +08:00
parent 5c74bb41c9
commit 2eaac168dc
81 changed files with 0 additions and 1 deletions

View File

@@ -0,0 +1,39 @@
import {BotCardVO} from "@/app/home/bots/components/bot-card/BotCardVO";
import styles from "./botCard.module.css";
export default function BotCard({
botCardVO
}: {
botCardVO: BotCardVO;
}) {
return (
<div className={`${styles.cardContainer}`}>
{/* icon和基本信息 */}
<div className={`${styles.iconBasicInfoContainer}`}>
{/* icon */}
<div className={`${styles.icon}`}>
ICO
</div>
{/* bot基本信息 */}
<div className={`${styles.basicInfoContainer}`}>
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
{botCardVO.name}
</div>
<div className={`${styles.basicInfoText}`}>
{botCardVO.adapter}
</div>
<div className={`${styles.basicInfoText}`}>
线{botCardVO.pipelineName}
</div>
</div>
</div>
{/* 描述和创建时间 */}
<div className={`${styles.urlAndUpdateText}`}>
{botCardVO.description}
</div>
{/* <div className={`${styles.urlAndUpdateText}`}>
更新时间:{botCardVO.updateTime}
</div> */}
</div>
)
}

View File

@@ -0,0 +1,28 @@
export interface IBotCardVO {
id: string;
name: string;
adapter: string;
description: string;
updateTime: string;
pipelineName: string;
}
export class BotCardVO implements IBotCardVO {
id: string;
adapter: string;
description: string;
name: string;
updateTime: string;
pipelineName: string;
constructor(props: IBotCardVO) {
this.id = props.id;
this.name = props.name;
this.adapter = props.adapter;
this.description = props.description;
this.updateTime = props.updateTime;
this.pipelineName = props.pipelineName;
}
}

View File

@@ -0,0 +1,67 @@
.iconBasicInfoContainer {
width: 300px;
height: 100px;
margin-left: 20px;
display: flex;
flex-direction: row;
}
.cardContainer {
width: 360px;
height: 200px;
background-color: #FFF;
border-radius: 9px;
box-shadow: rgba(0, 0, 0, 0.4) 0 1px 1px -1px;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-evenly;
}
.iconBasicInfoContainer {
width: 300px;
height: 100px;
margin-left: 20px;
display: flex;
flex-direction: row;
}
.icon {
width: 90px;
height: 90px;
border-radius: 5px;
font-size: 40px;
line-height: 90px;
text-align: center;
color: #ffffff;
background: rgba(96, 149, 209, 0.31);
border: 1px solid rgba(96, 149, 209, 0.31);
}
.basicInfoContainer {
width: 200px;
height: 90px;
padding-left: 20px;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
}
.basicInfoText {
}
.bigText {
font-size: 20px;
}
.urlAndUpdateText {
margin-left: 20px;
}
.createCardContainer {
font-size: 90px;
background: #6062E7;
color: white;
}

View File

@@ -0,0 +1,292 @@
import {
BotFormEntity,
IBotFormEntity
} from "@/app/home/bots/components/bot-form/BotFormEntity";
import { Button, Form, Input, notification, Select, Space } from "antd";
import { useEffect, useState } from "react";
import { IChooseAdapterEntity } from "@/app/home/bots/components/bot-form/ChooseAdapterEntity";
import {
DynamicFormItemConfig,
IDynamicFormItemConfig,
parseDynamicFormItemType
} from "@/app/home/components/dynamic-form/DynamicFormItemConfig";
import { UUID } from "uuidjs";
import DynamicFormComponent from "@/app/home/components/dynamic-form/DynamicFormComponent";
import { httpClient } from "@/app/infra/http/HttpClient";
import { Bot } from "@/app/infra/api/api-types";
export default function BotForm({
initBotId,
onFormSubmit,
onFormCancel
}: {
initBotId?: string;
onFormSubmit: (value: IBotFormEntity) => void;
onFormCancel: (value: IBotFormEntity) => void;
}) {
const [adapterNameToDynamicConfigMap, setAdapterNameToDynamicConfigMap] =
useState(new Map<string, IDynamicFormItemConfig[]>());
const [form] = Form.useForm<IBotFormEntity>();
const [showDynamicForm, setShowDynamicForm] = useState<boolean>(false);
const [dynamicForm] = Form.useForm();
const [adapterNameList, setAdapterNameList] = useState<
IChooseAdapterEntity[]
>([]);
const [dynamicFormConfigList, setDynamicFormConfigList] = useState<
IDynamicFormItemConfig[]
>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
useEffect(() => {
initBotFormComponent();
if (initBotId) {
onEditMode();
} else {
onCreateMode();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function initBotFormComponent() {
// 拉取adapter
const rawAdapterList = await httpClient.getAdapters();
// 初始化适配器选择列表
setAdapterNameList(
rawAdapterList.adapters.map((item) => {
return {
label: item.label.zh_CN,
value: item.name
};
})
);
// 初始化适配器表单map
rawAdapterList.adapters.forEach((rawAdapter) => {
adapterNameToDynamicConfigMap.set(
rawAdapter.name,
rawAdapter.spec.config.map(
(item) =>
new DynamicFormItemConfig({
default: item.default,
id: UUID.generate(),
label: item.label,
name: item.name,
required: item.required,
type: parseDynamicFormItemType(item.type)
})
)
);
});
// 拉取初始化表单信息
if (initBotId) {
getBotFieldById(initBotId).then((val) => {
form.setFieldsValue(val);
handleAdapterSelect(val.adapter);
dynamicForm.setFieldsValue(val.adapter_config);
});
} else {
form.resetFields();
}
setAdapterNameToDynamicConfigMap(adapterNameToDynamicConfigMap);
}
async function onCreateMode() {}
function onEditMode() {}
async function getBotFieldById(botId: string): Promise<IBotFormEntity> {
const bot = (await httpClient.getBot(botId)).bot;
return new BotFormEntity({
adapter: bot.adapter,
description: bot.description,
name: bot.name,
adapter_config: bot.adapter_config
});
}
function handleAdapterSelect(adapterName: string) {
console.log("Select adapter: ", adapterName);
if (adapterName) {
const dynamicFormConfigList =
adapterNameToDynamicConfigMap.get(adapterName);
console.log(dynamicFormConfigList);
if (dynamicFormConfigList) {
setDynamicFormConfigList(dynamicFormConfigList);
}
setShowDynamicForm(true);
} else {
setShowDynamicForm(false);
}
}
function handleSubmitButton() {
form.submit();
}
function handleFormFinish() {
dynamicForm.submit();
}
// 只有通过外层固定表单验证才会走到这里,真正的提交逻辑在这里
function onDynamicFormSubmit(value: object) {
setIsLoading(true);
console.log("set loading", true);
if (initBotId) {
// 编辑提交
console.log("submit edit", form.getFieldsValue(), value);
const updateBot: Bot = {
uuid: initBotId,
name: form.getFieldsValue().name,
description: form.getFieldsValue().description,
adapter: form.getFieldsValue().adapter,
adapter_config: value
};
httpClient
.updateBot(initBotId, updateBot)
.then((res) => {
// TODO success toast
console.log("update bot success", res);
onFormSubmit(form.getFieldsValue());
notification.success({
message: "更新成功",
description: "机器人更新成功"
});
})
.catch(() => {
// TODO error toast
notification.error({
message: "更新失败",
description: "机器人更新失败"
});
})
.finally(() => {
setIsLoading(false);
form.resetFields();
dynamicForm.resetFields();
});
} else {
// 创建提交
console.log("submit create", form.getFieldsValue(), value);
const newBot: Bot = {
name: form.getFieldsValue().name,
description: form.getFieldsValue().description,
adapter: form.getFieldsValue().adapter,
adapter_config: value
};
httpClient
.createBot(newBot)
.then((res) => {
// TODO success toast
notification.success({
message: "创建成功",
description: "机器人创建成功"
});
console.log(res);
onFormSubmit(form.getFieldsValue());
})
.catch(() => {
// TODO error toast
notification.error({
message: "创建失败",
description: "机器人创建失败"
});
})
.finally(() => {
setIsLoading(false);
form.resetFields();
dynamicForm.resetFields();
});
}
setShowDynamicForm(false);
console.log("set loading", false);
// TODO 刷新bot列表
// TODO 关闭当前弹窗 Already closed @setShowDynamicForm(false)?
}
function handleSaveButton() {
form.submit();
}
return (
<div>
<Form
form={form}
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}
layout="vertical"
onFinish={handleFormFinish}
disabled={isLoading}
>
<Form.Item<IBotFormEntity>
label={"机器人名称"}
name={"name"}
rules={[{ required: true, message: "该项为必填项哦~" }]}
>
<Input
placeholder="为机器人取个好听的名字吧~"
style={{ width: 260 }}
></Input>
</Form.Item>
<Form.Item<IBotFormEntity>
label={"描述"}
name={"description"}
rules={[{ required: true, message: "该项为必填项哦~" }]}
>
<Input placeholder="简单描述一下这个机器人"></Input>
</Form.Item>
<Form.Item<IBotFormEntity>
label={"平台/适配器选择"}
name={"adapter"}
rules={[{ required: true, message: "该项为必填项哦~" }]}
>
<Select
style={{ width: 220 }}
onChange={(value) => {
handleAdapterSelect(value);
}}
options={adapterNameList}
/>
</Form.Item>
</Form>
{showDynamicForm && (
<DynamicFormComponent
form={dynamicForm}
itemConfigList={dynamicFormConfigList}
onSubmit={onDynamicFormSubmit}
/>
)}
<Space>
{!initBotId && (
<Button
type="primary"
htmlType="button"
onClick={handleSubmitButton}
loading={isLoading}
>
</Button>
)}
{initBotId && (
<Button
type="primary"
htmlType="submit"
onClick={handleSaveButton}
loading={isLoading}
>
</Button>
)}
<Button
htmlType="button"
onClick={() => {
onFormCancel(form.getFieldsValue());
}}
disabled={isLoading}
>
</Button>
</Space>
</div>
);
}

View File

@@ -0,0 +1,20 @@
export interface IBotFormEntity {
name: string,
description: string,
adapter: string,
adapter_config: object;
}
export class BotFormEntity implements IBotFormEntity {
adapter: string;
description: string;
name: string;
adapter_config: object;
constructor(props: IBotFormEntity) {
this.adapter = props.adapter;
this.description = props.description;
this.name = props.name;
this.adapter_config = props.adapter_config;
}
}

View File

@@ -0,0 +1,4 @@
export interface IChooseAdapterEntity {
label: string
value: string
}