From 5a769a67480983c0e5d74d75b1da9d0084694e23 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Wed, 25 Feb 2026 23:12:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=8D=A1=E7=89=87=E5=92=8C=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8C=E4=BC=98=E5=8C=96=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/auth/store.ts | 19 ++-- src/pages/repos/components/RepoInfoCard.tsx | 95 +++++++++++++++++++ .../repos/modules/WorkspaceDetailDialog.tsx | 1 - src/pages/repos/repo/page.tsx | 32 +++++++ src/pages/repos/store/index.ts | 15 ++- src/routeTree.gen.ts | 24 ++++- src/routes/repo/index.tsx | 9 ++ 7 files changed, 177 insertions(+), 18 deletions(-) create mode 100644 src/pages/repos/components/RepoInfoCard.tsx create mode 100644 src/pages/repos/repo/page.tsx create mode 100644 src/routes/repo/index.tsx diff --git a/src/pages/auth/store.ts b/src/pages/auth/store.ts index 3868caf..765f81e 100644 --- a/src/pages/auth/store.ts +++ b/src/pages/auth/store.ts @@ -78,12 +78,19 @@ export const useLayoutStore = create((set, get) => ({ const token = await queryLogin.getToken(); if (token) { set({ me: {} }) - const me = await queryLogin.getMe(); - // const user = await queryLogin.checkLocalUser() as UserInfo; - const user = me.code === 200 ? me.data : undefined; - if (user) { - set({ me: user }); - set({ isAdmin: user.orgs?.includes?.('admin') || false }); + let me: UserInfo | undefined = undefined; + + const _user = await queryLogin.checkLocalUser() as UserInfo; + if (_user) { + me = _user; + } + if (!me) { + const res = await queryLogin.getMe(); + me = res.code === 200 ? res.data : undefined; + } + if (me) { + set({ me: me }); + set({ isAdmin: me.orgs?.includes?.('admin') || false }); } else { set({ me: undefined, isAdmin: false }); } diff --git a/src/pages/repos/components/RepoInfoCard.tsx b/src/pages/repos/components/RepoInfoCard.tsx new file mode 100644 index 0000000..95f415b --- /dev/null +++ b/src/pages/repos/components/RepoInfoCard.tsx @@ -0,0 +1,95 @@ +import { useRepoStore } from "../store"; +import { useShallow } from "zustand/shallow"; +import { toast } from "sonner"; +import { Card } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Star, GitFork, FileText, ExternalLink, Calendar, User, Copy } from "lucide-react"; + +export const RepoInfoCard = () => { + const repoStore = useRepoStore(useShallow((state) => ({ + getItem: state.getItem, + editRepo: state.editRepo, + }))); + const repo = repoStore.editRepo!; + const onClone = () => { + const url = `git clone https://cnb.cool/${repo.path}` + navigator.clipboard.writeText(url).then(() => { + toast.success('克隆地址已复制到剪贴板') + }).catch(() => { + toast.error('复制失败') + }) + } + if (!repo) { + return
Loading...
+ } + return ( +
+ {/* 顶部仓库信息卡片 */} + +
+ {/* 标题行 */} +
+
+ + {repo.path} + + + + {repo.visibility_level === 'Public' ? '公开' : repo.visibility_level === 'Private' ? '私有' : repo.visibility_level} + +
+ + + 在 CNB 上查看 + +
+ + {/* 描述 */} + {repo.description && ( +

+ {repo.description} +

+ )} + + {/* 主题标签 */} + {repo.topics && ( +
+ {repo.topics.split(',').map((topic: string, idx: number) => ( + + {topic.trim()} + + ))} +
+ )} + + {/* 语言和更新时间 */} +
+ {repo.last_update_nickname && ( + + + {repo.last_update_nickname} + + )} + {repo.last_updated_at && ( + + + {new Date(repo.last_updated_at).toLocaleDateString('zh-CN')} + + )} +
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/pages/repos/modules/WorkspaceDetailDialog.tsx b/src/pages/repos/modules/WorkspaceDetailDialog.tsx index 2d70c93..336fffd 100644 --- a/src/pages/repos/modules/WorkspaceDetailDialog.tsx +++ b/src/pages/repos/modules/WorkspaceDetailDialog.tsx @@ -237,7 +237,6 @@ export function WorkspaceDetailDialog() { getUrl: (data) => data.codebuddycn }, ].sort((a, b) => (a.order || 0) - (b.order || 0)) - console.log('workspaceLink', selectWorkspace) return ( diff --git a/src/pages/repos/repo/page.tsx b/src/pages/repos/repo/page.tsx new file mode 100644 index 0000000..0c77deb --- /dev/null +++ b/src/pages/repos/repo/page.tsx @@ -0,0 +1,32 @@ +import { useSearch } from "@tanstack/react-router"; +import { useRepoStore } from "../store"; +import { useEffect } from "react"; +import { useShallow } from "zustand/shallow"; +import { RepoInfoCard } from "../components/RepoInfoCard"; + +export const App = () => { + const params = useSearch({ strict: false }) as { repo?: string }; + const repoStore = useRepoStore(useShallow((state) => ({ + getItem: state.getItem, + editRepo: state.editRepo, + }))); + useEffect(() => { + if (params.repo) { + repoStore.getItem(params.repo); + } else { + console.log('no repo param') + } + }, [params]) + if (!repoStore.editRepo) { + return
Loading...
+ } + return ( +
+
+ +
+
+ ) +} + +export default App; \ No newline at end of file diff --git a/src/pages/repos/store/index.ts b/src/pages/repos/store/index.ts index 43fba0e..7ca41d6 100644 --- a/src/pages/repos/store/index.ts +++ b/src/pages/repos/store/index.ts @@ -21,7 +21,7 @@ interface Data { freeze: boolean; status: number; // Public, Private - visibility_level: string; + visibility_level: string; flags: string; created_at: string; updated_at: string; @@ -88,6 +88,7 @@ type State = { setSelectedSyncRepo: (repo: Data | null) => void; buildSync: (data: Partial, params: { toRepo?: string, fromRepo?: string }) => Promise; buildUpdate: (data: Partial, params?: any) => Promise; + getItem: (repo: string) => Promise; } export const useRepoStore = create((set, get) => { @@ -113,17 +114,14 @@ export const useRepoStore = create((set, get) => { setSyncDialogOpen: (open) => set({ syncDialogOpen: open }), selectedSyncRepo: null, setSelectedSyncRepo: (repo) => set({ selectedSyncRepo: repo }), - getItem: async (id) => { + getItem: async (repo: string) => { const { setLoading } = get(); setLoading(true); try { - const res = await query.post({ - path: 'demo', - key: 'item', - data: { id } - }) + const res = await cnb.repo.getRepo(repo) if (res.code === 200) { - return res; + const data = res.data!; + set({ editRepo: data }) } else { toast.error(res.message || '请求失败'); } @@ -376,6 +374,7 @@ export const useRepoStore = create((set, get) => { toast.error(res.message || '更新失败') } } + } }) diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index c3ad052..0275425 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -11,6 +11,7 @@ import { Route as rootRouteImport } from './routes/__root' import { Route as LoginRouteImport } from './routes/login' import { Route as IndexRouteImport } from './routes/index' +import { Route as RepoIndexRouteImport } from './routes/repo/index' import { Route as ConfigIndexRouteImport } from './routes/config/index' import { Route as ConfigGiteaRouteImport } from './routes/config/gitea' @@ -24,6 +25,11 @@ const IndexRoute = IndexRouteImport.update({ path: '/', getParentRoute: () => rootRouteImport, } as any) +const RepoIndexRoute = RepoIndexRouteImport.update({ + id: '/repo/', + path: '/repo/', + getParentRoute: () => rootRouteImport, +} as any) const ConfigIndexRoute = ConfigIndexRouteImport.update({ id: '/config/', path: '/config/', @@ -40,12 +46,14 @@ export interface FileRoutesByFullPath { '/login': typeof LoginRoute '/config/gitea': typeof ConfigGiteaRoute '/config/': typeof ConfigIndexRoute + '/repo/': typeof RepoIndexRoute } export interface FileRoutesByTo { '/': typeof IndexRoute '/login': typeof LoginRoute '/config/gitea': typeof ConfigGiteaRoute '/config': typeof ConfigIndexRoute + '/repo': typeof RepoIndexRoute } export interface FileRoutesById { __root__: typeof rootRouteImport @@ -53,13 +61,14 @@ export interface FileRoutesById { '/login': typeof LoginRoute '/config/gitea': typeof ConfigGiteaRoute '/config/': typeof ConfigIndexRoute + '/repo/': typeof RepoIndexRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/login' | '/config/gitea' | '/config/' + fullPaths: '/' | '/login' | '/config/gitea' | '/config/' | '/repo/' fileRoutesByTo: FileRoutesByTo - to: '/' | '/login' | '/config/gitea' | '/config' - id: '__root__' | '/' | '/login' | '/config/gitea' | '/config/' + to: '/' | '/login' | '/config/gitea' | '/config' | '/repo' + id: '__root__' | '/' | '/login' | '/config/gitea' | '/config/' | '/repo/' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -67,6 +76,7 @@ export interface RootRouteChildren { LoginRoute: typeof LoginRoute ConfigGiteaRoute: typeof ConfigGiteaRoute ConfigIndexRoute: typeof ConfigIndexRoute + RepoIndexRoute: typeof RepoIndexRoute } declare module '@tanstack/react-router' { @@ -85,6 +95,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexRouteImport parentRoute: typeof rootRouteImport } + '/repo/': { + id: '/repo/' + path: '/repo' + fullPath: '/repo/' + preLoaderRoute: typeof RepoIndexRouteImport + parentRoute: typeof rootRouteImport + } '/config/': { id: '/config/' path: '/config' @@ -107,6 +124,7 @@ const rootRouteChildren: RootRouteChildren = { LoginRoute: LoginRoute, ConfigGiteaRoute: ConfigGiteaRoute, ConfigIndexRoute: ConfigIndexRoute, + RepoIndexRoute: RepoIndexRoute, } export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) diff --git a/src/routes/repo/index.tsx b/src/routes/repo/index.tsx new file mode 100644 index 0000000..c00f308 --- /dev/null +++ b/src/routes/repo/index.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from '@tanstack/react-router' +import App from '@/pages/repos/repo/page' +export const Route = createFileRoute('/repo/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return +}