Skip to content

Commit 071d1ce

Browse files
author
杨纲
committed
refactor: unify group fetching logic across manager components and improve rendering in file picker dialog
1 parent 89792be commit 071d1ce

File tree

8 files changed

+103
-78
lines changed

8 files changed

+103
-78
lines changed

frontend/src/components/console/files/file-picker-dialog.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect, useCallback } from "react"
1+
import React, { useState, useEffect, useCallback } from "react"
22
import {
33
Dialog,
44
DialogContent,
@@ -375,7 +375,11 @@ export default function FilePickerDialog({
375375
(空目录)
376376
</div>
377377
) : (
378-
node.children.map(child => renderNode(child))
378+
node.children.map(child => (
379+
<React.Fragment key={child.path}>
380+
{renderNode(child)}
381+
</React.Fragment>
382+
))
379383
)}
380384
</>
381385
)}
@@ -400,7 +404,11 @@ export default function FilePickerDialog({
400404
</div>
401405
) : (
402406
<div className="flex flex-col">
403-
{treeNodes.map(node => renderNode(node))}
407+
{treeNodes.map(node => (
408+
<React.Fragment key={node.path}>
409+
{renderNode(node)}
410+
</React.Fragment>
411+
))}
404412
</div>
405413
)}
406414
</div>

