feat: expose ai-cad from home sidebar
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-06 15:04:30 +08:00
parent 413b5ffac1
commit 3de40dc959
2 changed files with 130 additions and 116 deletions

View File

@ -2105,7 +2105,7 @@ function AiCadRailButton({
/>
<button
className={cn(
"flex w-10 flex-col items-center gap-1 rounded-[10px] border px-0 py-2 transition-all duration-150 ease-out",
"flex w-10 flex-col items-center gap-1 rounded-[8px] border px-0 py-2 transition-all duration-150 ease-out",
active
? "border-white/20 bg-[#2a2a2a] text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.05),0_6px_18px_rgba(0,0,0,0.18)]"
: "border-white/10 bg-transparent text-white/55 hover:border-white/15 hover:bg-white/6 hover:text-white"
@ -2135,7 +2135,7 @@ function AiCadToolbarGroup({
return (
<div
className={cn(
"flex flex-wrap items-center gap-2 rounded-[10px] border border-white/10 bg-[#171717] px-2 py-1.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.03)]",
"flex flex-wrap items-center gap-2 rounded-[8px] border border-white/10 bg-[#171717] px-2 py-1.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.03)]",
className
)}
>
@ -2159,11 +2159,11 @@ function AiCadMessageActionButton({
}) {
return (
<button
className="inline-flex items-center gap-1.5 rounded-md border border-white/10 bg-[#1b1b1b] px-2.5 py-1 text-[11px] text-white/65 transition-all duration-150 ease-out hover:border-white/15 hover:bg-[#262626] hover:text-white"
className="inline-flex items-center gap-1.5 rounded-[8px] border border-white/10 bg-[#1b1b1b] px-2.5 py-1 text-[10px] text-white/65 transition-all duration-150 ease-out hover:border-white/15 hover:bg-[#262626] hover:text-white"
onClick={onClick}
type="button"
>
<Icon className="h-3.5 w-3.5" />
<Icon className="h-3 w-3" />
{label}
</button>
);
@ -3666,19 +3666,19 @@ export function AiCadWorkbench() {
</div>
<div className="flex flex-wrap items-center gap-2">
<Badge className="rounded-md border-white/10 bg-[#1d1d1d] text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-[#1d1d1d] text-[11px] text-white/70">
<FolderOpen className="mr-1 h-3.5 w-3.5" />
{isLoadingWorkspaceList ? "正在读取" : normalizedWorkspaceName}
</Badge>
<Badge className="rounded-md border-white/10 bg-[#1d1d1d] text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-[#1d1d1d] text-[11px] text-white/70">
{versions.length} versions
</Badge>
<Badge className="rounded-md border-white/10 bg-[#1d1d1d] text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-[#1d1d1d] text-[11px] text-white/70">
{completedCount} completed
</Badge>
<Badge
className={cn(
"gap-1.5 rounded-md border",
"gap-1.5 rounded-[8px] border text-[11px]",
workspaceSyncState === "synced"
? "border-emerald-400/20 bg-emerald-400/10 text-emerald-100"
: workspaceSyncState === "syncing" ||
@ -3852,7 +3852,7 @@ export function AiCadWorkbench() {
<div className="text-[10px] text-white/55 uppercase tracking-[0.22em]">
Panel Layout
</div>
<Badge className="rounded-md border-white/10 bg-[#171717] text-white/60">
<Badge className="rounded-[8px] border-white/10 bg-[#171717] text-[11px] text-white/58">
left tree / center canvas / right agent
</Badge>
</div>
@ -4020,7 +4020,7 @@ export function AiCadWorkbench() {
<div className="text-[10px] text-white/35 uppercase tracking-[0.22em]">
Canvas Workspace
</div>
<Badge className="rounded-md border-white/10 bg-[#171717] text-[10px] text-white/55 uppercase tracking-[0.18em]">
<Badge className="rounded-[8px] border-white/10 bg-[#171717] text-[10px] text-white/52 uppercase tracking-[0.18em]">
Docked Panels
</Badge>
</div>
@ -4188,7 +4188,7 @@ export function AiCadWorkbench() {
</CardDescription>
</div>
<div className="flex items-center gap-2">
<Badge className="rounded-md border-white/10 bg-[#1b1b1b] text-white/70">
<Badge className="rounded-[8px] border-white/10 bg-[#1b1b1b] text-[11px] text-white/68">
Agent
</Badge>
<button
@ -4212,15 +4212,15 @@ export function AiCadWorkbench() {
<div className="rounded-[8px] border border-white/10 bg-[#1b1b1b] px-3 py-2">
<div className="flex flex-wrap items-center justify-between gap-2">
<div className="flex flex-wrap items-center gap-2">
<Badge className="rounded-md border-white/10 bg-[#232323] text-white/70">
<Badge className="rounded-[8px] border-white/10 bg-[#232323] text-[11px] text-white/68">
Session Context
</Badge>
{activeVersion ? (
<Badge className="rounded-md border-white/10 bg-[#232323] text-white/70">
<Badge className="rounded-[8px] border-white/10 bg-[#232323] text-[11px] text-white/68">
Focus V{activeVersion.versionNumber}
</Badge>
) : (
<Badge className="rounded-md border-white/10 bg-[#232323] text-white/55">
<Badge className="rounded-[8px] border-white/10 bg-[#232323] text-[11px] text-white/55">
New thread
</Badge>
)}
@ -4290,7 +4290,7 @@ export function AiCadWorkbench() {
</div>
{message.role !== "user" &&
message.state ? (
<Badge className="rounded-md border-white/10 bg-[#1b1b1b] text-[10px] text-white/60 uppercase tracking-[0.16em]">
<Badge className="rounded-[8px] border-white/10 bg-[#1b1b1b] text-[10px] text-white/58 uppercase tracking-[0.16em]">
{getMessageStateLabel(message.state)}
</Badge>
) : null}
@ -4589,12 +4589,12 @@ export function AiCadWorkbench() {
<div className="mt-3 flex flex-wrap items-center justify-between gap-3 border-white/10 border-t pt-3">
<div className="flex flex-wrap items-center gap-2">
<Badge className="rounded-md border-white/10 bg-[#1f1f1f] text-white/70">
<Badge className="rounded-[8px] border-white/10 bg-[#1f1f1f] text-[11px] text-white/68">
{activeWorkspaceId
? "1 workspace"
: "No workspace"}
</Badge>
<Badge className="rounded-md border-white/10 bg-[#1f1f1f] text-white/70">
<Badge className="rounded-[8px] border-white/10 bg-[#1f1f1f] text-[11px] text-white/68">
{generationProvider === "kittycad-cad"
? "KCL-ready"
: modelVersion}
@ -4687,20 +4687,20 @@ export function AiCadWorkbench() {
</p>
</div>
{activeVersion ? (
<Badge className="rounded-md border-white/10 bg-[#232323] text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-[#232323] text-[11px] text-white/70">
depth {activeVersionLineage.length}
</Badge>
) : null}
</div>
<div className="mt-3 flex flex-wrap gap-2">
<Badge className="rounded-md border-white/10 bg-white/5 text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-white/5 text-[11px] text-white/70">
roots {rootVersionCount}
</Badge>
<Badge className="rounded-md border-white/10 bg-white/5 text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-white/5 text-[11px] text-white/70">
branches {branchPointCount}
</Badge>
<Badge className="rounded-md border-white/10 bg-white/5 text-white/72">
<Badge className="rounded-[8px] border-white/10 bg-white/5 text-[11px] text-white/70">
variants {derivedVariantCount}
</Badge>
</div>
@ -4914,7 +4914,7 @@ export function AiCadWorkbench() {
.slice(0, 2)
.map((insight) => (
<Badge
className="rounded-md border-white/10 bg-[#1b1b1b] text-[10px] text-white/62"
className="rounded-[8px] border-white/10 bg-[#1b1b1b] text-[10px] text-white/60"
key={`${version.id}-${insight.key}`}
>
{insight.shortLabel}
@ -4922,7 +4922,7 @@ export function AiCadWorkbench() {
))}
{versionSemanticInsights.length >
2 ? (
<Badge className="rounded-md border-white/10 bg-[#1b1b1b] text-[10px] text-white/55">
<Badge className="rounded-[8px] border-white/10 bg-[#1b1b1b] text-[10px] text-white/54">
+
{versionSemanticInsights.length -
2}

View File

@ -10,6 +10,7 @@ import {
ArrowUp,
BarChart3,
Bell,
Box,
Briefcase,
ChevronDown,
Clapperboard,
@ -1521,119 +1522,132 @@ export function LovartHome({
</TooltipTrigger>
<TooltipContent side="right">图片编辑</TooltipContent>
</Tooltip>
{siteSettingsData?.agentEnabled !== false ? (
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
onClick={() => router.push("/canvas?mode=agent")}
title="智能体"
onClick={() => router.push("/ai-cad")}
title="AI-CAD"
>
<Wand2 className="h-[18px] w-[18px]" />
<Box className="h-[18px] w-[18px]" />
</button>
</TooltipTrigger>
<TooltipContent side="right">智能体</TooltipContent>
<TooltipContent side="right">AI-CAD</TooltipContent>
</Tooltip>
) : null}
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
onClick={() => router.push("/video-canvas")}
title="视频画布"
>
<Clapperboard className="h-[18px] w-[18px]" />
</button>
</TooltipTrigger>
<TooltipContent side="right">视频画布</TooltipContent>
</Tooltip>
{siteSettingsData?.productPlanningEnabled !== false ? (
{siteSettingsData?.agentEnabled !== false ? (
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
onClick={() => router.push("/canvas?mode=agent")}
title="智能体"
>
<Wand2 className="h-[18px] w-[18px]" />
</button>
</TooltipTrigger>
<TooltipContent side="right">智能体</TooltipContent>
</Tooltip>
) : null}
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
onClick={() => router.push("/product-planning")}
title="商品策划"
onClick={() => router.push("/video-canvas")}
title="视频画布"
>
<BarChart3 className="h-[18px] w-[18px]" />
<Clapperboard className="h-[18px] w-[18px]" />
</button>
</TooltipTrigger>
<TooltipContent side="right">商品策划</TooltipContent>
<TooltipContent side="right">视频画布</TooltipContent>
</Tooltip>
) : null}
{siteSettingsData?.toolbox1Enabled !== false && toolbox1Links.length > 0 ? (
<HoverCard openDelay={80} closeDelay={80}>
<HoverCardTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
title={siteSettingsData?.toolbox1Name || "工具箱"}
{siteSettingsData?.productPlanningEnabled !== false ? (
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
onClick={() => router.push("/product-planning")}
title="商品策划"
>
<BarChart3 className="h-[18px] w-[18px]" />
</button>
</TooltipTrigger>
<TooltipContent side="right">商品策划</TooltipContent>
</Tooltip>
) : null}
{siteSettingsData?.toolbox1Enabled !== false && toolbox1Links.length > 0 ? (
<HoverCard openDelay={80} closeDelay={80}>
<HoverCardTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
title={siteSettingsData?.toolbox1Name || "工具箱"}
>
<Briefcase className="h-[18px] w-[18px]" />
</button>
</HoverCardTrigger>
<HoverCardContent
side="right"
align="start"
className={`w-[248px] ${sidebarPopupBaseClass}`}
>
<Briefcase className="h-[18px] w-[18px]" />
</button>
</HoverCardTrigger>
<HoverCardContent
side="right"
align="start"
className={`w-[248px] ${sidebarPopupBaseClass}`}
>
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/50">
{siteSettingsData?.toolbox1Name || "工具箱"}
</div>
<div className="space-y-1">
{toolbox1Links.map((link) => (
<button
key={link.id}
type="button"
className="flex w-full items-center justify-between rounded-xl px-3 py-2 text-left text-[13px] text-black/80 hover:bg-black/5"
onClick={() => openNavLink(link.url)}
>
<span className="line-clamp-1">{link.name}</span>
<ArrowRight className="h-3.5 w-3.5 text-black/35" />
</button>
))}
</div>
</HoverCardContent>
</HoverCard>
) : null}
{siteSettingsData?.toolbox2Enabled === true && toolbox2Links.length > 0 ? (
<HoverCard openDelay={80} closeDelay={80}>
<HoverCardTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
title={siteSettingsData?.toolbox2Name || "工具箱2"}
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/50">
{siteSettingsData?.toolbox1Name || "工具箱"}
</div>
<div className="space-y-1">
{toolbox1Links.map((link) => (
<button
key={link.id}
type="button"
className="flex w-full items-center justify-between rounded-xl px-3 py-2 text-left text-[13px] text-black/80 hover:bg-black/5"
onClick={() => openNavLink(link.url)}
>
<span className="line-clamp-1">{link.name}</span>
<ArrowRight className="h-3.5 w-3.5 text-black/35" />
</button>
))}
</div>
</HoverCardContent>
</HoverCard>
) : null}
{siteSettingsData?.toolbox2Enabled === true && toolbox2Links.length > 0 ? (
<HoverCard openDelay={80} closeDelay={80}>
<HoverCardTrigger asChild>
<button
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
title={siteSettingsData?.toolbox2Name || "工具箱2"}
>
<Briefcase className="h-[18px] w-[18px]" />
</button>
</HoverCardTrigger>
<HoverCardContent
side="right"
align="start"
className={`w-[248px] ${sidebarPopupBaseClass}`}
>
<Briefcase className="h-[18px] w-[18px]" />
</button>
</HoverCardTrigger>
<HoverCardContent
side="right"
align="start"
className={`w-[248px] ${sidebarPopupBaseClass}`}
>
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/50">
{siteSettingsData?.toolbox2Name || "工具箱2"}
</div>
<div className="space-y-1">
{toolbox2Links.map((link) => (
<button
key={link.id}
type="button"
className="flex w-full items-center justify-between rounded-xl px-3 py-2 text-left text-[13px] text-black/80 hover:bg-black/5"
onClick={() => openNavLink(link.url)}
>
<span className="line-clamp-1">{link.name}</span>
<ArrowRight className="h-3.5 w-3.5 text-black/35" />
</button>
))}
</div>
</HoverCardContent>
</HoverCard>
) : null}
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/50">
{siteSettingsData?.toolbox2Name || "工具箱2"}
</div>
<div className="space-y-1">
{toolbox2Links.map((link) => (
<button
key={link.id}
type="button"
className="flex w-full items-center justify-between rounded-xl px-3 py-2 text-left text-[13px] text-black/80 hover:bg-black/5"
onClick={() => openNavLink(link.url)}
>
<span className="line-clamp-1">{link.name}</span>
<ArrowRight className="h-3.5 w-3.5 text-black/35" />
</button>
))}
</div>
</HoverCardContent>
</HoverCard>
) : null}
{user?.type === "admin" || user?.type === "agent_admin" ? (
<Tooltip>
<TooltipTrigger asChild>