|
|
|
// lib/modules/auth/controllers/auth_controller.dart
|
|
|
|
import 'package:flutter/material.dart'; // 导入此库以使用 TextEditingController
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:get_storage/get_storage.dart';
|
|
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
|
|
import 'package:problem_check_system/data/providers/auth_provider.dart';
|
|
|
|
import 'package:problem_check_system/data/models/login_model.dart';
|
|
|
|
import 'package:problem_check_system/app/routes/app_routes.dart';
|
|
|
|
|
|
|
|
class AuthController extends GetxController {
|
|
|
|
final AuthProvider _authProvider;
|
|
|
|
final GetStorage _storage;
|
|
|
|
|
|
|
|
// 将 TextEditingController 移动到控制器中,由控制器管理它们的生命周期
|
|
|
|
late final TextEditingController usernameController = TextEditingController();
|
|
|
|
late final TextEditingController passwordController = TextEditingController();
|
|
|
|
|
|
|
|
final isLoading = false.obs;
|
|
|
|
final rememberPassword = false.obs;
|
|
|
|
|
|
|
|
static const _usernameKey = 'username';
|
|
|
|
static const _passwordKey = 'password';
|
|
|
|
|
|
|
|
AuthController({
|
|
|
|
required AuthProvider authProvider,
|
|
|
|
required GetStorage storage,
|
|
|
|
}) : _authProvider = authProvider,
|
|
|
|
_storage = storage;
|
|
|
|
|
|
|
|
@override
|
|
|
|
void onInit() {
|
|
|
|
super.onInit();
|
|
|
|
_loadSavedCredentials();
|
|
|
|
}
|
|
|
|
|
|
|
|
void _loadSavedCredentials() {
|
|
|
|
final savedUsername = _storage.read(_usernameKey);
|
|
|
|
final savedPassword = _storage.read(_passwordKey);
|
|
|
|
|
|
|
|
if (savedUsername != null && savedPassword != null) {
|
|
|
|
// 从本地存储加载值,并设置给控制器
|
|
|
|
usernameController.text = savedUsername;
|
|
|
|
passwordController.text = savedPassword;
|
|
|
|
rememberPassword.value = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
String getToken() {
|
|
|
|
return _storage.read('token') ?? '';
|
|
|
|
}
|
|
|
|
|
|
|
|
// 移除了 updateUsername 和 updatePassword 方法,因为不再需要它们来同步值。
|
|
|
|
// TextEditingController 本身就是值的来源。
|
|
|
|
|
|
|
|
Future<void> login() async {
|
|
|
|
// 直接从控制器获取文本内容
|
|
|
|
final username = usernameController.text;
|
|
|
|
final password = passwordController.text;
|
|
|
|
|
|
|
|
if (username.isEmpty || password.isEmpty) {
|
|
|
|
Get.snackbar('输入错误', '用户名和密码不能为空');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
isLoading.value = true;
|
|
|
|
|
|
|
|
var connectivityResult = await (Connectivity().checkConnectivity());
|
|
|
|
bool isConnected =
|
|
|
|
connectivityResult.contains(ConnectivityResult.mobile) ||
|
|
|
|
connectivityResult.contains(ConnectivityResult.wifi) ||
|
|
|
|
connectivityResult.contains(ConnectivityResult.ethernet);
|
|
|
|
|
|
|
|
if (isConnected) {
|
|
|
|
await _onlineLogin(username, password);
|
|
|
|
} else {
|
|
|
|
await _offlineLogin(username, password);
|
|
|
|
}
|
|
|
|
|
|
|
|
isLoading.value = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _onlineLogin(String username, String password) async {
|
|
|
|
try {
|
|
|
|
final loginData = LoginModel(username: username, password: password);
|
|
|
|
|
|
|
|
final response = await _authProvider.signIn(loginData);
|
|
|
|
|
|
|
|
if (response.statusCode == 200 && response.data['token'] != null) {
|
|
|
|
final token = response.data['token'];
|
|
|
|
final refreshToken = response.data['refreshToken'];
|
|
|
|
|
|
|
|
_storage.write('token', token);
|
|
|
|
_storage.write('refreshToken', refreshToken);
|
|
|
|
|
|
|
|
// 如果记住密码,保存用户名和密码
|
|
|
|
if (rememberPassword.value) {
|
|
|
|
_storage.write(_usernameKey, username);
|
|
|
|
_storage.write(_passwordKey, password);
|
|
|
|
} else {
|
|
|
|
// 否则清除所有本地凭据
|
|
|
|
_storage.remove(_usernameKey);
|
|
|
|
_storage.remove(_passwordKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
Get.offAllNamed(AppRoutes.home);
|
|
|
|
} else {
|
|
|
|
Get.snackbar('登录失败', '服务器返回了异常数据');
|
|
|
|
}
|
|
|
|
} on DioException catch (e) {
|
|
|
|
if (e.response?.data != null && e.response?.data['detail'] != null) {
|
|
|
|
final serverMessage = e.response!.data['detail'];
|
|
|
|
Get.snackbar('登录失败', serverMessage);
|
|
|
|
} else {
|
|
|
|
Get.snackbar('网络错误', '登录失败,请检查您的网络连接');
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
Get.snackbar('错误', '发生未知错误: ${e.toString()}');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _offlineLogin(String username, String password) async {
|
|
|
|
final storedUsername = _storage.read(_usernameKey);
|
|
|
|
final storedPassword = _storage.read(_passwordKey);
|
|
|
|
|
|
|
|
if (storedUsername != null &&
|
|
|
|
storedPassword != null &&
|
|
|
|
storedUsername == username &&
|
|
|
|
storedPassword == password) {
|
|
|
|
Get.offAllNamed(AppRoutes.home);
|
|
|
|
Get.snackbar('离线登录成功', '您已离线登录到系统');
|
|
|
|
} else {
|
|
|
|
Get.snackbar('离线登录失败', '无网络连接,且无法验证本地凭证');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> logout() async {
|
|
|
|
_storage.remove('token');
|
|
|
|
_storage.remove('refreshToken');
|
|
|
|
Get.offAllNamed(AppRoutes.login);
|
|
|
|
}
|
|
|
|
}
|