diff --git a/web/src/app/home/bots/page.tsx b/web/src/app/home/bots/page.tsx index a3570eaf..c2760b01 100644 --- a/web/src/app/home/bots/page.tsx +++ b/web/src/app/home/bots/page.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import { useEffect, useState } from "react"; 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 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" +import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent"; import { httpClient } from "@/app/infra/http/HttpClient"; import { Bot } from "@/app/infra/api/api-types"; export default function BotConfigPage() { - const router = useRouter(); - const [pageShowRule, setPageShowRule] = useState(BotConfigPageShowRule.NO_BOT) - const [modalOpen, setModalOpen] = useState(false); - const [botList, setBotList] = useState([]) - const [isEditForm, setIsEditForm] = useState(false) - const [nowSelectedBotCard, setNowSelectedBotCard] = useState() - const [isLoading, setIsLoading] = useState(false) + const router = useRouter(); + const [pageShowRule, setPageShowRule] = useState( + BotConfigPageShowRule.NO_BOT + ); + const [modalOpen, setModalOpen] = useState(false); + const [botList, setBotList] = useState([]); + const [isEditForm, setIsEditForm] = useState(false); + const [nowSelectedBotCard, setNowSelectedBotCard] = useState(); + const [isLoading, setIsLoading] = useState(false); + useEffect(() => { + // TODO:补齐加载转圈逻辑 + setIsLoading(true); + checkHasLLM().then((hasLLM) => { + if (hasLLM) { + getBotList(); + } else { + setPageShowRule(BotConfigPageShowRule.NO_LLM); + setIsLoading(false); + } + }); + }, []); - useEffect(() => { - // TODO:补齐加载转圈逻辑 - setIsLoading(true) - checkHasLLM().then((hasLLM) => { - if (hasLLM) { - getBotList() - } else { - setPageShowRule(BotConfigPageShowRule.NO_LLM) - setIsLoading(false) - } - }) - }, []) + async function checkHasLLM(): Promise { + // NOT IMPL + return true; + } - async function checkHasLLM(): Promise { - // NOT IMPL - return true - } + function getBotList() { + httpClient + .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() { - httpClient.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 handleCreateBotClick() { + setIsEditForm(false); + setNowSelectedCard(undefined); + setModalOpen(true); + } - function handleCreateBotClick() { - setIsEditForm(false) - setNowSelectedCard(undefined) - setModalOpen(true); - } + function setNowSelectedCard(cardVO: BotCardVO | undefined) { + setNowSelectedBotCard(cardVO); + } - function setNowSelectedCard(cardVO: BotCardVO | undefined) { - setNowSelectedBotCard(cardVO) - } + function selectBot(cardVO: BotCardVO) { + setIsEditForm(true); + setNowSelectedCard(cardVO); + console.log("set now vo", cardVO); + setModalOpen(true); + } - function selectBot(cardVO: BotCardVO) { - setIsEditForm(true) - setNowSelectedCard(cardVO) - console.log("set now vo", cardVO) - setModalOpen(true) - } + return ( +
+ + setModalOpen(false)} + onCancel={() => setModalOpen(false)} + width={700} + footer={null} + destroyOnClose={true} + > + { + getBotList(); + setModalOpen(false); + }} + onFormCancel={() => setModalOpen(false)} + /> + + {pageShowRule === BotConfigPageShowRule.NO_LLM && ( + { + router.push("/home/models"); + }} + /> + )} - return ( -
- - {/* 删除 spin,使用 spin 会导致盒子塌陷。 */} - setModalOpen(false)} - onCancel={() => setModalOpen(false)} - width={700} - footer={null} - destroyOnClose={true} - > - { - getBotList() - setModalOpen(false) - }} - onFormCancel={() => setModalOpen(false)} - /> - - {pageShowRule === BotConfigPageShowRule.NO_LLM && - { - router.push("/home/models"); - }} - /> - } - - {pageShowRule === BotConfigPageShowRule.NO_BOT && - - } - - {pageShowRule === BotConfigPageShowRule.HAVE_BOT && -
- {botList.map(cardVO => { - return ( -
{ selectBot(cardVO) }} - > - -
) - })} - -
- } + {pageShowRule === BotConfigPageShowRule.NO_BOT && ( + + )} + + {/* 注意:其余的返回内容需要保持在Spin组件外部 */} + {pageShowRule === BotConfigPageShowRule.HAVE_BOT && ( +
+ {botList.map((cardVO) => { + return ( +
{ + selectBot(cardVO); + }} + > + +
+ ); + })} +
- - ) + )} +
+ ); } enum BotConfigPageShowRule { - NO_LLM, - NO_BOT, - HAVE_BOT, -} \ No newline at end of file + NO_LLM, + NO_BOT, + HAVE_BOT +} diff --git a/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx b/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx index 39c2be86..b6e149ae 100644 --- a/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx +++ b/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx @@ -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 { 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 styles from "@/app/home/plugins/plugins.module.css"; import { Modal, Input } from "antd"; import { GithubOutlined } from "@ant-design/icons"; +import { httpClient } from "@/app/infra/http/HttpClient"; export default function PluginInstalledComponent() { - const [pluginList, setPluginList] = useState([]) - const [modalOpen, setModalOpen] = useState(false) - const [githubURL, setGithubURL] = useState("") - + const [pluginList, setPluginList] = useState([]); + const [modalOpen, setModalOpen] = useState(false); + const [githubURL, setGithubURL] = useState(""); useEffect(() => { initData(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, []); function initData() { - getPluginList().then((value) => { - setPluginList(value) - }) + getPluginList(); } - async function getPluginList() { - return [ - 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 - }), - 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 getPluginList() { + httpClient.getPlugins().then((value) => { + setPluginList( + value.plugins.map((plugin) => { + return new PluginCardVO({ + author: plugin.author, + description: plugin.description.zh_CN, + handlerCount: 0, + name: plugin.name, + version: plugin.version, + isInitialized: plugin.status === "initialized" + }); + }) + ); + }); } function handleModalConfirm() { - installPlugin(githubURL) - setModalOpen(false) + installPlugin(githubURL); + setModalOpen(false); } function installPlugin(url: string) { - // TODO 接安装Plugin的接口 - console.log("installPlugin: ", url) + httpClient + .installPluginFromGithub(url) + .then(() => { + // 安装后重新拉取 + getPluginList(); + }) + .catch((err) => { + console.log("error when install plugin:", err); + }); } return (
@@ -231,25 +63,19 @@ export default function PluginInstalledComponent() {
- 从 GitHub 安装插件
} - centered open={modalOpen} - onOk={() => handleModalConfirm()} + onOk={handleModalConfirm} onCancel={() => setModalOpen(false)} - width={500} destroyOnClose={true} >
-
- 目前仅支持从 GitHub 安装 -
+
目前仅支持从 GitHub 安装
- { - pluginList.map((vo, index) => { - return
+ {pluginList.map((vo, index) => { + return ( +
- }) - } + ); + })} { - setModalOpen(true) + setModalOpen(true); }} />
- ) + ); } diff --git a/web/src/app/infra/http/HttpClient.ts b/web/src/app/infra/http/HttpClient.ts index a8bb53cc..58462059 100644 --- a/web/src/app/infra/http/HttpClient.ts +++ b/web/src/app/infra/http/HttpClient.ts @@ -26,7 +26,8 @@ import { ApiRespSystemInfo, ApiRespAsyncTasks, ApiRespAsyncTask, - ApiRespUserToken, MarketPluginResponse + ApiRespUserToken, + MarketPluginResponse } from "../api/api-types"; import { notification } from "antd"; @@ -50,22 +51,19 @@ export interface RequestConfig extends AxiosRequestConfig { class HttpClient { private instance: AxiosInstance; - private disableToken: boolean = false + private disableToken: boolean = false; // 暂不需要SSR // private ssrInstance: AxiosInstance | null = null - constructor( - baseURL?: string, - disableToken?: boolean - ) { + constructor(baseURL?: string, disableToken?: boolean) { this.instance = axios.create({ baseURL: baseURL || this.getBaseUrl(), timeout: 15000, headers: { - "Content-Type": "application/json", + "Content-Type": "application/json" } }); - this.disableToken = disableToken || false + this.disableToken = disableToken || false; this.initInterceptors(); } @@ -129,9 +127,9 @@ class HttpClient { const errMessage = data?.message || error.message; switch (status) { - case 401: - window.location.href = "/login"; - break; + // case 401: + // window.location.href = "/login"; + // break; case 403: console.error("Permission denied:", errMessage); break; @@ -358,7 +356,7 @@ class HttpClient { public getMarketPlugins( page: number, page_size: number, - query: string, + query: string ): Promise { return this.post(`/api/v1/market/plugins`, { page, @@ -366,7 +364,7 @@ class HttpClient { query, sort_by: "stars", sort_order: "DESC" - }) + }); } public installPluginFromGithub( source: string @@ -415,4 +413,4 @@ class HttpClient { export const httpClient = new HttpClient("https://version-4.langbot.dev"); // 临时写法,未来两种Client都继承自HttpClient父类,不允许共享方法 -export const spaceClient = new HttpClient("https://space.langbot.app") +export const spaceClient = new HttpClient("https://space.langbot.app");