fix(pre-planting): 修复预种页面 5 个 UI 问题(纯前端,零后端改动)

=== 问题 1:流水明细合同按钮 500 错误 ===
文件: ledger_detail_page.dart
原因: 预种订单(PPL 前缀)无合同,但流水详情弹窗显示「查看合同/下载合同」按钮
修复: _showTransactionDetail 检测 refOrderId.startsWith('PPL'),
      预种订单传 showContractButtons: false,弹窗不渲染合同按钮区

=== 问题 2:流水备注显示英文 ===
文件: ledger_detail_page.dart
原因: 备注字段存储的是 'Plant payment (from frozen)'(后端写入,不改后端)
修复: _TransactionDetailSheet 展示备注时,若订单号以 PPL 开头则显示「预种」

=== 问题 3:预种明细订单金额单位错误 ===
文件: pre_planting_position_page.dart
修复: '${order.totalAmount.toInt()} USDT' → '${order.totalAmount.toInt()} 绿积分'

=== 问题 4:省市显示数字代码(如 44 · 4401)===
文件: pre_planting_position_page.dart / pre_planting_purchase_page.dart
原因: provinceName/cityName 为 null 时回退显示 provinceCode/cityCode
修复:
  - position 页:条件改为 provinceName != null && cityName != null,无中文名则不显示省市行
  - purchase 页:加载时不再 fallback 到代码;锁定显示无名称时显示「已锁定」;
    购买确认弹窗省市行无名称时显示「-」

=== 问题 5:「合并进度」改为「合成进度」===
文件: pre_planting_position_page.dart / pre_planting_purchase_page.dart
修复: 两处 Text('合并进度') → Text('合成进度')

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-28 06:25:38 -08:00
parent f4c9535e12
commit 2d7b02aa96
3 changed files with 80 additions and 68 deletions

View File

