Skip to content

Commit f6daab0

Browse files
committed
[claudesquad] update from 'better-fe' on 13 Jul 25 03:51 CST (paused)
1 parent 48c95b4 commit f6daab0

File tree

3 files changed

+141
-72
lines changed

3 files changed

+141
-72
lines changed

ui/src/components/Navbar.tsx

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ export function Navbar() {
2828
const isMobile = useIsMobile();
2929

3030
return (
31-
<nav className="border-b">
32-
<div className="px-4 h-14 flex items-center justify-between">
33-
<div className="flex items-center gap-6">
31+
<nav className="border-b bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-slate-200/50 dark:border-slate-800/50 shadow-sm">
32+
<div className="px-4 h-16 flex items-center justify-between max-w-7xl mx-auto">
3433
{/* 移动端汉堡菜单靠左对齐 */}
3534
{isMobile && (
3635
<DropdownMenu>
@@ -83,20 +82,22 @@ export function Navbar() {
8382
{/* 只在非移动端显示标题 */}
8483
{!isMobile && (
8584
<NavLink to="/" className="hover:opacity-80 transition-opacity">
86-
<h1 className="font-medium">Rabbit Digger Pro</h1>
85+
<h1 className="text-xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
86+
Rabbit Digger Pro
87+
</h1>
8788
</NavLink>
8889
)}
8990

9091
{/* 桌面导航 */}
9192
{!isMobile && (
9293
<div className="flex items-center gap-6">
93-
<NavLink
94+
<NavLink
9495
to="/"
9596
className={({ isActive }) => cn(
96-
"flex items-center gap-2 px-2 py-1 rounded-md transition-colors",
97+
"flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200",
9798
isActive
98-
? "text-primary font-medium"
99-
: "text-foreground/70 hover:text-foreground"
99+
? "bg-gradient-to-r from-blue-500 to-purple-500 text-white shadow-md shadow-blue-500/25"
100+
: "text-foreground/70 hover:text-foreground hover:bg-slate-100 dark:hover:bg-slate-800"
100101
)}
101102
>
102103
<Home className="h-4 w-4" />
@@ -105,10 +106,10 @@ export function Navbar() {
105106
<NavLink
106107
to="/connection"
107108
className={({ isActive }) => cn(
108-
"flex items-center gap-2 px-2 py-1 rounded-md transition-colors",
109+
"flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200",
109110
isActive
110-
? "text-primary font-medium"
111-
: "text-foreground/70 hover:text-foreground"
111+
? "bg-gradient-to-r from-blue-500 to-purple-500 text-white shadow-md shadow-blue-500/25"
112+
: "text-foreground/70 hover:text-foreground hover:bg-slate-100 dark:hover:bg-slate-800"
112113
)}
113114
>
114115
<Activity className="h-4 w-4" />
@@ -117,10 +118,10 @@ export function Navbar() {
117118
<NavLink
118119
to="/logs"
119120
className={({ isActive }) => cn(
120-
"flex items-center gap-2 px-2 py-1 rounded-md transition-colors",
121+
"flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200",
121122
isActive
122-
? "text-primary font-medium"
123-
: "text-foreground/70 hover:text-foreground"
123+
? "bg-gradient-to-r from-blue-500 to-purple-500 text-white shadow-md shadow-blue-500/25"
124+
: "text-foreground/70 hover:text-foreground hover:bg-slate-100 dark:hover:bg-slate-800"
124125
)}
125126
>
126127
<ScrollText className="h-4 w-4" />
@@ -141,7 +142,7 @@ export function Navbar() {
141142
}
142143
}}
143144
>
144-
<SelectTrigger className={cn(isMobile ? "w-36" : "w-[200px]")}>
145+
<SelectTrigger className={cn(isMobile ? "w-36" : "w-[200px] bg-white/50 dark:bg-slate-800/50 border-slate-200 dark:border-slate-700")}>
145146
<SelectValue placeholder="选择实例" />
146147
</SelectTrigger>
147148
<SelectContent>
@@ -178,10 +179,10 @@ export function Navbar() {
178179
<NavLink
179180
to="/settings"
180181
className={({ isActive }) => cn(
181-
"flex items-center gap-2 px-2 py-1 rounded-md transition-colors",
182+
"flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200",
182183
isActive
183-
? "text-primary font-medium"
184-
: "text-foreground/70 hover:text-foreground"
184+
? "bg-gradient-to-r from-blue-500 to-purple-500 text-white shadow-md shadow-blue-500/25"
185+
: "text-foreground/70 hover:text-foreground hover:bg-slate-100 dark:hover:bg-slate-800"
185186
)}
186187
>
187188
<Settings className="h-4 w-4" />

ui/src/pages/main/index.tsx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,36 @@ import { SelectNetPanel } from "./select"
33

44
export const MainPage: React.FC = () => {
55
return (
6-
<div className="container py-4 max-w-[1024px] mx-auto">
7-
<Card>
8-
<CardHeader>
9-
<CardTitle>选择网络</CardTitle>
10-
<CardDescription>你可以在这里更改代理节点</CardDescription>
11-
</CardHeader>
12-
<CardContent className="space-y-2">
13-
<SelectNetPanel />
14-
</CardContent>
15-
</Card>
6+
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-slate-100 dark:from-slate-900 dark:via-slate-950 dark:to-slate-900">
7+
<div className="container py-8 max-w-6xl mx-auto px-4">
8+
<div className="text-center mb-8">
9+
<h1 className="text-4xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent mb-2">
10+
网络代理管理
11+
</h1>
12+
<p className="text-lg text-muted-foreground">
13+
智能选择最优代理节点,提升网络体验
14+
</p>
15+
</div>
16+
17+
<Card className="border-0 shadow-xl bg-white/80 dark:bg-slate-900/80 backdrop-blur-sm">
18+
<CardHeader className="border-b border-slate-200/50 dark:border-slate-800/50">
19+
<div className="flex items-center justify-between">
20+
<div>
21+
<CardTitle className="text-2xl font-semibold flex items-center gap-2">
22+
<div className="w-2 h-8 bg-gradient-to-b from-blue-500 to-purple-500 rounded-full"></div>
23+
节点选择
24+
</CardTitle>
25+
<CardDescription className="text-base mt-1">
26+
选择最适合您的代理节点,支持延迟测试和批量管理
27+
</CardDescription>
28+
</div>
29+
</div>
30+
</CardHeader>
31+
<CardContent className="p-6">
32+
<SelectNetPanel />
33+
</CardContent>
34+
</Card>
35+
</div>
1636
</div>
1737
)
1838
}

ui/src/pages/main/select.tsx

Lines changed: 92 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,23 @@ const SelectNetItem: React.FC<SelectNetItemProps> = ({
5353
<Collapsible
5454
open={isOpen}
5555
onOpenChange={onToggleOpen}
56-
className="border rounded-lg p-2"
56+
className="border border-slate-200 dark:border-slate-700 rounded-xl bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm shadow-sm hover:shadow-md transition-all duration-300"
5757
>
58-
<CollapsibleTrigger className="flex items-center justify-between w-full p-2">
59-
<span className="text-lg font-medium">{netName}</span>
58+
<CollapsibleTrigger className="flex items-center justify-between w-full p-4 hover:bg-slate-50/50 dark:hover:bg-slate-800/50 rounded-xl transition-all duration-200">
59+
<div className="flex items-center gap-3">
60+
<div className="w-3 h-3 rounded-full bg-gradient-to-r from-blue-500 to-purple-500" />
61+
<span className="text-lg font-semibold text-slate-800 dark:text-slate-200">{netName}</span>
62+
{net.selected && (
63+
<span className="text-xs px-2 py-1 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-full">
64+
{net.selected}
65+
</span>
66+
)}
67+
</div>
6068
<div className="flex items-center gap-2">
6169
<Button
6270
variant="ghost"
6371
size="icon"
64-
className="h-8 w-8"
72+
className="h-9 w-9 hover:bg-slate-100 dark:hover:bg-slate-700 rounded-lg transition-all duration-200"
6573
disabled={net.list?.some(item => testingStates[item])}
6674
onClick={(e) => {
6775
e.preventDefault();
@@ -70,38 +78,64 @@ const SelectNetItem: React.FC<SelectNetItemProps> = ({
7078
}
7179
}}
7280
>
73-
<Timer className={clsx("h-4 w-4", {
74-
"animate-spin": net.list?.some(item => testingStates[item])
81+
<Timer className={clsx("h-4 w-4 text-slate-600 dark:text-slate-400", {
82+
"animate-spin text-blue-500": net.list?.some(item => testingStates[item])
7583
})} />
7684
</Button>
77-
<ChevronDown
78-
className={clsx("h-4 w-4 transition-transform duration-200", {
79-
"transform rotate-180": isOpen
80-
})}
81-
/>
85+
<div className={clsx("h-8 w-8 flex items-center justify-center rounded-lg bg-slate-100 dark:bg-slate-800 transition-all duration-200", {
86+
"bg-gradient-to-r from-blue-500 to-purple-500 text-white": isOpen
87+
})}>
88+
<ChevronDown
89+
className={clsx("h-4 w-4 text-slate-600 dark:text-slate-400 transition-transform duration-200", {
90+
"transform rotate-180 text-white": isOpen
91+
})}
92+
/>
93+
</div>
8294
</div>
8395
</CollapsibleTrigger>
84-
<CollapsibleContent className="mt-2 flex flex-wrap gap-2">
85-
{net.list?.map((item) => {
86-
const latency = latencyResults[item]?.response;
87-
const { text: latencyText, colorClass } = formatLatency(latency);
96+
<CollapsibleContent className="px-4 pb-4">
97+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3">
98+
{net.list?.map((item) => {
99+
const latency = latencyResults[item]?.response;
100+
const { text: latencyText, colorClass } = formatLatency(latency);
101+
const isSelected = item === net.selected;
102+
const isTesting = testingStates[item];
88103

89-
return (
90-
<Button
91-
key={item}
92-
variant={item === net.selected ? 'default' : 'outline'}
93-
onClick={() => onSelect(item)}
94-
disabled={testingStates[item]}
95-
>
96-
{item}
97-
{item in latencyResults && (
98-
<span className={cn("ml-2 text-xs", colorClass)}>
99-
{latencyText}
100-
</span>
101-
)}
102-
</Button>
103-
);
104-
})}
104+
return (
105+
<Button
106+
key={item}
107+
variant={isSelected ? 'default' : 'outline'}
108+
onClick={() => onSelect(item)}
109+
disabled={isTesting}
110+
className={cn(
111+
"h-auto py-3 px-4 text-left transition-all duration-200",
112+
isSelected && "bg-gradient-to-r from-blue-500 to-purple-500 border-0 shadow-md shadow-blue-500/25",
113+
!isSelected && "hover:bg-slate-50 dark:hover:bg-slate-800 hover:border-slate-300 dark:hover:border-slate-600",
114+
isTesting && "opacity-50 cursor-not-allowed"
115+
)}
116+
>
117+
<div className="flex flex-col items-start gap-1">
118+
<span className="font-medium text-sm">{item}</span>
119+
{item in latencyResults && (
120+
<div className="flex items-center gap-1">
121+
<span className={cn("text-xs font-medium", colorClass)}>
122+
{latencyText}
123+
</span>
124+
<span className="text-xs text-slate-500 dark:text-slate-400">
125+
{latencyResults[item]?.region && `• ${latencyResults[item]?.region}`}
126+
</span>
127+
</div>
128+
)}
129+
</div>
130+
{isTesting && (
131+
<div className="absolute top-2 right-2">
132+
<div className="w-2 h-2 bg-blue-500 rounded-full animate-pulse" />
133+
</div>
134+
)}
135+
</Button>
136+
);
137+
})}
138+
</div>
105139
</CollapsibleContent>
106140
</Collapsible>
107141
);
@@ -200,19 +234,33 @@ export const SelectNetPanel: React.FC = () => {
200234

201235
return (
202236
<div className="space-y-4">
203-
{selectNets.map(([netName, net]) => (
204-
<SelectNetItem
205-
key={netName}
206-
netName={netName}
207-
net={net}
208-
isOpen={openStates[netName]}
209-
onToggleOpen={() => toggleOpen(netName)}
210-
onSelect={(selected) => handleSelect(netName, selected)}
211-
testingStates={testingStates}
212-
latencyResults={latencyResults}
213-
onBatchSpeedTest={handleBatchSpeedTest}
214-
/>
215-
))}
237+
{selectNets.length === 0 ? (
238+
<div className="text-center py-12">
239+
<div className="w-16 h-16 mx-auto mb-4 bg-gradient-to-r from-blue-500 to-purple-500 rounded-full flex items-center justify-center">
240+
<Activity className="h-8 w-8 text-white" />
241+
</div>
242+
<h3 className="text-lg font-medium text-slate-800 dark:text-slate-200 mb-2">
243+
暂无可用节点
244+
</h3>
245+
<p className="text-sm text-slate-600 dark:text-slate-400">
246+
请检查配置文件或添加新的代理节点
247+
</p>
248+
</div>
249+
) : (
250+
selectNets.map(([netName, net]) => (
251+
<SelectNetItem
252+
key={netName}
253+
netName={netName}
254+
net={net}
255+
isOpen={openStates[netName]}
256+
onToggleOpen={() => toggleOpen(netName)}
257+
onSelect={(selected) => handleSelect(netName, selected)}
258+
testingStates={testingStates}
259+
latencyResults={latencyResults}
260+
onBatchSpeedTest={handleBatchSpeedTest}
261+
/>
262+
))
263+
)}
216264
</div>
217265
);
218266
};

0 commit comments

Comments
 (0)