From 5e755d860ff2bee2fa46a0c1065d59031b76878b Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Mon, 20 Jul 2026 23:34:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=97=A5=E5=BF=97=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E4=BC=98=E5=8C=96=E3=80=81=E4=B8=BB=E9=A1=B5=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=8A=A8=E7=94=BB=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- lib/pages/battery_health_page.dart | 217 +++++++++++++++-------------- lib/pages/changelog_page.dart | 4 +- pubspec.yaml | 1 + 4 files changed, 114 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 8dfa530..7230277 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ flutter pub get # Debug 版本 -flutter run +flutter run --debug # Release APK flutter build apk --release --target-platform android-arm64 diff --git a/lib/pages/battery_health_page.dart b/lib/pages/battery_health_page.dart index e62945d..5cc5f27 100644 --- a/lib/pages/battery_health_page.dart +++ b/lib/pages/battery_health_page.dart @@ -18,8 +18,8 @@ import '../widgets/battery_summary.dart'; import '../widgets/battery_info_panel.dart'; import '../widgets/charge_entry.dart'; import '../widgets/charge_detail_page.dart'; -import '../widgets/battery_data_layout.dart'; // 🆕 1.6.0 UI 拆分 -import '../pages/changelog_page.dart'; // 🆕 1.6.0 更新日志 +import '../widgets/trend_chart.dart'; +import '../pages/changelog_page.dart'; // --- 潘通色定义 --- const Color kHealthGreen = Color(0xFF00B140); @@ -33,8 +33,7 @@ class BatteryHealthPage extends StatefulWidget { State createState() => _BatteryHealthPageState(); } -class _BatteryHealthPageState extends State - with SingleTickerProviderStateMixin { +class _BatteryHealthPageState extends State { // ---------- 数据 ---------- double _currentCap = 0; int _cycleCount = 0; @@ -67,11 +66,6 @@ class _BatteryHealthPageState extends State final BatteryDataService _dataService = BatteryDataService(); SafPermissionState _safState = SafPermissionState.unauthorized; - // 动画控制 - late AnimationController _chargeAnimationController; - late Animation _bottomSlide; - late Animation _entryFadeIn; - // 平台通道 static const _methodChannel = MethodChannel('com.lxh.battery_health/charge'); static const _eventChannel = EventChannel( @@ -88,8 +82,6 @@ class _BatteryHealthPageState extends State super.initState(); dev.log('🔵 ========== initState 开始 ==========', name: 'BatteryHealth'); - _initAnimations(); - _getInitialChargeState(); _chargeEventSubscription = _eventChannel.receiveBroadcastStream().listen(( @@ -135,31 +127,10 @@ class _BatteryHealthPageState extends State void dispose() { _chargeEventSubscription?.cancel(); _pollTimer?.cancel(); - _chargeAnimationController.dispose(); _dbService.database.then((db) => db.close()).ignore(); super.dispose(); } - // ---------- 动画初始化 ---------- - void _initAnimations() { - _chargeAnimationController = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 500), - ); - _bottomSlide = Tween(begin: 0, end: 24).animate( - CurvedAnimation( - parent: _chargeAnimationController, - curve: Curves.easeInOutCubic, - ), - ); - _entryFadeIn = Tween(begin: 0, end: 1).animate( - CurvedAnimation( - parent: _chargeAnimationController, - curve: const Interval(0.0, 0.5, curve: Curves.easeIn), - ), - ); - } - // ---------- 设备信息 ---------- Future _getDeviceInfo() async { dev.log('🔵 _getDeviceInfo 开始', name: 'BatteryHealth'); @@ -276,7 +247,6 @@ class _BatteryHealthPageState extends State _chargeCurr = 0.0; _wiredLevel = null; _chargingStartTime = null; - _updateChargeState(); return; } @@ -311,7 +281,6 @@ class _BatteryHealthPageState extends State _chargePower = 0.0; _chargeVolt = 0.0; _chargeCurr = 0.0; - _updateChargeState(); }); if (_isCharging) { @@ -350,7 +319,6 @@ class _BatteryHealthPageState extends State _currentCap = recent.first['capacity'].toDouble(); _maxVolt = recent.first['volt_max'] ?? 0; _minVolt = recent.first['volt_min'] ?? 0; - // 🟢 数据库目前不存温度,后续升级可扩展,暂时保留为 0 _maxTemp = 0; _minTemp = 0; _cycleCount = 0; @@ -362,8 +330,6 @@ class _BatteryHealthPageState extends State setState(() => _hasData = false); } if (_isCharging) _fetchChargeDataFromLog(); - _chargeAnimationController.reset(); - _updateChargeState(); return; } @@ -375,23 +341,16 @@ class _BatteryHealthPageState extends State dev.log('🔵 文件为空', name: 'BatteryHealth'); setState(() => _hasData = false); if (_isCharging) _fetchChargeDataFromLog(); - _chargeAnimationController.reset(); - _updateChargeState(); return; } - // 🟢 提取所有有效行(包含 tbat=) final validLines = lines.where((line) => line.contains('tbat=')).toList(); if (validLines.isEmpty) { dev.log('🔵 无有效数据行', name: 'BatteryHealth'); setState(() => _hasData = false); - _chargeAnimationController.reset(); - _updateChargeState(); return; } - // 🟢 1.4.7 核心改动:字段提取与容量提取解耦 - // 无论 cap 是否为 null,都提取常规字段 final lastLine = validLines.last; final cycle = _extractCycle(lastLine); final temp = _extractTemp(lastLine); @@ -404,16 +363,13 @@ class _BatteryHealthPageState extends State name: 'BatteryHealth', ); - // 🟢 容量提取(可能为 null) final cap = CapacityExtractor.extractCapacity(lines); int? finalCap; if (cap != null) { - // ✅ 今日有充满记录,直接使用 finalCap = cap; dev.log('🔵 从日志提取容量: $cap', name: 'BatteryHealth'); } else { - // ⚠️ 今日无充满记录,尝试从数据库复制前一天容量 dev.log('🔵 今日无充满记录,尝试复制前一天容量', name: 'BatteryHealth'); final recent = await _dbService.queryRecentData(1); if (recent.isNotEmpty) { @@ -425,7 +381,6 @@ class _BatteryHealthPageState extends State } } - // 🟢 一次性 setState 更新所有字段 setState(() { _currentCap = (finalCap ?? _currentCap).toDouble(); _cycleCount = cycle; @@ -444,8 +399,6 @@ class _BatteryHealthPageState extends State } await _updateTrendChart(); - _chargeAnimationController.reset(); - _updateChargeState(); dev.log( '🔵 ========== readBatteryCapacity 完成 ==========', name: 'BatteryHealth', @@ -453,8 +406,6 @@ class _BatteryHealthPageState extends State } catch (e) { dev.log('🔵 readBatteryCapacity 异常: $e', name: 'BatteryHealth'); setState(() => _hasData = false); - _chargeAnimationController.reset(); - _updateChargeState(); } } @@ -588,26 +539,6 @@ class _BatteryHealthPageState extends State } } - // ---------- 动画控制 ---------- - void _startChargeAnimation() { - if (_chargeAnimationController.isAnimating) return; - _chargeAnimationController.forward(); - } - - void _stopChargeAnimation() { - if (_chargeAnimationController.isAnimating) return; - _chargeAnimationController.reverse(); - } - - void _updateChargeState() { - if (!mounted) return; - if (_isCharging) { - _startChargeAnimation(); - } else { - _stopChargeAnimation(); - } - } - // ---------- 显示辅助 ---------- String _getDisplayPower() { if (!_isCharging) return ''; @@ -629,7 +560,6 @@ class _BatteryHealthPageState extends State // ---------- Build ---------- @override Widget build(BuildContext context) { - // 计算健康度百分比(显式转为 double) final double healthPercent = (_designCap > 0) ? (_currentCap / _designCap) * 100 : 0.0; @@ -661,14 +591,12 @@ class _BatteryHealthPageState extends State ), ), actions: [ - // 刷新按钮(左移) IconButton( icon: const Icon(Icons.refresh), onPressed: readBatteryCapacity, tooltip: '刷新数据', color: Colors.black, ), - // 三点菜单 PopupMenuButton( icon: const Icon(Icons.more_vert), color: Colors.white, @@ -683,10 +611,8 @@ class _BatteryHealthPageState extends State ); break; case 'dark_mode': - // 1.7 再实现 break; case 'about': - // 1.7 再实现 break; } }, @@ -707,38 +633,113 @@ class _BatteryHealthPageState extends State ], ), body: _hasData - ? AnimatedBuilder( - animation: _chargeAnimationController, - builder: (context, child) { - // 🟢 修复:传入 healthPercent 为 double,移除未定义的动画参数 - // 动画在 BatteryDataLayout 内部不处理,由父级 AnimatedBuilder 控制 - return BatteryDataLayout( - deviceModel: _deviceModel, - healthPercent: healthPercent, - cycleCount: _cycleCount, - currentCap: _currentCap, - designCap: _designCap, - trendData: _trendData, - isCharging: _isCharging, - chargeSummary: chargeSummary, - batteryVolt: _batteryVolt, - batteryTemp: _batteryTemp, - maxVolt: _maxVolt, - minVolt: _minVolt, - maxTemp: _maxTemp, - minTemp: _minTemp, - chargeType: _chargeType, - isWireless: _isWireless, - chargePower: _chargePower, - chargeVolt: _chargeVolt, - chargeCurr: _chargeCurr, - wiredLevel: _wiredLevel, - // 🟢 动画参数由父级 AnimatedBuilder 控制, - // BatteryDataLayout 不再需要透传 animation 参数 - ); - }, + ? Column( + children: [ + // 🟢 可滚动区域(带 RepaintBoundary) + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 设备型号 + Text( + _deviceModel, + style: const TextStyle( + fontSize: 14, + color: Colors.grey, + fontWeight: FontWeight.w400, + ), + ), + const SizedBox(height: 4), + + // 🟢 BatterySummary 用 RepaintBoundary 隔离 + RepaintBoundary( + child: BatterySummary( + healthPercent: healthPercent, + cycleCount: _cycleCount, + currentCap: _currentCap, + designCap: _designCap, + ), + ), + + const SizedBox(height: 24), + + // 🟢 TrendChart 用 RepaintBoundary 隔离 + RepaintBoundary( + child: TrendChart( + data: _trendData, + designCap: _designCap, + ), + ), + + const SizedBox(height: 8), + + // 🟢 充电条目 - 保留 AnimatedOpacity,但加 RepaintBoundary + RepaintBoundary( + child: AnimatedOpacity( + opacity: _isCharging ? 1.0 : 0.0, + duration: const Duration(milliseconds: 300), + child: ChargeEntry( + summary: chargeSummary, + isCharging: _isCharging, + onTap: () { + if (_isCharging) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChargeDetailPage( + chargeType: _chargeType, + isWireless: _isWireless, + power: _chargePower, + volt: _chargeVolt, + curr: _chargeCurr, + wiredLevel: _wiredLevel, + ), + ), + ); + } + }, + ), + ), + ), + + const SizedBox(height: 4), + + // 🟢 BatteryInfoPanel 也用 RepaintBoundary + RepaintBoundary( + child: BatteryInfoPanel( + batteryVolt: _batteryVolt, + batteryTemp: _batteryTemp, + maxVolt: _maxVolt, + minVolt: _minVolt, + maxTemp: _maxTemp, + minTemp: _minTemp, + ), + ), + ], + ), + ), + ), + ], ) - : const EmptyStateLayout(), + : const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.battery_unknown, size: 64, color: Colors.grey), + SizedBox(height: 16), + Text( + '暂无数据', + style: TextStyle(fontSize: 18, color: Colors.grey), + ), + Text( + '点击右上角刷新尝试', + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + ], + ), + ), ), ); } diff --git a/lib/pages/changelog_page.dart b/lib/pages/changelog_page.dart index ac15fe5..6866470 100644 --- a/lib/pages/changelog_page.dart +++ b/lib/pages/changelog_page.dart @@ -65,9 +65,11 @@ class _ChangelogPageState extends State { ), ) : SingleChildScrollView( - padding: const EdgeInsets.all(20), + padding: const EdgeInsets.all(16.0), child: Markdown( data: _markdownContent, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), styleSheet: MarkdownStyleSheet( h1: const TextStyle( fontFamily: 'HarmonyOS_Sans_SC', diff --git a/pubspec.yaml b/pubspec.yaml index e22e306..686e062 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -81,6 +81,7 @@ flutter: - asset: assets/fonts/flymeFont.ttf assets: - assets/icons/ + - assets/CHANGELOG.md # To add assets to your application, add an assets section, like this: # assets: