account_cubit.dart 7.77 KB
import 'dart:io';

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

class AccountState extends Equatable {
  final bool loaded;
  final String name;
  final String phone;
  final String nickname;
  final String imgIcon;

  final String appleId;

  // 孩子信息
  final String className;
  final String stuName;

  // 是否绑定孩子
  final bool bindStu;

  const AccountState({
    this.loaded = false,
    this.name = '',
    this.phone = '',
    this.nickname = '',
    this.imgIcon = '',
    this.appleId = '',
    this.className = '',
    this.stuName = '',
    this.bindStu = true,
  });

  AccountState copyWith({
    bool? loaded,
    String? name,
    String? phone,
    String? nickname,
    String? imgIcon,
    String? appleId,
    String? className,
    String? stuName,
    bool? bindStu,
  }) {
    return AccountState(
      loaded: loaded ?? this.loaded,
      name: name ?? this.name,
      phone: phone ?? this.phone,
      nickname: nickname ?? this.nickname,
      imgIcon: imgIcon ?? this.imgIcon,
      appleId: appleId ?? this.appleId,
      className: className ?? this.className,
      stuName: stuName ?? this.stuName,
      bindStu: bindStu ?? this.bindStu,
    );
  }

  @override
  List<Object?> get props => [
        loaded,
        name,
        phone,
        nickname,
        imgIcon,
        appleId,
        className,
        stuName,
        bindStu,
      ];
}

class AccountCubit extends Cubit<AccountState> {
  late final PhoneAuthRepository _phoneAuthRepository;
  late final UserAuthRepository _userAuthRepository;

  AccountCubit(super.initialState) {
    _phoneAuthRepository = getIt.get<PhoneAuthRepository>();
    _userAuthRepository = getIt.get<UserAuthRepository>();
    init();
  }

  Future<void> init() async {
    var sharedPreferences = getIt.get<SharedPreferences>();
    var userCode = sharedPreferences.getString('auth_userCode') ?? '';
    var className = sharedPreferences.getString('auth_className') ?? '';
    var stuName = sharedPreferences.getString('auth_stuName') ?? '';
    try {
      var result = await _phoneAuthRepository.bindCheck(userCode);
      if (result != null) {
        var code = result['code'];
        var data = result['data'];
        if (code != 0) {
          emit(state.copyWith(loaded: true, bindStu: false));
          return;
        }

        emit(
          state.copyWith(
            loaded: true,
            name: data['name'],
            phone: data['phone'],
            nickname: data['nickname'],
            imgIcon: data['imgIcon'],
            className: className,
            stuName: stuName,
          ),
        );
      }

      var result2 = await _userAuthRepository.binded(userCode);
      if (result2 != null) {
        var code2 = result2['code'];
        var data2 = result2['data'];
        if (code2 == 0 && data2 != null) {
          emit(state.copyWith(appleId: data2['appleId']));
        }
      }
    } catch (e) {
      debugPrint('init error: $e');
    }
  }

  Future<void> goSetUserInfo() async {
    dynamic result = await router.push(
      '/account/user',
      extra: {
        'name': state.name,
        'nickname': state.nickname,
        'avatar': state.imgIcon,
      },
    );

    if (result != null && result.isNotEmpty) {
      Map<String, dynamic> resultMap = Map<String, dynamic>.from(result);
      emit(state.copyWith(imgIcon: resultMap['avatar'], name: resultMap['name'], nickname: resultMap['nickname']));
    }
  }

  Future<void> goBind() async {
    dynamic result = await router.push(
      '/account/phone',
      extra: {
        'phone': state.phone,
      },
    );
    if (result != null) {
      emit(state.copyWith(phone: result['phone']));
    }
    // if (result != null && result.isNotEmpty) {
    //   emit(state.copyWith(phone: result));
    // }
  }

  Future<void> goLogoff() async {
    await router.push(
      '/account/logoff',
      extra: {
        'phone': state.phone,
      },
    );
  }

