refactor(client): 往来/设备/登录/关于颜色迁移到 context.tokens

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-25 00:20:11 +08:00
parent 9afe0dcf6e
commit a7298b643c
6 changed files with 99 additions and 97 deletions
+8 -8
View File
@@ -8,7 +8,7 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../core/config/app_config.dart';
import '../../core/config/app_info.dart';
import '../../core/theme/app_theme.dart';
import '../../core/theme/context_tokens.dart';
import '../../core/update/app_updater.dart';
import '../../core/utils/dialog_util.dart';
import '../../providers/feedback_provider.dart';
@@ -42,7 +42,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
_AboutRow(
label: '最新版本',
value: 'v${updateInfo.latestVersion}',
valueColor: AppTheme.success,
valueColor: context.tokens.success,
trailing: TextButton(
onPressed: () => startInAppUpdate(context, updateInfo),
child: const Text('立即更新'),
@@ -52,7 +52,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
_AboutRow(
label: '最新版本',
value: updateInfo != null ? '已是最新' : '检查中…',
valueColor: AppTheme.textSecondary,
valueColor: context.tokens.muted,
trailing: TextButton(
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
@@ -469,10 +469,10 @@ class _AboutSection extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppTheme.primaryDark)),
color: context.tokens.primaryDark)),
const Divider(height: 24),
...children,
],
@@ -504,14 +504,14 @@ class _AboutRow extends StatelessWidget {
SizedBox(
width: 88,
child: Text(label,
style: const TextStyle(
fontSize: 13, color: AppTheme.textSecondary)),
style: TextStyle(
fontSize: 13, color: context.tokens.muted)),
),
Expanded(
child: Text(value,
style: TextStyle(
fontSize: 13,
color: valueColor ?? AppTheme.textPrimary,
color: valueColor ?? context.tokens.text,
fontWeight: FontWeight.w500)),
),
if (trailing != null) trailing!,
+33 -33
View File
@@ -9,7 +9,7 @@ import 'package:url_launcher/url_launcher.dart';
import '../../core/auth/auth_state.dart';
import '../../core/config/app_config.dart';
import '../../core/config/app_constants.dart';
import '../../core/theme/app_theme.dart';
import '../../core/theme/context_tokens.dart';
import '../../core/storage/login_history.dart';
import '../../providers/connectivity_provider.dart';
import '../../repositories/auth_repository.dart';
@@ -111,7 +111,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
showDialog<void>(
context: context,
builder: (ctx) => AlertDialog(
icon: const Icon(Icons.lock_outline, color: AppTheme.danger),
icon: Icon(Icons.lock_outline, color: context.tokens.danger),
title: const Text('登录已失效'),
content: Text(msg),
actions: [
@@ -305,23 +305,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
width: double.infinity,
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: AppTheme.danger.withAlpha(15),
color: context.tokens.danger.withAlpha(15),
borderRadius: BorderRadius.circular(6),
border: Border.all(color: AppTheme.danger.withAlpha(80)),
border: Border.all(color: context.tokens.danger.withAlpha(80)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
Row(
children: [
Icon(Icons.lock_clock_outlined,
color: AppTheme.danger, size: 18),
SizedBox(width: 8),
color: context.tokens.danger, size: 18),
const SizedBox(width: 8),
Expanded(
child: Text(
'授权已过期,账号已锁定',
style: TextStyle(
color: AppTheme.danger,
color: context.tokens.danger,
fontSize: 14,
fontWeight: FontWeight.w600),
),
@@ -329,10 +329,10 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
],
),
const SizedBox(height: 6),
const Text(
Text(
'当前门店授权已到期,暂时无法登录。请续费授权后重试,或联系客服协助开通。',
style: TextStyle(
color: AppTheme.textSecondary, fontSize: 13, height: 1.4),
color: context.tokens.muted, fontSize: 13, height: 1.4),
),
const SizedBox(height: 12),
Wrap(
@@ -344,7 +344,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
icon: const Icon(Icons.open_in_new, size: 16),
label: const Text('前往官网续费'),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.danger,
backgroundColor: context.tokens.danger,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 14, vertical: 10),
@@ -357,8 +357,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
icon: const Icon(Icons.support_agent_outlined, size: 16),
label: const Text('复制客服邮箱'),
style: OutlinedButton.styleFrom(
foregroundColor: AppTheme.danger,
side: BorderSide(color: AppTheme.danger.withAlpha(120)),
foregroundColor: context.tokens.danger,
side: BorderSide(color: context.tokens.danger.withAlpha(120)),
padding: const EdgeInsets.symmetric(
horizontal: 14, vertical: 10),
shape: RoundedRectangleBorder(
@@ -384,7 +384,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
}
});
return Scaffold(
backgroundColor: AppTheme.primaryDark,
backgroundColor: context.tokens.primaryDark,
body: Stack(
children: [
Positioned.fill(
@@ -419,7 +419,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: AppTheme.primary.withAlpha(102),
color: context.tokens.primary.withAlpha(102),
blurRadius: 12,
offset: const Offset(0, 4),
),
@@ -436,21 +436,21 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
),
),
const SizedBox(height: 20),
const Text(
Text(
'岩美酒库',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
color: AppTheme.primaryDark,
color: context.tokens.primaryDark,
letterSpacing: 1,
),
),
const SizedBox(height: 6),
const Text(
Text(
'专业酒水仓储 · 进销存一体化管理',
style: TextStyle(
fontSize: 13,
color: AppTheme.textSecondary),
color: context.tokens.muted),
),
const SizedBox(height: 32),
@@ -470,7 +470,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
_hotelShowing
? Icons.arrow_drop_up
: Icons.arrow_drop_down,
color: AppTheme.textSecondary,
color: context.tokens.muted,
)
: null,
),
@@ -499,7 +499,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
_usernameShowing
? Icons.arrow_drop_up
: Icons.arrow_drop_down,
color: AppTheme.textSecondary,
color: context.tokens.muted,
)
: null,
),
@@ -583,21 +583,21 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 10),
decoration: BoxDecoration(
color: AppTheme.danger.withAlpha(15),
color: context.tokens.danger.withAlpha(15),
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: AppTheme.danger.withAlpha(80)),
color: context.tokens.danger.withAlpha(80)),
),
child: Row(
children: [
const Icon(Icons.error_outline,
color: AppTheme.danger, size: 16),
Icon(Icons.error_outline,
color: context.tokens.danger, size: 16),
const SizedBox(width: 8),
Expanded(
child: Text(
_errorMessage!,
style: const TextStyle(
color: AppTheme.danger,
style: TextStyle(
color: context.tokens.danger,
fontSize: 13),
),
),
@@ -637,11 +637,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
Uri.parse('${AppConfig.publicBaseUrl}/register/'),
mode: LaunchMode.externalApplication,
),
child: const Text(
child: Text(
'还没有门店账号?前往官网注册',
style: TextStyle(
fontSize: 15,
color: AppTheme.textSecondary,
color: context.tokens.muted,
),
),
),
@@ -721,14 +721,14 @@ class _HistoryMenuItemState extends State<_HistoryMenuItem> {
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
child: Row(
children: [
const Icon(Icons.history,
size: 14, color: AppTheme.textSecondary),
Icon(Icons.history,
size: 14, color: context.tokens.muted),
const SizedBox(width: 8),
Text(
widget.value,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
color: AppTheme.textPrimary,
color: context.tokens.text,
),
),
],
@@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
import '../../core/auth/auth_state.dart';
import '../../core/theme/app_theme.dart';
import '../../core/theme/context_tokens.dart';
import '../../models/session.dart';
import '../../providers/session_provider.dart';
import '../../widgets/data_table_card.dart';
@@ -35,8 +35,8 @@ class DeviceManagementScreen extends ConsumerWidget {
const SizedBox(width: 12),
Text(
canKick ? '管理员可强制下线其他登录设备' : '仅查看,无操作权限',
style: const TextStyle(
fontSize: 12, color: AppTheme.textSecondary),
style: TextStyle(
fontSize: 12, color: context.tokens.muted),
),
const Spacer(),
IconButton(
@@ -56,12 +56,12 @@ class DeviceManagementScreen extends ConsumerWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline,
size: 40, color: AppTheme.textSecondary),
Icon(Icons.error_outline,
size: 40, color: context.tokens.muted),
const SizedBox(height: 12),
Text('加载失败:$e',
style:
const TextStyle(color: AppTheme.textSecondary)),
TextStyle(color: context.tokens.muted)),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () =>
@@ -86,13 +86,13 @@ class DeviceManagementScreen extends ConsumerWidget {
children: [
Icon(Icons.circle,
size: 9,
color: online ? AppTheme.success : AppTheme.textSecondary),
color: online ? context.tokens.success : context.tokens.muted),
const SizedBox(width: 4),
Text(online ? '在线' : '离线',
style: TextStyle(
fontSize: 13,
color:
online ? AppTheme.success : AppTheme.textSecondary)),
online ? context.tokens.success : context.tokens.muted)),
],
);
@@ -101,15 +101,15 @@ class DeviceManagementScreen extends ConsumerWidget {
Widget? kickButton(DeviceSession s, {bool dense = false}) {
if (!canKick) return null;
if (s.isCurrent) {
return const Text('当前设备',
style: TextStyle(fontSize: 12, color: AppTheme.textSecondary));
return Text('当前设备',
style: TextStyle(fontSize: 12, color: context.tokens.muted));
}
return TextButton(
key: Key('btn_kick_${s.id}'),
onPressed: () => _confirmKick(context, ref, s),
child: Text('强制下线',
style: TextStyle(
fontSize: dense ? 13 : 12, color: AppTheme.danger)),
fontSize: dense ? 13 : 12, color: context.tokens.danger)),
);
}
@@ -144,16 +144,16 @@ class DeviceManagementScreen extends ConsumerWidget {
],
rows: sessions.isEmpty
? [
const DataRow(cells: [
DataRow(cells: [
DataCell(Text('暂无在线设备',
style: TextStyle(color: AppTheme.textSecondary))),
DataCell(SizedBox()),
DataCell(SizedBox()),
DataCell(SizedBox()),
DataCell(SizedBox()),
DataCell(SizedBox()),
DataCell(SizedBox()),
DataCell(SizedBox()),
style: TextStyle(color: context.tokens.muted))),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
])
]
: sessions.map((s) {
@@ -170,12 +170,12 @@ class DeviceManagementScreen extends ConsumerWidget {
padding: const EdgeInsets.symmetric(
horizontal: 6, vertical: 1),
decoration: BoxDecoration(
color: AppTheme.primary.withAlpha(26),
color: context.tokens.primary.withAlpha(26),
borderRadius: BorderRadius.circular(4),
),
child: const Text('本机',
child: Text('本机',
style: TextStyle(
fontSize: 11, color: AppTheme.primary)),
fontSize: 11, color: context.tokens.primary)),
),
],
],
@@ -183,10 +183,10 @@ class DeviceManagementScreen extends ConsumerWidget {
DataCell(Text('${s.platformLabel} · ${s.platformClassLabel}')),
DataCell(Text(s.deviceName.isEmpty ? '-' : s.deviceName)),
DataCell(Text(s.ip.isEmpty ? '-' : s.ip,
style: const TextStyle(
style: TextStyle(
fontFamily: 'monospace',
fontSize: 12,
color: AppTheme.textSecondary))),
color: context.tokens.muted))),
DataCell(Text(fmt(s.createdAt))),
DataCell(Text(fmt(s.lastSeenAt))),
DataCell(onlineBadge(s.online)),
@@ -213,7 +213,7 @@ class DeviceManagementScreen extends ConsumerWidget {
ElevatedButton(
onPressed: () => Navigator.of(ctx).pop(true),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.danger,
backgroundColor: context.tokens.danger,
foregroundColor: Colors.white),
child: const Text('强制下线'),
),
@@ -224,13 +224,13 @@ class DeviceManagementScreen extends ConsumerWidget {
try {
await ref.read(sessionListProvider.notifier).forceLogout(s.id);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('已下线'), backgroundColor: AppTheme.success));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('已下线'), backgroundColor: context.tokens.success));
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('操作失败:$e'), backgroundColor: AppTheme.danger));
content: Text('操作失败:$e'), backgroundColor: context.tokens.danger));
}
}
}
@@ -5,7 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/models/page_result.dart';
import '../../core/responsive/responsive.dart';
import '../../core/config/app_constants.dart';
import '../../core/theme/app_theme.dart';
import '../../core/theme/context_tokens.dart';
import '../../models/partner.dart';
import '../../providers/partner_provider.dart';
import '../../widgets/data_table_card.dart';
@@ -59,10 +59,10 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.cloud_off, size: 40, color: AppTheme.textSecondary),
Icon(Icons.cloud_off, size: 40, color: context.tokens.muted),
const SizedBox(height: 12),
const Text('暂无数据,网络不可用',
style: const TextStyle(color: AppTheme.textSecondary)),
Text('暂无数据,网络不可用',
style: TextStyle(color: context.tokens.muted)),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () =>
@@ -102,10 +102,10 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.cloud_off, size: 40, color: AppTheme.textSecondary),
Icon(Icons.cloud_off, size: 40, color: context.tokens.muted),
const SizedBox(height: 12),
const Text('暂无数据,网络不可用',
style: const TextStyle(color: AppTheme.textSecondary)),
Text('暂无数据,网络不可用',
style: TextStyle(color: context.tokens.muted)),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () =>
@@ -159,8 +159,8 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
style: TextStyle(
fontSize: 12,
color: p.status == 'enabled'
? AppTheme.success
: AppTheme.textSecondary,
? context.tokens.success
: context.tokens.muted,
),
),
fields: [
@@ -182,8 +182,8 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
child: TextButton(
key: Key('btn_delete_${p.id}'),
onPressed: () => onDelete(p),
child: const Text('删除',
style: TextStyle(fontSize: 13, color: AppTheme.danger)),
child: Text('删除',
style: TextStyle(fontSize: 13, color: context.tokens.danger)),
),
),
],
@@ -251,7 +251,7 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
const DataCell(SizedBox()),
DataCell(Text(isSupplier ? '暂无供应商' : '暂无客户',
style:
const TextStyle(color: AppTheme.textSecondary))),
TextStyle(color: context.tokens.muted))),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
const DataCell(SizedBox()),
@@ -263,10 +263,10 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
.map((p) => DataRow(
cells: [
DataCell(Text(p.code ?? '-',
style: const TextStyle(
style: TextStyle(
fontFamily: 'monospace',
fontSize: 12,
color: AppTheme.textSecondary))),
color: context.tokens.muted))),
DataCell(SizedBox(
width: 180,
child: Text(p.name,
@@ -286,8 +286,8 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
style: TextStyle(
fontSize: 13,
color: p.status == 'enabled'
? AppTheme.success
: AppTheme.textSecondary,
? context.tokens.success
: context.tokens.muted,
),
)),
DataCell(Row(
@@ -307,10 +307,10 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
child: TextButton(
key: Key('btn_delete_${p.id}'),
onPressed: () => onDelete(p),
child: const Text('删除',
child: Text('删除',
style: TextStyle(
fontSize: 12,
color: AppTheme.danger)),
color: context.tokens.danger)),
),
),
],
@@ -354,7 +354,7 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
ElevatedButton(
onPressed: () => Navigator.of(ctx).pop(true),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.danger,
backgroundColor: context.tokens.danger,
foregroundColor: Colors.white),
child: const Text('删除'),
),
@@ -373,15 +373,15 @@ class _PartnersScreenState extends ConsumerState<PartnersScreen> {
.deletePartner(partner.id);
}
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('删除成功'),
backgroundColor: AppTheme.success));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('删除成功'),
backgroundColor: context.tokens.success));
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('删除失败:$e'),
backgroundColor: AppTheme.danger));
backgroundColor: context.tokens.danger));
}
}
}
@@ -466,7 +466,7 @@ class _PartnerFormDialogState extends ConsumerState<_PartnerFormDialog> {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(widget.partner != null ? '更新成功' : '创建成功'),
backgroundColor: AppTheme.success,
backgroundColor: context.tokens.success,
),
);
}
@@ -475,7 +475,7 @@ class _PartnerFormDialogState extends ConsumerState<_PartnerFormDialog> {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('保存失败:$e'),
backgroundColor: AppTheme.danger),
backgroundColor: context.tokens.danger),
);
}
} finally {
+2 -1
View File
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
import 'package:jiu_client/core/auth/auth_state.dart';
import 'package:jiu_client/core/theme/themes.dart';
import 'package:jiu_client/providers/connectivity_provider.dart';
import 'package:jiu_client/repositories/auth_repository.dart';
import 'package:jiu_client/screens/auth/login_screen.dart';
@@ -29,7 +30,7 @@ Widget _buildApp() {
(_) => ConnectivityNotifier(skipInit: true),
),
],
child: MaterialApp.router(routerConfig: router),
child: MaterialApp.router(theme: buildTheme('a'), routerConfig: router),
);
}
+2 -1
View File
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
import 'package:jiu_client/core/theme/themes.dart';
import 'package:jiu_client/providers/connectivity_provider.dart';
import 'package:jiu_client/screens/auth/login_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -29,7 +30,7 @@ Widget _buildTestApp() {
(_) => ConnectivityNotifier(skipInit: true),
),
],
child: MaterialApp.router(routerConfig: router),
child: MaterialApp.router(theme: buildTheme('a'), routerConfig: router),
);
}