frontend/src/components/manager/add-image.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ export default function AddImage({
3535
const [selectOpen, setSelectOpen] = useState(false)
3636
const selectRef = useRef<HTMLDivElement>(null)
3737

38+
const fetchGroups = async () => {
39+
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
40+
if (resp.code === 0) {
41+
setGroups(resp.data?.groups || [])
42+
} else {
43+
toast.error("获取分组列表失败: " + resp.message);
44+
}
45+
})
46+
}
47+
3848
useEffect(() => {
3949
if (open) {
4050
fetchGroups()
@@ -57,16 +67,6 @@ export default function AddImage({
5767
}
5868
}, [selectOpen])
5969

60-
const fetchGroups = async () => {
61-
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
62-
if (resp.code === 0) {
63-
setGroups(resp.data?.groups || [])
64-
} else {
65-
toast.error("获取分组列表失败: " + resp.message);
66-
}
67-
})
68-
}
69-
7070
const handleGroupCheckboxChange = (groupId: string, checked: boolean) => {
7171
if (checked) {
7272
setSelectedGroupIds([...selectedGroupIds, groupId])

frontend/src/components/manager/add-model.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ export default function AddModel({
5353
const [selectOpen, setSelectOpen] = useState(false)
5454
const selectRef = useRef<HTMLDivElement>(null)
5555

56+
const fetchGroups = async () => {
57+
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
58+
if (resp.code === 0) {
59+
setGroups(resp.data?.groups || [])
60+
} else {
61+
toast.error("获取分组列表失败: " + resp.message);
62+
}
63+
})
64+
}
65+
5666
useEffect(() => {
5767
if (open) {
5868
fetchGroups()
@@ -75,16 +85,6 @@ export default function AddModel({
7585
}
7686
}, [selectOpen])
7787

78-
const fetchGroups = async () => {
79-
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
80-
if (resp.code === 0) {
81-
setGroups(resp.data?.groups || [])
82-
} else {
83-
toast.error("获取分组列表失败: " + resp.message);
84-
}
85-
})
86-
}
87-
8888
const handleGroupCheckboxChange = (groupId: string, checked: boolean) => {
8989
if (checked) {
9090
setSelectedGroupIds([...selectedGroupIds, groupId])

frontend/src/components/manager/edit-host.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ export default function EditHost({
3838
const [remark, setRemark] = useState("")
3939
const selectRef = useRef<HTMLDivElement>(null)
4040

41+
const fetchGroups = async () => {
42+
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
43+
if (resp.code === 0) {
44+
setGroups(resp.data?.groups || [])
45+
} else {
46+
toast.error("获取分组列表失败: " + resp.message);
47+
}
48+
})
49+
}
50+
4151
useEffect(() => {
4252
if (open) {
4353
fetchGroups()
@@ -69,16 +79,6 @@ export default function EditHost({
6979
}
7080
}, [selectOpen])
7181

72-
const fetchGroups = async () => {
73-
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
74-
if (resp.code === 0) {
75-
setGroups(resp.data?.groups || [])
76-
} else {
77-
toast.error("获取分组列表失败: " + resp.message);
78-
}
79-
})
80-
}
81-
8282
const handleGroupCheckboxChange = (groupId: string, checked: boolean) => {
8383
if (checked) {
8484
setSelectedGroupIds([...selectedGroupIds, groupId])

frontend/src/components/manager/edit-image.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ export default function EditImage({
3939
const [selectOpen, setSelectOpen] = useState(false)
4040
const selectRef = useRef<HTMLDivElement>(null)
4141

42+
const fetchGroups = async () => {
43+
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
44+
if (resp.code === 0) {
45+
setGroups(resp.data?.groups || [])
46+
} else {
47+
toast.error("获取分组列表失败: " + resp.message);
48+
}
49+
})
50+
}
51+
4252
useEffect(() => {
4353
if (open) {
4454
fetchGroups()
@@ -70,16 +80,6 @@ export default function EditImage({
7080
}
7181
}, [selectOpen])
7282

73-
const fetchGroups = async () => {
74-
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
75-
if (resp.code === 0) {
76-
setGroups(resp.data?.groups || [])
77-
} else {
78-
toast.error("获取分组列表失败: " + resp.message);
79-
}
80-
})
81-
}
82-
8383
const handleGroupCheckboxChange = (groupId: string, checked: boolean) => {
8484
if (checked) {
8585
setSelectedGroupIds([...selectedGroupIds, groupId])

frontend/src/components/manager/edit-model.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ export default function EditModel({
5353
const [selectOpen, setSelectOpen] = useState(false)
5454
const selectRef = useRef<HTMLDivElement>(null)
5555

56+
const fetchGroups = async () => {
57+
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
58+
if (resp.code === 0) {
59+
setGroups(resp.data?.groups || [])
60+
} else {
61+
toast.error("获取分组列表失败: " + resp.message);
62+
}
63+
})
64+
}
65+
5666
useEffect(() => {
5767
if (open) {
5868
fetchGroups()
@@ -87,16 +97,6 @@ export default function EditModel({
8797
}
8898
}, [selectOpen])
8999

90-
const fetchGroups = async () => {
91-
await apiRequest('v1TeamsGroupsList', {}, [], (resp) => {
92-
if (resp.code === 0) {
93-
setGroups(resp.data?.groups || [])
94-
} else {
95-
toast.error("获取分组列表失败: " + resp.message);
96-
}
97-
})
98-
}
99-
100100
const handleGroupCheckboxChange = (groupId: string, checked: boolean) => {
101101
if (checked) {
102102
setSelectedGroupIds([...selectedGroupIds, groupId])

frontend/src/components/welcome/git-bot.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,29 @@ const GitBot = () => {
1717

1818
useEffect(() => {
1919
let currentIndex = 0;
20-
const interval = setInterval(() => {
20+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
21+
22+
const tick = () => {
2123
if (currentIndex <= typewriterText.length) {
2224
setDisplayedText(typewriterText.slice(0, currentIndex));
23-
currentIndex++;
24-
} else {
25-
// 重置动画,循环播放
26-
setTimeout(() => {
27-
setDisplayedText("");
28-
currentIndex = 0;
29-
}, 2000);
25+
currentIndex += 1;
26+
timeoutId = setTimeout(tick, 100);
27+
return;
3028
}
31-
}, 100);
3229

33-
return () => clearInterval(interval);
30+
// 完整播放结束后,停顿 2s 再重置并重新开始
31+
timeoutId = setTimeout(() => {
32+
setDisplayedText("");
33+
currentIndex = 0;
34+
tick();
35+
}, 2000);
36+
};
37+
38+
tick();
39+
40+
return () => {
41+
if (timeoutId) clearTimeout(timeoutId);
42+
};
3443
}, []);
3544

3645
const advantages = [

frontend/src/pages/playground-detail.tsx

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Header from "@/components/welcome/header"
22
import Footer from "@/components/welcome/footer";
33
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
44
import dayjs from "dayjs";
5-
import { useEffect, useState } from "react";
5+
import { useCallback, useEffect, useState } from "react";
66
import { useSearchParams } from "react-router-dom";
77
import { apiRequest } from "@/utils/requestUtils";
88
import { ConstsPostKind, type DomainPlaygroundPost } from "@/api/Api";
@@ -167,9 +167,20 @@ const PlaygroundDetailPage = () => {
167167

168168
const fileTree = buildTree(zipFiles);
169169

170+
const fetchPost = useCallback(async () => {
171+
if (!postId) {
172+
return
173+
}
174+
await apiRequest('v1PlaygroundPostsDetail', {}, [postId], (resp) => {
175+
if (resp.code === 0) {
176+
setPost(resp.data)
177+
}
178+
})
179+
}, [postId])
180+
170181
useEffect(() => {
171182
fetchPost()
172-
}, [postId])
183+
}, [fetchPost])
173184

174185
useEffect(() => {
175186
if (post?.task_post?.code) {
@@ -196,17 +207,6 @@ const PlaygroundDetailPage = () => {
196207
}
197208
}, [zipFiles])
198209

199-
const fetchPost = async () => {
200-
if (!postId) {
201-
return
202-
}
203-
await apiRequest('v1PlaygroundPostsDetail', {}, [postId], (resp) => {
204-
if (resp.code === 0) {
205-
setPost(resp.data)
206-
}
207-
})
208-
}
209-
210210
const loadZipFile = async (url: string) => {
211211
setLoadingZip(true)
212212
try {
@@ -321,7 +321,11 @@ const PlaygroundDetailPage = () => {
321321
</div>
322322
{isExpanded && node.children.length > 0 && (
323323
<div>
324-
{node.children.map(child => renderTreeNode(child, depth + 1))}
324+
{node.children.map(child => (
325+
<React.Fragment key={child.path}>
326+
{renderTreeNode(child, depth + 1)}
327+
</React.Fragment>
328+
))}
325329
</div>
326330
)}
327331
</div>
@@ -438,7 +442,11 @@ const PlaygroundDetailPage = () => {
438442
</div>
439443
) : (
440444
<div className="flex flex-col pr-3">
441-
{fileTree.map(node => renderTreeNode(node, 0))}
445+
{fileTree.map(node => (
446+
<React.Fragment key={node.path}>
447+
{renderTreeNode(node, 0)}
448+
</React.Fragment>
449+
))}
442450
</div>
443451
)}
444452
</div>}

0 commit comments

Comments
 (0)