chore: release client-v1.0.57
Deploy Client / build-windows (push) Failing after 21s
Deploy Client / build-client-web (push) Successful in 42s
Deploy Client / build-macos (push) Successful in 2m8s
Deploy Client / build-android (push) Successful in 1m25s
Deploy Client / build-ios (push) Successful in 2m47s
Deploy Client / release-deploy-client (push) Has been skipped

设备/状态管理屏(查看本店在线设备/会话,管理员可强制下线)、登录携带设备信息、
会话心跳(/auth/ping)、被踢下线/会话失效提示、顶栏精简 + 用户名移至左侧栏底部。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-17 23:13:05 +08:00
parent 53fa259284
commit 90f318e246
12 changed files with 547 additions and 32 deletions
+52 -29
View File
@@ -11,6 +11,7 @@ import '../../core/config/app_config.dart';
import '../../core/responsive/responsive.dart';
import '../../core/theme/app_theme.dart';
import '../../providers/connectivity_provider.dart';
import '../../providers/session_heartbeat.dart';
import '../../providers/shop_provider.dart';
import '../../providers/update_provider.dart';
import '../../core/update/app_updater.dart';
@@ -72,6 +73,7 @@ class _AppShellState extends ConsumerState<AppShell> {
path: '/finance'),
_NavItem(icon: Icons.people, label: '往来单位', path: '/partners'),
_NavItem(icon: Icons.category, label: '基础数据', path: '/products'),
_NavItem(icon: Icons.devices, label: '设备管理', path: '/devices'),
_NavItem(icon: Icons.settings, label: '系统设置', path: '/settings'),
_NavItem(icon: Icons.info_outline, label: '关于我们', path: '/about'),
];
@@ -166,6 +168,8 @@ class _AppShellState extends ConsumerState<AppShell> {
@override
Widget build(BuildContext context) {
final user = ref.watch(authStateProvider).user;
// 登录态心跳:随 shell 挂载存活,~30s 一次,感知被踢下线
ref.watch(sessionHeartbeatProvider);
final isOnline = ref.watch(connectivityProvider);
final location = GoRouterState.of(context).matchedLocation;
final isMobile = context.isMobile;
@@ -237,35 +241,7 @@ class _AppShellState extends ConsumerState<AppShell> {
],
const Spacer(),
if (user != null) ...[
// 窄屏隐藏门店号/用户名文字块,仅保留用户菜单,避免顶栏拥挤
if (!isMobile) ...[
MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () =>
_showShopPanel(context, user, version: appVersion),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.business,
color: Colors.white70, size: 14),
const SizedBox(width: 4),
Text(user.shopNo,
style: const TextStyle(
color: Colors.white70, fontSize: 13)),
],
),
),
),
const SizedBox(width: 20),
const Icon(Icons.person_outline,
color: Colors.white70, size: 14),
const SizedBox(width: 4),
Text(user.username,
style: const TextStyle(
color: Colors.white70, fontSize: 13)),
const SizedBox(width: 8),
],
// 门店号已移除;用户名移到左侧栏底部。顶栏仅保留「个人设置」下拉。
PopupMenuButton<String>(
icon: const Icon(Icons.keyboard_arrow_down,
color: Colors.white70),
@@ -324,6 +300,53 @@ class _AppShellState extends ConsumerState<AppShell> {
}).toList(),
),
),
// 当前登录账号(顶栏移下来的用户名):点击弹门店/账号/版本面板
if (user != null) ...[
const Divider(height: 1, color: Colors.white24),
SizedBox(
height: 48,
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => _showShopPanel(context, user,
version: appVersion),
hoverColor: Colors.white.withAlpha(13),
splashColor: Colors.white.withAlpha(26),
child: Row(
children: [
SizedBox(
width: _sidebarExpanded ? 16 : 3),
Expanded(
child: Row(
mainAxisAlignment: _sidebarExpanded
? MainAxisAlignment.start
: MainAxisAlignment.center,
children: [
const Icon(Icons.person_outline,
color: Colors.white60,
size: 20),
if (_sidebarExpanded) ...[
const SizedBox(width: 12),
Expanded(
child: Text(
user.username,
style: const TextStyle(
color: Colors.white70,
fontSize: 14),
overflow:
TextOverflow.ellipsis,
),
),
],
],
),
),
],
),
),
),
),
],
// 退出登录(侧栏底部常驻;统一为左侧导航唯一退出入口)
const Divider(height: 1, color: Colors.white24),
SizedBox(