From 8b48d80cd49c8061c0d1032bfae8aedd92cac567 Mon Sep 17 00:00:00 2001 From: hailin Date: Wed, 4 Mar 2026 06:42:50 -0800 Subject: [PATCH] =?UTF-8?q?feat(app):=20=E9=A2=84=E7=A7=8D=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E4=B8=89=E6=8C=89=E9=92=AE=E5=90=88=E5=B9=B6=E4=B8=BA?= =?UTF-8?q?=E5=8D=95=E5=85=A5=E5=8F=A3=20Hub=20=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 背景 「我」页面原有三个并排的预种按钮(预种购买 / 预种明细 / 团队预种), 三等分宽度导致文字拥挤,视觉层级也不清晰。 ## 改动内容 ### 新增文件 - `pre_planting_hub_page.dart` 预种计划 Hub 汇总页,竖排展示三个功能入口卡片: · 预种购买(金色)→ /pre-planting/purchase · 预种明细(棕色)→ /pre-planting/position · 团队预种(绿色)→ /pre-planting/team 页面为纯导航页,无需加载数据;风格与 pre_planting_purchase_page 一致(渐变背景、金色「← 返回」Header、Inter 字体)。 ### 修改文件 - `route_paths.dart` / `route_names.dart` 新增路由常量 prePlantingHub = '/pre-planting/hub' - `app_router.dart` 注册 GoRoute(path: prePlantingHub) → PrePlantingHubPage 新增对应 import - `profile_page.dart` · 删除 `_buildPrePlantingButtons()`(三按钮并排 Widget) · 删除已无用的三个导航方法: _goToPrePlantingPurchase / _goToPrePlantingPosition / _goToTeamPrePlanting · 新增 `_buildPrePlantingEntryButton()`: 满宽 48px 按钮,文字「申请预种计划」,点击跳转 Hub 页 · 布局调用处改为 _buildPrePlantingEntryButton() Co-Authored-By: Claude Sonnet 4.6 --- .../pages/pre_planting_hub_page.dart | 191 ++++++++++++++++++ .../presentation/pages/profile_page.dart | 165 +++------------ .../mobile-app/lib/routes/app_router.dart | 8 + .../mobile-app/lib/routes/route_names.dart | 1 + .../mobile-app/lib/routes/route_paths.dart | 1 + 5 files changed, 232 insertions(+), 134 deletions(-) create mode 100644 frontend/mobile-app/lib/features/pre_planting/presentation/pages/pre_planting_hub_page.dart diff --git a/frontend/mobile-app/lib/features/pre_planting/presentation/pages/pre_planting_hub_page.dart b/frontend/mobile-app/lib/features/pre_planting/presentation/pages/pre_planting_hub_page.dart new file mode 100644 index 00000000..a5bee691 --- /dev/null +++ b/frontend/mobile-app/lib/features/pre_planting/presentation/pages/pre_planting_hub_page.dart @@ -0,0 +1,191 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import '../../../../routes/route_paths.dart'; + +/// [2026-03-04] 预种计划 Hub 页面 +/// +/// 作为「我」页面「申请预种计划」按钮的下级页面, +/// 汇总展示预种三大功能入口:预种购买、预种明细、团队预种。 +class PrePlantingHubPage extends StatelessWidget { + const PrePlantingHubPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xFFFFF7E6), Color(0xFFEAE0C8)], + ), + ), + child: SafeArea( + child: Column( + children: [ + _buildHeader(context), + Expanded( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + const SizedBox(height: 8), + _buildEntryCard( + context, + icon: Icons.add_circle_outline, + color: const Color(0xFFD4AF37), + title: '预种购买', + subtitle: '购买预种份额,累计 10 份合成 1 棵树', + onTap: () => context.push(RoutePaths.prePlantingPurchase), + ), + const SizedBox(height: 12), + _buildEntryCard( + context, + icon: Icons.account_balance_wallet_outlined, + color: const Color(0xFF5D4037), + title: '预种明细', + subtitle: '查看预种订单和合并记录', + onTap: () => context.push(RoutePaths.prePlantingPosition), + ), + const SizedBox(height: 12), + _buildEntryCard( + context, + icon: Icons.groups_outlined, + color: const Color(0xFF2E7D32), + title: '团队预种', + subtitle: '查看个人与团队预种统计', + onTap: () => context.push(RoutePaths.teamPrePlanting), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildHeader(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: const Color(0xFFFFF7E6).withValues(alpha: 0.8), + ), + child: Row( + children: [ + GestureDetector( + onTap: () => context.pop(), + child: Container( + width: 32, + height: 32, + alignment: Alignment.center, + child: const Icon( + Icons.arrow_back_ios, + color: Color(0xFFD4AF37), + size: 20, + ), + ), + ), + const SizedBox(width: 4), + GestureDetector( + onTap: () => context.pop(), + child: const Text( + '返回', + style: TextStyle( + fontSize: 16, + fontFamily: 'Inter', + height: 1.5, + color: Color(0xFFD4AF37), + ), + ), + ), + const SizedBox(width: 42), + const Expanded( + child: Text( + '预种计划', + style: TextStyle( + fontSize: 18, + fontFamily: 'Inter', + fontWeight: FontWeight.w700, + height: 1.25, + letterSpacing: -0.27, + color: Color(0xFF5D4037), + ), + ), + ), + ], + ), + ); + } + + Widget _buildEntryCard( + BuildContext context, { + required IconData icon, + required Color color, + required String title, + required String subtitle, + required VoidCallback onTap, + }) { + return GestureDetector( + onTap: onTap, + child: Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18), + decoration: BoxDecoration( + color: Colors.white.withValues(alpha: 0.85), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: color.withValues(alpha: 0.25), + width: 1, + ), + ), + child: Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + color: color.withValues(alpha: 0.12), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(icon, color: color, size: 24), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: color, + ), + ), + const SizedBox(height: 4), + Text( + subtitle, + style: const TextStyle( + fontSize: 13, + fontFamily: 'Inter', + color: Color(0xFF8D6E63), + ), + ), + ], + ), + ), + Icon( + Icons.chevron_right, + color: color.withValues(alpha: 0.6), + size: 20, + ), + ], + ), + ), + ); + } +} diff --git a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart index fc720267..1ddfd497 100644 --- a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart +++ b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart @@ -1356,16 +1356,6 @@ class _ProfilePageState extends ConsumerState { } } - /// [2026-02-17] 进入预种计划购买页 - void _goToPrePlantingPurchase() { - context.push(RoutePaths.prePlantingPurchase); - } - - /// [2026-02-17] 进入预种持仓页 - void _goToPrePlantingPosition() { - context.push(RoutePaths.prePlantingPosition); - } - /// 谷歌验证器 void _goToGoogleAuth() { context.push(RoutePaths.googleAuth); @@ -1551,10 +1541,10 @@ class _ProfilePageState extends ConsumerState { // 认种按钮 _buildPlantingButton(), const SizedBox(height: 8), - // [2026-02-17] 预种计划按钮(购买 + 查看持仓) + // [2026-03-04] 预种计划入口(三功能合并为单按钮) // 仅在后台管理端预种开关开启时显示 if (_isPrePlantingActive) ...[ - _buildPrePlantingButtons(), + _buildPrePlantingEntryButton(), const SizedBox(height: 8), ], const SizedBox(height: 16), @@ -2041,136 +2031,43 @@ class _ProfilePageState extends ConsumerState { ); } - /// [2026-02-17] 构建预种计划按钮行(购买 + 查看持仓) - /// - /// 两个按钮并排显示: - /// - 左侧「预种购买」:跳转到预种购买页(选择份数 → 支付 1887 USDT/份) - /// - 右侧「预种持仓」:跳转到预种持仓页(查看订单、合并记录、签约) - Widget _buildPrePlantingButtons() { - return Row( - children: [ - // 预种购买按钮 - Expanded( - child: GestureDetector( - onTap: _goToPrePlantingPurchase, - child: Container( - height: 44, - decoration: BoxDecoration( - color: const Color(0xFFD4AF37).withValues(alpha: 0.15), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: const Color(0xFFD4AF37).withValues(alpha: 0.4), - width: 1, - ), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.add_circle_outline, - color: Color(0xFFD4AF37), - size: 18, - ), - SizedBox(width: 6), - Text( - '预种购买', - style: TextStyle( - fontSize: 14, - fontFamily: 'Inter', - fontWeight: FontWeight.w600, - color: Color(0xFFD4AF37), - ), - ), - ], - ), - ), + /// [2026-03-04] 构建预种计划入口按钮(原三按钮合并为一个) + Widget _buildPrePlantingEntryButton() { + return GestureDetector( + onTap: () => context.push(RoutePaths.prePlantingHub), + child: Container( + width: double.infinity, + height: 48, + decoration: BoxDecoration( + color: const Color(0xFFD4AF37).withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: const Color(0xFFD4AF37).withValues(alpha: 0.4), + width: 1, ), ), - const SizedBox(width: 8), - // 预种持仓按钮 - Expanded( - child: GestureDetector( - onTap: _goToPrePlantingPosition, - child: Container( - height: 44, - decoration: BoxDecoration( - color: const Color(0xFF5D4037).withValues(alpha: 0.08), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: const Color(0xFF5D4037).withValues(alpha: 0.2), - width: 1, - ), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.account_balance_wallet_outlined, - color: Color(0xFF5D4037), - size: 18, - ), - SizedBox(width: 6), - Text( - '预种明细', - style: TextStyle( - fontSize: 14, - fontFamily: 'Inter', - fontWeight: FontWeight.w600, - color: Color(0xFF5D4037), - ), - ), - ], + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.eco_outlined, color: Color(0xFFD4AF37), size: 20), + SizedBox(width: 8), + Text( + '申请预种计划', + style: TextStyle( + fontSize: 15, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: Color(0xFFD4AF37), ), ), - ), + SizedBox(width: 4), + Icon(Icons.chevron_right, color: Color(0xFFD4AF37), size: 18), + ], ), - const SizedBox(width: 8), - // [2026-03-02] 团队预种按钮(功能6) - Expanded( - child: GestureDetector( - onTap: _goToTeamPrePlanting, - child: Container( - height: 44, - decoration: BoxDecoration( - color: const Color(0xFF2E7D32).withValues(alpha: 0.08), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: const Color(0xFF2E7D32).withValues(alpha: 0.2), - width: 1, - ), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.groups_outlined, - color: Color(0xFF2E7D32), - size: 18, - ), - SizedBox(width: 6), - Text( - '团队预种', - style: TextStyle( - fontSize: 14, - fontFamily: 'Inter', - fontWeight: FontWeight.w600, - color: Color(0xFF2E7D32), - ), - ), - ], - ), - ), - ), - ), - ], + ), ); } - /// [2026-03-02] 进入团队预种页(功能6) - void _goToTeamPrePlanting() { - context.push(RoutePaths.teamPrePlanting); - } - /// 构建主要内容卡片 Widget _buildMainContentCard() { // Widget 结构始终保持,数据值根据状态显示 "0" 或实际值 diff --git a/frontend/mobile-app/lib/routes/app_router.dart b/frontend/mobile-app/lib/routes/app_router.dart index 9bb40d79..3bc7e4ef 100644 --- a/frontend/mobile-app/lib/routes/app_router.dart +++ b/frontend/mobile-app/lib/routes/app_router.dart @@ -45,6 +45,7 @@ import '../features/contract_signing/presentation/pages/contract_signing_page.da import '../features/contract_signing/presentation/pages/pending_contracts_page.dart'; import '../features/pending_actions/presentation/pages/pending_actions_page.dart'; // [2026-02-17] 新增:预种计划页面(1887 USDT/份,累计 10 份合成 1 棵树) +import '../features/pre_planting/presentation/pages/pre_planting_hub_page.dart'; import '../features/pre_planting/presentation/pages/pre_planting_purchase_page.dart'; import '../features/pre_planting/presentation/pages/pre_planting_position_page.dart'; import '../features/pre_planting/presentation/pages/pre_planting_merge_detail_page.dart'; @@ -445,6 +446,13 @@ final appRouterProvider = Provider((ref) { builder: (context, state) => const ChangePhonePage(), ), + // [2026-03-04] Pre-Planting Hub Page (预种计划 - 入口汇总) + GoRoute( + path: RoutePaths.prePlantingHub, + name: RouteNames.prePlantingHub, + builder: (context, state) => const PrePlantingHubPage(), + ), + // [2026-02-17] Pre-Planting Purchase Page (预种计划 - 购买页) GoRoute( path: RoutePaths.prePlantingPurchase, diff --git a/frontend/mobile-app/lib/routes/route_names.dart b/frontend/mobile-app/lib/routes/route_names.dart index cccab651..d1517ffa 100644 --- a/frontend/mobile-app/lib/routes/route_names.dart +++ b/frontend/mobile-app/lib/routes/route_names.dart @@ -56,6 +56,7 @@ class RouteNames { static const changePhone = 'change-phone'; // [2026-02-17] Pre-Planting (预种计划) + static const prePlantingHub = 'pre-planting-hub'; // [2026-03-04] Hub 汇总入口页 static const prePlantingPurchase = 'pre-planting-purchase'; // 购买页 static const prePlantingPosition = 'pre-planting-position'; // 持仓页 static const prePlantingMergeDetail = 'pre-planting-merge'; // 合并详情页 diff --git a/frontend/mobile-app/lib/routes/route_paths.dart b/frontend/mobile-app/lib/routes/route_paths.dart index 17d5748a..942f5af1 100644 --- a/frontend/mobile-app/lib/routes/route_paths.dart +++ b/frontend/mobile-app/lib/routes/route_paths.dart @@ -56,6 +56,7 @@ class RoutePaths { static const changePhone = '/kyc/change-phone'; // [2026-02-17] Pre-Planting (预种计划) + static const prePlantingHub = '/pre-planting/hub'; // [2026-03-04] Hub 汇总入口页 static const prePlantingPurchase = '/pre-planting/purchase'; // 购买页 static const prePlantingPosition = '/pre-planting/position'; // 持仓页 static const prePlantingMergeDetail = '/pre-planting/merge'; // 合并详情页