diff --git a/client/lib/screens/nodes_page.dart b/client/lib/screens/nodes_page.dart index be8b797..82a01ae 100644 --- a/client/lib/screens/nodes_page.dart +++ b/client/lib/screens/nodes_page.dart @@ -13,6 +13,7 @@ import '../state/nodes_provider.dart'; import '../widgets/app_top_bar.dart'; import '../widgets/country_code.dart'; import '../widgets/pangolin_field.dart'; +import '../widgets/page_body.dart'; import '../widgets/pangolin_icons.dart'; import '../widgets/server_tile.dart'; import '../widgets/smart_select_card.dart'; @@ -128,31 +129,32 @@ class _NodesPageState extends ConsumerState { ]); if (widget.isWide) { - // 对照 dapp.jsx DServers:padding 4/28、网格 gap 10。智能卡置顶(CLAUDE.md §5 规范,三端一致)。 + // 桌面 Nodes 页宽度统一为 view-body(600 居中)、单列 server-row 行列表—— + // 镜像原型 design/prototype/screens/ui-desktop.html 的 .nodes-view(真相源)。 + // 智能卡置顶(CLAUDE.md §5 规范,三端一致)。 return RefreshIndicator( color: c.accent, backgroundColor: c.surface, onRefresh: _refresh, - child: ListView( - padding: const EdgeInsets.fromLTRB(28, 4, 28, 24), - children: [ - smartCard, - const SizedBox(height: 14), - ConstrainedBox(constraints: const BoxConstraints(maxWidth: 440), child: searchRow), - const SizedBox(height: 14), - GridView.count( - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - mainAxisSpacing: 10, - crossAxisSpacing: 10, - childAspectRatio: 4.4, + child: PageBody( + child: ListView( + padding: const EdgeInsets.fromLTRB(28, 4, 28, 24), children: [ - for (final n in nodes) - _NodeGridTile(node: n, lang: t.lang, active: !smart && n.code == selected, onTap: () => _onTapNode(n)), + smartCard, + const SizedBox(height: 14), + ConstrainedBox(constraints: const BoxConstraints(maxWidth: 440), child: searchRow), + const SizedBox(height: 14), + for (var i = 0; i < nodes.length; i++) ...[ + _NodeGridTile( + node: nodes[i], + lang: t.lang, + active: !smart && nodes[i].code == selected, + onTap: () => _onTapNode(nodes[i]), + ), + if (i < nodes.length - 1) const SizedBox(height: 10), + ], ], ), - ], ), ); } @@ -226,7 +228,6 @@ class _SearchBox extends StatelessWidget { } } -/// 宽屏双列网格中的节点块。 /// 刷新按钮(搜索框右侧):点击刷新节点列表(受 10s 限流);刷新中显示 spinner。 class _RefreshButton extends StatelessWidget { const _RefreshButton({required this.refreshing, required this.onTap}); @@ -256,6 +257,7 @@ class _RefreshButton extends StatelessWidget { } } +/// 宽屏 Nodes 页单列节点行(镜像原型 .server-row);自然高度撑高,不依赖网格 aspect ratio。 class _NodeGridTile extends StatelessWidget { const _NodeGridTile({required this.node, required this.lang, required this.active, required this.onTap}); final Node node; diff --git a/client/test/golden/goldens/desktop_servers.png b/client/test/golden/goldens/desktop_servers.png index e3cb8ed..213e7aa 100644 Binary files a/client/test/golden/goldens/desktop_servers.png and b/client/test/golden/goldens/desktop_servers.png differ diff --git a/client/test/golden/goldens/tablet_servers_dark_zh.png b/client/test/golden/goldens/tablet_servers_dark_zh.png index 4914eef..b09fab3 100644 Binary files a/client/test/golden/goldens/tablet_servers_dark_zh.png and b/client/test/golden/goldens/tablet_servers_dark_zh.png differ diff --git a/client/test/golden/goldens/tablet_servers_light_en.png b/client/test/golden/goldens/tablet_servers_light_en.png index 48da3f4..b8366a5 100644 Binary files a/client/test/golden/goldens/tablet_servers_light_en.png and b/client/test/golden/goldens/tablet_servers_light_en.png differ diff --git a/client/test/golden/goldens/tablet_servers_light_zh.png b/client/test/golden/goldens/tablet_servers_light_zh.png index 6d1e623..4368000 100644 Binary files a/client/test/golden/goldens/tablet_servers_light_zh.png and b/client/test/golden/goldens/tablet_servers_light_zh.png differ diff --git a/design/prototype/screens/ui-desktop.html b/design/prototype/screens/ui-desktop.html index f3efee1..dae1d00 100644 --- a/design/prototype/screens/ui-desktop.html +++ b/design/prototype/screens/ui-desktop.html @@ -116,7 +116,7 @@ .rate-chip .u{ font-size:10px; color:var(--fg3); } /* ---- 节点视图 ---- */ - .nodes-view{ padding:var(--space-5) var(--space-6) var(--space-6); } + /* .nodes-view 宽度/内边距由 view-body 原子承担(见 atoms.css),此处不再重复声明 */ .searchbar{ display:flex; align-items:center; gap:9px; background:var(--bg-subtle); border-radius:var(--radius-md); padding:9px 13px; margin-bottom:var(--space-4); max-width:360px; } .searchbar svg{ width:17px; height:17px; color:var(--fg3); } @@ -474,7 +474,7 @@
-
+