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
+13 -3
View File
@@ -33,8 +33,11 @@ final apiClientProvider = Provider<ApiClient>((ref) {
onTokenRefreshed: (newToken) {
ref.read(authStateProvider.notifier).updateAccessToken(newToken);
},
onAuthFailed: () {
onAuthFailed: (reason) {
if (ref.read(authStateProvider).isLoggedIn) {
if (reason != null) {
ref.read(sessionEndedMessageProvider.notifier).state = reason;
}
ref.read(authStateProvider.notifier).logout();
}
},
@@ -54,7 +57,7 @@ class ApiClient {
String? token,
String? refreshToken,
void Function(String newToken)? onTokenRefreshed,
void Function()? onAuthFailed,
void Function(String? reason)? onAuthFailed,
void Function()? onConnectionError,
}) {
_dio = Dio(BaseOptions(
@@ -110,7 +113,14 @@ class ApiClient {
return handler.resolve(retryResp);
} catch (refreshErr) {
debugPrint('[ApiClient] refresh failed: $refreshErr');
if (!_disposed) onAuthFailed?.call();
// 区分「被踢/会话失效」与普通登录过期,便于登录页给出明确提示
String? reason;
if (refreshErr is DioException &&
refreshErr.response?.data is Map &&
refreshErr.response?.data['code'] == 'SESSION_REVOKED') {
reason = '您的账号已在其他设备登录,或登录已失效,请重新登录';
}
if (!_disposed) onAuthFailed?.call(reason);
}
} else if (e.response?.statusCode == 401) {
debugPrint('[ApiClient] got 401 on ${e.requestOptions.path}, no refresh token');