import 'dart:developer'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:dio/dio.dart'; import '../core/api_client.dart'; import '../core/local_database.dart'; class UserInfo { final String id; final String phone; final String role; final String? name; final String? avatarUrl; UserInfo({required this.id, required this.phone, this.role = 'User', this.name, this.avatarUrl}); } class AuthState { final UserInfo? user; final bool isLoggedIn; final bool isLoading; const AuthState({this.user, this.isLoggedIn = false, this.isLoading = true}); } final authProvider = NotifierProvider(AuthNotifier.new); final localDbProvider = Provider((ref) => LocalDatabase.instance); final apiClientProvider = Provider((ref) { return ApiClient(db: ref.watch(localDbProvider)); }); class AuthNotifier extends Notifier { @override AuthState build() { _checkAuth(); // 初始为"加载中",让启动闸门显示 Splash 盖住登录页/首页初始态 return const AuthState(isLoggedIn: false, isLoading: true); } Future _checkAuth() async { final db = ref.read(localDbProvider); final refresh = await db.read('refresh_token'); if (refresh == null) { // 无 token:判定完成、未登录 state = const AuthState(isLoggedIn: false, isLoading: false); return; } state = const AuthState(isLoading: true); try { final response = await Dio(BaseOptions(baseUrl: baseUrl)) .post('/api/auth/refresh', data: {'refreshToken': refresh}); final data = response.data['data']; if (data != null) { await db.write('access_token', data['accessToken']); await db.write('refresh_token', data['refreshToken']); final u = data['user'] as Map?; state = AuthState(isLoggedIn: true, isLoading: false, user: UserInfo(id: '', phone: '', role: u?['role'] ?? 'User'), ); _loadProfile(); } else { state = const AuthState(isLoggedIn: false, isLoading: false); } } catch (_) { state = const AuthState(isLoggedIn: false, isLoading: false); } } Future _loadProfile() async { // Admin 不查 profile(无 User 记录) if (state.user?.role == 'Admin') return; try { final api = ref.read(apiClientProvider); final response = await api.get('/api/user/profile'); final user = response.data['data']; if (user != null) { state = AuthState(isLoggedIn: true, isLoading: false, user: UserInfo( id: user['id'] ?? '', phone: user['phone'] ?? '', role: user['role'] ?? state.user?.role ?? 'User', name: user['name'], avatarUrl: user['avatarUrl'], ), ); } } catch (e) { log('[Auth] loadProfile: $e'); } } Future refreshProfile() => _loadProfile(); /// 发送验证码 Future<({String? error, String? devCode})> sendSms(String phone) async { try { final api = ref.read(apiClientProvider); final response = await api.post('/api/auth/send-sms', data: {'phone': phone}); return (error: null, devCode: response.data['data']?['devCode'] as String?); } catch (e) { return (error: '发送失败: $e', devCode: null); } } /// 注册(新用户,需选身份) Future register(String phone, String code, String name, String doctorId) async { try { final api = ref.read(apiClientProvider); final response = await api.post('/api/auth/register', data: { 'phone': phone, 'smsCode': code, 'name': name, 'doctorId': doctorId, }); final data = response.data['data']; if (data == null) return response.data['message'] ?? '注册失败'; await api.saveTokens(data['accessToken'], data['refreshToken']); final user = data['user']; state = AuthState(isLoggedIn: true, isLoading: false, user: UserInfo(id: user['id'] ?? '', phone: user['phone'] ?? '', role: user['role'] ?? 'User'), ); return null; } catch (e) { return '注册失败: $e'; } } /// 登录(已有账号) Future login(String phone, String code) async { try { final api = ref.read(apiClientProvider); final response = await api.post('/api/auth/login', data: {'phone': phone, 'smsCode': code}); final data = response.data['data']; if (data == null) return response.data['message'] ?? '登录失败'; await api.saveTokens(data['accessToken'], data['refreshToken']); final user = data['user']; state = AuthState(isLoggedIn: true, isLoading: false, user: UserInfo( id: user['id'] ?? '', phone: user['phone'] ?? '', role: user['role'] ?? 'User', name: user['name'], avatarUrl: user['avatarUrl'], ), ); return null; } catch (e) { return '登录失败: $e'; } } /// 登出 Future logout() async { final api = ref.read(apiClientProvider); final db = ref.read(localDbProvider); final refresh = await db.read('refresh_token'); if (refresh != null) { try { await api.post('/api/auth/logout', data: {'refreshToken': refresh}); } catch (e) { log('[Auth] logout: $e'); } } await api.clearTokens(); state = const AuthState(isLoggedIn: false, isLoading: false); } } /// 便捷:当前用户角色 final userRoleProvider = Provider((ref) { return ref.watch(authProvider).user?.role ?? 'User'; });