Skip to content

Commit 927f017

Browse files
committed
feat(task-detail): 右侧面板标题栏增加关闭按钮
1 parent 0a63afb commit 927f017

5 files changed

Lines changed: 77 additions & 16 deletions

File tree

frontend/src/components/console/task/task-changes-panel.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ interface TaskChangesPanelProps {
1414
fileChangesMap: Map<string, RepoFileChange>
1515
taskManager: TaskWebSocketManager | null
1616
disabled?: boolean
17+
onClosePanel?: () => void
1718
}
1819

19-
export function TaskChangesPanel({ fileChanges, fileChangesMap, taskManager, disabled }: TaskChangesPanelProps) {
20+
export function TaskChangesPanel({ fileChanges, fileChangesMap, taskManager, disabled, onClosePanel }: TaskChangesPanelProps) {
2021
const sortedPaths = [...fileChanges].sort((a, b) => a.localeCompare(b))
2122
const [selectedFile, setSelectedFile] = useState<string | null>(null)
2223
const [diffContent, setDiffContent] = useState<string>("")
@@ -41,8 +42,13 @@ export function TaskChangesPanel({ fileChanges, fileChangesMap, taskManager, dis
4142
if (disabled) {
4243
return (
4344
<div className="flex flex-col h-full min-h-0 rounded-lg border overflow-hidden">
44-
<div className="flex items-center gap-2 px-4 py-1 min-h-11 border-b bg-muted/50 shrink-0">
45+
<div className="flex items-center justify-between gap-2 pl-4 pr-2 py-1 min-h-11 border-b bg-muted/50 shrink-0">
4546
<span className="text-sm font-medium">文件变更</span>
47+
{onClosePanel && (
48+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
49+
<IconX className="size-4" />
50+
</Button>
51+
)}
4652
</div>
4753
<div className="flex-1 min-h-0 flex flex-col">
4854
<Empty className="border border-dashed w-full flex-1 min-h-0">
@@ -106,8 +112,13 @@ export function TaskChangesPanel({ fileChanges, fileChangesMap, taskManager, dis
106112

107113
const fileListPanel = (
108114
<div className="flex flex-col min-h-0 flex-1 rounded-lg border overflow-hidden">
109-
<div className="flex items-center gap-2 px-4 py-1 min-h-11 border-b bg-muted/30 shrink-0">
115+
<div className="flex items-center justify-between gap-2 pl-4 pr-2 py-1 min-h-11 border-b bg-muted/30 shrink-0">
110116
<span className="text-sm font-medium">变更文件</span>
117+
{onClosePanel && (
118+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
119+
<IconX className="size-4" />
120+
</Button>
121+
)}
111122
</div>
112123
<div className={cn("flex-1 min-h-0 py-2 overflow-x-hidden", sortedPaths.length === 0 ? "flex flex-col" : "overflow-y-auto")}>
113124
{sortedPaths.length === 0 ? (

frontend/src/components/console/task/task-file-explorer.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ interface TaskFileExplorerProps {
4444
changedPaths?: string[]
4545
taskManager: TaskWebSocketManager | null
4646
onRefresh?: () => void
47+
onClosePanel?: () => void
4748
envid?: string
4849
}
4950

@@ -352,6 +353,7 @@ export const TaskFileExplorer = ({
352353
changedPaths,
353354
taskManager,
354355
onRefresh,
356+
onClosePanel,
355357
envid,
356358
}: TaskFileExplorerProps): React.JSX.Element => {
357359
const rootRef = useRef<DirNodeRef>(null)
@@ -502,8 +504,13 @@ export const TaskFileExplorer = ({
502504
if (disabled) {
503505
return (
504506
<div className={cn("flex flex-col h-full min-h-0", className)}>
505-
<div className="flex items-center gap-2 px-4 py-1 min-h-11 border-b bg-muted/50 shrink-0">
507+
<div className="flex items-center justify-between gap-2 px-4 py-1 min-h-11 border-b bg-muted/50 shrink-0">
506508
<span className="text-sm font-medium">项目文件</span>
509+
{onClosePanel && (
510+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
511+
<IconX className="size-4" />
512+
</Button>
513+
)}
507514
</div>
508515
<div className="flex-1 min-h-0 flex flex-col">
509516
<Empty className="border border-dashed w-full flex-1 min-h-0">
@@ -523,7 +530,7 @@ export const TaskFileExplorer = ({
523530

524531
const fileTreePanel = (
525532
<div className="flex flex-col min-h-0 flex-1 rounded-lg border overflow-hidden">
526-
<div className="flex items-center justify-between px-4 py-1 min-h-11 border-b bg-muted/30 shrink-0">
533+
<div className="flex items-center justify-between pl-4 pr-2 py-1 min-h-11 border-b bg-muted/30 shrink-0">
527534
<div className="flex items-center gap-2">
528535
<span className="text-sm font-medium">项目文件</span>
529536
</div>
@@ -544,6 +551,16 @@ export const TaskFileExplorer = ({
544551
alwaysVisible
545552
hideDestructive
546553
/>
554+
{onClosePanel && (
555+
<Tooltip>
556+
<TooltipTrigger asChild>
557+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
558+
<IconX className="size-4" />
559+
</Button>
560+
</TooltipTrigger>
561+
<TooltipContent>关闭面板</TooltipContent>
562+
</Tooltip>
563+
)}
547564
</div>
548565
</div>
549566
<div className="flex-1 min-h-0 overflow-y-auto py-1 flex flex-col">

frontend/src/components/console/task/task-preview-panel.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { Item, ItemContent, ItemTitle, ItemGroup, ItemActions, ItemDescription }
2323
import { Spinner } from "@/components/ui/spinner"
2424
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
2525
import { apiRequest } from "@/utils/requestUtils"
26-
import { IconAccessPoint, IconAlertCircle, IconCloudOff, IconCopy, IconDotsVertical, IconHandStop, IconTrash } from "@tabler/icons-react"
26+
import { IconAccessPoint, IconAlertCircle, IconCloudOff, IconCopy, IconDotsVertical, IconHandStop, IconTrash, IconX } from "@tabler/icons-react"
2727
import { useState } from "react"
2828
import { toast } from "sonner"
2929

@@ -33,6 +33,7 @@ interface TaskPreviewPanelProps {
3333
vmId: string | undefined
3434
onSuccess?: () => void
3535
disabled?: boolean
36+
onClosePanel?: () => void
3637
}
3738

3839
export function TaskPreviewPanel({
@@ -41,6 +42,7 @@ export function TaskPreviewPanel({
4142
vmId,
4243
onSuccess,
4344
disabled,
45+
onClosePanel,
4446
}: TaskPreviewPanelProps) {
4547
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false)
4648
const [portToDelete, setPortToDelete] = useState<DomainVMPort | null>(null)
@@ -152,8 +154,13 @@ export function TaskPreviewPanel({
152154
if (disabled) {
153155
return (
154156
<div className="flex flex-col h-full min-h-0 rounded-lg border overflow-hidden">
155-
<div className="flex items-center gap-2 px-3 py-2 min-h-12 border-b bg-muted/50 shrink-0">
157+
<div className="flex items-center justify-between gap-2 pl-4 pr-2 py-2 min-h-12 border-b bg-muted/50 shrink-0">
156158
<span className="text-sm font-medium">在线预览</span>
159+
{onClosePanel && (
160+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
161+
<IconX className="size-4" />
162+
</Button>
163+
)}
157164
</div>
158165
<div className="flex-1 min-h-0 flex flex-col p-2">
159166
<Empty className="w-full flex-1 min-h-0">
@@ -174,8 +181,13 @@ export function TaskPreviewPanel({
174181
return (
175182
<>
176183
<div className="flex flex-col h-full min-h-0 rounded-lg border overflow-hidden">
177-
<div className="flex items-center gap-2 px-4 py-1 min-h-11 border-b bg-muted/30 shrink-0">
184+
<div className="flex items-center justify-between gap-2 pl-4 pr-2 py-1 min-h-11 border-b bg-muted/30 shrink-0">
178185
<span className="text-sm font-medium">在线预览</span>
186+
{onClosePanel && (
187+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
188+
<IconX className="size-4" />
189+
</Button>
190+
)}
179191
</div>
180192
<div className="flex-1 min-h-0 overflow-auto flex flex-col p-2">
181193
{(ports && ports.length > 0) ? (

frontend/src/components/console/task/task-terminal-panel.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import { Empty, EmptyDescription, EmptyHeader, EmptyMedia } from "@/components/u
2323
interface TaskTerminalPanelProps {
2424
envid?: string
2525
disabled?: boolean
26+
onClosePanel?: () => void
2627
}
2728

28-
export function TaskTerminalPanel({ envid, disabled }: TaskTerminalPanelProps) {
29+
export function TaskTerminalPanel({ envid, disabled, onClosePanel }: TaskTerminalPanelProps) {
2930
const [sessions, setSessions] = useState<DomainTerminal[]>([])
3031
const [currentSessionId, setCurrentSessionId] = useState<string | null>(null)
3132
const [signal, setSignal] = useState<number>(0)
@@ -139,9 +140,16 @@ export function TaskTerminalPanel({ envid, disabled }: TaskTerminalPanelProps) {
139140
if (disabled) {
140141
return (
141142
<div className="flex flex-col h-full min-h-0">
142-
<div className="flex items-center gap-2 px-4 py-1 min-h-11 border-b bg-muted/50 shrink-0">
143-
<IconTerminal2 className="size-4 text-primary" />
144-
<span className="text-sm font-medium">终端</span>
143+
<div className="flex items-center justify-between gap-2 px-4 py-1 min-h-11 border-b bg-muted/50 shrink-0">
144+
<div className="flex items-center gap-2">
145+
<IconTerminal2 className="size-4 text-primary" />
146+
<span className="text-sm font-medium">终端</span>
147+
</div>
148+
{onClosePanel && (
149+
<Button variant="ghost" size="icon" className="size-8 shrink-0 hover:text-primary" onClick={onClosePanel}>
150+
<IconX className="size-4" />
151+
</Button>
152+
)}
145153
</div>
146154
<div className="flex-1 min-h-0 flex flex-col">
147155
<Empty className="border border-dashed w-full flex-1 min-h-0">
@@ -169,7 +177,7 @@ export function TaskTerminalPanel({ envid, disabled }: TaskTerminalPanelProps) {
169177
<Button
170178
variant="ghost"
171179
size="icon"
172-
className="size-8 shrink-0 cursor-pointer hover:text-primary"
180+
className="size-8 shrink-0 hover:text-primary"
173181
onClick={handleNewSession}
174182
disabled={disabled}
175183
>
@@ -195,7 +203,7 @@ export function TaskTerminalPanel({ envid, disabled }: TaskTerminalPanelProps) {
195203
<Button
196204
variant="ghost"
197205
size="icon"
198-
className="size-5 shrink-0 opacity-0 group-hover:opacity-100 hover:bg-destructive/10 hover:text-primary rounded cursor-pointer"
206+
className="size-5 shrink-0 opacity-0 group-hover:opacity-100 hover:bg-destructive/10 hover:text-primary rounded"
199207
onClick={(e) => handleCloseTab(e, sid)}
200208
>
201209
<IconX className="size-3" />
@@ -207,12 +215,22 @@ export function TaskTerminalPanel({ envid, disabled }: TaskTerminalPanelProps) {
207215
<Button
208216
variant="ghost"
209217
size="icon"
210-
className="size-8 shrink-0 cursor-pointer hover:text-primary"
218+
className="size-8 shrink-0 hover:text-primary"
211219
onClick={() => fetchSessions()}
212220
disabled={disabled}
213221
>
214222
<IconReload className="size-4" />
215223
</Button>
224+
{onClosePanel && (
225+
<Button
226+
variant="ghost"
227+
size="icon"
228+
className="size-8 shrink-0 hover:text-primary"
229+
onClick={onClosePanel}
230+
>
231+
<IconX className="size-4" />
232+
</Button>
233+
)}
216234
</div>
217235

218236
<div className="flex-1 min-h-0 flex flex-col">

frontend/src/pages/console/user/task/task-detail.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,15 @@ export default function TaskDetailPage() {
380380
changedPaths={changedPaths}
381381
taskManager={taskManager.current}
382382
onRefresh={fetchFileChanges}
383+
onClosePanel={() => setActivePanel(null)}
383384
envid={envid}
384385
/>
385386
</div>
386387
)}
387388
{activePanel === "terminal" && (
388389
<div className="flex-1 min-h-0 overflow-hidden">
389390
<div className="h-full w-full border rounded-md overflow-hidden">
390-
<TaskTerminalPanel envid={envid} disabled={!vmOnline} />
391+
<TaskTerminalPanel envid={envid} disabled={!vmOnline} onClosePanel={() => setActivePanel(null)} />
391392
</div>
392393
</div>
393394
)}
@@ -398,6 +399,7 @@ export default function TaskDetailPage() {
398399
fileChangesMap={fileChangesMap}
399400
taskManager={taskManager.current}
400401
disabled={!vmOnline}
402+
onClosePanel={() => setActivePanel(null)}
401403
/>
402404
</div>
403405
)}
@@ -409,6 +411,7 @@ export default function TaskDetailPage() {
409411
vmId={task?.virtualmachine?.id}
410412
onSuccess={fetchTaskDetail}
411413
disabled={!vmOnline}
414+
onClosePanel={() => setActivePanel(null)}
412415
/>
413416
</div>
414417
)}

0 commit comments

Comments
 (0)