import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'ix_developer_tools.dart'; /// 轻量级日志条目组件 class SimpleLogCard extends StatefulWidget { final ConsoleLogEntry log; const SimpleLogCard({super.key, required this.log}); @override State createState() => _SimpleLogCardState(); } class _SimpleLogCardState extends State with SingleTickerProviderStateMixin { bool _isExpanded = false; late AnimationController _animationController; late Animation _expandAnimation; late Animation _iconRotation; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 250), vsync: this, ); _expandAnimation = CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, ); _iconRotation = Tween(begin: 0.0, end: 0.5).animate(_expandAnimation); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final fullMessage = '${widget.log.tag}: ${widget.log.message}'; return Container( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 3), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.white, Colors.blue, ], ), border: Border.all(color: Colors.blue[200]!, width: 1), boxShadow: [ BoxShadow( color: Colors.blue[100]!.withValues(alpha: 0.3), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: Column( children: [ // 主要内容区域 InkWell( onTap: _toggleExpansion, borderRadius: const BorderRadius.vertical(top: Radius.circular(12)), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ // 状态指示器 Container( width: 10, height: 10, decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.cyan[400]!, Colors.teal[500]!], ), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.cyan[300]!.withValues(alpha: 0.5), blurRadius: 4, offset: const Offset(0, 1), ), ], ), ), const SizedBox(width: 12), // 时间标签 Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.purple[500]!, Colors.pink[500]!], ), borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.purple[200]!.withValues(alpha: 0.5), blurRadius: 3, offset: const Offset(0, 1), ), ], ), child: Text( widget.log.formattedTime, style: const TextStyle( fontFamily: 'monospace', fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 12), // 日志内容 Expanded( child: Text( fullMessage, style: const TextStyle( fontFamily: 'monospace', fontSize: 13, color: Colors.black87, fontWeight: FontWeight.w500, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), // 展开/收起图标 AnimatedBuilder( animation: _iconRotation, builder: (context, child) { return Transform.rotate( angle: _iconRotation.value * 3.14159, child: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.blue[100], shape: BoxShape.circle, ), child: Icon( Icons.keyboard_arrow_down, color: Colors.blue[700], size: 16, ), ), ); }, ), ], ), ), ), // 展开的详细内容 SizeTransition( sizeFactor: _expandAnimation, child: Container( width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.blue[50]!, Colors.indigo[50]!], ), borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), ), child: Column( children: [ // 分割线 Container( height: 2, margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.blue[300]!, Colors.purple[300]!], ), borderRadius: BorderRadius.circular(1), ), ), // 详细内容 Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 4), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.orange[500]!, Colors.deepOrange[600]! ], ), borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.orange[200]!.withValues(alpha: 0.5), blurRadius: 3, offset: const Offset(0, 1), ), ], ), child: const Text( '完整内容', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.white, fontSize: 11, ), ), ), const Spacer(), ElevatedButton.icon( icon: const Icon(Icons.copy, size: 14), label: const Text('复制'), style: ElevatedButton.styleFrom( backgroundColor: Colors.teal[600], foregroundColor: Colors.white, elevation: 3, padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), onPressed: () => _copyToClipboard(fullMessage), ), ], ), const SizedBox(height: 12), Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.blue[200]!, width: 1), ), child: SelectableText( fullMessage, style: const TextStyle( fontFamily: 'monospace', fontSize: 13, color: Colors.black87, height: 1.4, ), ), ), ], ), ), ], ), ), ), ], ), ); } void _toggleExpansion() { setState(() { _isExpanded = !_isExpanded; if (_isExpanded) { _animationController.forward(); } else { _animationController.reverse(); } }); } void _copyToClipboard(String text) { Clipboard.setData(ClipboardData(text: text)); Get.snackbar( '🎉 复制成功', '日志内容已复制到剪贴板', duration: const Duration(seconds: 1), snackPosition: SnackPosition.bottom, backgroundColor: Colors.green[500], colorText: Colors.white, borderRadius: 10, margin: const EdgeInsets.all(16), boxShadows: [ BoxShadow( color: Colors.green[200]!.withValues(alpha: 0.5), blurRadius: 6, offset: const Offset(0, 3), ), ], ); } }