feat(client): 登录模块对接后端 API
- auth_state: 增加 refreshToken 字段 + flutter_secure_storage 持久化 - api_client: 增加 401 自动 refresh + retry 拦截器 - auth_repository: 封装 POST /api/v1/auth/login 调用,错误信息本地化 - login_screen: 增加门店编号字段,调真实 API,行内错误展示 - main: 启动时 restore 持久化登录态,避免每次重启都要重新登录 - 修复 app_shell: hotelName → hotelNo - 修复 widget_test: 移除失效的占位测试 测试账号:门店编号 H001 / 用户名 admin / 密码 password123 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import '../core/api/api_client.dart';
|
||||
import '../core/auth/auth_state.dart';
|
||||
|
||||
class AuthException implements Exception {
|
||||
final String message;
|
||||
const AuthException(this.message);
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
|
||||
class AuthRepository {
|
||||
/// POST /api/v1/auth/login
|
||||
/// Request: { hotel_code, username, password }
|
||||
/// Response: { data: { access_token, refresh_token, expires_in, user: { id, username, real_name, role } } }
|
||||
static Future<AuthUser> login({
|
||||
required String hotelCode,
|
||||
required String username,
|
||||
required String password,
|
||||
}) async {
|
||||
try {
|
||||
final resp = await PublicApiClient.post('/auth/login', data: {
|
||||
'hotel_code': hotelCode,
|
||||
'username': username,
|
||||
'password': password,
|
||||
});
|
||||
|
||||
final data = resp.data['data'] as Map<String, dynamic>;
|
||||
final user = data['user'] as Map<String, dynamic>;
|
||||
|
||||
return AuthUser(
|
||||
accessToken: data['access_token'] as String,
|
||||
refreshToken: data['refresh_token'] as String,
|
||||
username: user['username'] as String,
|
||||
realName: user['real_name'] as String? ?? username,
|
||||
hotelNo: hotelCode,
|
||||
hotelId: (user['id'] as num).toInt(),
|
||||
);
|
||||
} on DioException catch (e) {
|
||||
final msg = e.response?.data?['error'] as String?;
|
||||
throw AuthException(msg ?? _networkError(e));
|
||||
}
|
||||
}
|
||||
|
||||
static String _networkError(DioException e) {
|
||||
switch (e.type) {
|
||||
case DioExceptionType.connectionTimeout:
|
||||
case DioExceptionType.receiveTimeout:
|
||||
return '连接超时,请检查网络';
|
||||
case DioExceptionType.connectionError:
|
||||
return '无法连接到服务器(localhost:8080),请先启动后端';
|
||||
default:
|
||||
return '网络错误:${e.message}';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user