合并冲突

This commit is contained in:
chris
2025-04-29 15:32:06 +08:00
parent d42b29d673
commit 44b005ffdd
3 changed files with 200 additions and 370 deletions
+142 -136
View File
@@ -1,4 +1,4 @@
"use client" "use client";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import styles from "./botConfig.module.css"; import styles from "./botConfig.module.css";
@@ -8,155 +8,161 @@ import { BotCardVO } from "@/app/home/bots/components/bot-card/BotCardVO";
import { Modal, notification, Spin } from "antd"; import { Modal, notification, Spin } from "antd";
import BotForm from "@/app/home/bots/components/bot-form/BotForm"; import BotForm from "@/app/home/bots/components/bot-form/BotForm";
import BotCard from "@/app/home/bots/components/bot-card/BotCard"; import BotCard from "@/app/home/bots/components/bot-card/BotCard";
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent" import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent";
import { httpClient } from "@/app/infra/http/HttpClient"; import { httpClient } from "@/app/infra/http/HttpClient";
import { Bot } from "@/app/infra/api/api-types"; import { Bot } from "@/app/infra/api/api-types";
export default function BotConfigPage() { export default function BotConfigPage() {
const router = useRouter(); const router = useRouter();
const [pageShowRule, setPageShowRule] = useState<BotConfigPageShowRule>(BotConfigPageShowRule.NO_BOT) const [pageShowRule, setPageShowRule] = useState<BotConfigPageShowRule>(
const [modalOpen, setModalOpen] = useState<boolean>(false); BotConfigPageShowRule.NO_BOT
const [botList, setBotList] = useState<BotCardVO[]>([]) );
const [isEditForm, setIsEditForm] = useState(false) const [modalOpen, setModalOpen] = useState<boolean>(false);
const [nowSelectedBotCard, setNowSelectedBotCard] = useState<BotCardVO>() const [botList, setBotList] = useState<BotCardVO[]>([]);
const [isLoading, setIsLoading] = useState(false) const [isEditForm, setIsEditForm] = useState(false);
const [nowSelectedBotCard, setNowSelectedBotCard] = useState<BotCardVO>();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
// TODO:补齐加载转圈逻辑
setIsLoading(true);
checkHasLLM().then((hasLLM) => {
if (hasLLM) {
getBotList();
} else {
setPageShowRule(BotConfigPageShowRule.NO_LLM);
setIsLoading(false);
}
});
}, []);
useEffect(() => { async function checkHasLLM(): Promise<boolean> {
// TODO:补齐加载转圈逻辑 // NOT IMPL
setIsLoading(true) return true;
checkHasLLM().then((hasLLM) => { }
if (hasLLM) {
getBotList()
} else {
setPageShowRule(BotConfigPageShowRule.NO_LLM)
setIsLoading(false)
}
})
}, [])
async function checkHasLLM(): Promise<boolean> { function getBotList() {
// NOT IMPL httpClient
return true .getBots()
} .then((resp) => {
const botList: BotCardVO[] = resp.bots.map((bot: Bot) => {
return new BotCardVO({
adapter: bot.adapter,
description: bot.description,
id: bot.uuid || "",
name: bot.name,
updateTime: bot.updated_at || "",
pipelineName: bot.use_pipeline_name || ""
});
});
if (botList.length === 0) {
setPageShowRule(BotConfigPageShowRule.NO_BOT);
} else {
setPageShowRule(BotConfigPageShowRule.HAVE_BOT);
}
setBotList(botList);
})
.catch((err) => {
console.error("get bot list error", err);
// TODO HACK: need refactor to hook mode Notification, but it's not working under render
notification.error({
message: "获取机器人列表失败",
description: err.message,
placement: "bottomRight"
});
})
.finally(() => {
setIsLoading(false);
});
}
function getBotList() { function handleCreateBotClick() {
httpClient.getBots().then((resp) => { setIsEditForm(false);
const botList: BotCardVO[] = resp.bots.map((bot: Bot) => { setNowSelectedCard(undefined);
return new BotCardVO({ setModalOpen(true);
adapter: bot.adapter, }
description: bot.description,
id: bot.uuid || "",
name: bot.name,
updateTime: bot.updated_at || "",
pipelineName: bot.use_pipeline_name || "",
})
})
if (botList.length === 0) {
setPageShowRule(BotConfigPageShowRule.NO_BOT)
} else {
setPageShowRule(BotConfigPageShowRule.HAVE_BOT)
}
setBotList(botList)
}).catch((err) => {
console.error("get bot list error", err)
// TODO HACK: need refactor to hook mode Notification, but it's not working under render
notification.error({
message: "获取机器人列表失败",
description: err.message,
placement: "bottomRight",
})
}).finally(() => {
setIsLoading(false)
})
}
function handleCreateBotClick() { function setNowSelectedCard(cardVO: BotCardVO | undefined) {
setIsEditForm(false) setNowSelectedBotCard(cardVO);
setNowSelectedCard(undefined) }
setModalOpen(true);
}
function setNowSelectedCard(cardVO: BotCardVO | undefined) { function selectBot(cardVO: BotCardVO) {
setNowSelectedBotCard(cardVO) setIsEditForm(true);
} setNowSelectedCard(cardVO);
console.log("set now vo", cardVO);
setModalOpen(true);
}
function selectBot(cardVO: BotCardVO) { return (
setIsEditForm(true) <div className={styles.configPageContainer}>
setNowSelectedCard(cardVO) <Spin spinning={isLoading} tip="加载中..." size="large">
console.log("set now vo", cardVO) <Modal
setModalOpen(true) title={isEditForm ? "编辑机器人" : "创建机器人"}
} centered
open={modalOpen}
onOk={() => setModalOpen(false)}
onCancel={() => setModalOpen(false)}
width={700}
footer={null}
destroyOnClose={true}
>
<BotForm
initBotId={nowSelectedBotCard?.id}
onFormSubmit={() => {
getBotList();
setModalOpen(false);
}}
onFormCancel={() => setModalOpen(false)}
/>
</Modal>
{pageShowRule === BotConfigPageShowRule.NO_LLM && (
<EmptyAndCreateComponent
title={"需要先创建大模型才能配置机器人哦~"}
subTitle={"快去创建一个吧!"}
buttonText={"创建大模型 GO"}
onButtonClick={() => {
router.push("/home/models");
}}
/>
)}
return ( {pageShowRule === BotConfigPageShowRule.NO_BOT && (
<div className={styles.configPageContainer}> <EmptyAndCreateComponent
title={"您还未配置机器人哦~"}
{/* 删除 spin,使用 spin 会导致盒子塌陷。 */} subTitle={"快去创建一个吧!"}
<Modal buttonText={"创建机器人 +"}
title={isEditForm ? "编辑机器人" : "创建机器人"} onButtonClick={handleCreateBotClick}
centered />
open={modalOpen} )}
onOk={() => setModalOpen(false)} </Spin>
onCancel={() => setModalOpen(false)} {/* 注意:其余的返回内容需要保持在Spin组件外部 */}
width={700} {pageShowRule === BotConfigPageShowRule.HAVE_BOT && (
footer={null} <div className={`${styles.botListContainer}`}>
destroyOnClose={true} {botList.map((cardVO) => {
> return (
<BotForm <div
initBotId={nowSelectedBotCard?.id} key={cardVO.id}
onFormSubmit={() => { onClick={() => {
getBotList() selectBot(cardVO);
setModalOpen(false) }}
}} >
onFormCancel={() => setModalOpen(false)} <BotCard botCardVO={cardVO} />
/> </div>
</Modal> );
{pageShowRule === BotConfigPageShowRule.NO_LLM && })}
<EmptyAndCreateComponent <CreateCardComponent
title={"需要先创建大模型才能配置机器人哦~"} height={200}
subTitle={"快去创建一个吧!"} plusSize={90}
buttonText={"创建大模型 GO"} onClick={handleCreateBotClick}
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
height={200}
plusSize={90}
onClick={handleCreateBotClick}
/>
</div>
}
</div> </div>
)}
) </div>
);
} }
enum BotConfigPageShowRule { enum BotConfigPageShowRule {
NO_LLM, NO_LLM,
NO_BOT, NO_BOT,
HAVE_BOT, HAVE_BOT
} }
@@ -1,228 +1,60 @@
"use client" "use client";
import { useState, useEffect } from "react";
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent"; import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent";
import { PluginCardVO } from "@/app/home/plugins/plugin-installed/PluginCardVO"; import { PluginCardVO } from "@/app/home/plugins/plugin-installed/PluginCardVO";
import { useEffect, useState } from "react";
import PluginCardComponent from "@/app/home/plugins/plugin-installed/plugin-card/PluginCardComponent"; import PluginCardComponent from "@/app/home/plugins/plugin-installed/plugin-card/PluginCardComponent";
import styles from "@/app/home/plugins/plugins.module.css"; import styles from "@/app/home/plugins/plugins.module.css";
import { Modal, Input } from "antd"; import { Modal, Input } from "antd";
import { GithubOutlined } from "@ant-design/icons"; import { GithubOutlined } from "@ant-design/icons";
import { httpClient } from "@/app/infra/http/HttpClient";
export default function PluginInstalledComponent() { export default function PluginInstalledComponent() {
const [pluginList, setPluginList] = useState<PluginCardVO[]>([]) const [pluginList, setPluginList] = useState<PluginCardVO[]>([]);
const [modalOpen, setModalOpen] = useState(false) const [modalOpen, setModalOpen] = useState(false);
const [githubURL, setGithubURL] = useState("") const [githubURL, setGithubURL] = useState("");
useEffect(() => { useEffect(() => {
initData(); initData();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, []);
function initData() { function initData() {
getPluginList().then((value) => { getPluginList();
setPluginList(value)
})
} }
async function getPluginList() { function getPluginList() {
return [ httpClient.getPlugins().then((value) => {
new PluginCardVO({ setPluginList(
description: "一般的描述", value.plugins.map((plugin) => {
handlerCount: 0, return new PluginCardVO({
name: "插件AAA", author: plugin.author,
author: "/hana", description: plugin.description.zh_CN,
version: "0.1", handlerCount: 0,
isInitialized: false name: plugin.name,
}), version: plugin.version,
new PluginCardVO({ isInitialized: plugin.status === "initialized"
description: "一般的描述", });
handlerCount: 0, })
name: "插件AAA", );
author: "/hana", });
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}), new PluginCardVO({
description: "一般的描述",
handlerCount: 0,
name: "插件AAA",
author: "/hana",
version: "0.1",
isInitialized: false
}),
]
} }
function handleModalConfirm() { function handleModalConfirm() {
installPlugin(githubURL) installPlugin(githubURL);
setModalOpen(false) setModalOpen(false);
} }
function installPlugin(url: string) { function installPlugin(url: string) {
// TODO 接安装Plugin的接口 httpClient
console.log("installPlugin: ", url) .installPluginFromGithub(url)
.then(() => {
// 安装后重新拉取
getPluginList();
})
.catch((err) => {
console.log("error when install plugin:", err);
});
} }
return ( return (
<div className={`${styles.pluginListContainer}`}> <div className={`${styles.pluginListContainer}`}>
@@ -231,25 +63,19 @@ export default function PluginInstalledComponent() {
<div className={`${styles.modalTitle}`}> <div className={`${styles.modalTitle}`}>
<GithubOutlined <GithubOutlined
style={{ style={{
fontSize: '30px', fontSize: "30px",
marginRight: '20px' marginRight: "20px"
}} }}
type="setting"
/> />
<span> GitHub </span>
</div> </div>
} }
centered
open={modalOpen} open={modalOpen}
onOk={() => handleModalConfirm()} onOk={handleModalConfirm}
onCancel={() => setModalOpen(false)} onCancel={() => setModalOpen(false)}
width={500}
destroyOnClose={true} destroyOnClose={true}
> >
<div className={`${styles.modalBody}`}> <div className={`${styles.modalBody}`}>
<div> <div> GitHub </div>
GitHub
</div>
<Input <Input
placeholder="请输入插件的Github链接" placeholder="请输入插件的Github链接"
value={githubURL} value={githubURL}
@@ -257,20 +83,20 @@ export default function PluginInstalledComponent() {
/> />
</div> </div>
</Modal> </Modal>
{ {pluginList.map((vo, index) => {
pluginList.map((vo, index) => { return (
return <div key={index}> <div key={index}>
<PluginCardComponent cardVO={vo} /> <PluginCardComponent cardVO={vo} />
</div> </div>
}) );
} })}
<CreateCardComponent <CreateCardComponent
height={140} height={140}
plusSize={90} plusSize={90}
onClick={() => { onClick={() => {
setModalOpen(true) setModalOpen(true);
}} }}
/> />
</div> </div>
) );
} }
+12 -14
View File
@@ -26,7 +26,8 @@ import {
ApiRespSystemInfo, ApiRespSystemInfo,
ApiRespAsyncTasks, ApiRespAsyncTasks,
ApiRespAsyncTask, ApiRespAsyncTask,
ApiRespUserToken, MarketPluginResponse ApiRespUserToken,
MarketPluginResponse
} from "../api/api-types"; } from "../api/api-types";
import { notification } from "antd"; import { notification } from "antd";
@@ -50,22 +51,19 @@ export interface RequestConfig extends AxiosRequestConfig {
class HttpClient { class HttpClient {
private instance: AxiosInstance; private instance: AxiosInstance;
private disableToken: boolean = false private disableToken: boolean = false;
// 暂不需要SSR // 暂不需要SSR
// private ssrInstance: AxiosInstance | null = null // private ssrInstance: AxiosInstance | null = null
constructor( constructor(baseURL?: string, disableToken?: boolean) {
baseURL?: string,
disableToken?: boolean
) {
this.instance = axios.create({ this.instance = axios.create({
baseURL: baseURL || this.getBaseUrl(), baseURL: baseURL || this.getBaseUrl(),
timeout: 15000, timeout: 15000,
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json"
} }
}); });
this.disableToken = disableToken || false this.disableToken = disableToken || false;
this.initInterceptors(); this.initInterceptors();
} }
@@ -129,9 +127,9 @@ class HttpClient {
const errMessage = data?.message || error.message; const errMessage = data?.message || error.message;
switch (status) { switch (status) {
case 401: // case 401:
window.location.href = "/login"; // window.location.href = "/login";
break; // break;
case 403: case 403:
console.error("Permission denied:", errMessage); console.error("Permission denied:", errMessage);
break; break;
@@ -358,7 +356,7 @@ class HttpClient {
public getMarketPlugins( public getMarketPlugins(
page: number, page: number,
page_size: number, page_size: number,
query: string, query: string
): Promise<MarketPluginResponse> { ): Promise<MarketPluginResponse> {
return this.post(`/api/v1/market/plugins`, { return this.post(`/api/v1/market/plugins`, {
page, page,
@@ -366,7 +364,7 @@ class HttpClient {
query, query,
sort_by: "stars", sort_by: "stars",
sort_order: "DESC" sort_order: "DESC"
}) });
} }
public installPluginFromGithub( public installPluginFromGithub(
source: string source: string
@@ -415,4 +413,4 @@ class HttpClient {
export const httpClient = new HttpClient("https://version-4.langbot.dev"); export const httpClient = new HttpClient("https://version-4.langbot.dev");
// 临时写法,未来两种Client都继承自HttpClient父类,不允许共享方法 // 临时写法,未来两种Client都继承自HttpClient父类,不允许共享方法
export const spaceClient = new HttpClient("https://space.langbot.app") export const spaceClient = new HttpClient("https://space.langbot.app");