深色模式代码第二轮补充
This commit is contained in:
@@ -45,6 +45,17 @@ class MyApp extends StatelessWidget {
|
|||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
),
|
),
|
||||||
extensions: [colors], // 🆕 注册 ThemeExtension
|
extensions: [colors], // 🆕 注册 ThemeExtension
|
||||||
|
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
backgroundColor: colors.background, // ← 关键:和 Scaffold 一致
|
||||||
|
foregroundColor: colors.textPrimary,
|
||||||
|
surfaceTintColor: Colors.transparent, // ← 关掉 M3 的滑动变色
|
||||||
|
elevation: 0,
|
||||||
|
scrolledUnderElevation: 0,
|
||||||
|
shadowColor: Colors.transparent,
|
||||||
|
iconTheme: IconThemeData(color: colors.textPrimary),
|
||||||
|
),
|
||||||
|
|
||||||
textTheme: TextTheme(
|
textTheme: TextTheme(
|
||||||
displayMedium: TextStyle(
|
displayMedium: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
|
|||||||
+21
-37
@@ -1,16 +1,16 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
class AboutPage extends StatelessWidget {
|
class AboutPage extends StatelessWidget {
|
||||||
const AboutPage({super.key});
|
const AboutPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
final c = context.colors;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text(
|
title: const Text(
|
||||||
'关于',
|
'关于',
|
||||||
@@ -19,10 +19,10 @@ class AboutPage extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: c.background,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
foregroundColor: Theme.of(context).iconTheme.color,
|
foregroundColor: c.textPrimary,
|
||||||
iconTheme: IconThemeData(color: Theme.of(context).iconTheme.color),
|
iconTheme: IconThemeData(color: c.textPrimary),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -30,15 +30,12 @@ class AboutPage extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
// Logo
|
|
||||||
Container(
|
Container(
|
||||||
width: 120,
|
width: 120,
|
||||||
height: 120,
|
height: 120,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: isDark
|
color: c.surface,
|
||||||
? Colors.grey.shade800
|
|
||||||
: const Color(0xFFF0F4F8),
|
|
||||||
),
|
),
|
||||||
child: ClipOval(
|
child: ClipOval(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
@@ -50,38 +47,39 @@ class AboutPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
const Text(
|
Text(
|
||||||
'MEIZU Battery Healthy',
|
'MEIZU Battery Healthy',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'版本 1.7.0',
|
'版本 1.8.0',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey.shade500,
|
color: c.textTertiary,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Divider(
|
Divider(
|
||||||
color: Colors.grey.shade300,
|
color: c.divider,
|
||||||
thickness: 0.5,
|
thickness: 0.5,
|
||||||
indent: 40,
|
indent: 40,
|
||||||
endIndent: 40,
|
endIndent: 40,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const Text(
|
Text(
|
||||||
'专机专配 · 仅针对魅族独家开发',
|
'专机专配 · 仅针对魅族独家开发',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: c.textSecondary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -90,13 +88,12 @@ class AboutPage extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
color: Colors.grey.shade400,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
// 源码链接按钮
|
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () => _launchUrl(context), // 注意这里传入了 context
|
onTap: () => _launchUrl(context),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
@@ -104,34 +101,24 @@ class AboutPage extends StatelessWidget {
|
|||||||
vertical: 12,
|
vertical: 12,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDark
|
color: c.surface,
|
||||||
? Colors.grey.shade800
|
|
||||||
: const Color(0xFFF0F4F8),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(Icons.code, size: 18, color: c.textPrimary),
|
||||||
Icons.code,
|
|
||||||
size: 18,
|
|
||||||
color: Theme.of(context).iconTheme.color,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
'查看源码 / 反馈',
|
'查看源码 / 反馈',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Icon(
|
Icon(Icons.open_in_new, size: 14, color: c.textTertiary),
|
||||||
Icons.open_in_new,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.grey.shade500,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -142,7 +129,7 @@ class AboutPage extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.grey.shade400,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -155,14 +142,11 @@ class AboutPage extends StatelessWidget {
|
|||||||
Future<void> _launchUrl(BuildContext context) async {
|
Future<void> _launchUrl(BuildContext context) async {
|
||||||
const url = 'https://git.whitetop.xyz/lxh2875931338/MEIZU-Battery-Healthy';
|
const url = 'https://git.whitetop.xyz/lxh2875931338/MEIZU-Battery-Healthy';
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// ✅ 直接尝试打开,不再检查 canLaunchUrl
|
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 如果打开失败,复制链接并提示
|
|
||||||
debugPrint('打开链接失败: $e');
|
debugPrint('打开链接失败: $e');
|
||||||
await Clipboard.setData(ClipboardData(text: url));
|
await Clipboard.setData(const ClipboardData(text: url));
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import '../theme/theme_service.dart';
|
import '../theme/theme_service.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
// --- 本地导入 ---
|
// --- 本地导入 ---
|
||||||
import '../models/device_matching.dart';
|
import '../models/device_matching.dart';
|
||||||
@@ -696,25 +697,25 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: const SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarColor: Color.fromRGBO(157, 212, 237, 0.1),
|
statusBarColor: context.colors.statusBarTint,
|
||||||
statusBarIconBrightness: Brightness.dark,
|
statusBarIconBrightness: Brightness.dark,
|
||||||
statusBarBrightness: Brightness.dark,
|
statusBarBrightness: Brightness.dark,
|
||||||
),
|
),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
scrolledUnderElevation: 0,
|
scrolledUnderElevation: 0,
|
||||||
shadowColor: Colors.transparent,
|
shadowColor: Colors.transparent,
|
||||||
surfaceTintColor: Colors.transparent,
|
surfaceTintColor: Colors.transparent,
|
||||||
title: const Text(
|
title: Text(
|
||||||
'电池健康度',
|
'电池健康度',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Colors.black,
|
color: context.colors.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -722,11 +723,11 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
|||||||
icon: const Icon(Icons.refresh),
|
icon: const Icon(Icons.refresh),
|
||||||
onPressed: readBatteryCapacity,
|
onPressed: readBatteryCapacity,
|
||||||
tooltip: '刷新数据',
|
tooltip: '刷新数据',
|
||||||
color: Colors.black,
|
color: context.colors.icon,
|
||||||
),
|
),
|
||||||
PopupMenuButton<String>(
|
PopupMenuButton<String>(
|
||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
color: Colors.white,
|
color: context.colors.surface,
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 'changelog':
|
case 'changelog':
|
||||||
@@ -772,9 +773,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
_deviceModel,
|
_deviceModel,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: context.colors.textTertiary,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart'; // 🟢 添加这一行
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
class ChangelogPage extends StatefulWidget {
|
class ChangelogPage extends StatefulWidget {
|
||||||
const ChangelogPage({super.key});
|
const ChangelogPage({super.key});
|
||||||
@@ -15,33 +16,27 @@ class _ChangelogPageState extends State<ChangelogPage>
|
|||||||
String _markdownContent = '';
|
String _markdownContent = '';
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
String? _error;
|
String? _error;
|
||||||
Widget? _cachedMarkdown;
|
|
||||||
|
|
||||||
// ---------- 滚动 ----------
|
// ---------- 滚动 ----------
|
||||||
final ScrollController _scrollController = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
double _scrollProgress = 0.0;
|
double _scrollProgress = 0.0;
|
||||||
bool _isScrolling = false;
|
bool _isScrolling = false;
|
||||||
|
|
||||||
// ---------- 呼吸动画(维持高刷感知) ----------
|
// ---------- 呼吸动画 ----------
|
||||||
late AnimationController _breathController;
|
late AnimationController _breathController;
|
||||||
late Animation<double> _breathAnimation;
|
late Animation<double> _breathAnimation;
|
||||||
|
|
||||||
// ---------- 原生刷新率控制 ----------
|
// ---------- 原生刷新率控制 ----------
|
||||||
// 🟢 改用 static final(不是 const)
|
|
||||||
static final _frameRateChannel = MethodChannel(
|
static final _frameRateChannel = MethodChannel(
|
||||||
'com.lxh.battery_health/frame_rate',
|
'com.lxh.battery_health/frame_rate',
|
||||||
);
|
);
|
||||||
|
|
||||||
// ---------- 生命周期 ----------
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_loadChangelog();
|
_loadChangelog();
|
||||||
|
|
||||||
// 进入页面时申请高刷(原生层)
|
|
||||||
_frameRateChannel.invokeMethod('setHighRefreshRate');
|
_frameRateChannel.invokeMethod('setHighRefreshRate');
|
||||||
|
|
||||||
// 呼吸动画:让进度条在滚动时轻微抖动,维持高刷感知
|
|
||||||
_breathController = AnimationController(
|
_breathController = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(milliseconds: 500),
|
duration: const Duration(milliseconds: 500),
|
||||||
@@ -70,16 +65,13 @@ class _ChangelogPageState extends State<ChangelogPage>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
// 离开页面时恢复默认刷新率
|
|
||||||
_frameRateChannel.invokeMethod('clearRefreshRate');
|
_frameRateChannel.invokeMethod('clearRefreshRate');
|
||||||
|
|
||||||
_scrollController.removeListener(_updateProgress);
|
_scrollController.removeListener(_updateProgress);
|
||||||
_scrollController.dispose();
|
_scrollController.dispose();
|
||||||
_breathController.dispose();
|
_breathController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- 方法 ----------
|
|
||||||
void _updateProgress() {
|
void _updateProgress() {
|
||||||
if (!_scrollController.hasClients) return;
|
if (!_scrollController.hasClients) return;
|
||||||
final maxScroll = _scrollController.position.maxScrollExtent;
|
final maxScroll = _scrollController.position.maxScrollExtent;
|
||||||
@@ -96,7 +88,6 @@ class _ChangelogPageState extends State<ChangelogPage>
|
|||||||
setState(() {
|
setState(() {
|
||||||
_markdownContent = content;
|
_markdownContent = content;
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
_cachedMarkdown = _buildMarkdown(content);
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -106,78 +97,75 @@ class _ChangelogPageState extends State<ChangelogPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMarkdown(String content) {
|
Widget _buildMarkdown(BuildContext context, String content) {
|
||||||
|
final c = context.colors;
|
||||||
return Markdown(
|
return Markdown(
|
||||||
data: content,
|
data: content,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
styleSheet: MarkdownStyleSheet(
|
styleSheet: MarkdownStyleSheet(
|
||||||
h1: const TextStyle(
|
h1: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: Colors.black,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
h2: const TextStyle(
|
h2: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Colors.black87,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
h3: const TextStyle(
|
h3: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Colors.black87,
|
color: c.textSecondary,
|
||||||
),
|
),
|
||||||
p: const TextStyle(
|
p: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.black87,
|
color: c.textSecondary,
|
||||||
),
|
),
|
||||||
listBullet: const TextStyle(
|
listBullet: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.black87,
|
color: c.textSecondary,
|
||||||
),
|
),
|
||||||
code: const TextStyle(
|
code: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.black87,
|
color: c.textSecondary,
|
||||||
backgroundColor: Color(0xFFF5F5F5),
|
backgroundColor: c.surface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Build ----------
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final c = context.colors;
|
||||||
final breathOffset = _isScrolling ? _breathAnimation.value : 0.0;
|
final breathOffset = _isScrolling ? _breathAnimation.value : 0.0;
|
||||||
final displayProgress = (_scrollProgress + breathOffset).clamp(0.0, 1.0);
|
final displayProgress = (_scrollProgress + breathOffset).clamp(0.0, 1.0);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.white,
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text(
|
title: Text(
|
||||||
'更新日志',
|
'更新日志',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.black,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.white,
|
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
foregroundColor: Colors.black,
|
foregroundColor: c.textPrimary,
|
||||||
iconTheme: const IconThemeData(color: Colors.black),
|
iconTheme: IconThemeData(color: c.textPrimary),
|
||||||
bottom: PreferredSize(
|
bottom: PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(2.0),
|
preferredSize: const Size.fromHeight(2.0),
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: displayProgress,
|
value: displayProgress,
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: c.divider,
|
||||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
valueColor: AlwaysStoppedAnimation<Color>(c.progressBar),
|
||||||
Color.fromRGBO(157, 212, 237, 1.0),
|
|
||||||
),
|
|
||||||
minHeight: 2.0,
|
minHeight: 2.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -188,16 +176,16 @@ class _ChangelogPageState extends State<ChangelogPage>
|
|||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
_error!,
|
_error!,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: SingleChildScrollView(
|
: SingleChildScrollView(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: _cachedMarkdown ?? const SizedBox.shrink(),
|
child: _buildMarkdown(context, _markdownContent),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import '../models/data_abnormal_type.dart';
|
import '../models/data_abnormal_type.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
class BatteryInfoPanel extends StatelessWidget {
|
class BatteryInfoPanel extends StatelessWidget {
|
||||||
final double batteryVolt;
|
final double batteryVolt;
|
||||||
@@ -9,9 +10,8 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
final double minVolt;
|
final double minVolt;
|
||||||
final double maxTemp;
|
final double maxTemp;
|
||||||
final double minTemp;
|
final double minTemp;
|
||||||
final DataAbnormalType abnormalType;
|
|
||||||
|
|
||||||
final double tempAvg;
|
final double tempAvg;
|
||||||
|
final DataAbnormalType abnormalType;
|
||||||
|
|
||||||
const BatteryInfoPanel({
|
const BatteryInfoPanel({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -27,19 +27,22 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final c = context.colors;
|
||||||
final bool isVoltageAbnormal =
|
final bool isVoltageAbnormal =
|
||||||
abnormalType == DataAbnormalType.voltageAbnormal;
|
abnormalType == DataAbnormalType.voltageAbnormal;
|
||||||
final Color voltColor = isVoltageAbnormal ? Colors.red : Colors.black;
|
final Color voltColor = isVoltageAbnormal ? c.healthRed : c.textPrimary;
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
// ---------- 电压列 ----------
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildInfoItem(
|
_buildInfoItem(
|
||||||
_buildIcon('voltage'),
|
context,
|
||||||
|
_buildIcon(context, 'voltage'),
|
||||||
'电压',
|
'电压',
|
||||||
'${batteryVolt.toStringAsFixed(3)}V',
|
'${batteryVolt.toStringAsFixed(3)}V',
|
||||||
textColor: voltColor,
|
textColor: voltColor,
|
||||||
@@ -53,22 +56,17 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.red,
|
color: c.voltUp,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: '↑ ',
|
text: '↑ ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.red,
|
color: c.voltUp,
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: '${maxVolt.toStringAsFixed(3)}V',
|
|
||||||
style: TextStyle(
|
|
||||||
color: isVoltageAbnormal ? Colors.red : Colors.red,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
TextSpan(text: '${maxVolt.toStringAsFixed(3)}V'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -79,22 +77,17 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.blue,
|
color: c.voltDown,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: '↓ ',
|
text: '↓ ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.blue,
|
color: c.voltDown,
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: '${minVolt.toStringAsFixed(3)}V',
|
|
||||||
style: TextStyle(
|
|
||||||
color: isVoltageAbnormal ? Colors.red : Colors.blue,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
TextSpan(text: '${minVolt.toStringAsFixed(3)}V'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -103,33 +96,34 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// ---------- 温度列 ----------
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildInfoItem(
|
_buildInfoItem(
|
||||||
_buildIcon('temperature'),
|
context,
|
||||||
|
_buildIcon(context, 'temperature'),
|
||||||
'温度',
|
'温度',
|
||||||
'${batteryTemp.toStringAsFixed(0)}℃',
|
'${batteryTemp.toStringAsFixed(0)}℃',
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
// 🆕 一行显示:↑ max ↓ min [avg] avg
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
RichText(
|
RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.red,
|
color: c.tempUp,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: '↑ ',
|
text: '↑ ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.red,
|
color: c.tempUp,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(text: '${maxTemp.toStringAsFixed(1)}℃'),
|
TextSpan(text: '${maxTemp.toStringAsFixed(1)}℃'),
|
||||||
@@ -139,18 +133,18 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
RichText(
|
RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.blue,
|
color: c.tempDown,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: '↓ ',
|
text: '↓ ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.blue,
|
color: c.tempDown,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(text: '${minTemp.toStringAsFixed(1)}℃'),
|
TextSpan(text: '${minTemp.toStringAsFixed(1)}℃'),
|
||||||
@@ -158,15 +152,15 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
_buildIcon('avg', size: 14),
|
_buildIcon(context, 'avg', size: 14),
|
||||||
const SizedBox(width: 2),
|
const SizedBox(width: 2),
|
||||||
Text(
|
Text(
|
||||||
'${tempAvg.toStringAsFixed(1)}℃',
|
'${tempAvg.toStringAsFixed(1)}℃',
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -178,50 +172,54 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildIcon(String type, {double size = 18}) {
|
Widget _buildIcon(BuildContext context, String type, {double size = 18}) {
|
||||||
|
final c = context.colors;
|
||||||
|
final filter = ColorFilter.mode(c.textTertiary, BlendMode.srcIn);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'voltage':
|
case 'voltage':
|
||||||
return SvgPicture.asset(
|
return SvgPicture.asset(
|
||||||
'assets/icons/si--lightning-fill.svg',
|
'assets/icons/si--lightning-fill.svg',
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
|
colorFilter: filter,
|
||||||
);
|
);
|
||||||
case 'temperature':
|
case 'temperature':
|
||||||
return SvgPicture.asset(
|
return SvgPicture.asset(
|
||||||
'assets/icons/mdi--temperature.svg',
|
'assets/icons/mdi--temperature.svg',
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
|
colorFilter: filter,
|
||||||
);
|
);
|
||||||
case 'avg': // 🆕
|
case 'avg':
|
||||||
return SvgPicture.asset(
|
return SvgPicture.asset(
|
||||||
'assets/icons/avg.svg',
|
'assets/icons/avg.svg',
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
|
colorFilter: filter,
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return Icon(Icons.help_outline, size: size, color: Colors.grey);
|
return Icon(Icons.help_outline, size: size, color: c.textTertiary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildInfoItem(
|
Widget _buildInfoItem(
|
||||||
|
BuildContext context,
|
||||||
Widget icon,
|
Widget icon,
|
||||||
String label,
|
String label,
|
||||||
String value, {
|
String value, {
|
||||||
Color textColor = Colors.black,
|
Color? textColor,
|
||||||
}) {
|
}) {
|
||||||
|
final c = context.colors;
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
icon,
|
icon,
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
@@ -231,7 +229,7 @@ class BatteryInfoPanel extends StatelessWidget {
|
|||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: textColor,
|
color: textColor ?? c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../models/data_abnormal_type.dart';
|
import '../models/data_abnormal_type.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
class BatterySummary extends StatelessWidget {
|
class BatterySummary extends StatelessWidget {
|
||||||
final double healthPercent;
|
final double healthPercent;
|
||||||
@@ -19,25 +20,23 @@ class BatterySummary extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final c = context.colors;
|
||||||
final bool isAbnormal = abnormalType != DataAbnormalType.none;
|
final bool isAbnormal = abnormalType != DataAbnormalType.none;
|
||||||
final bool isCapacityAbnormal =
|
final bool isCapacityAbnormal =
|
||||||
abnormalType == DataAbnormalType.capacityTooLow ||
|
abnormalType == DataAbnormalType.capacityTooLow ||
|
||||||
abnormalType == DataAbnormalType.capacityTooHigh;
|
abnormalType == DataAbnormalType.capacityTooHigh;
|
||||||
|
|
||||||
// 健康度颜色:异常时红色,否则按阈值
|
|
||||||
final Color healthColor = isAbnormal
|
final Color healthColor = isAbnormal
|
||||||
? Colors.red
|
? c.healthRed
|
||||||
: (healthPercent < 70 ? Colors.red : Colors.black);
|
: (healthPercent < 70 ? c.healthRed : c.textPrimary);
|
||||||
|
|
||||||
// 容量颜色:异常时红色,否则灰色
|
|
||||||
final Color capacityColor = isCapacityAbnormal
|
final Color capacityColor = isCapacityAbnormal
|
||||||
? Colors.red
|
? c.healthRed
|
||||||
: const Color(0xFF5F5F5F);
|
: c.textSecondary;
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
// 健康度大数字
|
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||||
textBaseline: TextBaseline.alphabetic,
|
textBaseline: TextBaseline.alphabetic,
|
||||||
@@ -60,34 +59,33 @@ class BatterySummary extends StatelessWidget {
|
|||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
color: healthColor == Colors.red
|
color: healthColor == c.healthRed
|
||||||
? Colors.red
|
? c.healthRed
|
||||||
: Colors.grey.shade600,
|
: c.textSecondary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
// cycles + mAh
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
RichText(
|
RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
height: 1.2,
|
height: 1.2,
|
||||||
color: Colors.black,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: '$cycleCount'),
|
TextSpan(text: '$cycleCount'),
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: ' cycles',
|
text: ' cycles',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
color: Colors.black,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import '../utils/charge_utils.dart';
|
import '../utils/charge_utils.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
class ChargeDetailPage extends StatelessWidget {
|
class ChargeDetailPage extends StatelessWidget {
|
||||||
final String chargeType;
|
final String chargeType;
|
||||||
@@ -41,50 +42,53 @@ class ChargeDetailPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final c = context.colors;
|
||||||
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: const SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarColor: Color.fromRGBO(157, 212, 237, 0.1),
|
statusBarColor: c.statusBarTint,
|
||||||
statusBarIconBrightness: Brightness.dark,
|
statusBarIconBrightness: isDark ? Brightness.light : Brightness.dark,
|
||||||
statusBarBrightness: Brightness.dark,
|
statusBarBrightness: Theme.of(context).brightness,
|
||||||
),
|
),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Colors.white,
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('充电详情'),
|
title: const Text('充电详情'),
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: c.background,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
scrolledUnderElevation: 0,
|
scrolledUnderElevation: 0,
|
||||||
shadowColor: Colors.transparent,
|
shadowColor: Colors.transparent,
|
||||||
surfaceTintColor: Colors.transparent,
|
surfaceTintColor: Colors.transparent,
|
||||||
foregroundColor: Colors.black,
|
foregroundColor: c.textPrimary,
|
||||||
iconTheme: const IconThemeData(color: Colors.black),
|
iconTheme: IconThemeData(color: c.textPrimary),
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildTextRow('协议', _getProtocolDisplay()),
|
_buildTextRow(context, '协议', _getProtocolDisplay()),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
|
|
||||||
if (!isWireless) ...[
|
if (!isWireless) ...[
|
||||||
_buildTextRow('标定档位', _getRequestedDisplay()),
|
_buildTextRow(context, '标定档位', _getRequestedDisplay()),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
_buildTextRow('实际功率', _getActualDisplay()),
|
_buildTextRow(context, '实际功率', _getActualDisplay()),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
] else ...[
|
] else ...[
|
||||||
_buildTextRow('功率', ChargeUtils.getDisplayPowerWireless(power)),
|
_buildTextRow(
|
||||||
|
context,
|
||||||
|
'功率',
|
||||||
|
ChargeUtils.getDisplayPowerWireless(power),
|
||||||
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
],
|
],
|
||||||
|
_buildDetailRow(context, '电压', volt, 'V'),
|
||||||
_buildDetailRow('电压', volt, 'V'),
|
|
||||||
const Divider(),
|
const Divider(),
|
||||||
_buildDetailRow('电流', curr, 'A'),
|
_buildDetailRow(context, '电流', curr, 'A'),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
|
if (isWireless) _buildTextRow(context, '类型', '无线'),
|
||||||
if (isWireless) _buildTextRow('类型', '无线'),
|
if (!isWireless && wiredLevel == null)
|
||||||
if (!isWireless && wiredLevel == null) _buildTextRow('档位', '自动'),
|
_buildTextRow(context, '档位', '自动'),
|
||||||
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Center(
|
Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -92,7 +96,7 @@ class ChargeDetailPage extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.grey.shade500,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -103,8 +107,8 @@ class ChargeDetailPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 纯文本行(协议、功率、档位等)
|
Widget _buildTextRow(BuildContext context, String label, String value) {
|
||||||
Widget _buildTextRow(String label, String value) {
|
final c = context.colors;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -112,20 +116,20 @@ class ChargeDetailPage extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
value,
|
value,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC', // 复杂字符串保持 Harmony
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.black87,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -133,8 +137,13 @@ class ChargeDetailPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 数值行(电压/电流,数字用 Flyme,单位用 Harmony)
|
Widget _buildDetailRow(
|
||||||
Widget _buildDetailRow(String label, double value, String unit) {
|
BuildContext context,
|
||||||
|
String label,
|
||||||
|
double value,
|
||||||
|
String unit,
|
||||||
|
) {
|
||||||
|
final c = context.colors;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -142,24 +151,24 @@ class ChargeDetailPage extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
RichText(
|
RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.black87,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: value.toStringAsFixed(2),
|
text: value.toStringAsFixed(2),
|
||||||
style: const TextStyle(fontFamily: 'Flyme'), // 🟢 数字用 Flyme
|
style: const TextStyle(fontFamily: 'Flyme'),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: unit,
|
text: unit,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
class ChargeEntry extends StatelessWidget {
|
class ChargeEntry extends StatelessWidget {
|
||||||
final String summary;
|
final String summary;
|
||||||
@@ -14,6 +15,7 @@ class ChargeEntry extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final c = context.colors;
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: isCharging ? onTap : null,
|
onTap: isCharging ? onTap : null,
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -21,11 +23,11 @@ class ChargeEntry extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
summary,
|
summary,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC', // 🟢 混合文本用 Harmony
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.black87,
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
@@ -36,7 +38,7 @@ class ChargeEntry extends StatelessWidget {
|
|||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.grey.shade700,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
@@ -46,7 +48,7 @@ class ChargeEntry extends StatelessWidget {
|
|||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.grey.shade700,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
|
|
||||||
// --- 潘通色定义 ---
|
|
||||||
const Color kHealthGreen = Color(0xFF00B140);
|
|
||||||
const Color kHealthYellow = Color(0xFFEFDF00);
|
|
||||||
const Color kHealthOrange = Color(0xFFD75A16);
|
|
||||||
|
|
||||||
/// 趋势图柱状图组件
|
|
||||||
class TrendChart extends StatelessWidget {
|
class TrendChart extends StatelessWidget {
|
||||||
final List<Map<String, dynamic>> data;
|
final List<Map<String, dynamic>> data;
|
||||||
final int designCap;
|
final int designCap;
|
||||||
@@ -14,6 +9,8 @@ class TrendChart extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final c = context.colors;
|
||||||
|
|
||||||
List<Map<String, dynamic>> displayData = data.isNotEmpty
|
List<Map<String, dynamic>> displayData = data.isNotEmpty
|
||||||
? data
|
? data
|
||||||
: _getMockData();
|
: _getMockData();
|
||||||
@@ -48,12 +45,13 @@ class TrendChart extends StatelessWidget {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
Text(
|
||||||
'容量百分比变动趋势(近15天)',
|
'容量百分比变动趋势(近15天)',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
|
color: c.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -64,13 +62,13 @@ class TrendChart extends StatelessWidget {
|
|||||||
height: 180,
|
height: 180,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: const [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'100',
|
'100',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -79,7 +77,7 @@ class TrendChart extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'Flyme',
|
fontFamily: 'Flyme',
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -106,14 +104,14 @@ class TrendChart extends StatelessWidget {
|
|||||||
Color barColor;
|
Color barColor;
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
if (value >= 80) {
|
if (value >= 80) {
|
||||||
barColor = kHealthGreen;
|
barColor = c.healthGreen;
|
||||||
} else if (value >= 70) {
|
} else if (value >= 70) {
|
||||||
barColor = kHealthYellow;
|
barColor = c.healthYellow;
|
||||||
} else {
|
} else {
|
||||||
barColor = Colors.red;
|
barColor = c.healthRed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
barColor = Colors.grey.shade300;
|
barColor = c.barEmpty;
|
||||||
}
|
}
|
||||||
double clampedValue = value.clamp(70.0, 100.0);
|
double clampedValue = value.clamp(70.0, 100.0);
|
||||||
double heightFactor =
|
double heightFactor =
|
||||||
@@ -144,10 +142,10 @@ class TrendChart extends StatelessWidget {
|
|||||||
bottom: 2,
|
bottom: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
sevenDaysAgoDate,
|
sevenDaysAgoDate,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -158,10 +156,10 @@ class TrendChart extends StatelessWidget {
|
|||||||
bottom: 2,
|
bottom: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
todayDate,
|
todayDate,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
color: Colors.black,
|
color: c.textPrimary,
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
@@ -176,14 +174,14 @@ class TrendChart extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (percents.every((v) => v == 0))
|
if (percents.every((v) => v == 0))
|
||||||
const Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 8.0),
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'暂无历史数据,请点击刷新按钮更新',
|
'暂无历史数据,请点击刷新按钮更新',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'HarmonyOS_Sans_SC',
|
fontFamily: 'HarmonyOS_Sans_SC',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.grey,
|
color: c.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.7.1
|
version: 1.8.0
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.9.2
|
sdk: ^3.9.2
|
||||||
|
|||||||
Reference in New Issue
Block a user