account_phone_cubit.dart 4.3 KB
import 'dart:async';

import 'package:appframe/config/locator.dart';
import 'package:appframe/config/routes.dart';
import 'package:appframe/data/repositories/phone_auth_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:shared_preferences/shared_preferences.dart';

class AccountPhoneState extends Equatable {
  final String phone;

  final bool showSnackBar;
  final String snackBarMsg;
  final bool allowSend;
  final int seconds;

  const AccountPhoneState({
    this.phone = '',
    this.showSnackBar = false,
    this.snackBarMsg = '',
    this.allowSend = true,
    this.seconds = 0,
  });

  AccountPhoneState copyWith({
    String? phone,
    bool? showSnackBar,
    String? snackBarMsg,
    bool? allowSend,
    int? seconds,
  }) {
    return AccountPhoneState(
      phone: phone ?? this.phone,
      showSnackBar: showSnackBar ?? this.showSnackBar,
      snackBarMsg: snackBarMsg ?? this.snackBarMsg,
      allowSend: allowSend ?? this.allowSend,
      seconds: seconds ?? this.seconds,
    );
  }

  @override
  List<Object?> get props => [
        phone,
        showSnackBar,
        snackBarMsg,
        allowSend,
        seconds,
      ];
}

class AccountPhoneCubit extends Cubit<AccountPhoneState> {
  late TextEditingController _phoneController;
  late TextEditingController _codeController;
  Timer? _timer;
  int countdown = 60; // 倒计时秒数

  late final PhoneAuthRepository _phoneAuthRepository;

  TextEditingController get phoneController => _phoneController;

  TextEditingController get codeController => _codeController;

  AccountPhoneCubit(super.initialState) {
    _phoneController = TextEditingController();
    _codeController = TextEditingController();

    _phoneController.text = '';
    _codeController.text = '';

    _phoneAuthRepository = getIt.get<PhoneAuthRepository>();
  }

  /// 开始倒计时
  void startCountdown() {
    countdown = 60;
    emit(state.copyWith(allowSend: false, seconds: countdown));

    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      countdown--;
      if (countdown <= 0) {
        _timer?.cancel();
        emit(state.copyWith(allowSend: true, seconds: 60));
      } else {
        emit(state.copyWith(seconds: countdown));
      }
    });
  }

  /// 发送验证码
  Future<void> sendVerificationCode() async {
    if (state.allowSend) {
      // 验证手机号码
      String phone = _phoneController.text;
      if (!RegExp(r'^1[3-9][0-9]{9}$').hasMatch(phone)) {
        emit(state.copyWith(showSnackBar: true, snackBarMsg: '请输入正确的手机号码'));
        emit(state.copyWith(showSnackBar: false));
        return;
      }

      // 发送验证码
      var result = await _phoneAuthRepository.verifyCode(phone, 1);
      if (result['code'] != 0) {
        emit(state.copyWith(showSnackBar: true, snackBarMsg: result['error']));
        emit(state.copyWith(showSnackBar: false));
        return;
      }

      emit(state.copyWith(allowSend: false, seconds: 60));

      // 开始倒计时
      startCountdown();
    }
  }

  Future<void> bind() async {
    String phone = _phoneController.text;
    String verifyCode = _codeController.text;

    if (!RegExp(r'^1[3-9][0-9]{9}$').hasMatch(phone)) {
      emit(state.copyWith(showSnackBar: true, snackBarMsg: '请输入正确的手机号码'));
      emit(state.copyWith(showSnackBar: false));
      return;
    }

    if (!RegExp(r'^\d{4}$').hasMatch(verifyCode)) {
      emit(state.copyWith(showSnackBar: true, snackBarMsg: '请输入正确的验证码'));
      emit(state.copyWith(showSnackBar: false));
      return;
    }

    var sharedPreferences = getIt.get<SharedPreferences>();
    var userCode = sharedPreferences.getString('auth_userCode') ?? '';
    var result = await _phoneAuthRepository.bind(userCode, phone, verifyCode);
    if (result['code'] != 0) {
      emit(state.copyWith(showSnackBar: true, snackBarMsg: result['error']));
      emit(state.copyWith(showSnackBar: false));
      return;
    }

    // 绑定成功,返回手机号码
    router.pop(phone);
  }

  @override
  Future<void> close() async {
    try {
      _phoneController.dispose();
    } catch (e) {
      print(e);
    }

    try {
      _codeController.dispose();
    } catch (e) {
      print(e);
    }

    await super.close();
  }
}