@ -345,9 +345,9 @@ class _PrePlantingPositionPageState
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// //
const Text( const Text(
'进度', '进度',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontFamily: 'Inter', fontFamily: 'Inter',
@ -389,8 +389,8 @@ class _PrePlantingPositionPageState
), ),
], ],
), ),
// //
if (pos.hasProvinceCity) ...[ if (pos.provinceName != null && pos.cityName != null) ...[
const SizedBox(height: 12), const SizedBox(height: 12),
Row( Row(
children: [ children: [
@ -401,7 +401,7 @@ class _PrePlantingPositionPageState
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
'${pos.provinceName ?? pos.provinceCode} · ${pos.cityName ?? pos.cityCode}', '${pos.provinceName!} · ${pos.cityName!}',
style: const TextStyle( style: const TextStyle(
fontSize: 13, fontSize: 13,
color: Color(0xFF745D43), color: Color(0xFF745D43),
@ -594,7 +594,7 @@ class _PrePlantingPositionPageState
const SizedBox(width: 16), const SizedBox(width: 16),
_buildInfoChip( _buildInfoChip(
Icons.monetization_on_outlined, Icons.monetization_on_outlined,
'${order.totalAmount.toInt()} USDT', '${order.totalAmount.toInt()} 绿积分',
), ),
], ],
), ),

View File

@ -166,12 +166,12 @@ class _PrePlantingPurchasePageState
_pricePerPortion = pricingConfig.totalPortionPrice.toDouble(); _pricePerPortion = pricingConfig.totalPortionPrice.toDouble();
_isLoading = false; _isLoading = false;
// // 退
if (position.hasProvinceCity) { if (position.hasProvinceCity) {
_selectedProvinceCode = position.provinceCode; _selectedProvinceCode = position.provinceCode;
_selectedProvinceName = position.provinceName ?? position.provinceCode; _selectedProvinceName = position.provinceName;
_selectedCityCode = position.cityCode; _selectedCityCode = position.cityCode;
_selectedCityName = position.cityName ?? position.cityCode; _selectedCityName = position.cityName;
} }
// 1 // 1
@ -445,7 +445,9 @@ class _PrePlantingPurchasePageState
const SizedBox(height: 8), const SizedBox(height: 8),
_buildDialogRow( _buildDialogRow(
'省市', '省市',
'${_selectedProvinceName ?? "-"} · ${_selectedCityName ?? "-"}', _selectedProvinceName != null && _selectedCityName != null
? '$_selectedProvinceName · $_selectedCityName'
: '-',
), ),
if (_position != null) ...[ if (_position != null) ...[
const Divider(height: 24, color: Color(0x338B5A2B)), const Divider(height: 24, color: Color(0x338B5A2B)),
@ -884,7 +886,7 @@ class _PrePlantingPurchasePageState
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const Text( const Text(
'进度', '进度',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontFamily: 'Inter', fontFamily: 'Inter',
@ -1037,7 +1039,9 @@ class _PrePlantingPurchasePageState
children: [ children: [
Text( Text(
_hasSelectedProvinceCity _hasSelectedProvinceCity
? (_selectedProvinceName != null && _selectedCityName != null
? '$_selectedProvinceName · $_selectedCityName' ? '$_selectedProvinceName · $_selectedCityName'
: '已锁定')
: '点击选择省份和城市', : '点击选择省份和城市',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,

View File

@ -1116,14 +1116,18 @@ class _LedgerDetailPageState extends ConsumerState<LedgerDetailPage>
Future<void> _showTransactionDetail(LedgerEntry entry) async { Future<void> _showTransactionDetail(LedgerEntry entry) async {
if (entry.refOrderId == null) return; if (entry.refOrderId == null) return;
// PPL
final bool isPrePlanting = entry.refOrderId!.startsWith('PPL');
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
builder: (context) => _TransactionDetailSheet( builder: (context) => _TransactionDetailSheet(
entry: entry, entry: entry,
onViewContract: () => _viewContractPdf(entry.refOrderId!), showContractButtons: !isPrePlanting,
onDownloadContract: () => _downloadContractPdf(entry.refOrderId!), onViewContract: isPrePlanting ? null : () => _viewContractPdf(entry.refOrderId!),
onDownloadContract: isPrePlanting ? null : () => _downloadContractPdf(entry.refOrderId!),
), ),
); );
} }
@ -1231,13 +1235,15 @@ class _LedgerDetailPageState extends ConsumerState<LedgerDetailPage>
/// ///
class _TransactionDetailSheet extends StatelessWidget { class _TransactionDetailSheet extends StatelessWidget {
final LedgerEntry entry; final LedgerEntry entry;
final VoidCallback onViewContract; final VoidCallback? onViewContract;
final VoidCallback onDownloadContract; final VoidCallback? onDownloadContract;
final bool showContractButtons;
const _TransactionDetailSheet({ const _TransactionDetailSheet({
required this.entry, required this.entry,
required this.onViewContract, this.onViewContract,
required this.onDownloadContract, this.onDownloadContract,
this.showContractButtons = true,
}); });
@override @override
@ -1326,16 +1332,17 @@ class _TransactionDetailSheet extends StatelessWidget {
_buildDetailRow('交易后余额', '${_formatAmount(entry.balanceAfter!)} 绿积分'), _buildDetailRow('交易后余额', '${_formatAmount(entry.balanceAfter!)} 绿积分'),
_buildDetailRow('交易时间', _formatDateTime(entry.createdAt)), _buildDetailRow('交易时间', _formatDateTime(entry.createdAt)),
if (entry.memo != null && entry.memo!.isNotEmpty) if (entry.memo != null && entry.memo!.isNotEmpty)
_buildDetailRow('备注', entry.memo!), _buildDetailRow('备注',
entry.refOrderId?.startsWith('PPL') == true ? '预种' : entry.memo!),
], ],
), ),
), ),
// 线 //
if (showContractButtons) ...[
Container( Container(
height: 1, height: 1,
color: const Color(0x1A8B5A2B), color: const Color(0x1A8B5A2B),
), ),
//
Padding( Padding(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
child: Row( child: Row(
@ -1344,7 +1351,7 @@ class _TransactionDetailSheet extends StatelessWidget {
child: OutlinedButton.icon( child: OutlinedButton.icon(
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
onViewContract(); onViewContract?.call();
}, },
icon: const Icon(Icons.visibility_outlined, size: 18), icon: const Icon(Icons.visibility_outlined, size: 18),
label: const Text('查看合同'), label: const Text('查看合同'),
@ -1363,7 +1370,7 @@ class _TransactionDetailSheet extends StatelessWidget {
child: ElevatedButton.icon( child: ElevatedButton.icon(
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
onDownloadContract(); onDownloadContract?.call();
}, },
icon: const Icon(Icons.download_outlined, size: 18), icon: const Icon(Icons.download_outlined, size: 18),
label: const Text('下载合同'), label: const Text('下载合同'),
@ -1381,6 +1388,7 @@ class _TransactionDetailSheet extends StatelessWidget {
), ),
), ),
], ],
],
), ),
), ),
); );