Skip to content

Commit 1f64999

Browse files
feat: 添加任务查看页面 /console/task/view
- 新增任务查看页面,左侧显示任务列表,右侧 iframe 加载任务详情 - 添加路由配置和 allowedHosts 支持在线预览 - 支持任务切换、状态显示、时间显示等功能 Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
1 parent 17494bb commit 1f64999

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

frontend/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import PostCreatePage from "./pages/post-create"
2929
import ProjectIssuesPage from "./pages/console/user/project/issues"
3030
import ProjectTasksPage from "./pages/console/user/project/tasks"
3131
import TaskDevelopPage from "./pages/console/user/task/task-dev"
32+
import TaskViewPage from "./pages/console/user/task/task-view"
3233

3334
function App() {
3435
return (
@@ -56,6 +57,7 @@ function App() {
5657
</Route>
5758
<Route path="/console/terminal" element={<TerminalPage />} />
5859
<Route path="/console/files" element={<FileManagerPage />} />
60+
<Route path="/console/task/view" element={<TaskViewPage />} />
5961
<Route path="/console/task/develop/:taskId" element={<TaskDevelopPage />} />
6062
<Route path="/sharedterminal" element={<SharedTerminalPage />} />
6163
<Route path="/manager" element={<ManagerConsolePage />}>
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { type DomainProjectTask } from "@/api/Api"
2+
import { Badge } from "@/components/ui/badge"
3+
import { Button } from "@/components/ui/button"
4+
import { ScrollArea } from "@/components/ui/scroll-area"
5+
import { Spinner } from "@/components/ui/spinner"
6+
import { cn } from "@/lib/utils"
7+
import { stripMarkdown } from "@/utils/common"
8+
import { apiRequest } from "@/utils/requestUtils"
9+
import { IconPlus } from "@tabler/icons-react"
10+
import dayjs from "dayjs"
11+
import { useCallback, useEffect, useState } from "react"
12+
import { toast } from "sonner"
13+
14+
const PAGE_SIZE = 50
15+
16+
export default function TaskViewPage() {
17+
const [tasks, setTasks] = useState<DomainProjectTask[]>([])
18+
const [loading, setLoading] = useState(false)
19+
const [selectedTaskId, setSelectedTaskId] = useState<string | null>(null)
20+
const [selectedTask, setSelectedTask] = useState<DomainProjectTask | null>(null)
21+
22+
const fetchTasks = useCallback(async () => {
23+
setLoading(true)
24+
await apiRequest('v1UsersTasksList', { page: 1, size: PAGE_SIZE }, [], (resp) => {
25+
if (resp.code === 0) {
26+
const fetchedTasks = resp.data?.tasks || []
27+
setTasks(fetchedTasks)
28+
if (fetchedTasks.length > 0 && !selectedTaskId) {
29+
const firstTask = fetchedTasks[0]
30+
setSelectedTaskId(firstTask.id)
31+
setSelectedTask(firstTask)
32+
}
33+
} else {
34+
toast.error("获取任务列表失败: " + resp.message)
35+
}
36+
})
37+
setLoading(false)
38+
}, [selectedTaskId])
39+
40+
useEffect(() => {
41+
fetchTasks()
42+
}, [fetchTasks])
43+
44+
const taskTitle = selectedTask?.summary || stripMarkdown(selectedTask?.content || "")
45+
46+
return (
47+
<div className="flex h-screen overflow-hidden">
48+
<div className="w-80 border-r flex flex-col h-full bg-background overflow-hidden">
49+
<div className="p-2">
50+
<Button
51+
variant="outline"
52+
size="sm"
53+
className="w-full"
54+
onClick={() => window.location.href = '/console/tasks'}
55+
>
56+
<IconPlus className="w-4 h-4 mr-2" />
57+
启动新任务
58+
</Button>
59+
</div>
60+
<ScrollArea className="flex-1 h-0">
61+
<div className="p-2 space-y-2">
62+
{loading && tasks.length === 0 ? (
63+
<div className="flex justify-center py-8">
64+
<Spinner className="size-6" />
65+
</div>
66+
) : tasks.length === 0 ? (
67+
<div className="text-center py-8 text-muted-foreground text-sm">
68+
暂无任务
69+
</div>
70+
) : (
71+
tasks.map((task) => (
72+
<div
73+
key={task.id}
74+
className={cn(
75+
"p-3 rounded-lg border cursor-pointer transition-all hover:bg-accent",
76+
selectedTaskId === task.id && "bg-accent border-primary"
77+
)}
78+
onClick={() => {
79+
setSelectedTaskId(task.id)
80+
setSelectedTask(task)
81+
}}
82+
>
83+
<div className="font-medium text-sm line-clamp-1 break-all mb-2">
84+
{task.summary || stripMarkdown(task.content)}
85+
</div>
86+
<div className="flex items-center justify-between">
87+
<Badge variant="outline" className="text-xs">
88+
{task.status === "finished" && "已完成"}
89+
{task.status === "error" && "失败"}
90+
{task.status === "pending" && "等待中"}
91+
{task.status === "processing" && "执行中"}
92+
</Badge>
93+
<div className="text-xs text-muted-foreground">
94+
{dayjs.unix(task.created_at as number).fromNow()}
95+
</div>
96+
</div>
97+
</div>
98+
))
99+
)}
100+
</div>
101+
</ScrollArea>
102+
</div>
103+
<div className="flex-1 flex flex-col h-full">
104+
{selectedTaskId ? (
105+
<iframe
106+
key={selectedTaskId}
107+
src={`/console/task/develop/${selectedTaskId}`}
108+
className="w-full h-full border-0"
109+
title="任务详情"
110+
/>
111+
) : (
112+
<div className="flex items-center justify-center h-full text-muted-foreground">
113+
请选择一个任务查看详情
114+
</div>
115+
)}
116+
</div>
117+
</div>
118+
)
119+
}

frontend/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default defineConfig({
2323
},
2424
},
2525
server: {
26+
allowedHosts: ['.monkeycode-ai.online'],
2627
proxy: {
2728
'/api': {
2829
target: 'https://monkeycode-ai.com/',

0 commit comments

Comments
 (0)