优化web服务页面样式

This commit is contained in:
xintaofei
2026-03-25 23:52:01 +08:00
parent 20c5bb4944
commit 2d3d8d791f

View File

@@ -1,23 +1,49 @@
"use client"
import { useCallback, useEffect, useState } from "react"
import { Check, Copy, Eye, EyeOff } from "lucide-react"
import { Check, Copy, ExternalLink, Eye, EyeOff } from "lucide-react"
import {
startWebServer,
stopWebServer,
getWebServerStatus,
type WebServerInfo,
} from "@/lib/api"
import { openUrl } from "@/lib/platform"
function CopyableCard({
label,
value,
masked,
}: {
label: string
value: string
masked?: boolean
}) {
function AddressCard({ label, value }: { label: string; value: string }) {
const [hovered, setHovered] = useState(false)
return (
<div className="space-y-1.5">
<div className="text-xs font-medium text-muted-foreground">{label}</div>
<div
className="group relative flex items-center rounded-md border bg-muted/40 px-3 py-2"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
<code className="min-w-0 flex-1 truncate text-sm select-all">
{value}
</code>
<div
className={`ml-2 flex shrink-0 items-center gap-1 transition-opacity ${
hovered ? "opacity-100" : "opacity-0"
}`}
>
<button
type="button"
onClick={() => openUrl(value)}
className="inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground"
title="打开"
>
<ExternalLink className="h-3.5 w-3.5" />
</button>
</div>
</div>
</div>
)
}
function TokenCard({ label, value }: { label: string; value: string }) {
const [hovered, setHovered] = useState(false)
const [copied, setCopied] = useState(false)
const [revealed, setRevealed] = useState(false)
@@ -28,10 +54,9 @@ function CopyableCard({
setTimeout(() => setCopied(false), 1500)
}
const displayValue =
masked && !revealed
? value.slice(0, 4) + "\u2022".repeat(Math.max(value.length - 4, 8))
: value
const displayValue = revealed
? value
: "\u2022".repeat(Math.max(value.length, 12))
return (
<div className="space-y-1.5">
@@ -49,7 +74,6 @@ function CopyableCard({
hovered ? "opacity-100" : "opacity-0"
}`}
>
{masked && (
<button
type="button"
onClick={() => setRevealed((v) => !v)}
@@ -62,7 +86,6 @@ function CopyableCard({
<Eye className="h-3.5 w-3.5" />
)}
</button>
)}
<button
type="button"
onClick={handleCopy}
@@ -194,13 +217,9 @@ export function WebServiceSettings() {
{isRunning && (
<div className="space-y-3">
{status.addresses.map((addr) => (
<CopyableCard key={addr} label="访问地址" value={addr} />
<AddressCard key={addr} label="访问地址" value={addr} />
))}
<CopyableCard
label="访问 Token"
value={status.token}
masked
/>
<TokenCard label="访问 Token" value={status.token} />
<p className="text-xs text-muted-foreground">
Web 访 Token
</p>