import 'package:flutter/material.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/component/home_page/SleepDataModuleWidget.dart'; import 'package:EasyDartModule/EasyDartModule.dart' as es; import 'package:vbvs_app/enum/APPPackageType.dart'; import 'package:vbvs_app/language/AppLanguage.dart'; class SleepCard extends StatefulWidget { final dynamic sleepReport; final int? highlightItem; SleepCard({super.key, required this.sleepReport, this.highlightItem}); @override State createState() => _SleepCardState(); } class _SleepCardState extends State with TickerProviderStateMixin { final GlobalKey _highlightKey = GlobalKey(); AnimationController? _animationController; bool _shouldAnimate = false; int? _highlightedId; int _flashCount = 0; // 用于跟踪闪烁次数 @override void initState() { super.initState(); if (widget.highlightItem != null) { _highlightedId = widget.highlightItem; _shouldAnimate = true; _initAnimation(); } WidgetsBinding.instance.addPostFrameCallback((_) { if (widget.highlightItem != null && _highlightKey.currentContext != null) { Scrollable.ensureVisible( _highlightKey.currentContext!, duration: Duration(milliseconds: 500), curve: Curves.easeInOut, alignment: 0.3, ); } }); } void _initAnimation() { _animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 300), )..addStatusListener((status) { if (status == AnimationStatus.completed) { // 正向动画完成,开始反向动画 _animationController!.reverse(); } else if (status == AnimationStatus.dismissed) { // 反向动画完成,增加计数 _flashCount++; // 闪烁3次后停止 if (_flashCount >= 5) { _animationController!.dispose(); setState(() { _shouldAnimate = false; _highlightedId = null; }); } else { // 继续下一次闪烁 _animationController!.forward(); } } }); _animationController!.forward(); } @override void dispose() { _animationController?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { try { if (widget.sleepReport == null || widget.sleepReport is! Map || widget.sleepReport.isEmpty) { return Container(); } String? language = ""; if (AppConstants().ent_type == APPPackageType.MHT.code) { if (mhLanguageController.selectLanguage != null) { language = mhLanguageController.selectLanguage.value!.language_code; } } else { if (languageController.selectLanguage != null) { language = languageController.selectLanguage.value!.language_code; } } int num = AppLanguage().isChinese() ? 3 : 2; List data = widget.sleepReport['bs'] ?? []; return Container( width: double.infinity, decoration: BoxDecoration( color: themeController.currentColor.sc5, borderRadius: BorderRadius.circular(AppConstants().normal_container_radius), ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx), child: Wrap( spacing: 23.rpx, runSpacing: 25.rpx, children: List.generate(data.length, (index) { final item = data[index]; item['showTip'] = true; final bool isHighlighted = _shouldAnimate && item['id'] == _highlightedId; return SizedBox( width: (MediaQuery.of(context).size.width - 160.rpx) / num, child: AnimatedBuilder( animation: _animationController ?? AlwaysStoppedAnimation(0), builder: (context, child) { return Container( key: isHighlighted ? _highlightKey : null, decoration: isHighlighted ? BoxDecoration( border: Border.all( color: themeController.currentColor.sc2 .withOpacity( _animationController?.value ?? 0), width: 1.rpx, ), borderRadius: BorderRadius.circular(8), ) : null, child: SleepDataModuleWidget( data: item, sleepReportData: widget.sleepReport, ), ); }, ), ); }), ), ), ); } catch (e) { es.EasyDartModule.logger.error("数据卡片渲染异常${e}"); return Container(); } } }