feat(web): polish zone list and settings layout

Show Zone list as a table, align detail back navigation with proxy
route detail, and move edit/delete actions into the settings tab.
This commit is contained in:
ryan
2026-07-12 16:22:16 +08:00
parent d615d85a26
commit efcf61e32d
4 changed files with 193 additions and 120 deletions
@@ -1,6 +1,5 @@
'use client';
import Link from 'next/link';
import {usePathname, useRouter, useSearchParams} from 'next/navigation';
import {useCallback, useMemo, useState} from 'react';
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
@@ -118,11 +117,14 @@ export function ZonePageClient({zoneId}: {zoneId: number}) {
if (overviewQuery.isError || !overviewQuery.data) {
return (
<div className="space-y-4 py-6 px-1">
<Button variant="ghost" size="sm" className="h-8 px-2" asChild>
<Link href="/websites">
<ArrowLeft className="mr-1 size-4" />
返回网站列表
</Link>
<Button
variant="ghost"
size="sm"
className="h-8 gap-1.5 px-0 text-xs"
onClick={() => router.back()}
>
<ArrowLeft className="size-3.5" />
返回
</Button>
<EmptyStateWithBorder
icon={Globe}
@@ -141,7 +143,17 @@ export function ZonePageClient({zoneId}: {zoneId: number}) {
return (
<div className="space-y-6 py-6 px-1">
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="space-y-4">
<Button
variant="ghost"
size="sm"
className="h-8 gap-1.5 px-0 text-xs"
onClick={() => router.back()}
>
<ArrowLeft className="size-3.5" />
返回
</Button>
<div className="flex items-center gap-2">
<Globe className="size-5 text-primary" />
<div>
@@ -149,32 +161,6 @@ export function ZonePageClient({zoneId}: {zoneId: number}) {
<p className="text-sm text-muted-foreground">Zone 网站管理</p>
</div>
</div>
<div className="flex flex-wrap gap-2">
<Button variant="outline" size="sm" className="h-7 text-xs" asChild>
<Link href="/websites">
<ArrowLeft className="mr-1 size-3.5" />
返回
</Link>
</Button>
<Button
variant="outline"
size="sm"
className="h-7 text-xs"
onClick={() => setEditZone(true)}
>
<Pencil className="mr-1 size-3.5" />
编辑 Zone
</Button>
<Button
variant="destructive"
size="sm"
className="h-7 text-xs"
onClick={() => setConfirmDelete(true)}
>
<Trash2 className="mr-1 size-3.5" />
删除 Zone
</Button>
</div>
</div>
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
@@ -211,20 +197,48 @@ export function ZonePageClient({zoneId}: {zoneId: number}) {
<ZoneCertificatesPanel domains={overview.domains} certificates={certificates} />
</TabsContent>
<TabsContent value="settings">
<div className="rounded-lg border p-4">
<p className="text-sm font-semibold">Zone 设置</p>
<p className="mt-1 text-sm text-muted-foreground">
根域和备注可在此 Zone 的编辑操作中维护。
</p>
<Button
variant="outline"
size="sm"
className="mt-4 h-7 text-xs"
onClick={() => setEditZone(true)}
>
<Pencil className="mr-1 size-3.5" />
编辑根域与备注
</Button>
<div className="space-y-4">
<div className="rounded-lg border p-4">
<p className="text-sm font-semibold">基本信息</p>
<p className="mt-1 text-sm text-muted-foreground">
维护 Zone 的可注册根域。根域变更后,请确认其下域名仍归属该根域。
</p>
<div className="mt-3 grid gap-2 text-sm sm:grid-cols-2">
<div>
<p className="text-xs text-muted-foreground">当前根域</p>
<p className="mt-1 font-mono text-[13px] font-medium">{overview.zone.domain}</p>
</div>
<div>
<p className="text-xs text-muted-foreground">域名数量</p>
<p className="mt-1 font-mono text-[13px] font-medium">{overview.domains.length}</p>
</div>
</div>
<Button
variant="outline"
size="sm"
className="mt-4 h-7 text-xs"
onClick={() => setEditZone(true)}
>
<Pencil className="mr-1 size-3.5" />
编辑根域
</Button>
</div>
<div className="rounded-lg border border-destructive/30 p-4">
<p className="text-sm font-semibold text-destructive">危险操作</p>
<p className="mt-1 text-sm text-muted-foreground">
删除 Zone 前须清空其下全部域名;删除后不可恢复。
</p>
<Button
variant="destructive"
size="sm"
className="mt-4 h-7 text-xs"
onClick={() => setConfirmDelete(true)}
>
<Trash2 className="mr-1 size-3.5" />
删除 Zone
</Button>
</div>
</div>
</TabsContent>
</Tabs>