mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-19 19:06:07 +00:00
修复仓库冲突
This commit is contained in:
@@ -1,81 +1,71 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import styles from "./HomeSidebar.module.css"
|
import styles from "./HomeSidebar.module.css";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { SidebarChild, SidebarChildVO } from "@/app/home/components/home-sidebar/HomeSidebarChild";
|
import {
|
||||||
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
SidebarChild,
|
||||||
|
SidebarChildVO
|
||||||
|
} from "@/app/home/components/home-sidebar/HomeSidebarChild";
|
||||||
|
import { useRouter, usePathname } from "next/navigation";
|
||||||
import { sidebarConfigList } from "@/app/home/components/home-sidebar/sidbarConfigList";
|
import { sidebarConfigList } from "@/app/home/components/home-sidebar/sidbarConfigList";
|
||||||
|
|
||||||
// TODO 侧边导航栏要加动画
|
// TODO 侧边导航栏要加动画
|
||||||
export default function HomeSidebar({
|
export default function HomeSidebar({
|
||||||
onSelectedChange
|
onSelectedChangeAction
|
||||||
}: {
|
}: {
|
||||||
onSelectedChange: (sidebarChild: SidebarChildVO) => void
|
onSelectedChangeAction: (sidebarChild: SidebarChildVO) => void;
|
||||||
}) {
|
}) {
|
||||||
// 路由相关
|
// 路由相关
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
// 路由被动变化时处理
|
||||||
// 路由被动变化时处理
|
useEffect(() => {
|
||||||
useEffect(() => {
|
handleRouteChange(pathname);
|
||||||
handleRouteChange(pathname)
|
}, [pathname]);
|
||||||
}, [pathname, searchParams]);
|
|
||||||
|
|
||||||
const [selectedChild, setSelectedChild] = useState<SidebarChildVO>(sidebarConfigList[0])
|
const [selectedChild, setSelectedChild] = useState<SidebarChildVO>(
|
||||||
|
sidebarConfigList[0]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('HomeSidebar挂载完成');
|
console.log("HomeSidebar挂载完成");
|
||||||
initSelect()
|
initSelect();
|
||||||
return () => console.log('HomeSidebar卸载');
|
return () => console.log("HomeSidebar卸载");
|
||||||
}, []);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function handleChildClick(child: SidebarChildVO) {
|
||||||
|
setSelectedChild(child);
|
||||||
|
handleRoute(child);
|
||||||
|
onSelectedChangeAction(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSelect() {
|
||||||
|
handleChildClick(sidebarConfigList[0]);
|
||||||
|
}
|
||||||
|
|
||||||
function handleChildClick(child: SidebarChildVO) {
|
function handleRoute(child: SidebarChildVO) {
|
||||||
setSelectedChild(child)
|
console.log(child);
|
||||||
handleRoute(child)
|
router.push(`${child.route}`);
|
||||||
onSelectedChange(child)
|
}
|
||||||
}
|
|
||||||
|
function handleRouteChange(pathname: string) {
|
||||||
function initSelect() {
|
// TODO 这段逻辑并不好,未来router封装好后改掉
|
||||||
// 根据当前URL路径选择相应的菜单项,而不是总是使用第一个菜单项
|
// 判断在home下,并且路由更改的是自己的路由子组件则更新UI
|
||||||
const currentPath = pathname;
|
const routeList = pathname.split("/");
|
||||||
const matchedChild = sidebarConfigList.find(child => child.route === currentPath);
|
if (
|
||||||
|
routeList[1] === "home" &&
|
||||||
if (matchedChild) {
|
sidebarConfigList.find((childConfig) => childConfig.route === pathname)
|
||||||
// 如果找到匹配的菜单项,则选择它
|
) {
|
||||||
setSelectedChild(matchedChild);
|
console.log("find success");
|
||||||
onSelectedChange(matchedChild);
|
const routeSelectChild = sidebarConfigList.find(
|
||||||
} else {
|
(childConfig) => childConfig.route === pathname
|
||||||
// 如果没有匹配项,则回退到默认选择第一个菜单项
|
);
|
||||||
handleChildClick(sidebarConfigList[0]);
|
if (routeSelectChild) {
|
||||||
}
|
setSelectedChild(routeSelectChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRoute(child: SidebarChildVO) {
|
|
||||||
console.log(child)
|
|
||||||
router.push(`${child.route}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRouteChange(pathname: string) {
|
|
||||||
// TODO 这段逻辑并不好,未来router封装好后改掉
|
|
||||||
// 判断在home下,并且路由更改的是自己的路由子组件则更新UI
|
|
||||||
const routeList = pathname.split('/')
|
|
||||||
if (
|
|
||||||
routeList[1] === "home" &&
|
|
||||||
sidebarConfigList.find(childConfig =>
|
|
||||||
childConfig.route === pathname
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
console.log("find success")
|
|
||||||
const routeSelectChild = sidebarConfigList.find(childConfig =>
|
|
||||||
childConfig.route === pathname
|
|
||||||
)
|
|
||||||
if (routeSelectChild) {
|
|
||||||
setSelectedChild(routeSelectChild)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default function HomeLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [title, setTitle] = useState<string>("")
|
const [title, setTitle] = useState<string>("")
|
||||||
const onSelectedChange = (child: SidebarChildVO) => {
|
const onSelectedChangeAction = (child: SidebarChildVO) => {
|
||||||
setTitle(child.name)
|
setTitle(child.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ export default function HomeLayout({
|
|||||||
|
|
||||||
<Sider className="left">
|
<Sider className="left">
|
||||||
<HomeSidebar
|
<HomeSidebar
|
||||||
onSelectedChange={onSelectedChange}
|
onSelectedChangeAction={onSelectedChangeAction}
|
||||||
/>
|
/>
|
||||||
{/* HomeSidebar 为侧边栏 */}
|
{/* HomeSidebar 为侧边栏 */}
|
||||||
</Sider>
|
</Sider>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export default function PluginInstalledComponent() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initData()
|
initData()
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
function initData() {
|
function initData() {
|
||||||
|
|||||||
@@ -1,13 +1,33 @@
|
|||||||
import styles from "./pluginCard.module.css"
|
import styles from "./pluginCard.module.css"
|
||||||
import { PluginCardVO } from "@/app/home/plugins/plugin-installed/PluginCardVO";
|
import { PluginCardVO } from "@/app/home/plugins/plugin-installed/PluginCardVO";
|
||||||
import { GithubOutlined, LinkOutlined, ToolOutlined } from '@ant-design/icons';
|
import { GithubOutlined, LinkOutlined, ToolOutlined } from '@ant-design/icons';
|
||||||
import { Tag } from 'antd'
|
import { Switch, Tag } from 'antd'
|
||||||
|
import { useState } from "react";
|
||||||
|
import { httpClient } from "@/app/infra/http/HttpClient";
|
||||||
|
|
||||||
export default function PluginCardComponent({
|
export default function PluginCardComponent({
|
||||||
cardVO
|
cardVO
|
||||||
}: {
|
}: {
|
||||||
cardVO: PluginCardVO
|
cardVO: PluginCardVO
|
||||||
}) {
|
}) {
|
||||||
|
const [initialized, setInitialized] = useState(cardVO.isInitialized);
|
||||||
|
const [switchEnable, setSwitchEnable] = useState(true);
|
||||||
|
|
||||||
|
function handleEnable() {
|
||||||
|
setSwitchEnable(false);
|
||||||
|
httpClient
|
||||||
|
.togglePlugin(cardVO.author, cardVO.name, !initialized)
|
||||||
|
.then(() => {
|
||||||
|
setInitialized(!initialized);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("error: ", err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setSwitchEnable(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.cardContainer}`}>
|
<div className={`${styles.cardContainer}`}>
|
||||||
{/* header */}
|
{/* header */}
|
||||||
|
|||||||
@@ -1,90 +1,70 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import styles from "@/app/home/plugins/plugins.module.css";
|
import styles from "@/app/home/plugins/plugins.module.css";
|
||||||
import { PluginMarketCardVO } from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO";
|
import { PluginMarketCardVO } from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO";
|
||||||
import PluginMarketCardComponent from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardComponent";
|
import PluginMarketCardComponent from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardComponent";
|
||||||
import { Input, Pagination } from "antd";
|
import { Input, Pagination } from "antd";
|
||||||
import { debounce } from "lodash"
|
import { spaceClient } from "@/app/infra/http/HttpClient";
|
||||||
|
|
||||||
export default function PluginMarketComponent() {
|
export default function PluginMarketComponent() {
|
||||||
const [marketPluginList, setMarketPluginList] = useState<PluginMarketCardVO[]>([])
|
const [marketPluginList, setMarketPluginList] = useState<
|
||||||
const [searchKeyword, setSearchKeyword] = useState("")
|
PluginMarketCardVO[]
|
||||||
const [currentPage, setCurrentPage] = useState(1)
|
>([]);
|
||||||
const [totalItems, setTotalItems] = useState(0)
|
const [totalCount, setTotalCount] = useState(0);
|
||||||
const [loading, setLoading] = useState(false)
|
const [nowPage, setNowPage] = useState(1);
|
||||||
const pageSize = 10 // 每页显示的项目数量
|
const [searchKeyword, setSearchKeyword] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const pageSize = 10;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchPlugins(searchKeyword, currentPage)
|
initData();
|
||||||
}, [currentPage])
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
// 获取插件列表,整合了搜索和分页功能
|
function initData() {
|
||||||
async function fetchPlugins(keyword: string = "", page: number = 1): Promise<void> {
|
getPluginList();
|
||||||
setLoading(true)
|
|
||||||
try {
|
|
||||||
// 实际应用中,这里应该调用API获取数据
|
|
||||||
const result = await mockFetchPlugins(keyword, page, pageSize)
|
|
||||||
setMarketPluginList(result.data)
|
|
||||||
setTotalItems(result.total)
|
|
||||||
} finally {
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模拟从API获取数据
|
|
||||||
async function mockFetchPlugins(keyword: string, page: number, pageSize: number): Promise<{ data: PluginMarketCardVO[], total: number }> {
|
|
||||||
// 模拟API延迟
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 300))
|
|
||||||
|
|
||||||
// 创建模拟数据
|
|
||||||
const allPlugins: PluginMarketCardVO[] = []
|
|
||||||
const totalPlugins = 50 // 模拟总数据量
|
|
||||||
|
|
||||||
for (let i = 0; i < totalPlugins; i++) {
|
|
||||||
allPlugins.push(new PluginMarketCardVO({
|
|
||||||
pluginId: `plugin-${i}`,
|
|
||||||
description: `这是插件 ${i} 的描述,包含一些详细信息`,
|
|
||||||
name: `插件 ${i}`,
|
|
||||||
author: `/author-${i % 5}`, // 模拟5个不同的作者
|
|
||||||
version: `0.${i % 10}`,
|
|
||||||
githubURL: `https://github.com/author-${i % 5}/plugin-${i}`,
|
|
||||||
starCount: 10 + Math.floor(Math.random() * 100)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据关键词过滤
|
|
||||||
const filtered = keyword
|
|
||||||
? allPlugins.filter(p =>
|
|
||||||
p.name.toLowerCase().includes(keyword.toLowerCase()) ||
|
|
||||||
p.description.toLowerCase().includes(keyword.toLowerCase()))
|
|
||||||
: allPlugins
|
|
||||||
|
|
||||||
// 分页处理
|
|
||||||
const start = (page - 1) * pageSize
|
|
||||||
const end = start + pageSize
|
|
||||||
const paginatedData = filtered.slice(start, end)
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: paginatedData,
|
|
||||||
total: filtered.length
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInputSearchKeyword(keyword: string) {
|
function onInputSearchKeyword(keyword: string) {
|
||||||
setSearchKeyword(keyword)
|
// 这里记得加防抖,暂时没加
|
||||||
setCurrentPage(1) // 搜索时重置为第一页
|
setSearchKeyword(keyword);
|
||||||
debounceSearch(keyword)
|
setNowPage(1);
|
||||||
|
getPluginList(1, keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
const debounceSearch = useCallback(
|
function getPluginList(
|
||||||
debounce((keyword: string) => {
|
page: number = nowPage,
|
||||||
fetchPlugins(keyword, 1)
|
keyword: string = searchKeyword
|
||||||
}, 500), []
|
) {
|
||||||
)
|
setLoading(true);
|
||||||
|
spaceClient.getMarketPlugins(page, pageSize, keyword).then((res) => {
|
||||||
|
setMarketPluginList(
|
||||||
|
res.plugins.map(
|
||||||
|
(marketPlugin) =>
|
||||||
|
new PluginMarketCardVO({
|
||||||
|
author: marketPlugin.author,
|
||||||
|
description: marketPlugin.description,
|
||||||
|
githubURL: marketPlugin.repository,
|
||||||
|
name: marketPlugin.name,
|
||||||
|
pluginId: String(marketPlugin.ID),
|
||||||
|
starCount: marketPlugin.stars,
|
||||||
|
version: "version" in marketPlugin ? String(marketPlugin.version) : "1.0.0", // Default version if not provided
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setTotalCount(res.total);
|
||||||
|
setLoading(false);
|
||||||
|
console.log("market plugins:", res);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error("获取插件列表失败:", error);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handlePageChange(page: number) {
|
function handlePageChange(page: number) {
|
||||||
setCurrentPage(page)
|
setNowPage(page);
|
||||||
|
getPluginList(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -111,11 +91,11 @@ export default function PluginMarketComponent() {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{totalItems > 0 && (
|
{totalCount > 0 && (
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', width: '100%', marginTop: '20px' }}>
|
<div style={{ display: 'flex', justifyContent: 'center', width: '100%', marginTop: '20px' }}>
|
||||||
<Pagination
|
<Pagination
|
||||||
current={currentPage}
|
current={nowPage}
|
||||||
total={totalItems}
|
total={totalCount}
|
||||||
pageSize={pageSize}
|
pageSize={pageSize}
|
||||||
onChange={handlePageChange}
|
onChange={handlePageChange}
|
||||||
showSizeChanger={false}
|
showSizeChanger={false}
|
||||||
|
|||||||
Reference in New Issue
Block a user