Refactor Assistant navigation and update HomePage button
Updated the AppShell and Sidebar components to streamline navigation for the Assistant section, consolidating assistant-related pages under a single "assistants" key. Removed deprecated assistant sub-items and adjusted the HomePage button to link to the new assistant navigation. Enhanced the AssistantPage with a list view for managing assistants, including mock data for demonstration.
This commit is contained in:
@@ -6,7 +6,6 @@ import { Topbar } from "./Topbar";
|
|||||||
|
|
||||||
import { HomePage } from "@/components/pages/HomePage";
|
import { HomePage } from "@/components/pages/HomePage";
|
||||||
import { AssistantPage } from "@/components/pages/AssistantPage";
|
import { AssistantPage } from "@/components/pages/AssistantPage";
|
||||||
import { AssistantWorkflowPage } from "@/components/pages/AssistantWorkflowPage";
|
|
||||||
import { ComponentsModelsPage } from "@/components/pages/ComponentsModelsPage";
|
import { ComponentsModelsPage } from "@/components/pages/ComponentsModelsPage";
|
||||||
import { ComponentsKnowledgePage } from "@/components/pages/ComponentsKnowledgePage";
|
import { ComponentsKnowledgePage } from "@/components/pages/ComponentsKnowledgePage";
|
||||||
import { ComponentsToolsPage } from "@/components/pages/ComponentsToolsPage";
|
import { ComponentsToolsPage } from "@/components/pages/ComponentsToolsPage";
|
||||||
@@ -17,8 +16,7 @@ import { ProfilePage } from "@/components/pages/ProfilePage";
|
|||||||
|
|
||||||
export type NavKey =
|
export type NavKey =
|
||||||
| "home"
|
| "home"
|
||||||
| "assistant-prompt"
|
| "assistants"
|
||||||
| "assistant-workflow"
|
|
||||||
| "components-models"
|
| "components-models"
|
||||||
| "components-knowledge"
|
| "components-knowledge"
|
||||||
| "components-tools"
|
| "components-tools"
|
||||||
@@ -46,10 +44,7 @@ export function AppShell() {
|
|||||||
|
|
||||||
<div className="flex-1 overflow-y-auto px-8 py-10">
|
<div className="flex-1 overflow-y-auto px-8 py-10">
|
||||||
{active === "home" && <HomePage onNavigate={setActive} />}
|
{active === "home" && <HomePage onNavigate={setActive} />}
|
||||||
|
{active === "assistants" && <AssistantPage />}
|
||||||
{active === "assistant-prompt" && <AssistantPage />}
|
|
||||||
{active === "assistant-workflow" && <AssistantWorkflowPage />}
|
|
||||||
|
|
||||||
{active === "components-models" && <ComponentsModelsPage />}
|
{active === "components-models" && <ComponentsModelsPage />}
|
||||||
{active === "components-knowledge" && <ComponentsKnowledgePage />}
|
{active === "components-knowledge" && <ComponentsKnowledgePage />}
|
||||||
{active === "components-tools" && <ComponentsToolsPage />}
|
{active === "components-tools" && <ComponentsToolsPage />}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
Clock3,
|
Clock3,
|
||||||
Database,
|
Database,
|
||||||
Wrench,
|
Wrench,
|
||||||
FileText,
|
|
||||||
Home,
|
Home,
|
||||||
PlayCircle,
|
PlayCircle,
|
||||||
Video,
|
Video,
|
||||||
@@ -34,15 +33,6 @@ const mainItems: Array<{
|
|||||||
{ key: "test", label: "测试助手", icon: PlayCircle },
|
{ key: "test", label: "测试助手", icon: PlayCircle },
|
||||||
];
|
];
|
||||||
|
|
||||||
const assistantSubItems: Array<{
|
|
||||||
key: NavKey;
|
|
||||||
label: string;
|
|
||||||
icon: React.ComponentType<{ size?: number }>;
|
|
||||||
}> = [
|
|
||||||
{ key: "assistant-prompt", label: "提示词模式", icon: FileText },
|
|
||||||
{ key: "assistant-workflow", label: "工作流模式", icon: Workflow },
|
|
||||||
];
|
|
||||||
|
|
||||||
const componentSubItems: Array<{
|
const componentSubItems: Array<{
|
||||||
key: NavKey;
|
key: NavKey;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -59,8 +49,7 @@ export function Sidebar({
|
|||||||
onNavigate,
|
onNavigate,
|
||||||
onToggle,
|
onToggle,
|
||||||
}: SidebarProps) {
|
}: SidebarProps) {
|
||||||
const assistantActive =
|
const assistantActive = active === "assistants";
|
||||||
active === "assistant-prompt" || active === "assistant-workflow";
|
|
||||||
|
|
||||||
const componentActive =
|
const componentActive =
|
||||||
active === "components-models" || active === "components-knowledge" || active === "components-tools";
|
active === "components-models" || active === "components-knowledge" || active === "components-tools";
|
||||||
@@ -106,46 +95,14 @@ export function Sidebar({
|
|||||||
label="控制台"
|
label="控制台"
|
||||||
onClick={() => onNavigate("home")}
|
onClick={() => onNavigate("home")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="pt-2">
|
<div className="pt-2">
|
||||||
{collapsed ? (
|
|
||||||
<div
|
|
||||||
className="flex h-8 items-center justify-center"
|
|
||||||
aria-hidden="true"
|
|
||||||
title="创建助手"
|
|
||||||
>
|
|
||||||
<span className="h-px w-6 rounded-full bg-hairline-strong" />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
className={[
|
|
||||||
"flex h-11 w-full items-center gap-3 rounded-full px-3 text-sm",
|
|
||||||
assistantActive ? "text-foreground" : "text-muted-foreground",
|
|
||||||
].join(" ")}
|
|
||||||
>
|
|
||||||
<Bot size={18} />
|
|
||||||
<span className="font-medium">创建助手</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={[
|
|
||||||
"mt-1 space-y-1 transition-[padding] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]",
|
|
||||||
collapsed ? "pl-0" : "pl-5",
|
|
||||||
].join(" ")}
|
|
||||||
>
|
|
||||||
{assistantSubItems.map((item) => (
|
|
||||||
<NavButton
|
<NavButton
|
||||||
key={item.key}
|
active={assistantActive}
|
||||||
active={active === item.key}
|
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
icon={item.icon}
|
icon={Bot}
|
||||||
label={item.label}
|
label="创建助手"
|
||||||
onClick={() => onNavigate(item.key)}
|
onClick={() => onNavigate("assistants")}
|
||||||
small
|
|
||||||
/>
|
/>
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-2">
|
<div className="pt-2">
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import {
|
import {
|
||||||
Bot,
|
Bot,
|
||||||
Brain,
|
Brain,
|
||||||
|
Database,
|
||||||
Mic,
|
Mic,
|
||||||
|
MoreHorizontal,
|
||||||
|
Pencil,
|
||||||
|
Plus,
|
||||||
Rocket,
|
Rocket,
|
||||||
Save,
|
Save,
|
||||||
|
Search,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
|
Trash2,
|
||||||
|
Volume2,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -28,6 +34,7 @@ import {
|
|||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
type AssistantForm = {
|
type AssistantForm = {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -40,6 +47,47 @@ type AssistantForm = {
|
|||||||
enableInterrupt: boolean;
|
enableInterrupt: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type AssistantType = "提示词" | "工作流" | "Dify" | "FastGPT";
|
||||||
|
|
||||||
|
type AssistantListItem = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
type: AssistantType;
|
||||||
|
status: "运行中" | "草稿" | "已停用";
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockAssistants: AssistantListItem[] = [
|
||||||
|
{
|
||||||
|
id: "asst_001",
|
||||||
|
name: "政务视频咨询助手",
|
||||||
|
type: "提示词",
|
||||||
|
status: "运行中",
|
||||||
|
updatedAt: "2026-06-05 18:20",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "asst_002",
|
||||||
|
name: "热线工单辅助助手",
|
||||||
|
type: "工作流",
|
||||||
|
status: "草稿",
|
||||||
|
updatedAt: "2026-06-04 15:12",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "asst_003",
|
||||||
|
name: "Dify 知识库问答助手",
|
||||||
|
type: "Dify",
|
||||||
|
status: "运行中",
|
||||||
|
updatedAt: "2026-06-02 09:48",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "asst_004",
|
||||||
|
name: "FastGPT 售后咨询助手",
|
||||||
|
type: "FastGPT",
|
||||||
|
status: "已停用",
|
||||||
|
updatedAt: "2026-05-29 11:06",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
export function AssistantPage() {
|
export function AssistantPage() {
|
||||||
const [form, setForm] = useState<AssistantForm>({
|
const [form, setForm] = useState<AssistantForm>({
|
||||||
@@ -53,6 +101,8 @@ export function AssistantPage() {
|
|||||||
knowledgeBase: "政务政策知识库",
|
knowledgeBase: "政务政策知识库",
|
||||||
enableInterrupt: true,
|
enableInterrupt: true,
|
||||||
});
|
});
|
||||||
|
const [view, setView] = useState<"list" | "create">("list");
|
||||||
|
const [openMenuId, setOpenMenuId] = useState<string | null>(null);
|
||||||
|
|
||||||
function updateForm<K extends keyof AssistantForm>(
|
function updateForm<K extends keyof AssistantForm>(
|
||||||
key: K,
|
key: K,
|
||||||
@@ -63,7 +113,125 @@ export function AssistantPage() {
|
|||||||
[key]: value,
|
[key]: value,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
if (view === "list") {
|
||||||
|
return (
|
||||||
|
<div className="mx-auto flex w-full max-w-[1180px] flex-col gap-6">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<span className="h-3 w-3 rounded-full bg-blue-400 shadow-[0_0_0_4px_rgba(46,161,255,.16),0_0_14px_rgba(46,161,255,.35)]" />
|
||||||
|
<h1 className="text-3xl font-bold">创建助手</h1>
|
||||||
|
</div>
|
||||||
|
<p className="mt-2 text-sm text-muted-soft">
|
||||||
|
管理已有的视频助手,支持提示词、工作流、Dify 和 FastGPT 类型。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => setView("create")}
|
||||||
|
className="flex h-10 items-center gap-2 rounded-xl bg-blue-500 px-4 text-sm font-semibold text-white shadow-[0_8px_24px_rgba(29,123,255,.35)]"
|
||||||
|
>
|
||||||
|
<Plus size={16} />
|
||||||
|
创建助手
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section className="rounded-2xl border border-sidebar-border bg-sidebar p-5">
|
||||||
|
<div className="mb-5 flex items-center justify-between gap-4">
|
||||||
|
<div>
|
||||||
|
<div className="text-lg font-semibold">助手列表</div>
|
||||||
|
<div className="mt-1 text-sm text-muted-soft">
|
||||||
|
共 {mockAssistants.length} 个助手
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex h-10 w-[280px] items-center gap-3 rounded-xl border border-hairline-strong bg-surface-strong/60 px-3 text-sm text-muted-soft">
|
||||||
|
<Search size={16} />
|
||||||
|
<span>搜索助手名称...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="overflow-hidden rounded-2xl border border-hairline-strong">
|
||||||
|
<div className="grid grid-cols-[1fr_120px_120px_160px_120px] bg-surface-strong/70 px-5 py-3 text-xs font-medium text-muted-soft">
|
||||||
|
<div>助手名称</div>
|
||||||
|
<div>助手类型</div>
|
||||||
|
<div>状态</div>
|
||||||
|
<div>更新时间</div>
|
||||||
|
<div className="text-right">操作</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="divide-y divide-hairline-strong">
|
||||||
|
{mockAssistants.map((assistant) => (
|
||||||
|
<div
|
||||||
|
key={assistant.id}
|
||||||
|
className="grid grid-cols-[1fr_120px_120px_160px_120px] items-center px-5 py-4 text-sm transition-colors hover:bg-sidebar-accent/30"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div className="font-medium text-foreground">
|
||||||
|
{assistant.name}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-xs text-muted-soft">
|
||||||
|
{assistant.id}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<span className="rounded-full border border-hairline-strong bg-surface-strong px-2.5 py-1 text-xs text-muted-foreground">
|
||||||
|
{assistant.type}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
className={[
|
||||||
|
"rounded-full px-2.5 py-1 text-xs",
|
||||||
|
assistant.status === "运行中"
|
||||||
|
? "bg-green-500/10 text-green-400"
|
||||||
|
: assistant.status === "草稿"
|
||||||
|
? "bg-yellow-500/10 text-yellow-400"
|
||||||
|
: "bg-muted/30 text-muted-foreground",
|
||||||
|
].join(" ")}
|
||||||
|
>
|
||||||
|
{assistant.status}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-muted-soft">{assistant.updatedAt}</div>
|
||||||
|
|
||||||
|
<div className="relative flex justify-end gap-2">
|
||||||
|
<button className="flex h-8 items-center gap-1 rounded-lg border border-hairline-strong px-3 text-xs text-muted-foreground transition-colors hover:bg-sidebar-accent hover:text-foreground">
|
||||||
|
<Pencil size={14} />
|
||||||
|
编辑
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setOpenMenuId(
|
||||||
|
openMenuId === assistant.id ? null : assistant.id,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="flex h-8 w-8 items-center justify-center rounded-lg border border-hairline-strong text-muted-foreground transition-colors hover:bg-sidebar-accent hover:text-foreground"
|
||||||
|
>
|
||||||
|
<MoreHorizontal size={15} />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{openMenuId === assistant.id && (
|
||||||
|
<div className="absolute right-0 top-9 z-10 w-28 rounded-xl border border-hairline-strong bg-sidebar p-1 shadow-xl">
|
||||||
|
<button className="flex h-9 w-full items-center gap-2 rounded-lg px-3 text-sm text-red-400 transition-colors hover:bg-red-500/10">
|
||||||
|
<Trash2 size={14} />
|
||||||
|
删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto flex w-full max-w-[1180px] flex-col gap-6">
|
<div className="mx-auto flex w-full max-w-[1180px] flex-col gap-6">
|
||||||
<div className="flex items-start justify-between gap-6">
|
<div className="flex items-start justify-between gap-6">
|
||||||
@@ -78,6 +246,14 @@ export function AssistantPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex shrink-0 gap-3">
|
<div className="flex shrink-0 gap-3">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="lg"
|
||||||
|
className="gap-2 border-hairline-strong text-muted-foreground hover:text-foreground"
|
||||||
|
onClick={() => setView("list")}
|
||||||
|
>
|
||||||
|
返回列表
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="lg"
|
size="lg"
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function HomePage({ onNavigate }: HomePageProps) {
|
|||||||
<Button
|
<Button
|
||||||
size="lg"
|
size="lg"
|
||||||
className="gap-2 px-5"
|
className="gap-2 px-5"
|
||||||
onClick={() => onNavigate("assistant-prompt")}
|
onClick={() => onNavigate("assistants")}
|
||||||
>
|
>
|
||||||
<Plus size={17} />
|
<Plus size={17} />
|
||||||
创建助手
|
创建助手
|
||||||
|
|||||||
Reference in New Issue
Block a user