131 lines
4.6 KiB
Dart
131 lines
4.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../../../core/theme/app_spacing.dart';
|
|
import '../../../../data/models/coin.dart';
|
|
import '../../../components/coin_icon.dart';
|
|
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
|
|
|
/// 交易页顶部信息区:代币信息(左) + 价格信息(右) 同行展示
|
|
class PriceCard extends StatelessWidget {
|
|
final Coin coin;
|
|
final String tradingStatus;
|
|
final VoidCallback? onTapCoin;
|
|
|
|
const PriceCard({
|
|
super.key,
|
|
required this.coin,
|
|
this.tradingStatus = 'trading',
|
|
this.onTapCoin,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final colorScheme = Theme.of(context).colorScheme;
|
|
final isUp = coin.isUp;
|
|
final changeColor = isUp ? colorScheme.tertiary : colorScheme.error;
|
|
final isTrading = tradingStatus == 'trading';
|
|
final isLunch = tradingStatus == 'lunch_break';
|
|
final statusLabel = isTrading ? '交易中' : (isLunch ? '午休中' : '已收盘');
|
|
final statusColor = isTrading ? colorScheme.tertiary : (isLunch ? Colors.orange : colorScheme.onSurfaceVariant);
|
|
final showPrice = true;
|
|
|
|
return Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
// 左侧:代币信息
|
|
GestureDetector(
|
|
onTap: onTapCoin,
|
|
behavior: HitTestBehavior.opaque,
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
CoinIcon(symbol: coin.code, size: 28),
|
|
const SizedBox(width: 8),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
coin.code,
|
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700, color: colorScheme.onSurface),
|
|
),
|
|
Text(
|
|
' /USDT',
|
|
style: TextStyle(fontSize: 12, color: colorScheme.onSurfaceVariant),
|
|
),
|
|
const SizedBox(width: 2),
|
|
Icon(LucideIcons.chevronDown, size: 12, color: colorScheme.onSurfaceVariant),
|
|
],
|
|
),
|
|
// 交易状态
|
|
Text(
|
|
statusLabel,
|
|
style: TextStyle(fontSize: 11, color: statusColor, fontWeight: FontWeight.w500),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Spacer(),
|
|
// 右侧:价格 + 涨跌幅
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.baseline,
|
|
textBaseline: TextBaseline.alphabetic,
|
|
children: [
|
|
Text(
|
|
showPrice ? coin.formattedPrice : '--',
|
|
style: TextStyle(
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.w700,
|
|
color: showPrice ? colorScheme.onSurface : colorScheme.onSurfaceVariant,
|
|
),
|
|
),
|
|
if (showPrice) ...[
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
coin.formattedChange,
|
|
style: TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w600,
|
|
color: changeColor,
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
const SizedBox(height: 4),
|
|
// 24h 统计 — 小字一行
|
|
Text(
|
|
'高 ${_fmt(coin.high24h)} 低 ${_fmt(coin.low24h)} 量 ${_fmtVol(coin.volume24h)}',
|
|
style: TextStyle(fontSize: 10, color: colorScheme.onSurfaceVariant),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
String _fmt(double? v) {
|
|
if (v == null) return '--';
|
|
if (v >= 1000) return v.toStringAsFixed(2);
|
|
if (v >= 1) return v.toStringAsFixed(4);
|
|
return v.toStringAsFixed(6);
|
|
}
|
|
|
|
String _fmtVol(double? v) {
|
|
if (v == null) return '--';
|
|
if (v >= 1000000) return '${(v / 1000000).toStringAsFixed(2)}M';
|
|
if (v >= 1000) return '${(v / 1000).toStringAsFixed(2)}K';
|
|
return v.toStringAsFixed(2);
|
|
}
|
|
}
|