更新日志铺路部分,dev中
This commit is contained in:
@@ -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(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user