This commit is contained in:
sion
2026-04-21 08:09:45 +08:00
parent 0066615054
commit 5264043c21
1831 changed files with 15376 additions and 39973 deletions

View File

@@ -1,73 +1,130 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../data/models/coin.dart';
import '../../../components/coin_icon.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
/// 價格卡片組件
///
/// 顯示當前幣種價格和 24h 漲跌幅。
/// 佈局:大號價格(32px bold) + 漲跌幅徽章(圓角sm漲綠背景) + "24h 變化" 副標題。
/// 交易页顶部信息区:代币信息(左) + 价格信息(右) 同行展示
class PriceCard extends StatelessWidget {
final Coin coin;
const PriceCard({super.key, required this.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 ? context.appColors.up : context.appColors.down;
final changeBgColor = isUp
? context.appColors.upBackground
: context.appColors.downBackground;
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 Container(
width: double.infinity,
padding: const EdgeInsets.all(20), // 24px → 20px
decoration: BoxDecoration(
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: context.appColors.ghostBorder,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
return Padding(
padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 價格行:大號價格 + 漲跌幅徽章
Row(
// 左侧:代币信息
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: [
Text(
coin.formattedPrice,
style: AppTextStyles.numberLarge(context).copyWith(fontSize: 32),
),
const SizedBox(width: AppSpacing.sm),
// 漲跌幅徽章 - 圓角sm漲綠背景
Container(
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 4), // 調整 padding
decoration: BoxDecoration(
color: changeBgColor,
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Text(
coin.formattedChange,
style: AppTextStyles.numberSmall(context).copyWith(
color: changeColor,
fontWeight: FontWeight.w600,
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),
),
],
),
const SizedBox(height: AppSpacing.sm),
// 副標題
Text(
'24h 變化',
style: AppTextStyles.bodySmall(context),
),
],
),
);
}
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);
}
}