From b0acbbf3378559dac1aa46087218aaec7a314e90 Mon Sep 17 00:00:00 2001 From: xiongxiao Date: Mon, 23 Mar 2026 18:45:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=88=B6=E5=93=81?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E9=A1=B5=E9=9D=A2=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=94=AF=E6=8C=81=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=92=8C=E7=BC=96=E8=BE=91=E5=88=B6=E5=93=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9B=E6=9B=B4=E6=96=B0README=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 47 +++++- plan.md | 3 + src/pages/cloud-env/page.tsx | 58 +++++-- .../cnb-packages/components/CreateDialog.tsx | 105 ++++++++++++ .../cnb-packages/components/EditDialog.tsx | 117 +++++++++++++ .../cnb-packages/components/TagInput.tsx | 53 ++++++ src/pages/cnb-packages/components/index.ts | 3 + src/pages/cnb-packages/page.tsx | 153 +++++++++++++++++ src/pages/cnb-packages/store/index.ts | 154 ++++++++++++++++++ src/pages/sidebar/components/Sidebar.tsx | 19 ++- src/pages/workspaces/store/index.ts | 3 +- src/routeTree.gen.ts | 21 +++ src/routes/cnb-packages/index.tsx | 9 + 13 files changed, 717 insertions(+), 28 deletions(-) create mode 100644 plan.md create mode 100644 src/pages/cnb-packages/components/CreateDialog.tsx create mode 100644 src/pages/cnb-packages/components/EditDialog.tsx create mode 100644 src/pages/cnb-packages/components/TagInput.tsx create mode 100644 src/pages/cnb-packages/components/index.ts create mode 100644 src/pages/cnb-packages/page.tsx create mode 100644 src/pages/cnb-packages/store/index.ts create mode 100644 src/routes/cnb-packages/index.tsx diff --git a/README.md b/README.md index f41f094..1016a06 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,57 @@ # cnb center -一个应用工作台 +一个应用工作台。 + +cnb center 是对 cnb 的部分操作的可视化管理,是对 cnb 功能的补充,核心使用还是需要去使用 cnb。 ## 功能 1. 对话管理 2. 公共资源 3. 仓库管理 -4. 云开发(cloud-env) +4. 云端环境(cloud-env) 5. 我的应用 - NPC - Agent 管理 + - 任务管理 6. 其他 - 制品中心 - - 配置 \ No newline at end of file + - 历史记录 + - 配置 + + +## 对话管理功能 + +列出对应的知识库,知识库是可以动态添加的, 点击后对话应用会加载对应的知识库进行对话,对话过程可以执行实际的任务, 例如调用接口,执行命令等。 + +配置routes,转为指令 + +## 公共资源 + +分享的快速启动的程序应用宝库,技能,对话,npc,agent 等等。 + +## 仓库管理 + +基本的仓库管理,添加和编辑仓库,启动云段环境。 + +## 云端环境(cloud-env) + +单独的云端环境管理,提供云端环境的停止,查看。 + +## 我的应用 + +任务管理 + +## 其他 + +### 制品中心 + +添加对应的仓库,查看对应的制品。对 docker 镜像支持快速配置同步到制品中心。 + +### 配置 + +因为调用 cnb 需要一些配置,例如 token和 cookie等,提供一个界面来配置这些内容,方便使用。 + +### 历史记录 + +对话历史记录,任务执行历史记录等。 \ No newline at end of file diff --git a/plan.md b/plan.md new file mode 100644 index 0000000..a0d7f94 --- /dev/null +++ b/plan.md @@ -0,0 +1,3 @@ +# cnb-center + +是对 cnb 的部分操作的可视化管理,是对 cnb 功能的补充,核心使用还是需要去使用 cnb。 \ No newline at end of file diff --git a/src/pages/cloud-env/page.tsx b/src/pages/cloud-env/page.tsx index 30d555a..6267f5b 100644 --- a/src/pages/cloud-env/page.tsx +++ b/src/pages/cloud-env/page.tsx @@ -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: , getUrl: (d) => d.jumpUrl }, { key: 'webide', label: 'Web IDE', icon: , getUrl: (d) => d.webide }, { key: 'vscode', label: 'VS Code', icon: , getUrl: (d) => d.vscode }, - { key: 'cursor', label: 'Cursor', icon: , getUrl: (d) => d.cursor }, - { key: 'trae-cn', label: 'Trae', icon: , getUrl: (d) => d['trae-cn'] }, - { key: 'windsurf', label: 'Windsurf', icon: , getUrl: (d) => d.windsurf }, - { key: 'antigravity', label: 'Antigravity', icon: , getUrl: (d) => d.antigravity }, { key: 'ssh', label: 'SSH', icon: , getUrl: (d) => d.ssh }, - { key: 'remoteSsh', label: 'Remote SSH', icon: , getUrl: (d) => d.remoteSsh }, - { key: 'codebuddycn', label: 'CodeBuddy', icon: , 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(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 (
@@ -153,15 +165,24 @@ function WorkspaceCard({ workspace, onStop }: { workspace: WorkspaceInfo; onStop {workspace.branch} )}
- +
+ + +
{loading ? ( @@ -171,7 +192,7 @@ function WorkspaceCard({ workspace, onStop }: { workspace: WorkspaceInfo; onStop ))} ) : workspaceData ? ( -
+
{linkItems.map((item) => ( ))} @@ -234,6 +255,7 @@ export default function CloudEnvPage() {
)}
+ ) -} +} \ No newline at end of file diff --git a/src/pages/cnb-packages/components/CreateDialog.tsx b/src/pages/cnb-packages/components/CreateDialog.tsx new file mode 100644 index 0000000..c612f9c --- /dev/null +++ b/src/pages/cnb-packages/components/CreateDialog.tsx @@ -0,0 +1,105 @@ +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { TagInput } from "./TagInput"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; + +export function CreateDialog({ open, onClose, onSubmit }: { + open: boolean; + onClose: () => void; + onSubmit: (data: { title: string, tags?: string[], link?: string, summary?: string, description?: string }) => Promise; +}) { + const [title, setTitle] = useState(''); + const [tags, setTags] = useState([]); + const [link, setLink] = useState(''); + const [summary, setSummary] = useState(''); + const [description, setDescription] = useState(''); + const [submitting, setSubmitting] = useState(false); + + const handleSubmit = async () => { + if (!title.trim()) { + alert('请输入标题'); + return; + } + setSubmitting(true); + try { + await onSubmit({ + title: title.trim(), + tags, + link: link.trim(), + summary: summary.trim(), + description: description.trim(), + }); + } finally { + setSubmitting(false); + } + }; + + return ( + !open && onClose()}> + + + 创建制品 + 填写以下信息创建一个新的制品 + +
+
+ + setTitle(e.target.value)} + placeholder="请输入标题" + /> +
+
+ + +
+
+ + setLink(e.target.value)} + placeholder="https://..." + /> +
+
+ + setSummary(e.target.value)} + placeholder="简要描述" + /> +
+
+ +