feat(pre-planting): 合并后走正常签合同流程,购买第5份直接跳合并详情页
- pre_planting_service: CreatePrePlantingOrderResponse 增加 merged/mergeNo 字段 - pre_planting_purchase_page: 购买成功若触发合并,直接跳转合并详情签合同 - contract_check_service: 注入 PrePlantingService,checkAll 增加预种待签合并检查 - pending_contracts_page: 同时展示普通合同和预种合并待签卡片,复用现有签合同弹窗流程 - injection_container: contractCheckServiceProvider 注入 prePlantingService Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
26dcd1d2de
commit
b9b23c36d7
|
|
@ -166,10 +166,14 @@ final contractSigningServiceProvider = Provider<ContractSigningService>((ref) {
|
||||||
return ContractSigningService(apiClient: apiClient);
|
return ContractSigningService(apiClient: apiClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Contract Check Service Provider (用于启动时检查未签署合同)
|
// Contract Check Service Provider (用于启动时检查未签署合同,含预种待签合并)
|
||||||
final contractCheckServiceProvider = Provider<ContractCheckService>((ref) {
|
final contractCheckServiceProvider = Provider<ContractCheckService>((ref) {
|
||||||
final contractSigningService = ref.watch(contractSigningServiceProvider);
|
final contractSigningService = ref.watch(contractSigningServiceProvider);
|
||||||
return ContractCheckService(contractSigningService: contractSigningService);
|
final prePlantingService = ref.watch(prePlantingServiceProvider);
|
||||||
|
return ContractCheckService(
|
||||||
|
contractSigningService: contractSigningService,
|
||||||
|
prePlantingService: prePlantingService,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// KYC Service Provider (调用 identity-service)
|
// KYC Service Provider (调用 identity-service)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'contract_signing_service.dart';
|
import 'contract_signing_service.dart';
|
||||||
|
import 'pre_planting_service.dart';
|
||||||
|
|
||||||
/// 合同检查结果
|
/// 合同检查结果
|
||||||
class ContractCheckResult {
|
class ContractCheckResult {
|
||||||
|
|
@ -15,11 +16,15 @@ class ContractCheckResult {
|
||||||
/// 已付款但未完成 KYC 的订单数量
|
/// 已付款但未完成 KYC 的订单数量
|
||||||
final int paidOrderCount;
|
final int paidOrderCount;
|
||||||
|
|
||||||
|
/// 待签署的预种合并合同编号(有则跳到合并详情页)
|
||||||
|
final String? pendingPrePlantingMergeNo;
|
||||||
|
|
||||||
ContractCheckResult({
|
ContractCheckResult({
|
||||||
required this.hasPendingContracts,
|
required this.hasPendingContracts,
|
||||||
required this.requiresKyc,
|
required this.requiresKyc,
|
||||||
this.kycMessage,
|
this.kycMessage,
|
||||||
this.paidOrderCount = 0,
|
this.paidOrderCount = 0,
|
||||||
|
this.pendingPrePlantingMergeNo,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// 是否需要强制操作(有待签署合同或需要 KYC)
|
/// 是否需要强制操作(有待签署合同或需要 KYC)
|
||||||
|
|
@ -30,21 +35,23 @@ class ContractCheckResult {
|
||||||
/// 用于在 App 启动时检查用户是否有未签署的合同或需要完成 KYC
|
/// 用于在 App 启动时检查用户是否有未签署的合同或需要完成 KYC
|
||||||
class ContractCheckService {
|
class ContractCheckService {
|
||||||
final ContractSigningService _contractSigningService;
|
final ContractSigningService _contractSigningService;
|
||||||
|
final PrePlantingService _prePlantingService;
|
||||||
|
|
||||||
ContractCheckService({
|
ContractCheckService({
|
||||||
required ContractSigningService contractSigningService,
|
required ContractSigningService contractSigningService,
|
||||||
}) : _contractSigningService = contractSigningService;
|
required PrePlantingService prePlantingService,
|
||||||
|
}) : _contractSigningService = contractSigningService,
|
||||||
|
_prePlantingService = prePlantingService;
|
||||||
|
|
||||||
/// 检查是否有待签署的合同
|
/// 检查是否有待签署的合同(含预种合并合同)
|
||||||
/// 返回 true 表示有待签署合同,需要强制签署
|
/// 返回 true 表示有待签署合同,需要强制签署
|
||||||
Future<bool> hasPendingContracts() async {
|
Future<bool> hasPendingContracts() async {
|
||||||
try {
|
try {
|
||||||
// 获取未签署任务(包括待签署和超时未签署的)
|
|
||||||
final unsignedTasks = await _contractSigningService.getUnsignedTasks();
|
final unsignedTasks = await _contractSigningService.getUnsignedTasks();
|
||||||
return unsignedTasks.isNotEmpty;
|
if (unsignedTasks.isNotEmpty) return true;
|
||||||
|
final mergeNo = await _getPendingPrePlantingMergeNo();
|
||||||
|
return mergeNo != null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// debugPrint('[ContractCheckService] 检查待签署合同失败: $e');
|
|
||||||
// 检查失败时不阻止用户使用 App
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,23 +59,29 @@ class ContractCheckService {
|
||||||
/// 综合检查:待签署合同和 KYC 需求
|
/// 综合检查:待签署合同和 KYC 需求
|
||||||
///
|
///
|
||||||
/// 返回检查结果,包含:
|
/// 返回检查结果,包含:
|
||||||
/// - 是否有待签署的合同
|
/// - 是否有待签署的合同(含预种合并合同)
|
||||||
/// - 是否需要先完成 KYC(有已付款订单但未完成 KYC)
|
/// - 是否需要先完成 KYC(有已付款订单但未完成 KYC)
|
||||||
Future<ContractCheckResult> checkAll() async {
|
Future<ContractCheckResult> checkAll() async {
|
||||||
try {
|
try {
|
||||||
// 1. 检查未签署的合同
|
// 1. 检查普通认种未签署合同
|
||||||
final unsignedTasks = await _contractSigningService.getUnsignedTasks();
|
final unsignedTasks = await _contractSigningService.getUnsignedTasks();
|
||||||
final hasPending = unsignedTasks.isNotEmpty;
|
if (unsignedTasks.isNotEmpty) {
|
||||||
|
|
||||||
// 2. 如果有待签署的合同,直接返回(不需要再检查 KYC)
|
|
||||||
if (hasPending) {
|
|
||||||
// debugPrint('[ContractCheckService] 检测到 ${unsignedTasks.length} 个待签署合同');
|
|
||||||
return ContractCheckResult(
|
return ContractCheckResult(
|
||||||
hasPendingContracts: true,
|
hasPendingContracts: true,
|
||||||
requiresKyc: false,
|
requiresKyc: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 检查预种待签合并合同
|
||||||
|
final pendingMergeNo = await _getPendingPrePlantingMergeNo();
|
||||||
|
if (pendingMergeNo != null) {
|
||||||
|
return ContractCheckResult(
|
||||||
|
hasPendingContracts: true,
|
||||||
|
requiresKyc: false,
|
||||||
|
pendingPrePlantingMergeNo: pendingMergeNo,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 3. 没有待签署合同,检查是否有需要 KYC 的情况
|
// 3. 没有待签署合同,检查是否有需要 KYC 的情况
|
||||||
final kycResult = await _contractSigningService.checkKycRequirement();
|
final kycResult = await _contractSigningService.checkKycRequirement();
|
||||||
|
|
||||||
|
|
@ -79,8 +92,6 @@ class ContractCheckService {
|
||||||
paidOrderCount: kycResult.paidOrderCount,
|
paidOrderCount: kycResult.paidOrderCount,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// debugPrint('[ContractCheckService] 综合检查失败: $e');
|
|
||||||
// 检查失败时不阻止用户使用 App
|
|
||||||
return ContractCheckResult(
|
return ContractCheckResult(
|
||||||
hasPendingContracts: false,
|
hasPendingContracts: false,
|
||||||
requiresKyc: false,
|
requiresKyc: false,
|
||||||
|
|
@ -92,10 +103,24 @@ class ContractCheckService {
|
||||||
Future<int> getPendingContractCount() async {
|
Future<int> getPendingContractCount() async {
|
||||||
try {
|
try {
|
||||||
final unsignedTasks = await _contractSigningService.getUnsignedTasks();
|
final unsignedTasks = await _contractSigningService.getUnsignedTasks();
|
||||||
return unsignedTasks.length;
|
if (unsignedTasks.isNotEmpty) return unsignedTasks.length;
|
||||||
|
final mergeNo = await _getPendingPrePlantingMergeNo();
|
||||||
|
return mergeNo != null ? 1 : 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// debugPrint('[ContractCheckService] 获取待签署合同数量失败: $e');
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 查找第一个待签署的预种合并合同编号
|
||||||
|
Future<String?> _getPendingPrePlantingMergeNo() async {
|
||||||
|
try {
|
||||||
|
final merges = await _prePlantingService.getMerges();
|
||||||
|
final pending = merges.where(
|
||||||
|
(m) => m.contractStatus == PrePlantingContractStatus.pending,
|
||||||
|
);
|
||||||
|
return pending.isEmpty ? null : pending.first.mergeNo;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -230,12 +230,16 @@ class CreatePrePlantingOrderResponse {
|
||||||
final int portionCount;
|
final int portionCount;
|
||||||
final double totalAmount;
|
final double totalAmount;
|
||||||
final double pricePerPortion;
|
final double pricePerPortion;
|
||||||
|
final bool merged;
|
||||||
|
final String? mergeNo;
|
||||||
|
|
||||||
CreatePrePlantingOrderResponse({
|
CreatePrePlantingOrderResponse({
|
||||||
required this.orderNo,
|
required this.orderNo,
|
||||||
required this.portionCount,
|
required this.portionCount,
|
||||||
required this.totalAmount,
|
required this.totalAmount,
|
||||||
required this.pricePerPortion,
|
required this.pricePerPortion,
|
||||||
|
this.merged = false,
|
||||||
|
this.mergeNo,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory CreatePrePlantingOrderResponse.fromJson(Map<String, dynamic> json) {
|
factory CreatePrePlantingOrderResponse.fromJson(Map<String, dynamic> json) {
|
||||||
|
|
@ -244,6 +248,8 @@ class CreatePrePlantingOrderResponse {
|
||||||
portionCount: json['portionCount'] ?? 1,
|
portionCount: json['portionCount'] ?? 1,
|
||||||
totalAmount: (json['totalAmount'] ?? 3566).toDouble(),
|
totalAmount: (json['totalAmount'] ?? 3566).toDouble(),
|
||||||
pricePerPortion: (json['pricePerPortion'] ?? 3566).toDouble(),
|
pricePerPortion: (json['pricePerPortion'] ?? 3566).toDouble(),
|
||||||
|
merged: json['merged'] == true,
|
||||||
|
mergeNo: json['mergeNo']?.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import '../../../../core/di/injection_container.dart';
|
import '../../../../core/di/injection_container.dart';
|
||||||
import '../../../../core/services/contract_signing_service.dart';
|
import '../../../../core/services/contract_signing_service.dart';
|
||||||
|
import '../../../../core/services/pre_planting_service.dart';
|
||||||
import '../../../../routes/route_paths.dart';
|
import '../../../../routes/route_paths.dart';
|
||||||
|
|
||||||
/// 待签署合同列表页面
|
/// 待签署合同列表页面
|
||||||
/// 用于 App 启动时检查并强制用户签署未完成的合同
|
/// 用于 App 启动时检查并强制用户签署未完成的合同
|
||||||
|
/// 包含:普通认种合同 + 预种合并合同
|
||||||
class PendingContractsPage extends ConsumerStatefulWidget {
|
class PendingContractsPage extends ConsumerStatefulWidget {
|
||||||
/// 是否为强制模式(不允许跳过)
|
/// 是否为强制模式(不允许跳过)
|
||||||
final bool forceSign;
|
final bool forceSign;
|
||||||
|
|
@ -22,6 +24,7 @@ class PendingContractsPage extends ConsumerStatefulWidget {
|
||||||
|
|
||||||
class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
List<ContractSigningTask> _unsignedTasks = [];
|
List<ContractSigningTask> _unsignedTasks = [];
|
||||||
|
List<PrePlantingMerge> _pendingMerges = [];
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
String? _errorMessage;
|
String? _errorMessage;
|
||||||
|
|
||||||
|
|
@ -38,18 +41,29 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final service = ref.read(contractSigningServiceProvider);
|
final contractService = ref.read(contractSigningServiceProvider);
|
||||||
|
final prePlantingService = ref.read(prePlantingServiceProvider);
|
||||||
|
|
||||||
// 获取所有未签署任务(包括待签署和超时未签署)
|
// 并行加载:普通认种未签合同 + 预种待签合并
|
||||||
final tasks = await service.getUnsignedTasks();
|
final results = await Future.wait([
|
||||||
|
contractService.getUnsignedTasks(),
|
||||||
|
prePlantingService.getMerges(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
final tasks = results[0] as List<ContractSigningTask>;
|
||||||
|
final allMerges = results[1] as List<PrePlantingMerge>;
|
||||||
|
final pendingMerges = allMerges
|
||||||
|
.where((m) => m.contractStatus == PrePlantingContractStatus.pending)
|
||||||
|
.toList();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_unsignedTasks = tasks;
|
_unsignedTasks = tasks;
|
||||||
|
_pendingMerges = pendingMerges;
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果没有待签署任务,自动返回
|
// 如果没有任何待签署任务,自动返回
|
||||||
if (_unsignedTasks.isEmpty) {
|
if (_unsignedTasks.isEmpty && _pendingMerges.isEmpty) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
context.pop(true);
|
context.pop(true);
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +76,7 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 签署合同
|
/// 签署普通认种合同
|
||||||
Future<void> _signContract(ContractSigningTask task) async {
|
Future<void> _signContract(ContractSigningTask task) async {
|
||||||
final result = await context.push<bool>(
|
final result = await context.push<bool>(
|
||||||
'${RoutePaths.contractSigning}/${task.orderNo}',
|
'${RoutePaths.contractSigning}/${task.orderNo}',
|
||||||
|
|
@ -74,6 +88,13 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 签署预种合并合同(跳转到合并详情页)
|
||||||
|
Future<void> _signPrePlantingMerge(PrePlantingMerge merge) async {
|
||||||
|
await context.push('${RoutePaths.prePlantingMergeDetail}/${merge.mergeNo}');
|
||||||
|
// 返回后刷新,合并可能已签署
|
||||||
|
_loadTasks();
|
||||||
|
}
|
||||||
|
|
||||||
/// 跳过(仅非强制模式)
|
/// 跳过(仅非强制模式)
|
||||||
void _skip() {
|
void _skip() {
|
||||||
if (!widget.forceSign) {
|
if (!widget.forceSign) {
|
||||||
|
|
@ -177,7 +198,7 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_unsignedTasks.isEmpty) {
|
if (_unsignedTasks.isEmpty && _pendingMerges.isEmpty) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
|
@ -200,10 +221,12 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: _loadTasks,
|
onRefresh: _loadTasks,
|
||||||
color: const Color(0xFFD4AF37),
|
color: const Color(0xFFD4AF37),
|
||||||
child: ListView.builder(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
itemCount: _unsignedTasks.length,
|
children: [
|
||||||
itemBuilder: (context, index) => _buildTaskCard(_unsignedTasks[index]),
|
..._unsignedTasks.map((task) => _buildTaskCard(task)),
|
||||||
|
..._pendingMerges.map((merge) => _buildMergeCard(merge)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -289,95 +312,34 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
// 状态提示
|
|
||||||
if (isTimeout)
|
if (isTimeout)
|
||||||
Container(
|
_buildStatusHint(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
color: const Color(0xFFFFEBEE),
|
||||||
decoration: BoxDecoration(
|
icon: Icons.warning_amber_rounded,
|
||||||
color: const Color(0xFFFFEBEE),
|
iconColor: const Color(0xFFE53935),
|
||||||
borderRadius: BorderRadius.circular(8),
|
text: '签署已超时,请尽快补签',
|
||||||
),
|
textColor: const Color(0xFFE53935),
|
||||||
child: const Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.warning_amber_rounded, color: Color(0xFFE53935), size: 16),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'签署已超时,请尽快补签',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Color(0xFFE53935),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else if (isUrgent)
|
else if (isUrgent)
|
||||||
Container(
|
_buildStatusHint(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
color: const Color(0xFFFFF3E0),
|
||||||
decoration: BoxDecoration(
|
icon: Icons.access_time,
|
||||||
color: const Color(0xFFFFF3E0),
|
iconColor: const Color(0xFFFF9800),
|
||||||
borderRadius: BorderRadius.circular(8),
|
text: '剩余 ${_formatRemainingTime(task.remainingSeconds)}',
|
||||||
),
|
textColor: const Color(0xFFE65100),
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.access_time, color: Color(0xFFFF9800), size: 16),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'剩余 ${_formatRemainingTime(task.remainingSeconds)}',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Color(0xFFE65100),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
Container(
|
_buildStatusHint(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
color: const Color(0xFFE3F2FD),
|
||||||
decoration: BoxDecoration(
|
icon: Icons.timer,
|
||||||
color: const Color(0xFFE3F2FD),
|
iconColor: const Color(0xFF1976D2),
|
||||||
borderRadius: BorderRadius.circular(8),
|
text: '剩余 ${_formatRemainingTime(task.remainingSeconds)}',
|
||||||
),
|
textColor: const Color(0xFF1976D2),
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.timer, color: Color(0xFF1976D2), size: 16),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'剩余 ${_formatRemainingTime(task.remainingSeconds)}',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Color(0xFF1976D2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
// 签署按钮
|
_buildSignButton(
|
||||||
Container(
|
label: isTimeout ? '立即补签' : '立即签署',
|
||||||
width: double.infinity,
|
color: isTimeout ? const Color(0xFFE53935) : const Color(0xFFD4AF37),
|
||||||
height: 44,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isTimeout ? const Color(0xFFE53935) : const Color(0xFFD4AF37),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
isTimeout ? '立即补签' : '立即签署',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -386,6 +348,142 @@ class _PendingContractsPageState extends ConsumerState<PendingContractsPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 预种合并待签卡片
|
||||||
|
Widget _buildMergeCard(PrePlantingMerge merge) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.only(bottom: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withValues(alpha: 0.1),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
border: Border.all(color: const Color(0xFF4CAF50), width: 1),
|
||||||
|
),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => _signPrePlantingMerge(merge),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'合并编号: ${merge.mergeNo}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Color(0xFF666666),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'${merge.treeCount} 棵预种合并树',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Color(0xFF5D4037),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFE8F5E9),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'待签署',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF2E7D32),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_buildStatusHint(
|
||||||
|
color: const Color(0xFFE8F5E9),
|
||||||
|
icon: Icons.park_outlined,
|
||||||
|
iconColor: const Color(0xFF4CAF50),
|
||||||
|
text: '5 份预种份额已合并,请签署合同以开启挖矿',
|
||||||
|
textColor: const Color(0xFF2E7D32),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_buildSignButton(
|
||||||
|
label: '立即签署',
|
||||||
|
color: const Color(0xFF4CAF50),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStatusHint({
|
||||||
|
required Color color,
|
||||||
|
required IconData icon,
|
||||||
|
required Color iconColor,
|
||||||
|
required String text,
|
||||||
|
required Color textColor,
|
||||||
|
}) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(icon, color: iconColor, size: 16),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: TextStyle(fontSize: 12, color: textColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSignButton({required String label, required Color color}) {
|
||||||
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 44,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildStatusBadge(ContractSigningTask task) {
|
Widget _buildStatusBadge(ContractSigningTask task) {
|
||||||
Color bgColor;
|
Color bgColor;
|
||||||
Color textColor;
|
Color textColor;
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,8 @@ class _PrePlantingPurchasePageState
|
||||||
|
|
||||||
debugPrint(
|
debugPrint(
|
||||||
'[PrePlantingPurchase] 购买成功: orderNo=${response.orderNo}, '
|
'[PrePlantingPurchase] 购买成功: orderNo=${response.orderNo}, '
|
||||||
'portions=${response.portionCount}, total=${response.totalAmount}',
|
'portions=${response.portionCount}, total=${response.totalAmount}, '
|
||||||
|
'merged=${response.merged}, mergeNo=${response.mergeNo}',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|
@ -382,8 +383,13 @@ class _PrePlantingPurchasePageState
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 返回上一页(Profile 页面会自动刷新)
|
// 如果触发了合并(5 份凑满 1 棵树),直接跳转到合并详情页签合同
|
||||||
context.pop(true);
|
if (response.merged && response.mergeNo != null) {
|
||||||
|
context.push('${RoutePaths.prePlantingMergeDetail}/${response.mergeNo}');
|
||||||
|
} else {
|
||||||
|
// 返回上一页(Profile 页面会自动刷新)
|
||||||
|
context.pop(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
debugPrint('[PrePlantingPurchase] ★ 购买失败 type=${e.runtimeType}: $e');
|
debugPrint('[PrePlantingPurchase] ★ 购买失败 type=${e.runtimeType}: $e');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue