login_service.dart 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import 'package:path/path.dart' as path;
  2. import 'package:dio/dio.dart';
  3. import 'package:sino_med_cloud/core/constants/api_constants.dart';
  4. import 'package:sino_med_cloud/core/network/dio_client.dart';
  5. import 'package:sino_med_cloud/core/storage/local_storage.dart';
  6. import 'package:sino_med_cloud/core/utils/logger.dart';
  7. import '../data/auth_model.dart';
  8. /// 登录服务类
  9. class LoginService {
  10. /// 密码登录
  11. ///
  12. /// [mobile] 手机号
  13. /// [password] 密码(已加密)
  14. /// [loginSystem] 登录系统标识
  15. /// [loginType] 登录类型
  16. ///
  17. /// 返回 [AuthModel] 认证模型,如果登录失败则抛出异常
  18. static Future<AuthModel> passwordLogin({
  19. required String mobile,
  20. required String password,
  21. required String loginSystem,
  22. required String loginType,
  23. }) async {
  24. try {
  25. final parame = {
  26. "mobile": mobile,
  27. "login_system": loginSystem,
  28. "password": password,
  29. "login_type": loginType,
  30. };
  31. AppLogger.d('密码登录请求参数: $parame');
  32. final response = await DioClient.post<Map<String, dynamic>>(
  33. path.join(ApiConstants.baseUrl, ApiConstants.login),
  34. data: parame,
  35. );
  36. if (response.statusCode == 200) {
  37. final data = response.data;
  38. if (data != null && data['code'] == 20000) {
  39. AppLogger.d('密码登录成功: $data');
  40. final jsonData = data['data'] as Map<String, dynamic>;
  41. // 解析为 AuthModel
  42. final authModel = AuthModel.fromJson(jsonData);
  43. // 保存到本地存储
  44. await _saveAuthData(authModel);
  45. return authModel;
  46. } else {
  47. final errorMsg = data?['message'] ?? '登录失败';
  48. AppLogger.d('密码登录失败: $errorMsg');
  49. throw Exception(errorMsg);
  50. }
  51. } else {
  52. AppLogger.d('密码登录请求错误: ${response.statusCode}, ${response.statusMessage}');
  53. throw Exception('请求失败: ${response.statusCode}');
  54. }
  55. } catch (e) {
  56. AppLogger.e('密码登录错误', e);
  57. rethrow;
  58. }
  59. }
  60. /// 发送验证码
  61. ///
  62. /// [mobile] 手机号
  63. /// [scope] 验证码作用域,默认为 "yun-his-login-sms-send"
  64. ///
  65. /// 返回验证码字符串,如果发送失败则抛出异常
  66. static Future<String> sendSmsCode({
  67. required String mobile,
  68. String scope = "yun-his-login-sms-send",
  69. }) async {
  70. try {
  71. final parame = {
  72. "mobile": mobile,
  73. "scope": scope,
  74. };
  75. AppLogger.d('发送验证码请求参数: $parame');
  76. final response = await DioClient.post<Map<String, dynamic>>(
  77. path.join(ApiConstants.baseUrl, ApiConstants.sendSmsCode),
  78. data: parame,
  79. );
  80. if (response.statusCode == 200) {
  81. final data = response.data;
  82. if (data != null && data['code'] == 20000) {
  83. AppLogger.d('发送验证码成功: $data');
  84. final jsonData = data['data'] as Map<String, dynamic>;
  85. final smsCode = jsonData['code'] as String;
  86. return smsCode;
  87. } else {
  88. final errorMsg = data?['message'] ?? '发送验证码失败';
  89. AppLogger.d('发送验证码失败: $errorMsg');
  90. throw Exception(errorMsg);
  91. }
  92. } else {
  93. AppLogger.d('发送验证码请求错误: ${response.statusCode}, ${response.statusMessage}');
  94. throw Exception('请求失败: ${response.statusCode}');
  95. }
  96. } catch (e) {
  97. AppLogger.e('发送验证码错误', e);
  98. rethrow;
  99. }
  100. }
  101. /// 验证码登录
  102. ///
  103. /// [mobile] 手机号
  104. /// [smsCode] 验证码
  105. /// [loginSystem] 登录系统标识
  106. /// [loginType] 登录类型
  107. ///
  108. /// 返回 [AuthModel] 认证模型,如果登录失败则抛出异常
  109. static Future<AuthModel> smsLogin({
  110. required String mobile,
  111. required String smsCode,
  112. required String loginSystem,
  113. required String loginType,
  114. }) async {
  115. try {
  116. final parame = {
  117. "mobile": mobile,
  118. "sms_code": smsCode,
  119. "login_system": loginSystem,
  120. "login_type": loginType,
  121. };
  122. AppLogger.d('验证码登录请求参数: $parame');
  123. final response = await DioClient.post<Map<String, dynamic>>(
  124. path.join(ApiConstants.baseUrl, ApiConstants.login),
  125. data: parame,
  126. );
  127. if (response.statusCode == 200) {
  128. final data = response.data;
  129. if (data != null && data['code'] == 20000) {
  130. AppLogger.d('验证码登录成功: $data');
  131. final jsonData = data['data'] as Map<String, dynamic>;
  132. // 解析为 AuthModel
  133. final authModel = AuthModel.fromJson(jsonData);
  134. // 保存到本地存储
  135. await _saveAuthData(authModel);
  136. return authModel;
  137. } else {
  138. final errorMsg = data?['message'] ?? '登录失败';
  139. AppLogger.d('验证码登录失败: $errorMsg');
  140. throw Exception(errorMsg);
  141. }
  142. } else {
  143. AppLogger.d('验证码登录请求错误: ${response.statusCode}, ${response.statusMessage}');
  144. throw Exception('请求失败: ${response.statusCode}');
  145. }
  146. } catch (e) {
  147. AppLogger.e('验证码登录错误', e);
  148. rethrow;
  149. }
  150. }
  151. /// 保存认证数据到本地存储
  152. static Future<void> _saveAuthData(AuthModel authModel) async {
  153. // 保存 Token(会自动初始化)
  154. await LocalStorage.saveToken(authModel.accessToken);
  155. // 保存用户信息(会自动初始化)
  156. await LocalStorage.saveUserInfo(authModel.userInfo.toJson());
  157. // 保存机构信息列表(会自动初始化)
  158. final institutionInfoList = authModel.institutionInfo
  159. .map((item) => item.toJson())
  160. .toList();
  161. await LocalStorage.saveInstitutionInfo(institutionInfoList);
  162. }
  163. }