| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import 'package:flutter/foundation.dart';
- import 'package:dio/dio.dart';
- import 'package:shared_preferences/shared_preferences.dart';
-
- /// 用户认证服务 —— 登录 / 登出 / Token 持久化
- class AuthService extends ChangeNotifier {
- // --------------- 状态 ---------------
- String _token = '';
- String _username = '';
- String _displayName = '';
- String _avatarUrl = '';
- bool _isLoading = false;
-
- String get token => _token;
- String get username => _username;
- String get displayName => _displayName.isNotEmpty ? _displayName : _username;
- String get avatarUrl => _avatarUrl;
- bool get isLoggedIn => _token.isNotEmpty;
- bool get isLoading => _isLoading;
-
- // --------------- Dio (内部使用,不依赖 ApiService 避免循环) ---------------
- final Dio _dio = Dio(BaseOptions(
- baseUrl: 'http://10.0.2.2:8080/api',
- connectTimeout: const Duration(seconds: 15),
- receiveTimeout: const Duration(seconds: 15),
- ));
-
- // --------------- 初始化(app 启动时恢复 session) ---------------
- Future<void> init() async {
- final prefs = await SharedPreferences.getInstance();
- _token = prefs.getString('token') ?? '';
- _username = prefs.getString('username') ?? '';
- _displayName = prefs.getString('displayName') ?? '';
- _avatarUrl = prefs.getString('avatarUrl') ?? '';
- notifyListeners();
- }
-
- // --------------- 登录 ---------------
- Future<bool> login(String username, String password) async {
- _isLoading = true;
- notifyListeners();
-
- try {
- final res = await _dio.post('/base/auth/login', data: {
- 'username': username,
- 'password': password,
- });
-
- // 兼容两种响应格式
- final data = res.data;
- if (data is Map && (data['code'] == 200 || data['code'] == 0)) {
- final payload = data['data'] ?? data;
- _token = payload is String ? payload : (payload['token'] ?? payload['accessToken'] ?? '').toString();
- _username = payload is Map ? (payload['username'] ?? username).toString() : username;
- _displayName = payload is Map ? (payload['displayName'] ?? payload['nickName'] ?? '').toString() : '';
- _avatarUrl = payload is Map ? (payload['avatar'] ?? '').toString() : '';
-
- await _persist();
- _isLoading = false;
- notifyListeners();
- return true;
- }
- } catch (e) {
- debugPrint('Login error: $e');
- }
-
- _isLoading = false;
- notifyListeners();
- return false;
- }
-
- // --------------- 登出 ---------------
- Future<void> logout() async {
- _token = '';
- _username = '';
- _displayName = '';
- _avatarUrl = '';
-
- final prefs = await SharedPreferences.getInstance();
- await prefs.remove('token');
- await prefs.remove('username');
- await prefs.remove('displayName');
- await prefs.remove('avatarUrl');
-
- notifyListeners();
- }
-
- // --------------- 刷新用户信息 ---------------
- Future<void> refreshProfile() async {
- if (_token.isEmpty) return;
- try {
- final res = await _dio.get(
- '/base/user/info',
- options: Options(headers: {'Authorization': 'Bearer $_token'}),
- );
- final data = res.data;
- if (data is Map && (data['code'] == 200 || data['code'] == 0)) {
- final payload = data['data'] ?? data;
- if (payload is Map) {
- _displayName = (payload['displayName'] ?? payload['nickName'] ?? _displayName).toString();
- _avatarUrl = (payload['avatar'] ?? _avatarUrl).toString();
- await _persist();
- notifyListeners();
- }
- }
- } catch (e) {
- debugPrint('refreshProfile error: $e');
- }
- }
-
- // --------------- 持久化 ---------------
- Future<void> _persist() async {
- final prefs = await SharedPreferences.getInstance();
- await prefs.setString('token', _token);
- await prefs.setString('username', _username);
- await prefs.setString('displayName', _displayName);
- await prefs.setString('avatarUrl', _avatarUrl);
- }
- }
|