  Future<void> goApple() async {
    dynamic result = await router.push(
      '/account/apple',
      extra: {
        'appleId': state.appleId,
      },
    );
    if (result != null) {
      emit(state.copyWith(appleId: result['appleId']));
    }
  }

  ///
  /// 绑定Apple ID
  ///
  void appleBind() async {
    // 仅iOS平台支持Apple登录
    if (!Platform.isIOS) {
      Fluttertoast.showToast(msg: '当前平台不支持Apple账号绑定', gravity: ToastGravity.TOP);
      return;
    }

    // 已绑定Apple ID,不允许重复绑定
    if (state.appleId.isNotEmpty) {
      Fluttertoast.showToast(msg: '已绑定Apple账号', gravity: ToastGravity.TOP);
      return;
    }

    try {
      // 1. 获取Apple授权凭证
      AuthorizationCredentialAppleID credential = await SignInWithApple.getAppleIDCredential(
        scopes: [
          AppleIDAuthorizationScopes.email,
          AppleIDAuthorizationScopes.fullName,
        ],
      );

      debugPrint('Apple绑定 - 用户唯一标识: ${credential.userIdentifier}');
      debugPrint('Apple绑定 - 授权码: ${credential.authorizationCode}');
      debugPrint('Apple绑定 - 身份令牌: ${credential.identityToken}');

      if (credential.userIdentifier == null) {
        Fluttertoast.showToast(msg: '授权失败', gravity: ToastGravity.TOP, backgroundColor: Colors.red);
        return;
      }

      // 2. 获取当前用户信息
      var sharedPreferences = getIt.get<SharedPreferences>();
      var currentUserCode = sharedPreferences.getString('auth_userCode') ?? '';
      if (currentUserCode.isEmpty) {
        Fluttertoast.showToast(msg: '用户信息获取失败,请重新登录', gravity: ToastGravity.TOP, backgroundColor: Colors.red);
        return;
      }

      // 3. 调用绑定接口
      var bindResult = await _userAuthRepository.newBinding(
        credential.userIdentifier!,
        currentUserCode,
        'apple',
      ) as Map<String, dynamic>?;

      if (bindResult != null && bindResult['code'] == 0) {
        Fluttertoast.showToast(msg: 'Apple账号绑定成功', gravity: ToastGravity.TOP);
        emit(state.copyWith(appleId: credential.userIdentifier!));
      } else {
        var errorMsg = bindResult?['error'] ?? 'Apple账号绑定失败';
        Fluttertoast.showToast(msg: errorMsg, gravity: ToastGravity.TOP, backgroundColor: Colors.red);
      }
    } catch (e) {
      debugPrint('appleBind error: $e');
      // 用户取消授权时不提示错误
      if (e is SignInWithAppleAuthorizationException && e.code == AuthorizationErrorCode.canceled) {
        return;
      }
      Fluttertoast.showToast(msg: 'Apple账号绑定异常', gravity: ToastGravity.TOP, backgroundColor: Colors.red);
    }
  }

  Future<void> unbind() async {
    // var sharedPreferences = getIt.get<SharedPreferences>();
    // var userCode = sharedPreferences.getString('auth_userCode') ?? '';
    // _phoneAuthRepository.unbind(userCode);

    // 当前只会成功,不会失败
    // 解绑成功,跳转登录界面
    // router.go('/loginMain');

    // emit(state.copyWith(showSnackBar: true, snackBarMsg: '操作成功'));
    // emit(state.copyWith(showSnackBar: false));

    // await Future.delayed(Duration(seconds: 1));

    var sharedPreferences = getIt.get<SharedPreferences>();
    sharedPreferences.getKeys().forEach((key) {
      if (key.startsWith('auth_')) {
        sharedPreferences.remove(key);
      }
    });
    router.go('/loginMain');
  }
}