feat(web): improve zone domain list and detail navigation

合并 Zone 域名与路由展示,上游地址多行显示并支持路由详情跳转;
域名列表对齐用户管理页样式;Zone 页支持 ?tab= 定位;反代详情返回
使用浏览器历史上一级。
This commit is contained in:
ryan
2026-07-12 15:50:43 +08:00
parent 96b8ddc077
commit 7ef84cce52
6 changed files with 268 additions and 102 deletions
@@ -93,21 +93,36 @@ export function getRouteDomainsLabel(route: ProxyRouteItem): string {
return names.length > 0 ? names.join(', ') : '未绑定域名';
}
export function getUpstreamSummary(route: ProxyRouteItem): string {
/** Upstream address labels for display (supports multi-upstream). */
export function getUpstreamLabels(route: ProxyRouteItem): string[] {
if (route.upstream_type === 'pages') {
return route.pages_project_id
? `Pages 项目 #${route.pages_project_id}`
: 'Pages 项目未绑定';
return [
route.pages_project_id
? `Pages 项目 #${route.pages_project_id}`
: 'Pages 项目未绑定',
];
}
if (route.upstream_type === 'tunnel') {
const protocol = route.tunnel_target_protocol || 'http';
const target = route.tunnel_target_addr || '未配置目标';
return `Tunnel → ${protocol}://${target}`;
return [`Tunnel → ${protocol}://${target}`];
}
if ((route.upstream_list ?? []).length <= 1) {
return route.origin_url;
const list = (route.upstream_list ?? []).filter(Boolean);
if (list.length > 0) {
return list;
}
return `${route.upstream_list.length} 个上游,主上游 ${route.origin_url}`;
return route.origin_url ? [route.origin_url] : [];
}
export function getUpstreamSummary(route: ProxyRouteItem): string {
const labels = getUpstreamLabels(route);
if (labels.length === 0) {
return '未配置上游';
}
if (labels.length === 1) {
return labels[0];
}
return labels.join(' · ');
}
const originHostPattern =
@@ -1,6 +1,6 @@
'use client';
import Link from 'next/link';
import {useRouter} from 'next/navigation';
import {useCallback, useState} from 'react';
import {ArrowLeft, Loader2, Route, Upload} from 'lucide-react';
import {toast} from 'sonner';
@@ -41,6 +41,7 @@ interface RouteHeaderProps {
}
export function RouteHeader({ route }: RouteHeaderProps) {
const router = useRouter();
const [publishConfirmOpen, setPublishConfirmOpen] = useState(false);
const [diff, setDiff] = useState<ConfigDiffResult | null>(null);
const [diffLoading, setDiffLoading] = useState(false);
@@ -90,11 +91,14 @@ export function RouteHeader({ route }: RouteHeaderProps) {
return (
<>
<div className="space-y-4">
<Button variant="ghost" size="sm" className="h-8 gap-1.5 px-0 text-xs" asChild>
<Link href="/proxy-routes">
<ArrowLeft className="size-3.5" />
返回规则列表
</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>
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">