mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-21 09:47:13 +00:00
refactor: rename page routers
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export interface ICreateBotField {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
.configPageContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cardContainer {
|
||||
width: 420px;
|
||||
height: 220px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.botListContainer {
|
||||
align-self: flex-start;
|
||||
justify-self: flex-start;
|
||||
width: calc(100% - 60px);
|
||||
margin: auto;
|
||||
display: grid;
|
||||
grid-template-rows: repeat(auto-fill, minmax(220px, 1fr));
|
||||
grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
|
||||
gap: 15px;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
import {BotFormEntity, IBotFormEntity} from "@/app/home/bots/components/bot-form/BotFormEntity";
|
||||
import {fetchAdapterList} from "@/app/home/mock-api/index"
|
||||
import {Button, Form, Input, 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 {ICreateLLMField} from "@/app/home/models/ICreateLLMField";
|
||||
|
||||
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[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
initBotFormComponent()
|
||||
if (initBotId) {
|
||||
onEditMode()
|
||||
} else {
|
||||
onCreateMode()
|
||||
}
|
||||
}, [])
|
||||
|
||||
async function initBotFormComponent() {
|
||||
// 拉取adapter
|
||||
const rawAdapterList = await fetchAdapterList()
|
||||
// 初始化适配器选择列表
|
||||
setAdapterNameList(
|
||||
rawAdapterList.map(item => {
|
||||
return {
|
||||
label: item.label.zh_CN,
|
||||
value: item.name
|
||||
}
|
||||
})
|
||||
)
|
||||
// 初始化适配器表单map
|
||||
rawAdapterList.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)
|
||||
})
|
||||
} else {
|
||||
form.resetFields()
|
||||
}
|
||||
setAdapterNameToDynamicConfigMap(adapterNameToDynamicConfigMap)
|
||||
}
|
||||
|
||||
async function onCreateMode() {
|
||||
|
||||
}
|
||||
|
||||
function onEditMode() {
|
||||
|
||||
}
|
||||
|
||||
async function getBotFieldById(botId: string): Promise<IBotFormEntity> {
|
||||
return new BotFormEntity({
|
||||
adapter: "telegram",
|
||||
description: "模拟拉取bot",
|
||||
name: "模拟电报bot",
|
||||
adapter_config: {
|
||||
token: "aaabbbccc"
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function handleAdapterSelect(adapterName: string) {
|
||||
if (adapterName) {
|
||||
console.log(adapterNameToDynamicConfigMap)
|
||||
const dynamicFormConfigList = adapterNameToDynamicConfigMap.get(adapterName)
|
||||
if (dynamicFormConfigList) {
|
||||
console.log(dynamicFormConfigList)
|
||||
setDynamicFormConfigList(dynamicFormConfigList)
|
||||
}
|
||||
setShowDynamicForm(true)
|
||||
} else {
|
||||
setShowDynamicForm(false)
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubmitButton() {
|
||||
form.submit()
|
||||
}
|
||||
|
||||
function handleFormFinish(value: IBotFormEntity) {
|
||||
dynamicForm.submit()
|
||||
}
|
||||
|
||||
// 只有通过外层固定表单验证才会走到这里,真正的提交逻辑在这里
|
||||
function onDynamicFormSubmit(value: object) {
|
||||
if (initBotId) {
|
||||
// 编辑提交
|
||||
console.log('submit edit', form.getFieldsValue() ,value)
|
||||
} else {
|
||||
// 创建提交
|
||||
console.log('submit create', form.getFieldsValue() ,value)
|
||||
}
|
||||
onFormSubmit(form.getFieldsValue())
|
||||
setShowDynamicForm(false)
|
||||
form.resetFields()
|
||||
dynamicForm.resetFields()
|
||||
|
||||
}
|
||||
|
||||
function handleSaveButton() {
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{span: 5}}
|
||||
wrapperCol={{span: 18}}
|
||||
layout='vertical'
|
||||
onFinish={handleFormFinish}
|
||||
>
|
||||
<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}
|
||||
>
|
||||
提交
|
||||
</Button>
|
||||
}
|
||||
{
|
||||
initBotId &&
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
onClick={handleSaveButton}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
}
|
||||
<Button htmlType="button" onClick={() => {
|
||||
onFormCancel(form.getFieldsValue())
|
||||
}}>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface IChooseAdapterEntity {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
"use client"
|
||||
|
||||
import {useEffect, useState} from "react";
|
||||
import styles from "./botConfig.module.css";
|
||||
import EmptyAndCreateComponent from "@/app/home/components/empty-and-create-component/EmptyAndCreateComponent";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {BotCardVO} from "@/app/home/bots/components/bot-card/BotCardVO";
|
||||
import {Modal} from "antd";
|
||||
import BotForm from "@/app/home/bots/components/bot-form/BotForm";
|
||||
import BotCard from "@/app/home/bots/components/bot-card/BotCard";
|
||||
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent"
|
||||
|
||||
|
||||
export default function BotConfigPage() {
|
||||
const router = useRouter();
|
||||
const [pageShowRule, setPageShowRule] = useState<BotConfigPageShowRule>(BotConfigPageShowRule.NO_BOT)
|
||||
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
||||
const [botList, setBotList] = useState<BotCardVO[]>([])
|
||||
const [isEditForm, setIsEditForm] = useState(false)
|
||||
const [nowSelectedBotCard, setNowSelectedBotCard] = useState<BotCardVO>()
|
||||
|
||||
useEffect(() => {
|
||||
// TODO:补齐加载转圈逻辑
|
||||
checkHasLLM().then((hasLLM) => {
|
||||
if (hasLLM) {
|
||||
const botList = getBotList()
|
||||
if (botList.length === 0) {
|
||||
setPageShowRule(BotConfigPageShowRule.NO_BOT)
|
||||
} else {
|
||||
setPageShowRule(BotConfigPageShowRule.HAVE_BOT)
|
||||
}
|
||||
setBotList(botList)
|
||||
} else {
|
||||
setPageShowRule(BotConfigPageShowRule.NO_LLM)
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
async function checkHasLLM(): Promise<boolean> {
|
||||
// NOT IMPL
|
||||
return true
|
||||
}
|
||||
|
||||
function getBotList(): BotCardVO[] {
|
||||
let botList: BotCardVO[] = [
|
||||
new BotCardVO({
|
||||
adapter: "QQ bot",
|
||||
description: "1111",
|
||||
id: "1111",
|
||||
name: "第一个bot",
|
||||
updateTime: "202300001111",
|
||||
pipelineName: "默认流水线",
|
||||
}),
|
||||
new BotCardVO({
|
||||
adapter: "WX bot",
|
||||
description: "22211",
|
||||
id: "2222",
|
||||
name: "第2个bot",
|
||||
updateTime: "2025011011",
|
||||
pipelineName: "默认流水线",
|
||||
}),
|
||||
]
|
||||
// botList = []
|
||||
return botList
|
||||
}
|
||||
|
||||
function handleCreateBotClick() {
|
||||
setIsEditForm(false)
|
||||
setNowSelectedCard(undefined)
|
||||
setModalOpen(true);
|
||||
}
|
||||
|
||||
function setNowSelectedCard(cardVO: BotCardVO | undefined) {
|
||||
setNowSelectedBotCard(cardVO)
|
||||
}
|
||||
|
||||
function selectBot(cardVO: BotCardVO) {
|
||||
setIsEditForm(true)
|
||||
setNowSelectedCard(cardVO)
|
||||
console.log("set now vo", cardVO)
|
||||
setModalOpen(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.configPageContainer}>
|
||||
<Modal
|
||||
title={isEditForm ? "编辑机器人" : "创建机器人"}
|
||||
centered
|
||||
open={modalOpen}
|
||||
onOk={() => setModalOpen(false)}
|
||||
onCancel={() => setModalOpen(false)}
|
||||
width={700}
|
||||
footer={null}
|
||||
destroyOnClose={true}
|
||||
>
|
||||
<BotForm
|
||||
initBotId={nowSelectedBotCard?.id}
|
||||
onFormSubmit={() => setIsEditForm(false)}
|
||||
onFormCancel={() => setModalOpen(false)}
|
||||
/>
|
||||
</Modal>
|
||||
{pageShowRule === BotConfigPageShowRule.NO_LLM &&
|
||||
<EmptyAndCreateComponent
|
||||
title={"需要先创建大模型才能配置机器人哦~"}
|
||||
subTitle={"快去创建一个吧!"}
|
||||
buttonText={"创建大模型 GO!"}
|
||||
onButtonClick={() => {
|
||||
router.push("/home/models");
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
{pageShowRule === BotConfigPageShowRule.NO_BOT &&
|
||||
<EmptyAndCreateComponent
|
||||
title={"您还未配置机器人哦~"}
|
||||
subTitle={"快去创建一个吧!"}
|
||||
buttonText={"创建机器人 +"}
|
||||
onButtonClick={handleCreateBotClick}
|
||||
/>
|
||||
}
|
||||
|
||||
{pageShowRule === BotConfigPageShowRule.HAVE_BOT &&
|
||||
<div className={`${styles.botListContainer}`}
|
||||
>
|
||||
{botList.map(cardVO => {
|
||||
return (
|
||||
<div
|
||||
key={cardVO.id}
|
||||
onClick={() => {selectBot(cardVO)}}
|
||||
>
|
||||
<BotCard botCardVO={cardVO} />
|
||||
</div>)
|
||||
})}
|
||||
<CreateCardComponent
|
||||
width={360}
|
||||
height={200}
|
||||
plusSize={90}
|
||||
onClick={handleCreateBotClick}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
enum BotConfigPageShowRule {
|
||||
NO_LLM,
|
||||
NO_BOT,
|
||||
HAVE_BOT,
|
||||
}
|
||||
Reference in New Issue
Block a user