generated from kevisual/vite-react-template
feat: 添加制品中心页面及相关组件,支持创建和编辑制品功能;更新README文档
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCloudEnvStore } from './store'
|
||||
import { useRepoStore } from '../repos/store'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
@@ -25,11 +26,14 @@ import {
|
||||
Wind,
|
||||
Plane,
|
||||
Rocket,
|
||||
ExternalLink
|
||||
ExternalLink,
|
||||
Info
|
||||
} from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { WorkspaceInfo } from '@kevisual/cnb'
|
||||
import clsx from 'clsx'
|
||||
import { WorkspaceDetailDialog } from '../repos/modules/WorkspaceDetailDialog'
|
||||
import { useShallow } from 'zustand/shallow'
|
||||
|
||||
type WorkspaceOpen = {
|
||||
url?: string
|
||||
@@ -61,13 +65,7 @@ const linkItems: LinkItem[] = [
|
||||
{ key: 'jumpUrl', label: 'Jump', icon: <ExternalLink className="w-5 h-5" />, getUrl: (d) => d.jumpUrl },
|
||||
{ key: 'webide', label: 'Web IDE', icon: <Code2 className="w-5 h-5" />, getUrl: (d) => d.webide },
|
||||
{ key: 'vscode', label: 'VS Code', icon: <Code2 className="w-5 h-5" />, getUrl: (d) => d.vscode },
|
||||
{ key: 'cursor', label: 'Cursor', icon: <MousePointer2 className="w-5 h-5" />, getUrl: (d) => d.cursor },
|
||||
{ key: 'trae-cn', label: 'Trae', icon: <Rocket className="w-5 h-5" />, getUrl: (d) => d['trae-cn'] },
|
||||
{ key: 'windsurf', label: 'Windsurf', icon: <Wind className="w-5 h-5" />, getUrl: (d) => d.windsurf },
|
||||
{ key: 'antigravity', label: 'Antigravity', icon: <Plane className="w-5 h-5" />, getUrl: (d) => d.antigravity },
|
||||
{ key: 'ssh', label: 'SSH', icon: <Lock className="w-5 h-5" />, getUrl: (d) => d.ssh },
|
||||
{ key: 'remoteSsh', label: 'Remote SSH', icon: <Radio className="w-5 h-5" />, getUrl: (d) => d.remoteSsh },
|
||||
{ key: 'codebuddycn', label: 'CodeBuddy', icon: <Zap className="w-5 h-5" />, getUrl: (d) => d.codebuddycn },
|
||||
]
|
||||
|
||||
function LinkCard({ item, workspaceData }: { item: LinkItem; workspaceData: WorkspaceOpen }) {
|
||||
@@ -127,6 +125,10 @@ function WorkspaceCard({ workspace, onStop }: { workspace: WorkspaceInfo; onStop
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [workspaceData, setWorkspaceData] = useState<WorkspaceOpen | null>(null)
|
||||
const getWorkspaceDetail = useCloudEnvStore((state) => state.getWorkspaceDetail)
|
||||
const repoStore = useRepoStore(useShallow((state) => ({
|
||||
setShowWorkspaceDialog: state.setShowWorkspaceDialog,
|
||||
setWorkspaceTab: state.setWorkspaceTab,
|
||||
})))
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDetail = async () => {
|
||||
@@ -138,6 +140,16 @@ function WorkspaceCard({ workspace, onStop }: { workspace: WorkspaceInfo; onStop
|
||||
fetchDetail()
|
||||
}, [workspace, getWorkspaceDetail])
|
||||
|
||||
const handleShowDetail = async () => {
|
||||
const data = await getWorkspaceDetail(workspace)
|
||||
useRepoStore.setState({
|
||||
selectWorkspace: workspace,
|
||||
workspaceLink: data || {},
|
||||
showWorkspaceDialog: true,
|
||||
workspaceTab: 'dev'
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="p-4 space-y-4 border border-neutral-200 bg-white">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -153,15 +165,24 @@ function WorkspaceCard({ workspace, onStop }: { workspace: WorkspaceInfo; onStop
|
||||
<Badge variant="outline" className="text-xs">{workspace.branch}</Badge>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => onStop(workspace)}
|
||||
className="text-red-600 border-red-200 hover:bg-red-600 hover:text-white"
|
||||
>
|
||||
<Square className="w-4 h-4 mr-1" />
|
||||
停止
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleShowDetail}
|
||||
>
|
||||
<Info className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => onStop(workspace)}
|
||||
className="text-red-600 border-red-200 hover:bg-red-600 hover:text-white"
|
||||
>
|
||||
<Square className="w-4 h-4 mr-1" />
|
||||
停止
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
@@ -171,7 +192,7 @@ function WorkspaceCard({ workspace, onStop }: { workspace: WorkspaceInfo; onStop
|
||||
))}
|
||||
</div>
|
||||
) : workspaceData ? (
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{linkItems.map((item) => (
|
||||
<LinkCard key={item.key} item={item} workspaceData={workspaceData} />
|
||||
))}
|
||||
@@ -234,6 +255,7 @@ export default function CloudEnvPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<WorkspaceDetailDialog />
|
||||
</SidebarLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user