feat(client): 设备管理屏在线状态徽章 → StatusPill + golden

onlineBadge(在线/离线 圆点文字)→ StatusPill(圆点软底 pill,
success/okSoft 与 muted/infoSoft);整屏 golden ×三主题(桌面+移动)入回归闸。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TSKEiHsvauyxYUW2itzUXX
This commit is contained in:
wangjia
2026-06-25 13:41:07 +08:00
parent ae447f61e3
commit 2d28b067d8
8 changed files with 74 additions and 14 deletions
@@ -7,6 +7,7 @@ import '../../core/theme/context_tokens.dart';
import '../../models/session.dart';
import '../../providers/session_provider.dart';
import '../../widgets/data_table_card.dart';
import '../../widgets/kpi_card.dart';
import '../../widgets/mobile_list_card.dart';
/// 设备 / 状态管理:本店在线设备/会话列表。
@@ -81,20 +82,16 @@ class DeviceManagementScreen extends ConsumerWidget {
Widget _buildTable(BuildContext context, WidgetRef ref,
List<DeviceSession> sessions, bool canKick) {
Widget onlineBadge(bool online) => Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.circle,
size: 9,
color: online ? context.tokens.success : context.tokens.muted),
const SizedBox(width: 4),
Text(online ? '在线' : '离线',
style: TextStyle(
fontSize: 13,
color:
online ? context.tokens.success : context.tokens.muted)),
],
);
// 还原原型 .badge.b-在线/b-离线:圆点软底 pill。
Widget onlineBadge(bool online) => online
? StatusPill(
label: '在线',
color: context.tokens.success,
background: context.tokens.okSoft)
: StatusPill(
label: '离线',
color: context.tokens.muted,
background: context.tokens.infoSoft);
String fmt(DateTime? t) => t == null ? '-' : _fmt.format(t);
@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:jiu_client/models/session.dart';
import 'package:jiu_client/providers/session_provider.dart';
import 'package:jiu_client/screens/devices/device_management_screen.dart';
import '../support/golden_harness.dart';
/// design-distill 阶段4:设备管理整屏 golden × 三主题(桌面 + 移动)。
/// 验证在线/离线状态 → StatusPill 随主题换色。
/// 更新基准:flutter test --update-goldens test/golden/device_management_golden_test.dart
List<DeviceSession> _sessions() => [
DeviceSession(
id: 1, userId: 1, username: '王经理', realName: '王经理',
platform: 'macos', platformClass: 'desktop', deviceName: 'MacBook Pro',
ip: '192.168.1.12', createdAt: DateTime(2026, 6, 20, 9, 12),
lastSeenAt: DateTime(2026, 6, 25, 12, 50), online: true, isCurrent: true),
DeviceSession(
id: 2, userId: 2, username: '李销售', realName: '李销售',
platform: 'android', platformClass: 'mobile', deviceName: 'Xiaomi 14',
ip: '192.168.1.23', createdAt: DateTime(2026, 6, 24, 14, 30),
lastSeenAt: DateTime(2026, 6, 25, 11, 05), online: true, isCurrent: false),
DeviceSession(
id: 3, userId: 3, username: '张前台', realName: '张前台',
platform: 'windows', platformClass: 'desktop', deviceName: 'ThinkPad',
ip: '192.168.1.31', createdAt: DateTime(2026, 6, 22, 8, 40),
lastSeenAt: DateTime(2026, 6, 23, 18, 20), online: false, isCurrent: false),
];
class _FakeSessionNotifier extends SessionListNotifier {
@override
Future<List<DeviceSession>> build() async => _sessions();
@override
Future<void> reload() async {}
}
List<Override> _overrides() => [
sessionListProvider.overrideWith(() => _FakeSessionNotifier()),
];
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
SharedPreferences.setMockInitialValues({});
goldenAcrossThemes(
'device management 整屏(桌面)',
goldenPrefix: 'device_management',
child: () => const Scaffold(body: DeviceManagementScreen()),
overrides: _overrides,
logical: const Size(1280, 900),
);
goldenAcrossThemes(
'device management 整屏(移动)',
goldenPrefix: 'device_management_mobile',
child: () => const Scaffold(body: DeviceManagementScreen()),
overrides: _overrides,
logical: const Size(390, 1100),
);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB