"use client"
import { useCallback, useEffect, useState } from "react"
import { Check, Copy, Eye, EyeOff } from "lucide-react"
import {
startWebServer,
stopWebServer,
getWebServerStatus,
type WebServerInfo,
} from "@/lib/api"
function CopyableCard({
label,
value,
masked,
}: {
label: string
value: string
masked?: boolean
}) {
const [hovered, setHovered] = useState(false)
const [copied, setCopied] = useState(false)
const [revealed, setRevealed] = useState(false)
function handleCopy() {
navigator.clipboard.writeText(value)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
}
const displayValue =
masked && !revealed
? value.slice(0, 4) + "\u2022".repeat(Math.max(value.length - 4, 8))
: value
return (
{label}
setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
{displayValue}
{masked && (
)}
)
}
export function WebServiceSettings() {
const [status, setStatus] = useState(null)
const [port, setPort] = useState("3080")
const [loading, setLoading] = useState(false)
const [error, setError] = useState("")
const fetchStatus = useCallback(async () => {
try {
const info = await getWebServerStatus()
setStatus(info)
if (info) {
setPort(String(info.port))
}
} catch {
// Server status unavailable
}
}, [])
useEffect(() => {
fetchStatus()
}, [fetchStatus])
async function handleStart() {
setError("")
setLoading(true)
try {
const info = await startWebServer({
port: parseInt(port, 10) || 3080,
})
setStatus(info)
} catch (e: unknown) {
const msg =
e && typeof e === "object" && "message" in e
? (e as { message: string }).message
: "启动失败"
setError(msg)
} finally {
setLoading(false)
}
}
async function handleStop() {
setLoading(true)
try {
await stopWebServer()
setStatus(null)
} catch {
setError("停止失败")
} finally {
setLoading(false)
}
}
const isRunning = status !== null
return (
Web 服务
启用后可通过浏览器远程访问 Codeg
{/* Port config */}
setPort(e.target.value)}
disabled={isRunning}
min={1024}
max={65535}
className="flex h-9 w-32 rounded-md border border-input bg-background px-3 py-1 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
/>
{/* Start/Stop button */}
{isRunning ? "运行中" : "已停止"}
{error && (
{error}
)}
{/* Connection info */}
{isRunning && (
{status.addresses.map((addr) => (
))}
Web 客户端首次访问时需输入此 Token
)}
)
}