From 245bbb33b068b36656066731c50a837fb70c9bca Mon Sep 17 00:00:00 2001 From: abearxiong Date: Thu, 26 Feb 2026 01:39:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E5=92=8C=E4=BC=98=E5=8C=96=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E5=8D=A1=E7=89=87=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=9C=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=20RepoInfoCard=20=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/repos/components/BuildConfig.tsx | 12 +- src/pages/repos/components/RepoCard.tsx | 74 +++++-- src/pages/repos/components/RepoInfoCard.tsx | 231 -------------------- src/pages/repos/page.tsx | 39 +--- src/pages/repos/repo/page.tsx | 23 +- 5 files changed, 74 insertions(+), 305 deletions(-) delete mode 100644 src/pages/repos/components/RepoInfoCard.tsx diff --git a/src/pages/repos/components/BuildConfig.tsx b/src/pages/repos/components/BuildConfig.tsx index 3ecb64b..cdf96d9 100644 --- a/src/pages/repos/components/BuildConfig.tsx +++ b/src/pages/repos/components/BuildConfig.tsx @@ -1,13 +1,12 @@ import { useEffect, useState } from "react"; import { useRepoStore } from "../store"; import { useShallow } from "zustand/shallow"; -import { toast } from "sonner"; import CodeMirror from "@uiw/react-codemirror"; import { yaml } from "@codemirror/lang-yaml"; import { useLayoutStore } from "@/pages/auth/store"; import { Input } from "@/components/ui/input"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Workflow } from "lucide-react"; +import { ArrowLeft, Workflow } from "lucide-react"; +import { useNavigate } from "@tanstack/react-router"; export const BuildConfig = () => { const repoStore = useRepoStore(useShallow((state) => ({ @@ -21,6 +20,7 @@ export const BuildConfig = () => { buildWorkspace: state.buildWorkspace, }))); const repo = repoStore.editRepo!; + const navigate = useNavigate(); const me = useLayoutStore((state) => state.me); const [localConfig, setLocalConfig] = useState(repoStore.buildConfig?.config || ""); @@ -59,6 +59,12 @@ export const BuildConfig = () => { {/* 左侧边栏 - 配置信息 */}
+ 构建配置 + )}
{ - navigate({ to: `/repo?repo=${repo.path}` }) + if (!showReturn) { + navigate({ to: `/repo?repo=${repo.path}` }) + } else { + window.open(`https://cnb.cool/${repo.path}`, '_blank') + } }} > {repo.path} @@ -114,7 +135,7 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, size="sm" variant="outline" onClick={() => { - stopWorkspace(workspace) + store.stopWorkspace(workspace) }} className="h-8 w-8 p-0 border-neutral-200 hover:border-red-600 hover:bg-red-600 hover:text-white transition-all cursor-pointer" > @@ -137,9 +158,9 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, variant="outline" onClick={() => { if (!isWorkspaceActive) { - onStartWorkspace(repo) + store.startWorkspace(repo) } else { - getWorkspaceDetail(workspace) + store.getWorkspaceDetail(workspace) } }} @@ -167,7 +188,10 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, } /> - onEdit(repo)} className="cursor-pointer"> + { + store.setEditRepo(repo) + store.setShowEditDialog(true) + }} className="cursor-pointer"> 编辑 @@ -202,11 +226,11 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, 访问仓库 - onIssue(repo)} className="cursor-pointer"> + handleIssue(repo)} className="cursor-pointer"> 访问问题 - onSettings(repo)} className="cursor-pointer"> + handleSettings(repo)} className="cursor-pointer"> 访问设置 @@ -247,7 +271,8 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, variant="outline" className="bg-red-600 text-white border-red-600 hover:bg-red-700 hover:border-red-700" onClick={() => { - onDelete(repo) + if (repo.path) + store.deleteItem(repo.path) setDeletePopoverOpen(false) }} > @@ -309,7 +334,7 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, {isWorkspaceActive && { - getWorkspaceDetail(workspace) + store.getWorkspaceDetail(workspace) }}> 运行中 @@ -317,7 +342,10 @@ export function RepoCard({ repo, onStartWorkspace, onEdit, onIssue, onSettings, {isMine && ( onSync?.(repo)} + onClick={() => { + store.setSelectedSyncRepo(repo) + store.setSyncDialogOpen(true) + }} > 同步 diff --git a/src/pages/repos/components/RepoInfoCard.tsx b/src/pages/repos/components/RepoInfoCard.tsx deleted file mode 100644 index dee83a6..0000000 --- a/src/pages/repos/components/RepoInfoCard.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import { useNavigate } from "@tanstack/react-router"; -import { useMemo } from "react"; -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 { Button } from "@/components/ui/button"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; -import { Star, GitFork, FileText, ExternalLink, Calendar, User, Copy, ArrowLeft, Play, Square, Eye, BookOpen, RefreshCw } from "lucide-react"; -import { myOrgs } from "../store/build"; - -export const RepoInfoCard = () => { - const navigate = useNavigate(); - const { workspaceList, getWorkspaceDetail, stopWorkspace, editRepo, setSelectedSyncRepo, setSyncDialogOpen } = useRepoStore(useShallow((state) => ({ - workspaceList: state.workspaceList, - getWorkspaceDetail: state.getWorkspaceDetail, - stopWorkspace: state.stopWorkspace, - editRepo: state.editRepo, - setSelectedSyncRepo: state.setSelectedSyncRepo, - setSyncDialogOpen: state.setSyncDialogOpen, - }))); - const repo = editRepo!; - - const workspace = useMemo(() => { - return workspaceList.find(ws => ws.slug === repo.path) - }, [workspaceList, repo.path]) - const isWorkspaceActive = !!workspace - const owner = repo.path.split('/')[0] - const isMine = myOrgs.includes(owner) - const isKnowledge = repo?.flags === "KnowledgeBase" - - 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} - - {isKnowledge && ( - - - - -
- } - /> - -

知识库

-
- - - )} - {isWorkspaceActive && ( - - - - - )} -
-
- {isWorkspaceActive && ( - - - { - stopWorkspace(workspace) - }} - className="h-8 w-8 p-0 border-neutral-200 hover:border-red-600 hover:bg-red-600 hover:text-white transition-all cursor-pointer" - > - - - } - /> - -

停止工作区

-
-
-
- )} - - - { - if (!isWorkspaceActive) { - // TODO: 启动工作区 - } else { - getWorkspaceDetail(workspace) - } - }} - className="h-8 w-8 p-0 border-neutral-200 hover:border-neutral-900 hover:bg-neutral-900 hover:text-white transition-all cursor-pointer" - > - {isWorkspaceActive ? : } - - } - /> - -

{isWorkspaceActive ? '查看工作区' : '启动工作区'}

-
-
-
- - - CNB - -
-
- - {/* 描述 */} - {repo.description && ( -

- {repo.description} -

- )} - - {/* 主题标签和知识库 */} -
- {/* 主题标签 */} - {repo.topics && ( -
- {repo.topics.split(',').map((topic: string, idx: number) => ( - - {topic.trim()} - - ))} -
- )} - -
- - {/* 统计信息 */} -
- - - {repo.star_count} - - - - {repo.fork_count} - - - - {repo.open_issue_count} - - {isWorkspaceActive && ( - - - 运行中 - - )} - {isMine && ( - { - setSelectedSyncRepo(repo) - setSyncDialogOpen(true) - }} - > - - 同步 - - )} -
- - {/* 更新信息 */} -
- {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/page.tsx b/src/pages/repos/page.tsx index 727170d..4caff6a 100644 --- a/src/pages/repos/page.tsx +++ b/src/pages/repos/page.tsx @@ -13,21 +13,12 @@ import Fuse from 'fuse.js' import { useNavigate } from '@tanstack/react-router' export const App = () => { - const { list, refresh, loading, editRepo, setEditRepo, workspaceList, showEditDialog, setShowEditDialog, showCreateDialog, setShowCreateDialog, startWorkspace, deleteItem, setSelectedSyncRepo, setSyncDialogOpen } = useRepoStore(useShallow((state) => ({ + const { list, refresh, loading, workspaceList, setShowCreateDialog } = useRepoStore(useShallow((state) => ({ list: state.list, refresh: state.refresh, loading: state.loading, - editRepo: state.editRepo, - setEditRepo: state.setEditRepo, workspaceList: state.workspaceList, - showEditDialog: state.showEditDialog, - setShowEditDialog: state.setShowEditDialog, - showCreateDialog: state.showCreateDialog, setShowCreateDialog: state.setShowCreateDialog, - startWorkspace: state.startWorkspace, - deleteItem: state.deleteItem, - setSelectedSyncRepo: state.setSelectedSyncRepo, - setSyncDialogOpen: state.setSyncDialogOpen, }))) const [searchQuery, setSearchQuery] = useState('') const navigate = useNavigate(); @@ -35,28 +26,6 @@ export const App = () => { refresh({ showTips: false }) }, []) - const handleEdit = (repo: any) => { - setEditRepo(repo) - setShowEditDialog(true) - } - const handleIssue = (repo: any) => { - window.open(`https://cnb.cool/${repo.path}/-/issues`) - } - - const handleSettings = (repo: any) => { - window.open(`https://cnb.cool/${repo.path}/-/settings`) - } - - const handleDelete = (repo: any) => { - if (repo.path) - deleteItem(repo.path) - } - - const handleSync = (repo: any) => { - setSelectedSyncRepo(repo) - setSyncDialogOpen(true) - } - const appList = useMemo(() => { // 首先按活动状态排序 const sortedList = [...list].sort((a, b) => { @@ -133,12 +102,6 @@ export const App = () => { ))}
diff --git a/src/pages/repos/repo/page.tsx b/src/pages/repos/repo/page.tsx index 1c1c9e5..beb45ed 100644 --- a/src/pages/repos/repo/page.tsx +++ b/src/pages/repos/repo/page.tsx @@ -2,18 +2,18 @@ import { useSearch } from "@tanstack/react-router"; import { useRepoStore } from "../store"; import { useEffect, useState } from "react"; import { useShallow } from "zustand/shallow"; -import { RepoInfoCard } from "../components/RepoInfoCard"; import BuildConfig from "../components/BuildConfig"; import { CommonRepoDialog } from "../page"; +import { RepoCard } from "../components/RepoCard"; export const App = () => { - const params = useSearch({ strict: false }) as { repo?: string }; + const params = useSearch({ strict: false }) as { repo?: string, tab?: string }; const repoStore = useRepoStore(useShallow((state) => ({ getItem: state.getItem, editRepo: state.editRepo, refresH: state.refresh, }))); - const [activeTab, setActiveTab] = useState("build"); + const [activeTab, setActiveTab] = useState(params.tab || "build"); const tabs = [ { key: "build", label: "构建配置" }, { key: "info", label: "基本信息" }, @@ -31,16 +31,16 @@ export const App = () => { } return (
-
- -
-
+
{tabs.map(tab => (
setActiveTab(tab.key)} + onClick={() => { + setActiveTab(tab.key) + history.replaceState(null, '', `?repo=${params.repo}&tab=${tab.key}`) + }} > {tab.label}
@@ -48,8 +48,11 @@ export const App = () => {
{activeTab === 'build' && } {activeTab === 'info' && ( -
-
{JSON.stringify(repoStore.editRepo, null, 2)}
+
+ +
+
{JSON.stringify(repoStore.editRepo, null, 2)}
+
)}