更新日志铺路部分,dev中

This commit is contained in:
2026-07-20 23:16:39 +08:00
parent c8866a740a
commit 0d8c6b081d
6 changed files with 437 additions and 121 deletions
+93 -121
View File
@@ -4,21 +4,22 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:device_info_plus/device_info_plus.dart';
// 检查这些导入是否正确
import '../models/device_matching.dart'; // ✅ 存在
import '../models/saf_permission_state.dart'; // ✅ 存在
// --- 本地导入 ---
import '../models/device_matching.dart';
import '../models/saf_permission_state.dart';
import '../services/database_service.dart';
import '../services/battery_data_service.dart';
import '../services/saf_storage_service.dart'; // ✅ 存在
import '../logic/charge_parser.dart'; // ✅ 存在
import '../logic/capacity_extractor.dart'; // ✅ 存在(注意:不是 utils/)
import '../utils/time_utils.dart'; // ✅ 存在
import '../utils/charge_utils.dart'; // ✅ 存在
import '../widgets/trend_chart.dart'; // ⚠️ 需要确认文件内容完整
import '../widgets/battery_summary.dart'; // ⚠️ 需要确认文件内容完整
import '../widgets/battery_info_panel.dart'; // ⚠️ 需要确认文件内容完整
import '../widgets/charge_entry.dart'; // ⚠️ 需要确认文件内容完整
import '../widgets/charge_detail_page.dart'; // ✅ 存在
import '../services/saf_storage_service.dart';
import '../logic/charge_parser.dart';
import '../logic/capacity_extractor.dart';
import '../utils/time_utils.dart';
import '../utils/charge_utils.dart';
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 更新日志
// --- 潘通色定义 ---
const Color kHealthGreen = Color(0xFF00B140);
@@ -613,7 +614,6 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
if (_isWireless) {
return ChargeUtils.getDisplayPowerWireless(_chargePower);
} else {
// 🟢 1.5.0 改用新格式:实际/标定
return ChargeUtils.getMainDisplayPowerWired(
_chargePower,
_wiredLevel,
@@ -629,9 +629,17 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
// ---------- Build ----------
@override
Widget build(BuildContext context) {
// 计算健康度百分比(显式转为 double)
final double healthPercent = (_designCap > 0)
? (_currentCap / _designCap) * 100
: 0.0;
final String chargeSummary = _isCharging
? '充电中 · ${_getChargeTypeLabel()} · ${_getDisplayPower()}'
: '';
return AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle(
// 🟢 1.5.0 统一状态栏颜色
statusBarColor: Color.fromRGBO(157, 212, 237, 0.1),
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.dark,
@@ -653,120 +661,84 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
),
),
actions: [
// 刷新按钮(左移)
IconButton(
icon: const Icon(Icons.refresh),
onPressed: readBatteryCapacity,
tooltip: '刷新数据',
color: Colors.black,
),
// 三点菜单
PopupMenuButton<String>(
icon: const Icon(Icons.more_vert),
color: Colors.white,
onSelected: (value) {
switch (value) {
case 'changelog':
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ChangelogPage(),
),
);
break;
case 'dark_mode':
// 1.7 再实现
break;
case 'about':
// 1.7 再实现
break;
}
},
itemBuilder: (context) => [
const PopupMenuItem(value: 'changelog', child: Text('更新日志')),
const PopupMenuItem(
value: 'dark_mode',
enabled: false,
child: Text('深色模式(开发中)'),
),
const PopupMenuItem(
value: 'about',
enabled: false,
child: Text('关于(开发中)'),
),
],
),
],
),
body: _hasData ? _buildDataLayout() : _buildEmptyState(),
),
);
}
Widget _buildEmptyState() {
return 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)),
],
),
);
}
Widget _buildDataLayout() {
final healthPercent = (_designCap > 0)
? (_currentCap / _designCap) * 100
: 0;
String chargeSummary = '';
if (_isCharging) {
chargeSummary = '充电中 · ${_getChargeTypeLabel()} · ${_getDisplayPower()}';
}
return Padding(
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(
healthPercent: healthPercent.toDouble(), // 显式转换
cycleCount: _cycleCount,
currentCap: _currentCap,
designCap: _designCap,
),
const SizedBox(height: 24),
TrendChart(data: _trendData, designCap: _designCap),
const SizedBox(height: 8),
AnimatedBuilder(
animation: _chargeAnimationController,
builder: (context, child) {
final entryHeight = 28 * _entryFadeIn.value;
final chargeEntry = Opacity(
opacity: _entryFadeIn.value,
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,
),
),
);
}
},
),
);
return Column(
children: [
SizedBox(height: entryHeight, child: chargeEntry),
Transform.translate(
offset: Offset(0, _bottomSlide.value),
child: BatteryInfoPanel(
batteryVolt: _batteryVolt,
batteryTemp: _batteryTemp,
maxVolt: _maxVolt,
minVolt: _minVolt,
maxTemp: _maxTemp,
minTemp: _minTemp,
),
),
],
);
},
),
const Spacer(),
],
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 参数
);
},
)
: const EmptyStateLayout(),
),
);
}
+99
View File
@@ -0,0 +1,99 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_markdown/flutter_markdown.dart';
class ChangelogPage extends StatefulWidget {
const ChangelogPage({super.key});
@override
State<ChangelogPage> createState() => _ChangelogPageState();
}
class _ChangelogPageState extends State<ChangelogPage> {
String _markdownContent = '';
bool _isLoading = true;
String? _error;
@override
void initState() {
super.initState();
_loadChangelog();
}
Future<void> _loadChangelog() async {
try {
final content = await rootBundle.loadString('assets/CHANGELOG.md');
setState(() {
_markdownContent = content;
_isLoading = false;
});
} catch (e) {
setState(() {
_error = '无法加载更新日志: $e';
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text(
'更新日志',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.black,
),
),
backgroundColor: Colors.white,
elevation: 0,
foregroundColor: Colors.black,
iconTheme: const IconThemeData(color: Colors.black),
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: _error != null
? Center(
child: Text(
_error!,
style: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.grey,
),
),
)
: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Markdown(
data: _markdownContent,
styleSheet: MarkdownStyleSheet(
h1: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 24,
fontWeight: FontWeight.w700,
color: Colors.black,
),
h2: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
p: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
color: Colors.black87,
),
listBullet: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
color: Colors.black87,
),
),
),
),
);
}
}
+151
View File
@@ -0,0 +1,151 @@
import 'package:flutter/material.dart';
import '../widgets/trend_chart.dart';
import '../widgets/battery_summary.dart';
import '../widgets/battery_info_panel.dart';
import '../widgets/charge_entry.dart';
import '../widgets/charge_detail_page.dart';
/// 电池数据布局(含数据展示、趋势图、充电状态、电压温度面板)
class BatteryDataLayout extends StatelessWidget {
final String deviceModel;
final double healthPercent;
final int cycleCount;
final double currentCap;
final int designCap;
final List<Map<String, dynamic>> trendData;
final bool isCharging;
final String chargeSummary;
final double batteryVolt;
final double batteryTemp;
final double maxVolt;
final double minVolt;
final double maxTemp;
final double minTemp;
final String chargeType;
final bool isWireless;
final double chargePower;
final double chargeVolt;
final double chargeCurr;
final int? wiredLevel;
const BatteryDataLayout({
super.key,
required this.deviceModel,
required this.healthPercent,
required this.cycleCount,
required this.currentCap,
required this.designCap,
required this.trendData,
required this.isCharging,
required this.chargeSummary,
required this.batteryVolt,
required this.batteryTemp,
required this.maxVolt,
required this.minVolt,
required this.maxTemp,
required this.minTemp,
required this.chargeType,
required this.isWireless,
required this.chargePower,
required this.chargeVolt,
required this.chargeCurr,
this.wiredLevel,
});
@override
Widget build(BuildContext context) {
return Padding(
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(
healthPercent: healthPercent,
cycleCount: cycleCount,
currentCap: currentCap,
designCap: designCap,
),
const SizedBox(height: 24),
TrendChart(data: trendData, designCap: designCap),
const SizedBox(height: 8),
// 充电状态 + 信息面板(带进场动画)
_buildChargeAndInfoPanel(context),
const Spacer(),
],
),
);
}
Widget _buildChargeAndInfoPanel(BuildContext context) {
return Column(
children: [
// 充电状态入口(保持原有的透明度/位移动画由父级控制)
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(
batteryVolt: batteryVolt,
batteryTemp: batteryTemp,
maxVolt: maxVolt,
minVolt: minVolt,
maxTemp: maxTemp,
minTemp: minTemp,
),
],
);
}
}
/// 空状态布局(无数据时显示)
class EmptyStateLayout extends StatelessWidget {
const EmptyStateLayout({super.key});
@override
Widget build(BuildContext context) {
return 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)),
],
),
);
}
}