change_password_provider.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import 'dart:async';
  2. import 'dart:developer' as developer;
  3. import 'package:dio/dio.dart';
  4. import 'package:flutter_riverpod/flutter_riverpod.dart';
  5. import '../core/network/api_response.dart';
  6. import '../core/network/dio_client.dart';
  7. import '../data/services/auth_service.dart';
  8. // ── State ──────────────────────────────────────────────────
  9. class ChangePasswordState {
  10. final bool isLoading;
  11. final bool isSendingCode;
  12. final String? errorMessage;
  13. final int codeCooldown;
  14. const ChangePasswordState({
  15. this.isLoading = false,
  16. this.isSendingCode = false,
  17. this.errorMessage,
  18. this.codeCooldown = 0,
  19. });
  20. ChangePasswordState copyWith({
  21. bool? isLoading,
  22. bool? isSendingCode,
  23. String? errorMessage,
  24. int? codeCooldown,
  25. }) =>
  26. ChangePasswordState(
  27. isLoading: isLoading ?? this.isLoading,
  28. isSendingCode: isSendingCode ?? this.isSendingCode,
  29. errorMessage: errorMessage,
  30. codeCooldown: codeCooldown ?? this.codeCooldown,
  31. );
  32. }
  33. // ── Notifier ───────────────────────────────────────────────
  34. class ChangePasswordNotifier extends Notifier<ChangePasswordState> {
  35. AuthService get _service => AuthService(ref.read(dioClientProvider));
  36. Timer? _countdownTimer;
  37. @override
  38. ChangePasswordState build() {
  39. ref.onDispose(() => _countdownTimer?.cancel());
  40. return const ChangePasswordState();
  41. }
  42. void clearError() => state = state.copyWith(errorMessage: null);
  43. /// 发送邮箱验证码
  44. Future<bool> sendEmailCode() async {
  45. state = state.copyWith(isSendingCode: true, errorMessage: null);
  46. try {
  47. await _service.sendChangePasswordEmailCode();
  48. state = state.copyWith(isSendingCode: false);
  49. _startCountdown();
  50. return true;
  51. } catch (e) {
  52. state = state.copyWith(
  53. isSendingCode: false,
  54. errorMessage: _parseError(e),
  55. );
  56. return false;
  57. }
  58. }
  59. /// 提交修改登录密码
  60. Future<bool> changePassword({
  61. required String oldPassword,
  62. required String newPassword,
  63. required String vcode,
  64. }) async {
  65. state = state.copyWith(isLoading: true, errorMessage: null);
  66. try {
  67. await _service.changeLoginPassword(
  68. oldPassword: oldPassword,
  69. newPassword: newPassword,
  70. vcode: vcode,
  71. );
  72. state = state.copyWith(isLoading: false);
  73. return true;
  74. } catch (e) {
  75. state = state.copyWith(
  76. isLoading: false,
  77. errorMessage: _parseError(e),
  78. );
  79. return false;
  80. }
  81. }
  82. void _startCountdown() {
  83. _countdownTimer?.cancel();
  84. state = state.copyWith(codeCooldown: 60);
  85. _countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
  86. final remaining = state.codeCooldown - 1;
  87. state = state.copyWith(codeCooldown: remaining);
  88. if (remaining <= 0) {
  89. timer.cancel();
  90. _countdownTimer = null;
  91. }
  92. });
  93. }
  94. String _parseError(Object e) {
  95. developer.log('ChangePassword error: $e', name: 'CHANGE_PWD', error: e);
  96. if (e is DioException) {
  97. if (e.error is ApiException) return (e.error as ApiException).message;
  98. final responseData = e.response?.data;
  99. if (responseData is Map<String, dynamic>) {
  100. final msg = responseData['message'] as String? ??
  101. responseData['msg'] as String?;
  102. if (msg != null && msg.isNotEmpty) return msg;
  103. }
  104. return e.message ?? 'errNetworkError';
  105. }
  106. if (e is ApiException) return e.message;
  107. return e.toString();
  108. }
  109. }
  110. // ── Provider ──────────────────────────────────────────────
  111. final changePasswordProvider =
  112. NotifierProvider<ChangePasswordNotifier, ChangePasswordState>(
  113. ChangePasswordNotifier.new,
  114. );