Files
jiu/client/lib/providers/session_heartbeat.dart
T
wangjia 90f318e246
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
chore: release client-v1.0.57
设备/状态管理屏(查看本店在线设备/会话,管理员可强制下线)、登录携带设备信息、
会话心跳(/auth/ping)、被踢下线/会话失效提示、顶栏精简 + 用户名移至左侧栏底部。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:13:05 +08:00

41 lines
1.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/api/api_client.dart';
import '../core/auth/auth_state.dart';
/// 登录态心跳:已登录时每 30s 打一次 POST /auth/ping。
/// 若会话已被撤销(被踢/管理员强制下线),后端返回 401,
/// ApiClient 的拦截器会触发 refresh→失败→onAuthFailed→logout
/// 因此空闲用户也能在 ~30s 内感知到被下线。
final sessionHeartbeatProvider = Provider<SessionHeartbeat>((ref) {
final hb = SessionHeartbeat(ref);
ref.onDispose(hb.dispose);
hb.start();
return hb;
});
class SessionHeartbeat {
final Ref _ref;
Timer? _timer;
SessionHeartbeat(this._ref);
void start() {
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 30), (_) => _ping());
}
Future<void> _ping() async {
if (!_ref.read(authStateProvider).isLoggedIn) return;
try {
await _ref.read(apiClientProvider).post('/auth/ping');
} catch (e) {
// 401 已由 ApiClient 拦截器处理(触发登出);其余错误忽略
debugPrint('[Heartbeat] ping failed: $e');
}
}
void dispose() => _timer?.cancel();
}