feat(app): 预种计划三按钮合并为单入口 Hub 页面

## 背景
「我」页面原有三个并排的预种按钮(预种购买 / 预种明细 / 团队预种),
三等分宽度导致文字拥挤,视觉层级也不清晰。

## 改动内容

### 新增文件
- `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 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-03-04 06:42:50 -08:00
parent 979ba379c1
commit 8b48d80cd4
5 changed files with 232 additions and 134 deletions

View File

@ -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,
),
],
),
),
);
}
}

View File

@ -1356,16 +1356,6 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
}
}
/// [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<ProfilePage> {
//
_buildPlantingButton(),
const SizedBox(height: 8),
// [2026-02-17] +
// [2026-03-04]
//
if (_isPrePlantingActive) ...[
_buildPrePlantingButtons(),
_buildPrePlantingEntryButton(),
const SizedBox(height: 8),
],
const SizedBox(height: 16),
@ -2041,20 +2031,13 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
);
}
/// [2026-02-17] +
///
///
/// - 1887 USDT/
/// -
Widget _buildPrePlantingButtons() {
return Row(
children: [
//
Expanded(
child: GestureDetector(
onTap: _goToPrePlantingPurchase,
/// [2026-03-04]
Widget _buildPrePlantingEntryButton() {
return GestureDetector(
onTap: () => context.push(RoutePaths.prePlantingHub),
child: Container(
height: 44,
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFFD4AF37).withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(8),
@ -2066,111 +2049,25 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.add_circle_outline,
color: Color(0xFFD4AF37),
size: 18,
),
SizedBox(width: 6),
Icon(Icons.eco_outlined, color: Color(0xFFD4AF37), size: 20),
SizedBox(width: 8),
Text(
'预种购买',
'申请预种计划',
style: TextStyle(
fontSize: 14,
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),
//
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),
),
),
],
),
),
),
),
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"

View File

@ -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<GoRouter>((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,

View File

@ -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'; //

View File

@ -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'; //