refactor: simplify ai-cad workbench chrome
This commit is contained in:
parent
c74dffdcd6
commit
6d07b1a915
@ -17,10 +17,14 @@ import {
|
||||
Grid3X3,
|
||||
History,
|
||||
Loader2,
|
||||
MousePointer2,
|
||||
Orbit,
|
||||
Pencil,
|
||||
Plug,
|
||||
Plus,
|
||||
RotateCcw,
|
||||
Send,
|
||||
Settings2,
|
||||
ThumbsDown,
|
||||
ThumbsUp,
|
||||
Trash2,
|
||||
@ -57,6 +61,13 @@ import {
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Collapsible, CollapsibleContent } from "@/components/ui/collapsible";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import {
|
||||
@ -2336,6 +2347,8 @@ export function AiCadWorkbench() {
|
||||
const [modelingCutType, setModelingCutType] =
|
||||
useState<ModelingCutType>("fillet");
|
||||
const [isModelingBusy, setIsModelingBusy] = useState(false);
|
||||
const [isModelingToolsDialogOpen, setIsModelingToolsDialogOpen] =
|
||||
useState(false);
|
||||
const [messages, setMessages] = useState<ChatMessage[]>(
|
||||
createWelcomeMessages
|
||||
);
|
||||
@ -4269,10 +4282,23 @@ export function AiCadWorkbench() {
|
||||
: "Ready for first pass"}
|
||||
</Badge>
|
||||
{generationProvider === "kittycad-cad" ? (
|
||||
<AiCadToolbarGroup className="shrink-0" label="Modeling">
|
||||
<AiCadToolbarGroup className="shrink-0" label="Tools">
|
||||
<button
|
||||
className="inline-flex h-7 items-center gap-1.5 rounded-[7px] border border-[#ddd7ca] bg-white px-2.5 text-[#5f594d] text-[12px] transition-all duration-150 ease-out hover:bg-[#faf7ef] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={
|
||||
isModelingBusy || !isOfficialModelingAvailable
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(handleCreateRectangleSketch())
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
Start Sketch
|
||||
</button>
|
||||
<button
|
||||
className={cn(
|
||||
"inline-flex h-7 items-center gap-1.5 rounded-[7px] border px-2 text-[12px] transition-all duration-150 ease-out",
|
||||
"inline-flex h-7 w-7 items-center justify-center rounded-[7px] border transition-all duration-150 ease-out disabled:cursor-not-allowed disabled:opacity-50",
|
||||
modelingConnectionState === "connected"
|
||||
? "border-[#bfd9c9] bg-[#ecfbf2] text-[#173225]"
|
||||
: "border-[#ddd7ca] bg-white text-[#5f594d] hover:bg-[#faf7ef]"
|
||||
@ -4287,57 +4313,66 @@ export function AiCadWorkbench() {
|
||||
: ensureModelingSession()
|
||||
)
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
{modelingSessionId ? "Connected" : "Connect"}
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex h-7 items-center gap-1.5 rounded-[7px] border border-[#ddd7ca] bg-white px-2 text-[#5f594d] text-[12px] transition-all duration-150 ease-out hover:bg-[#faf7ef]"
|
||||
disabled={
|
||||
isModelingBusy || !isOfficialModelingAvailable
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(handleCreateRectangleSketch())
|
||||
title={
|
||||
modelingSessionId
|
||||
? "断开官方 modeling 会话"
|
||||
: "连接官方 modeling 会话"
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
Sketch
|
||||
<Plug className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex h-7 items-center gap-1.5 rounded-[7px] border border-[#ddd7ca] bg-white px-2 text-[#5f594d] text-[12px] transition-all duration-150 ease-out hover:bg-[#faf7ef]"
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-[7px] border border-[#ddd7ca] bg-white text-[#5f594d] transition-all duration-150 ease-out hover:bg-[#faf7ef] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSketchId
|
||||
}
|
||||
onClick={() => swallowAsync(handleExtrudeSketch())}
|
||||
title="拉伸当前草图"
|
||||
type="button"
|
||||
>
|
||||
Extrude
|
||||
<Box className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex h-7 items-center gap-1.5 rounded-[7px] border border-[#ddd7ca] bg-white px-2 text-[#5f594d] text-[12px] transition-all duration-150 ease-out hover:bg-[#faf7ef]"
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-[7px] border border-[#ddd7ca] bg-white text-[#5f594d] transition-all duration-150 ease-out hover:bg-[#faf7ef] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSolidId
|
||||
}
|
||||
onClick={() => swallowAsync(handleSelectCurrentBody())}
|
||||
title="选择当前实体"
|
||||
type="button"
|
||||
>
|
||||
Select
|
||||
<MousePointer2 className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex h-7 items-center gap-1.5 rounded-[7px] border border-[#ddd7ca] bg-white px-2 text-[#5f594d] text-[12px] transition-all duration-150 ease-out hover:bg-[#faf7ef]"
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-[7px] border border-[#ddd7ca] bg-white text-[#5f594d] transition-all duration-150 ease-out hover:bg-[#faf7ef] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSolidId
|
||||
}
|
||||
onClick={() => swallowAsync(handleCutSelectedEdges())}
|
||||
title={
|
||||
modelingCutType === "fillet"
|
||||
? "对选中边执行圆角"
|
||||
: "对选中边执行倒角"
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
{modelingCutType === "fillet" ? "Fillet" : "Chamfer"}
|
||||
<WandSparkles className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-[7px] border border-[#ddd7ca] bg-white text-[#5f594d] transition-all duration-150 ease-out hover:bg-[#faf7ef] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={!isOfficialModelingAvailable}
|
||||
onClick={() => setIsModelingToolsDialogOpen(true)}
|
||||
title="打开官方建模工具参数"
|
||||
type="button"
|
||||
>
|
||||
<Settings2 className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</AiCadToolbarGroup>
|
||||
) : null}
|
||||
@ -4627,234 +4662,6 @@ export function AiCadWorkbench() {
|
||||
</ScrollArea>
|
||||
|
||||
<div className="border-[#e6e0d3] border-t bg-white px-4 py-4">
|
||||
{generationProvider === "kittycad-cad" ? (
|
||||
<div className="mb-4 rounded-[10px] border border-[#ddd7ca] bg-[#fbfaf6] p-3">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<div>
|
||||
<div className="font-medium text-[#201c16] text-sm">
|
||||
官方建模工具
|
||||
</div>
|
||||
<p className="mt-1 text-[#7f7768] text-xs leading-5">
|
||||
这一组直接走官方{" "}
|
||||
<code className="rounded bg-white px-1 py-0.5 text-[11px]">
|
||||
ws/modeling/commands
|
||||
</code>
|
||||
,不是前端假按钮。
|
||||
</p>
|
||||
</div>
|
||||
<Badge
|
||||
className={cn(
|
||||
"rounded-full px-2 py-0.5 text-[10px]",
|
||||
modelingConnectionState === "connected"
|
||||
? "border-emerald-200 bg-emerald-50 text-emerald-700"
|
||||
: modelingConnectionState === "error"
|
||||
? "border-rose-200 bg-rose-50 text-rose-700"
|
||||
: "border-[#ddd7ca] bg-white text-[#5f594d]"
|
||||
)}
|
||||
>
|
||||
{modelingConnectionState}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 grid gap-2 sm:grid-cols-3">
|
||||
<Input
|
||||
className="h-9 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingWidth(event.target.value)
|
||||
}
|
||||
placeholder="宽度"
|
||||
value={modelingWidth}
|
||||
/>
|
||||
<Input
|
||||
className="h-9 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingHeight(event.target.value)
|
||||
}
|
||||
placeholder="高度"
|
||||
value={modelingHeight}
|
||||
/>
|
||||
<Input
|
||||
className="h-9 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingDepth(event.target.value)
|
||||
}
|
||||
placeholder="拉伸深度"
|
||||
value={modelingDepth}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-2 grid gap-2 sm:grid-cols-[minmax(0,1fr)_120px_120px]">
|
||||
<Input
|
||||
className="h-9 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingEdgeIndices(event.target.value)
|
||||
}
|
||||
placeholder="边索引,例如 0,1,2,3"
|
||||
value={modelingEdgeIndices}
|
||||
/>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setModelingCutType(value as ModelingCutType)
|
||||
}
|
||||
value={modelingCutType}
|
||||
>
|
||||
<SelectTrigger className="h-9 border-[#ddd7ca] bg-white text-sm">
|
||||
<SelectValue placeholder="切边类型" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="fillet">Fillet</SelectItem>
|
||||
<SelectItem value="chamfer">
|
||||
Chamfer
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
className="h-9 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingCutSize(event.target.value)
|
||||
}
|
||||
placeholder="半径 / 距离"
|
||||
value={modelingCutSize}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 flex flex-wrap gap-2">
|
||||
<Button
|
||||
className="h-8 rounded-[8px] border-[#ddd7ca] bg-white text-[#201c16] hover:bg-[#f4f1e8]"
|
||||
disabled={
|
||||
isModelingBusy || !isOfficialModelingAvailable
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(
|
||||
modelingSessionId
|
||||
? handleDisconnectModelingSession()
|
||||
: ensureModelingSession()
|
||||
)
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
{modelingSessionId ? "断开会话" : "连接会话"}
|
||||
</Button>
|
||||
<Button
|
||||
className="h-8 rounded-[8px]"
|
||||
disabled={
|
||||
isModelingBusy || !isOfficialModelingAvailable
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(handleCreateRectangleSketch())
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
草图矩形
|
||||
</Button>
|
||||
<Button
|
||||
className="h-8 rounded-[8px]"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSketchId
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(handleExtrudeSketch())
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
拉伸
|
||||
</Button>
|
||||
<Button
|
||||
className="h-8 rounded-[8px]"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSolidId
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(handleSelectCurrentBody())
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
选择当前实体
|
||||
</Button>
|
||||
<Button
|
||||
className="h-8 rounded-[8px]"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSolidId
|
||||
}
|
||||
onClick={() =>
|
||||
swallowAsync(handleCutSelectedEdges())
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
{modelingCutType === "fillet"
|
||||
? "执行圆角"
|
||||
: "执行倒角"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 space-y-1 text-[#7f7768] text-xs leading-5">
|
||||
<p>
|
||||
当前平面:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{truncateIdentifier(modelingPlaneId, 16)}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
当前草图:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{truncateIdentifier(modelingSketchId, 16)}
|
||||
</span>
|
||||
,当前实体:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{truncateIdentifier(modelingSolidId, 16)}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
当前选择:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{modelingSelectedEntityIds.length > 0
|
||||
? modelingSelectedEntityIds
|
||||
.map((item) =>
|
||||
truncateIdentifier(item, 10)
|
||||
)
|
||||
.join(", ")
|
||||
: "未选择"}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{modelingError ? (
|
||||
<div className="mt-3 rounded-[8px] border border-rose-200 bg-rose-50 px-3 py-2 text-rose-700 text-xs leading-5">
|
||||
{modelingError}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{modelingLogLines.length > 0 ? (
|
||||
<div className="mt-3 rounded-[8px] border border-[#e3ddcf] bg-white px-3 py-2">
|
||||
<div className="text-[#8a8272] text-[11px] uppercase tracking-[0.12em]">
|
||||
session log
|
||||
</div>
|
||||
<div className="mt-2 space-y-1 text-[#5f594d] text-xs leading-5">
|
||||
{modelingLogLines.slice(0, 3).map((line) => (
|
||||
<p key={line}>{line}</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="rounded-[8px] border border-[#d7d0c1] bg-white">
|
||||
<Textarea
|
||||
className="min-h-[120px] resize-none border-0 bg-transparent px-4 py-4 text-[#201c16] text-[15px] placeholder:text-[#9a9385] focus-visible:ring-0 focus-visible:ring-offset-0"
|
||||
@ -4891,6 +4698,20 @@ export function AiCadWorkbench() {
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{generationProvider === "kittycad-cad" ? (
|
||||
<Button
|
||||
className="h-10 w-10 rounded-[8px] border-[#ddd7ca] bg-white p-0 text-[#5f594d] hover:bg-[#f4f1e8]"
|
||||
onClick={() =>
|
||||
setIsModelingToolsDialogOpen(true)
|
||||
}
|
||||
size="icon"
|
||||
title="打开官方建模工具"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<Settings2 className="h-4 w-4" />
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
@ -5744,28 +5565,20 @@ export function AiCadWorkbench() {
|
||||
<div className="flex h-12 items-center justify-between border-[#e6e0d3] border-b px-4">
|
||||
<div className="flex min-w-0 items-center gap-2.5">
|
||||
<Orbit className="h-4 w-4 text-[#6f695d]" />
|
||||
<div className="font-medium text-[15px]">
|
||||
{activeVersion ? "建模画布" : "Canvas"}
|
||||
</div>
|
||||
{activeVersion ? null : (
|
||||
<div className="truncate text-[#8b8375] text-[12px]">
|
||||
The center canvas stays focused on the current
|
||||
model.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{activeVersion ? (
|
||||
<div className="text-[#8b8375] text-[11px]">
|
||||
Preview-first canvas
|
||||
</div>
|
||||
) : null}
|
||||
<div className="font-medium text-[15px]">Canvas</div>
|
||||
{activeVersion ? (
|
||||
<Badge className="rounded-md border-[#ddd7ca] bg-white text-[#5f594d]">
|
||||
V{activeVersion.versionNumber}
|
||||
</Badge>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="text-[#8b8375] text-[11px]">
|
||||
{activeVersion
|
||||
? "Preview-first canvas"
|
||||
: "Ready for prompt"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="min-h-0 flex-1 overflow-hidden p-0">
|
||||
@ -6878,6 +6691,227 @@ export function AiCadWorkbench() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
onOpenChange={setIsModelingToolsDialogOpen}
|
||||
open={isModelingToolsDialogOpen}
|
||||
>
|
||||
<DialogContent className="max-w-2xl border-[#ddd7ca] bg-[#fbfaf6] p-0 text-[#201c16]">
|
||||
<DialogHeader className="border-[#e6e0d3] border-b px-6 py-5">
|
||||
<DialogTitle className="flex items-center gap-2 text-[18px]">
|
||||
<WandSparkles className="h-4 w-4 text-[#6f695d]" />
|
||||
官方建模工具
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-[#7f7768] text-sm leading-6">
|
||||
这里的动作直接调用 Zoo 官方{" "}
|
||||
<code className="rounded bg-white px-1 py-0.5 text-[#5f594d] text-[11px]">
|
||||
ws/modeling/commands
|
||||
</code>
|
||||
。主界面保持画布优先,这些参数收在弹层里。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4 px-6 py-5">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Badge
|
||||
className={cn(
|
||||
"rounded-full px-2 py-0.5 text-[10px]",
|
||||
modelingConnectionState === "connected"
|
||||
? "border-emerald-200 bg-emerald-50 text-emerald-700"
|
||||
: modelingConnectionState === "error"
|
||||
? "border-rose-200 bg-rose-50 text-rose-700"
|
||||
: "border-[#ddd7ca] bg-white text-[#5f594d]"
|
||||
)}
|
||||
>
|
||||
{modelingConnectionState}
|
||||
</Badge>
|
||||
<Badge className="rounded-full border-[#ddd7ca] bg-white px-2 py-0.5 text-[#5f594d] text-[10px]">
|
||||
{modelingSessionId ? "session live" : "session idle"}
|
||||
</Badge>
|
||||
<Badge className="rounded-full border-[#ddd7ca] bg-white px-2 py-0.5 text-[#5f594d] text-[10px]">
|
||||
{modelingCutType === "fillet" ? "fillet" : "chamfer"}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
<Input
|
||||
className="h-10 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) => setModelingWidth(event.target.value)}
|
||||
placeholder="宽度"
|
||||
value={modelingWidth}
|
||||
/>
|
||||
<Input
|
||||
className="h-10 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingHeight(event.target.value)
|
||||
}
|
||||
placeholder="高度"
|
||||
value={modelingHeight}
|
||||
/>
|
||||
<Input
|
||||
className="h-10 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) => setModelingDepth(event.target.value)}
|
||||
placeholder="拉伸深度"
|
||||
value={modelingDepth}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 sm:grid-cols-[minmax(0,1fr)_140px_140px]">
|
||||
<Input
|
||||
className="h-10 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingEdgeIndices(event.target.value)
|
||||
}
|
||||
placeholder="边索引,例如 0,1,2,3"
|
||||
value={modelingEdgeIndices}
|
||||
/>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setModelingCutType(value as ModelingCutType)
|
||||
}
|
||||
value={modelingCutType}
|
||||
>
|
||||
<SelectTrigger className="h-10 border-[#ddd7ca] bg-white text-sm">
|
||||
<SelectValue placeholder="切边类型" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="fillet">Fillet</SelectItem>
|
||||
<SelectItem value="chamfer">Chamfer</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
className="h-10 border-[#ddd7ca] bg-white text-sm"
|
||||
onChange={(event) =>
|
||||
setModelingCutSize(event.target.value)
|
||||
}
|
||||
placeholder="半径 / 距离"
|
||||
value={modelingCutSize}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
className="rounded-full border-[#ddd7ca] bg-white text-[#201c16] hover:bg-[#f4f1e8]"
|
||||
disabled={isModelingBusy || !isOfficialModelingAvailable}
|
||||
onClick={() =>
|
||||
swallowAsync(
|
||||
modelingSessionId
|
||||
? handleDisconnectModelingSession()
|
||||
: ensureModelingSession()
|
||||
)
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
{modelingSessionId ? "断开会话" : "连接会话"}
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-full border-[#ddd7ca] bg-white text-[#201c16] hover:bg-[#f4f1e8]"
|
||||
disabled={isModelingBusy || !isOfficialModelingAvailable}
|
||||
onClick={() =>
|
||||
swallowAsync(handleCreateRectangleSketch())
|
||||
}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
草图矩形
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-full border-[#ddd7ca] bg-white text-[#201c16] hover:bg-[#f4f1e8]"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSketchId
|
||||
}
|
||||
onClick={() => swallowAsync(handleExtrudeSketch())}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
拉伸
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-full border-[#ddd7ca] bg-white text-[#201c16] hover:bg-[#f4f1e8]"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSolidId
|
||||
}
|
||||
onClick={() => swallowAsync(handleSelectCurrentBody())}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
选择当前实体
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-full border-[#ddd7ca] bg-white text-[#201c16] hover:bg-[#f4f1e8]"
|
||||
disabled={
|
||||
isModelingBusy ||
|
||||
!isOfficialModelingAvailable ||
|
||||
!modelingSolidId
|
||||
}
|
||||
onClick={() => swallowAsync(handleCutSelectedEdges())}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
{modelingCutType === "fillet" ? "执行圆角" : "执行倒角"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border border-[#e3ddcf] bg-white px-4 py-3 text-[#7f7768] text-xs leading-6">
|
||||
<p>
|
||||
当前平面:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{truncateIdentifier(modelingPlaneId, 16)}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
当前草图:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{truncateIdentifier(modelingSketchId, 16)}
|
||||
</span>
|
||||
,当前实体:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{truncateIdentifier(modelingSolidId, 16)}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
当前选择:
|
||||
<span className="font-mono text-[#5f594d]">
|
||||
{modelingSelectedEntityIds.length > 0
|
||||
? modelingSelectedEntityIds
|
||||
.map((item) => truncateIdentifier(item, 10))
|
||||
.join(", ")
|
||||
: "未选择"}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{modelingError ? (
|
||||
<div className="rounded-[10px] border border-rose-200 bg-rose-50 px-4 py-3 text-rose-700 text-sm leading-6">
|
||||
{modelingError}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{modelingLogLines.length > 0 ? (
|
||||
<div className="rounded-[10px] border border-[#e3ddcf] bg-white px-4 py-3">
|
||||
<div className="text-[#8a8272] text-[11px] uppercase tracking-[0.12em]">
|
||||
session log
|
||||
</div>
|
||||
<div className="mt-2 space-y-1 text-[#5f594d] text-xs leading-5">
|
||||
{modelingLogLines.slice(0, 4).map((line) => (
|
||||
<p key={line}>{line}</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user