Commit 056970d81f6fc136aef89e88912071f87b2f4bc2

Authored by Key
1 parent 725dc3f2

feat: api

lib/app/splash_page.dart
@@ -2,7 +2,7 @@ import 'dart:async'; @@ -2,7 +2,7 @@ import 'dart:async';
2 2
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:wow_english/common/extension/string_extension.dart'; 4 import 'package:wow_english/common/extension/string_extension.dart';
5 -import 'package:wow_english/network/basic_configuration.dart'; 5 +import 'package:wow_english/network/basic_configuration.dart.txt';
6 import 'package:wow_english/route/route.dart'; 6 import 'package:wow_english/route/route.dart';
7 7
8 8
@@ -59,4 +59,4 @@ class _TransitionViewState extends State<TransitionView> { @@ -59,4 +59,4 @@ class _TransitionViewState extends State<TransitionView> {
59 ), 59 ),
60 ); 60 );
61 } 61 }
62 -}  
63 \ No newline at end of file 62 \ No newline at end of file
  63 +}
lib/common/request/api_response/api_response_entity.dart 0 → 100644
  1 +import 'dart:convert';
  2 +
  3 +import 'api_response_entity.g.dart';
  4 +
  5 +class ApiResponse<T> {
  6 + int? code;
  7 + String? msg;
  8 + T? data;
  9 +
  10 + ApiResponse();
  11 +
  12 + factory ApiResponse.fromJson(Map<String, dynamic> json) => $ApiResponseFromJson<T>(json);
  13 +
  14 + Map<String, dynamic> toJson() => $ApiResponseToJson(this);
  15 +
  16 + @override
  17 + String toString() {
  18 + return jsonEncode(this);
  19 + }
  20 +}
lib/common/request/api_response/api_response_entity.g.dart 0 → 100644
  1 +import 'package:flutter/foundation.dart';
  2 +
  3 +import '../../../generated/json/base/json_convert_content.dart';
  4 +import 'api_response_entity.dart';
  5 +
  6 +ApiResponse<T> $ApiResponseFromJson<T>(Map<String, dynamic> json) {
  7 + final ApiResponse<T> apiResponseEntity = ApiResponse<T>();
  8 + final int? code = jsonConvert.convert<int>(json['code']);
  9 + if (code != null) {
  10 + apiResponseEntity.code = code;
  11 + }
  12 + final String? msg = jsonConvert.convert<String>(json['msg']);
  13 + if (msg != null) {
  14 + apiResponseEntity.msg = msg;
  15 + }
  16 + String type = T.toString();
  17 + T? data;
  18 + if (kDebugMode) {
  19 + print("type:$type");
  20 + }
  21 + if (json['data'] != null) {
  22 + data = jsonConvert.convert<T>(json['data']);
  23 + }
  24 + if (data != null) {
  25 + apiResponseEntity.data = data;
  26 + }
  27 + return apiResponseEntity;
  28 +}
  29 +
  30 +Map<String, dynamic> $ApiResponseToJson(ApiResponse entity) {
  31 + final Map<String, dynamic> data = <String, dynamic>{};
  32 + data['code'] = entity.code;
  33 + data['msg'] = entity.msg;
  34 + data['data'] = entity.data;
  35 + return data;
  36 +}
lib/common/request/api_response/raw_data.dart 0 → 100644
  1 +class RawData{
  2 + dynamic value;
  3 +}
0 \ No newline at end of file 4 \ No newline at end of file
lib/common/request/apis.dart 0 → 100644
  1 +class Apis {
  2 + /// app初始化配置信息
  3 + // GET /system/app/config
  4 + // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897678
  5 + static const String appConfig = 'system/app/config';
  6 +
  7 + /// 登陆
  8 + static const String login = 'login';
  9 +
  10 + /// 登出
  11 + static const String logout = 'logout';
  12 +
  13 + /// 发送验证码
  14 + static const String sendSmsCode = 'system/send/code';
  15 +
  16 + /// 课程模块
  17 + // GET /home/courseModule
  18 + // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663
  19 + static const String courseModule = 'home/courseModule';
  20 +
  21 + /// 课程列表
  22 + // GET /home/courseLesson
  23 + // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897662
  24 + static const String courseLesson = 'home/courseLesson';
  25 +}
lib/common/request/config.dart 0 → 100644
  1 +///request config
  2 +class RequestConfig {
  3 + static String baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/';
  4 + static const connectTimeout = Duration(seconds: 15);
  5 + static const successCode = 200;
  6 +}
lib/common/request/dao/user_dao.dart 0 → 100644
  1 +import '../../../models/user_entity.dart';
  2 +import '../api_response/api_response_entity.dart';
  3 +import '../apis.dart';
  4 +import '../exception.dart';
  5 +import '../request_client.dart';
  6 +
  7 +class UserDao {
  8 + static loginByPassword(
  9 + phoneNumber,
  10 + password,
  11 + Function(ApiResponse<UserEntity>)? onResponse,
  12 + bool Function(ApiException)? onError,
  13 + ) async {
  14 + /*await DioUtil().requestData(
  15 + HttpMethod.post,
  16 + Api.login,
  17 + data: {
  18 + 'phoneNum':phoneNumber,
  19 + 'type':'pwd',
  20 + 'password':password},
  21 + successCallBack: (data){
  22 + emitter(LoginResultChangeState(true));
  23 + },
  24 + errorCallBack: (error){
  25 + emitter(LoginResultChangeState(false));
  26 + });*/
  27 + var params = {'phoneNum': phoneNumber, 'type': 'pwd', 'password': password};
  28 + await requestClient.post(Apis.login, data: params, onResponse: onResponse, onError: onError);
  29 + }
  30 +
  31 + static loginBySmsCode(phoneNumber, smsCode) {}
  32 +}
lib/common/request/exception.dart 0 → 100644
  1 +import 'package:dio/dio.dart';
  2 +
  3 +import 'api_response/api_response_entity.dart';
  4 +
  5 +class ApiException implements Exception {
  6 + static const unknownException = "未知错误";
  7 + final String? message;
  8 + final int? code;
  9 + String? stackInfo;
  10 +
  11 + ApiException([this.code, this.message]);
  12 +
  13 + factory ApiException.fromDioError(DioException error) {
  14 + switch (error.type) {
  15 + case DioExceptionType.connectionTimeout:
  16 + return BadRequestException(-1, "连接超时");
  17 + case DioExceptionType.sendTimeout:
  18 + return BadRequestException(-1, "请求超时");
  19 + case DioExceptionType.receiveTimeout:
  20 + return BadRequestException(-1, "响应超时");
  21 + case DioExceptionType.badCertificate:
  22 + return BadRequestException(-1, "证书错误");
  23 + case DioExceptionType.badResponse:
  24 + return BadRequestException(-1, "返回错误");
  25 + case DioExceptionType.cancel:
  26 + return BadRequestException(-1, "请求取消");
  27 + case DioExceptionType.connectionError:
  28 + return BadRequestException(-1, "连接错误");
  29 + case DioExceptionType.unknown:
  30 + try {
  31 + /// http错误码带业务错误信息
  32 + ApiResponse apiResponse = ApiResponse.fromJson(error.response?.data);
  33 + if (apiResponse.code != null) {
  34 + return ApiException(apiResponse.code, apiResponse.msg);
  35 + }
  36 +
  37 + int? errCode = error.response?.statusCode;
  38 + switch (errCode) {
  39 + case 400:
  40 + return BadRequestException(errCode, "请求语法错误");
  41 + case 401:
  42 + return UnauthorisedException(errCode!, "没有权限");
  43 + case 403:
  44 + return UnauthorisedException(errCode!, "服务器拒绝执行");
  45 + case 404:
  46 + return UnauthorisedException(errCode!, "无法连接服务器");
  47 + case 405:
  48 + return UnauthorisedException(errCode!, "请求方法被禁止");
  49 + case 500:
  50 + return UnauthorisedException(errCode!, "服务器内部错误");
  51 + case 502:
  52 + return UnauthorisedException(errCode!, "无效的请求");
  53 + case 503:
  54 + return UnauthorisedException(errCode!, "服务器异常");
  55 + case 505:
  56 + return UnauthorisedException(errCode!, "不支持HTTP协议请求");
  57 + default:
  58 + return ApiException(errCode, error.response?.statusMessage ?? '未知错误');
  59 + }
  60 + } on Exception catch (e) {
  61 + return ApiException(-1, unknownException);
  62 + }
  63 + default:
  64 + return ApiException(-1, error.message);
  65 + }
  66 + }
  67 +
  68 + factory ApiException.from(dynamic exception) {
  69 + if (exception is DioException) {
  70 + return ApiException.fromDioError(exception);
  71 + }
  72 + if (exception is ApiException) {
  73 + return exception;
  74 + } else {
  75 + var apiException = ApiException(-1, unknownException);
  76 + apiException.stackInfo = exception?.toString();
  77 + return apiException;
  78 + }
  79 + }
  80 +}
  81 +
  82 +/// 请求错误
  83 +class BadRequestException extends ApiException {
  84 + BadRequestException([int? code, String? message]) : super(code, message);
  85 +}
  86 +
  87 +/// 未认证异常
  88 +class UnauthorisedException extends ApiException {
  89 + UnauthorisedException([int code = -1, String message = '']) : super(code, message);
  90 +}
lib/common/request/exception_handler.dart 0 → 100644
  1 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  2 +
  3 +import 'exception.dart';
  4 +
  5 +
  6 +bool handleException(ApiException exception,
  7 + {bool Function(ApiException)? onError}) {
  8 + if (onError?.call(exception) == true) {
  9 + return true;
  10 + }
  11 +
  12 + if (exception.code == 401) {
  13 + ///todo to login
  14 + return true;
  15 + }
  16 + EasyLoading.showError(exception.message ?? ApiException.unknownException);
  17 +
  18 + return false;
  19 +}
lib/common/request/request.dart 0 → 100644
  1 +import '../../utils/loading.dart';
  2 +import 'exception.dart';
  3 +import 'exception_handler.dart';
  4 +
  5 +Future request(
  6 + Function() block, {
  7 + bool showLoading = true,
  8 + bool Function(ApiException)? onError,
  9 +}) async {
  10 + try {
  11 + await loading(block, isShowLoading: showLoading);
  12 + } catch (e) {
  13 + handleException(ApiException.from(e), onError: onError);
  14 + }
  15 + return;
  16 +}
lib/common/request/request_client.dart 0 → 100644
  1 +import 'dart:convert';
  2 +
  3 +import 'package:dio/dio.dart';
  4 +import 'package:pretty_dio_logger/pretty_dio_logger.dart';
  5 +
  6 +import 'api_response/api_response_entity.dart';
  7 +import 'api_response/raw_data.dart';
  8 +import 'config.dart';
  9 +import 'exception.dart';
  10 +import 'token_interceptor.dart';
  11 +
  12 +RequestClient requestClient = RequestClient();
  13 +
  14 +class RequestClient {
  15 + late Dio _dio;
  16 +
  17 + RequestClient() {
  18 + _dio = Dio(BaseOptions(baseUrl: RequestConfig.baseUrl, connectTimeout: RequestConfig.connectTimeout));
  19 + _dio.interceptors.add(TokenInterceptor());
  20 + _dio.interceptors.add(PrettyDioLogger(requestHeader: true, requestBody: true, responseHeader: true));
  21 + }
  22 +
  23 + Future<T?> request<T>(
  24 + String url, {
  25 + required String method,
  26 + Map<String, dynamic>? queryParameters,
  27 + data,
  28 + Map<String, dynamic>? headers,
  29 + Function(ApiResponse<T>)? onResponse,
  30 + bool Function(ApiException)? onError,
  31 + }) async {
  32 + try {
  33 + Options options = Options()
  34 + ..method = method
  35 + ..headers = headers;
  36 +
  37 + data = _convertRequestData(data);
  38 +
  39 + Response response = await _dio.request(url, queryParameters: queryParameters, data: data, options: options);
  40 +
  41 + return _handleResponse<T>(response, onResponse);
  42 + } catch (e) {
  43 + var exception = ApiException.from(e);
  44 + if (onError?.call(exception) != true) {
  45 + throw exception;
  46 + }
  47 + }
  48 +
  49 + return null;
  50 + }
  51 +
  52 + _convertRequestData(data) {
  53 + if (data != null) {
  54 + data = jsonDecode(jsonEncode(data));
  55 + }
  56 + return data;
  57 + }
  58 +
  59 + /// get
  60 + Future<T?> get<T>(
  61 + String url, {
  62 + Map<String, dynamic>? queryParameters,
  63 + Map<String, dynamic>? headers,
  64 + bool showLoading = true,
  65 + Function(ApiResponse<T>)? onResponse,
  66 + bool Function(ApiException)? onError,
  67 + }) {
  68 + return request(url,
  69 + method: 'GET', queryParameters: queryParameters, headers: headers, onResponse: onResponse, onError: onError);
  70 + }
  71 +
  72 + /// post
  73 + Future<T?> post<T>(
  74 + String url, {
  75 + Map<String, dynamic>? queryParameters,
  76 + data,
  77 + Map<String, dynamic>? headers,
  78 + bool showLoading = true,
  79 + Function(ApiResponse<T>)? onResponse,
  80 + bool Function(ApiException)? onError,
  81 + }) {
  82 + return request(url,
  83 + method: "POST",
  84 + queryParameters: queryParameters,
  85 + data: data,
  86 + headers: headers,
  87 + onResponse: onResponse,
  88 + onError: onError);
  89 + }
  90 +
  91 + /// delete
  92 + Future<T?> delete<T>(
  93 + String url, {
  94 + Map<String, dynamic>? queryParameters,
  95 + data,
  96 + Map<String, dynamic>? headers,
  97 + bool showLoading = true,
  98 + Function(ApiResponse<T>)? onResponse,
  99 + bool Function(ApiException)? onError,
  100 + }) {
  101 + return request(url,
  102 + method: "DELETE",
  103 + queryParameters: queryParameters,
  104 + data: data,
  105 + headers: headers,
  106 + onResponse: onResponse,
  107 + onError: onError);
  108 + }
  109 +
  110 + /// put
  111 + Future<T?> put<T>(
  112 + String url, {
  113 + Map<String, dynamic>? queryParameters,
  114 + data,
  115 + Map<String, dynamic>? headers,
  116 + bool showLoading = true,
  117 + Function(ApiResponse<T>)? onResponse,
  118 + bool Function(ApiException)? onError,
  119 + }) {
  120 + return request(url,
  121 + method: "PUT",
  122 + queryParameters: queryParameters,
  123 + data: data,
  124 + headers: headers,
  125 + onResponse: onResponse,
  126 + onError: onError);
  127 + }
  128 +
  129 + /// 请求响应内容处理
  130 + T? _handleResponse<T>(
  131 + Response response,
  132 + Function(ApiResponse<T>)? onResponse,
  133 + ) {
  134 + int statusCode = response.statusCode ?? -1;
  135 + print('statusCode=$statusCode');
  136 + // 200..299 成功响应
  137 + if (statusCode >= 200 && statusCode <= 299) {
  138 + if (T.toString() == (RawData).toString()) {
  139 + RawData raw = RawData();
  140 + raw.value = response.data;
  141 + return raw as T;
  142 + } else {
  143 + ApiResponse<T> apiResponse = ApiResponse<T>.fromJson(response.data);
  144 + onResponse?.call(apiResponse);
  145 + return _handleBusinessResponse<T>(apiResponse);
  146 + }
  147 + } else {
  148 + var exception = ApiException(response.statusCode, ApiException.unknownException);
  149 + throw exception;
  150 + }
  151 + }
  152 +
  153 + /// 业务内容处理
  154 + T? _handleBusinessResponse<T>(ApiResponse<T> response) {
  155 + if (response.code == RequestConfig.successCode) {
  156 + return response.data;
  157 + } else {
  158 + var exception = ApiException(response.code, response.msg);
  159 + throw exception;
  160 + }
  161 + }
  162 +}
lib/common/request/token_interceptor.dart 0 → 100644
  1 +import 'package:dio/dio.dart';
  2 +
  3 +class TokenInterceptor extends Interceptor {
  4 + @override
  5 + void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
  6 + /// todo 判断token不为空插入
  7 + options.headers["Auth-token"] = '';
  8 + options.headers["version"] = '1.0.0';
  9 + super.onRequest(options, handler);
  10 + }
  11 +}
lib/generated/json/base/json_convert_content.dart 0 → 100644
  1 +// ignore_for_file: non_constant_identifier_names
  2 +// ignore_for_file: camel_case_types
  3 +// ignore_for_file: prefer_single_quotes
  4 +
  5 +// This file is automatically generated. DO NOT EDIT, all your changes would be lost.
  6 +import 'package:flutter/material.dart' show debugPrint;
  7 +import 'package:wow_english/models/user_entity.dart';
  8 +
  9 +JsonConvert jsonConvert = JsonConvert();
  10 +typedef JsonConvertFunction<T> = T Function(Map<String, dynamic> json);
  11 +typedef EnumConvertFunction<T> = T Function(String value);
  12 +
  13 +class JsonConvert {
  14 + static final Map<String, JsonConvertFunction> convertFuncMap = {
  15 + (UserEntity).toString(): UserEntity.fromJson,
  16 + };
  17 +
  18 + T? convert<T>(dynamic value, {EnumConvertFunction? enumConvert}) {
  19 + if (value == null) {
  20 + return null;
  21 + }
  22 + if (value is T) {
  23 + return value;
  24 + }
  25 + try {
  26 + return _asT<T>(value, enumConvert: enumConvert);
  27 + } catch (e, stackTrace) {
  28 + debugPrint('asT<$T> $e $stackTrace');
  29 + return null;
  30 + }
  31 + }
  32 +
  33 + List<T?>? convertList<T>(List<dynamic>? value, {EnumConvertFunction? enumConvert}) {
  34 + if (value == null) {
  35 + return null;
  36 + }
  37 + try {
  38 + return value.map((dynamic e) => _asT<T>(e,enumConvert: enumConvert)).toList();
  39 + } catch (e, stackTrace) {
  40 + debugPrint('asT<$T> $e $stackTrace');
  41 + return <T>[];
  42 + }
  43 + }
  44 +
  45 +List<T>? convertListNotNull<T>(dynamic value, {EnumConvertFunction? enumConvert}) {
  46 + if (value == null) {
  47 + return null;
  48 + }
  49 + try {
  50 + return (value as List<dynamic>).map((dynamic e) => _asT<T>(e,enumConvert: enumConvert)!).toList();
  51 + } catch (e, stackTrace) {
  52 + debugPrint('asT<$T> $e $stackTrace');
  53 + return <T>[];
  54 + }
  55 + }
  56 +
  57 + T? _asT<T extends Object?>(dynamic value,
  58 + {EnumConvertFunction? enumConvert}) {
  59 + final String type = T.toString();
  60 + final String valueS = value.toString();
  61 + if (enumConvert != null) {
  62 + return enumConvert(valueS) as T;
  63 + } else if (type == "String") {
  64 + return valueS as T;
  65 + } else if (type == "int") {
  66 + final int? intValue = int.tryParse(valueS);
  67 + if (intValue == null) {
  68 + return double.tryParse(valueS)?.toInt() as T?;
  69 + } else {
  70 + return intValue as T;
  71 + }
  72 + } else if (type == "double") {
  73 + return double.parse(valueS) as T;
  74 + } else if (type == "DateTime") {
  75 + return DateTime.parse(valueS) as T;
  76 + } else if (type == "bool") {
  77 + if (valueS == '0' || valueS == '1') {
  78 + return (valueS == '1') as T;
  79 + }
  80 + return (valueS == 'true') as T;
  81 + } else if (type == "Map" || type.startsWith("Map<")) {
  82 + return value as T;
  83 + } else {
  84 + if (convertFuncMap.containsKey(type)) {
  85 + return convertFuncMap[type]!(Map<String, dynamic>.from(value)) as T;
  86 + } else {
  87 + throw UnimplementedError('$type unimplemented');
  88 + }
  89 + }
  90 + }
  91 +
  92 + //list is returned by type
  93 + static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
  94 + if(<UserEntity>[] is M){
  95 + return data.map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e)).toList() as M;
  96 + }
  97 +
  98 + debugPrint("${M.toString()} not found");
  99 +
  100 + return null;
  101 +}
  102 +
  103 + static M? fromJsonAsT<M>(dynamic json) {
  104 + if (json is List) {
  105 + return _getListChildType<M>(json.map((e) => e as Map<String, dynamic>).toList());
  106 + } else {
  107 + return jsonConvert.convert<M>(json);
  108 + }
  109 + }
  110 +}
lib/generated/json/base/json_field.dart 0 → 100644
  1 +// ignore_for_file: non_constant_identifier_names
  2 +// ignore_for_file: camel_case_types
  3 +// ignore_for_file: prefer_single_quotes
  4 +
  5 +// This file is automatically generated. DO NOT EDIT, all your changes would be lost.
  6 +
  7 +class JsonSerializable{
  8 + const JsonSerializable();
  9 +}
  10 +
  11 +class JSONField {
  12 + //Specify the parse field name
  13 + final String? name;
  14 +
  15 + //Whether to participate in toJson
  16 + final bool? serialize;
  17 +
  18 + //Whether to participate in fromMap
  19 + final bool? deserialize;
  20 +
  21 + //Enumeration or not
  22 + final bool? isEnum;
  23 +
  24 + const JSONField({this.name, this.serialize, this.deserialize, this.isEnum});
  25 +}
lib/generated/json/user_entity.g.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_convert_content.dart';
  2 +import 'package:wow_english/models/user_entity.dart';
  3 +
  4 +UserEntity $UserEntityFromJson(Map<String, dynamic> json) {
  5 + final UserEntity userEntity = UserEntity();
  6 + final int? id = jsonConvert.convert<int>(json['id']);
  7 + if (id != null) {
  8 + userEntity.id = id;
  9 + }
  10 + final String? name = jsonConvert.convert<String>(json['name']);
  11 + if (name != null) {
  12 + userEntity.name = name;
  13 + }
  14 + final int? age = jsonConvert.convert<int>(json['age']);
  15 + if (age != null) {
  16 + userEntity.age = age;
  17 + }
  18 + final int? gender = jsonConvert.convert<int>(json['gender']);
  19 + if (gender != null) {
  20 + userEntity.gender = gender;
  21 + }
  22 + final String? avatarUrl = jsonConvert.convert<String>(json['avatarUrl']);
  23 + if (avatarUrl != null) {
  24 + userEntity.avatarUrl = avatarUrl;
  25 + }
  26 + final String? phoneNum = jsonConvert.convert<String>(json['phoneNum']);
  27 + if (phoneNum != null) {
  28 + userEntity.phoneNum = phoneNum;
  29 + }
  30 + final String? token = jsonConvert.convert<String>(json['token']);
  31 + if (token != null) {
  32 + userEntity.token = token;
  33 + }
  34 + final int? expireTime = jsonConvert.convert<int>(json['expireTime']);
  35 + if (expireTime != null) {
  36 + userEntity.expireTime = expireTime;
  37 + }
  38 + return userEntity;
  39 +}
  40 +
  41 +Map<String, dynamic> $UserEntityToJson(UserEntity entity) {
  42 + final Map<String, dynamic> data = <String, dynamic>{};
  43 + data['id'] = entity.id;
  44 + data['name'] = entity.name;
  45 + data['age'] = entity.age;
  46 + data['gender'] = entity.gender;
  47 + data['avatarUrl'] = entity.avatarUrl;
  48 + data['phoneNum'] = entity.phoneNum;
  49 + data['token'] = entity.token;
  50 + data['expireTime'] = entity.expireTime;
  51 + return data;
  52 +}
lib/home/home_page.dart
@@ -32,6 +32,8 @@ class _HomePageView extends StatelessWidget { @@ -32,6 +32,8 @@ class _HomePageView extends StatelessWidget {
32 Navigator.of(AppRouter.context).pushNamed(AppRouteName.listen); 32 Navigator.of(AppRouter.context).pushNamed(AppRouteName.listen);
33 } else if (type == HeaderActionType.shop) { 33 } else if (type == HeaderActionType.shop) {
34 Navigator.of(AppRouter.context).pushNamed(AppRouteName.shop); 34 Navigator.of(AppRouter.context).pushNamed(AppRouteName.shop);
  35 + } else if (type == HeaderActionType.user) {
  36 + Navigator.of(AppRouter.context).pushNamed(AppRouteName.user);
35 } else { 37 } else {
36 // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicPic); 38 // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicPic);
37 // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicWord); 39 // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicWord);
@@ -117,4 +119,4 @@ class _HomePageView extends StatelessWidget { @@ -117,4 +119,4 @@ class _HomePageView extends StatelessWidget {
117 ), 119 ),
118 ); 120 );
119 }); 121 });
120 -}  
121 \ No newline at end of file 122 \ No newline at end of file
  123 +}
lib/home/widgets/home_tab_header_widget.dart
@@ -12,7 +12,7 @@ enum HeaderActionType { @@ -12,7 +12,7 @@ enum HeaderActionType {
12 //购买 12 //购买
13 shop, 13 shop,
14 //个人信息 14 //个人信息
15 - userinfo 15 + user
16 } 16 }
17 17
18 class HomeTabHeaderWidget extends StatelessWidget { 18 class HomeTabHeaderWidget extends StatelessWidget {
@@ -34,7 +34,7 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -34,7 +34,7 @@ class HomeTabHeaderWidget extends StatelessWidget {
34 GestureDetector( 34 GestureDetector(
35 onTap: () { 35 onTap: () {
36 if(actionTap != null) { 36 if(actionTap != null) {
37 - actionTap!(HeaderActionType.userinfo); 37 + actionTap!(HeaderActionType.user);
38 } 38 }
39 }, 39 },
40 child: Container( 40 child: Container(
@@ -56,7 +56,7 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -56,7 +56,7 @@ class HomeTabHeaderWidget extends StatelessWidget {
56 GestureDetector( 56 GestureDetector(
57 onTap: () { 57 onTap: () {
58 if(actionTap != null) { 58 if(actionTap != null) {
59 - actionTap!(HeaderActionType.userinfo); 59 + actionTap!(HeaderActionType.user);
60 } 60 }
61 }, 61 },
62 child: Container( 62 child: Container(
@@ -128,4 +128,4 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -128,4 +128,4 @@ class HomeTabHeaderWidget extends StatelessWidget {
128 ), 128 ),
129 ); 129 );
130 } 130 }
131 -}  
132 \ No newline at end of file 131 \ No newline at end of file
  132 +}
lib/login/loginpage/bloc/login_bloc.dart
1 import 'package:flutter/cupertino.dart'; 1 import 'package:flutter/cupertino.dart';
2 import 'package:flutter_bloc/flutter_bloc.dart'; 2 import 'package:flutter_bloc/flutter_bloc.dart';
3 -import 'package:wow_english/network/api.dart';  
4 -import 'package:wow_english/network/network_manager.dart'; 3 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  4 +
  5 +import '../../../common/request/api_response/api_response_entity.dart';
  6 +import '../../../common/request/apis.dart';
  7 +import '../../../common/request/request.dart';
  8 +import '../../../common/request/request_client.dart';
  9 +import '../../../models/user_entity.dart';
5 10
6 part 'login_event.dart'; 11 part 'login_event.dart';
7 part 'login_state.dart'; 12 part 'login_state.dart';
@@ -9,26 +14,35 @@ part &#39;login_state.dart&#39;; @@ -9,26 +14,35 @@ part &#39;login_state.dart&#39;;
9 enum LoginType { 14 enum LoginType {
10 ///密码登陆 15 ///密码登陆
11 pwd, 16 pwd,
  17 +
12 ///验证码登陆 18 ///验证码登陆
13 sms, 19 sms,
14 } 20 }
15 21
16 class LoginBloc extends Bloc<LoginEvent, LoginState> { 22 class LoginBloc extends Bloc<LoginEvent, LoginState> {
17 -  
18 bool _canLogin = false; 23 bool _canLogin = false;
  24 +
19 ///是否可以发送验证码 25 ///是否可以发送验证码
20 bool _canSendSms = false; 26 bool _canSendSms = false;
  27 +
21 ///是否阅读协议 28 ///是否阅读协议
22 bool _agreement = false; 29 bool _agreement = false;
  30 +
23 ///登陆方式 31 ///登陆方式
24 - LoginType _loginType = LoginType.sms; 32 + //LoginType _loginType = LoginType.sms;
  33 + bool _isSmsLoginType = true;
25 34
26 final TextEditingController phoneNumController = TextEditingController(); 35 final TextEditingController phoneNumController = TextEditingController();
27 final TextEditingController checkNumController = TextEditingController(); 36 final TextEditingController checkNumController = TextEditingController();
28 37
29 bool get canLogin => _canLogin; 38 bool get canLogin => _canLogin;
  39 +
30 bool get agreement => _agreement; 40 bool get agreement => _agreement;
31 - LoginType get loginType => _loginType; 41 +
  42 + //LoginType get loginType => _loginType;
  43 +
  44 + bool get isSmsLoginType => _isSmsLoginType;
  45 +
32 bool get canSendSms => _canSendSms; 46 bool get canSendSms => _canSendSms;
33 47
34 LoginBloc() : super(LoginInitial()) { 48 LoginBloc() : super(LoginInitial()) {
@@ -40,22 +54,40 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; { @@ -40,22 +54,40 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
40 on<RequestSmsCodeEvent>(_requestSmsCodeApi); 54 on<RequestSmsCodeEvent>(_requestSmsCodeApi);
41 } 55 }
42 56
43 -  
44 ///请求登陆 57 ///请求登陆
45 void _requestLoginApi(RequestLoginEvent event, Emitter<LoginState> emitter) async { 58 void _requestLoginApi(RequestLoginEvent event, Emitter<LoginState> emitter) async {
46 - await DioUtil().requestData(  
47 - Api.login,  
48 - method: HttpMethod.post,  
49 - data: {  
50 - 'phoneNum':'17730280759',  
51 - 'type':_loginType.toString(),  
52 - 'password':'asd123456'},  
53 - successCallBack: (data){  
54 - emitter(LoginResultChangeState(true)); 59 + var phoneNumber = phoneNumController.text;
  60 + if (phoneNumber.isEmpty) {
  61 + EasyLoading.showToast('号码不能为空');
  62 + return;
  63 + }
  64 +
  65 + var checkNumber = checkNumController.text;
  66 + if (checkNumber.isEmpty) {
  67 + var text = _isSmsLoginType ? '密码' : '验证码';
  68 + EasyLoading.showToast('$text不能为空');
  69 + return;
  70 + }
  71 + var checkKey = _isSmsLoginType ? 'smsCode' : 'password';
  72 + var type = _isSmsLoginType ? 'sms_code' : 'pwd';
  73 +
  74 + request(() async {
  75 + var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber};
  76 + await requestClient.post(
  77 + Apis.login,
  78 + data: params,
  79 + onResponse: (ApiResponse<UserEntity> response) {
  80 + print('response=$response');
  81 + // todo 持久化用户对象
  82 + // todo 写入全局对象
  83 + //emitter.call(LoginResultChangeState());
  84 + },
  85 + onError: (e) {
  86 + EasyLoading.showToast('登陆失败:${e.message}');
  87 + return true;
55 }, 88 },
56 - errorCallBack: (error){  
57 - emitter(LoginResultChangeState(false));  
58 - }); 89 + );
  90 + });
59 } 91 }
60 92
61 ///请求验证码 93 ///请求验证码
@@ -65,10 +97,10 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; { @@ -65,10 +97,10 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
65 97
66 ///切换登陆方式 98 ///切换登陆方式
67 void _changeLoginType(ChangeLoginTypeEvent event, Emitter<LoginState> emitter) async { 99 void _changeLoginType(ChangeLoginTypeEvent event, Emitter<LoginState> emitter) async {
68 - if (_loginType == LoginType.sms) {  
69 - _loginType = LoginType.pwd; 100 + if (_isSmsLoginType) {
  101 + _isSmsLoginType = false;
70 } else { 102 } else {
71 - _loginType = LoginType.sms; 103 + _isSmsLoginType = true;
72 } 104 }
73 checkNumController.clear(); 105 checkNumController.clear();
74 if (_loginStateChange()) { 106 if (_loginStateChange()) {
@@ -79,7 +111,7 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; { @@ -79,7 +111,7 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
79 111
80 ///手机号输入 112 ///手机号输入
81 void _changePhoneNumber(PhoneNumChangeEvent event, Emitter<LoginState> emitter) async { 113 void _changePhoneNumber(PhoneNumChangeEvent event, Emitter<LoginState> emitter) async {
82 - if(phoneNumController.text.isNotEmpty) { 114 + if (phoneNumController.text.isNotEmpty) {
83 if (!_canSendSms) { 115 if (!_canSendSms) {
84 _canSendSms = true; 116 _canSendSms = true;
85 emitter(SmsSendTypeChangeState()); 117 emitter(SmsSendTypeChangeState());
@@ -99,7 +131,7 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; { @@ -99,7 +131,7 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
99 } 131 }
100 132
101 ///验证码/密码输入变化 133 ///验证码/密码输入变化
102 - void _checkFiledChange(CheckFieldChangeEvent event,Emitter<LoginState> emitter) async { 134 + void _checkFiledChange(CheckFieldChangeEvent event, Emitter<LoginState> emitter) async {
103 if (_loginStateChange()) { 135 if (_loginStateChange()) {
104 emitter(LoginEventChangeState()); 136 emitter(LoginEventChangeState());
105 } 137 }
lib/login/loginpage/bloc/login_state.dart
@@ -4,18 +4,20 @@ part of &#39;login_bloc.dart&#39;; @@ -4,18 +4,20 @@ part of &#39;login_bloc.dart&#39;;
4 abstract class LoginState {} 4 abstract class LoginState {}
5 5
6 class LoginInitial extends LoginState {} 6 class LoginInitial extends LoginState {}
  7 +
7 ///登陆按钮状态 8 ///登陆按钮状态
8 class LoginEventChangeState extends LoginState {} 9 class LoginEventChangeState extends LoginState {}
  10 +
9 ///切换登陆方式 11 ///切换登陆方式
10 class LoginTypeChangeState extends LoginState {} 12 class LoginTypeChangeState extends LoginState {}
  13 +
11 ///发送验证码按钮状态 14 ///发送验证码按钮状态
12 class SmsSendTypeChangeState extends LoginState {} 15 class SmsSendTypeChangeState extends LoginState {}
  16 +
13 ///是否同意协议 17 ///是否同意协议
14 class AgreementTypeChangeState extends LoginState {} 18 class AgreementTypeChangeState extends LoginState {}
15 ///获取验证码 19 ///获取验证码
16 class SmsCodeRequestState extends LoginState {} 20 class SmsCodeRequestState extends LoginState {}
  21 +
17 ///登陆请求结果 22 ///登陆请求结果
18 -class LoginResultChangeState extends LoginState {  
19 - bool result = false;  
20 - LoginResultChangeState(this.result);  
21 -} 23 +class LoginResultChangeState extends LoginState {}
lib/login/loginpage/login_page.dart
1 import 'package:flutter/gestures.dart'; 1 import 'package:flutter/gestures.dart';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 import 'package:flutter_bloc/flutter_bloc.dart'; 3 import 'package:flutter_bloc/flutter_bloc.dart';
4 -import 'package:flutter_easyloading/flutter_easyloading.dart';  
5 import 'package:flutter_screenutil/flutter_screenutil.dart'; 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
6 import 'package:wow_english/common/extension/string_extension.dart'; 5 import 'package:wow_english/common/extension/string_extension.dart';
7 import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; 6 import 'package:wow_english/common/widgets/textfield_customer_widget.dart';
@@ -27,7 +26,6 @@ class _LoginPageView extends StatelessWidget { @@ -27,7 +26,6 @@ class _LoginPageView extends StatelessWidget {
27 return BlocListener<LoginBloc,LoginState>( 26 return BlocListener<LoginBloc,LoginState>(
28 listener: (context, state){ 27 listener: (context, state){
29 if (state is LoginResultChangeState) { 28 if (state is LoginResultChangeState) {
30 - EasyLoading.showToast('登陆接口回调');  
31 Navigator.of(context).pushNamed(AppRouteName.home); 29 Navigator.of(context).pushNamed(AppRouteName.home);
32 } 30 }
33 }, 31 },
@@ -61,7 +59,7 @@ class _LoginPageView extends StatelessWidget { @@ -61,7 +59,7 @@ class _LoginPageView extends StatelessWidget {
61 ), 59 ),
62 padding: EdgeInsets.symmetric(horizontal: 18.w,vertical: 5.h), 60 padding: EdgeInsets.symmetric(horizontal: 18.w,vertical: 5.h),
63 child: Text( 61 child: Text(
64 - bloc.loginType == LoginType.sms?'密码登陆':'验证码密码', 62 + bloc.isSmsLoginType?'密码登陆':'验证码密码',
65 style: TextStyle( 63 style: TextStyle(
66 fontSize: 16.sp 64 fontSize: 16.sp
67 ), 65 ),
@@ -78,11 +76,11 @@ class _LoginPageView extends StatelessWidget { @@ -78,11 +76,11 @@ class _LoginPageView extends StatelessWidget {
78 width: 131.w, 76 width: 131.w,
79 ), 77 ),
80 Offstage( 78 Offstage(
81 - offstage: bloc.loginType == LoginType.pwd, 79 + offstage: !bloc.isSmsLoginType,
82 child: _buildSmsViewWidget(), 80 child: _buildSmsViewWidget(),
83 ), 81 ),
84 Offstage( 82 Offstage(
85 - offstage: bloc.loginType == LoginType.sms, 83 + offstage: bloc.isSmsLoginType,
86 child: _buildPwdViewWidget(), 84 child: _buildPwdViewWidget(),
87 ), 85 ),
88 Row( 86 Row(
@@ -313,5 +311,3 @@ class _LoginPageView extends StatelessWidget { @@ -313,5 +311,3 @@ class _LoginPageView extends StatelessWidget {
313 ); 311 );
314 }); 312 });
315 } 313 }
316 -  
317 -  
lib/models/response_model.dart renamed to lib/models/response_model.dart.txt
lib/models/response_model.g.dart renamed to lib/models/response_model.g.dart.txt
1 // GENERATED CODE - DO NOT MODIFY BY HAND 1 // GENERATED CODE - DO NOT MODIFY BY HAND
2 2
3 -part of 'response_model.dart'; 3 +part of 'response_model.dart.txt';
4 4
5 // ************************************************************************** 5 // **************************************************************************
6 // JsonSerializableGenerator 6 // JsonSerializableGenerator
lib/models/test_model.dart deleted
1 -import 'package:json_annotation/json_annotation.dart';  
2 -  
3 -part 'test_model.g.dart';  
4 -  
5 -@JsonSerializable()  
6 -class TestModel {  
7 - @JsonKey(name: 'test_name')  
8 - String? name;  
9 - @JsonKey(defaultValue: '男')  
10 - String? sex;  
11 - int? age;  
12 -  
13 - TestModel({this.name,this.sex,this.age});  
14 -  
15 - factory TestModel.fromJson(Map<String, dynamic> json) => _$TestModelFromJson(json);  
16 -  
17 - Map<String, dynamic> toJson() => _$TestModelToJson(this);  
18 -}  
19 \ No newline at end of file 0 \ No newline at end of file
lib/models/test_model.g.dart deleted
1 -// GENERATED CODE - DO NOT MODIFY BY HAND  
2 -  
3 -part of 'test_model.dart';  
4 -  
5 -// **************************************************************************  
6 -// JsonSerializableGenerator  
7 -// **************************************************************************  
8 -  
9 -TestModel _$TestModelFromJson(Map<String, dynamic> json) => TestModel(  
10 - name: json['test_name'] as String?,  
11 - sex: json['sex'] as String? ?? '男',  
12 - age: json['age'] as int?,  
13 - );  
14 -  
15 -Map<String, dynamic> _$TestModelToJson(TestModel instance) => <String, dynamic>{  
16 - 'test_name': instance.name,  
17 - 'sex': instance.sex,  
18 - 'age': instance.age,  
19 - };  
lib/models/user_entity.dart 0 → 100644
  1 +import 'dart:convert';
  2 +
  3 +import 'package:wow_english/generated/json/base/json_field.dart';
  4 +import 'package:wow_english/generated/json/user_entity.g.dart';
  5 +
  6 +@JsonSerializable()
  7 +class UserEntity {
  8 + late int id;
  9 + late String name;
  10 + late int age;
  11 + late int gender;
  12 + late String avatarUrl;
  13 + late String phoneNum;
  14 + late String token;
  15 + late int expireTime;
  16 +
  17 + UserEntity();
  18 +
  19 + factory UserEntity.fromJson(Map<String, dynamic> json) => $UserEntityFromJson(json);
  20 +
  21 + Map<String, dynamic> toJson() => $UserEntityToJson(this);
  22 +
  23 + @override
  24 + String toString() {
  25 + return jsonEncode(this);
  26 + }
  27 +}
lib/network/api.dart renamed to lib/network/api.dart.txt
lib/network/basic_configuration.dart renamed to lib/network/basic_configuration.dart.txt
1 enum DevelopEvent { 1 enum DevelopEvent {
2 ///开发环境 2 ///开发环境
3 dev, 3 dev,
  4 +
4 ///正式环境 5 ///正式环境
5 formal 6 formal
6 } 7 }
@@ -12,12 +13,13 @@ class BasicConfigurationManager { @@ -12,12 +13,13 @@ class BasicConfigurationManager {
12 13
13 //服务器地址 14 //服务器地址
14 String? baseUrl; 15 String? baseUrl;
  16 +
15 //SessionId 17 //SessionId
16 String? sessionId; 18 String? sessionId;
17 19
18 - BasicConfigurationManager._internal(){ 20 + BasicConfigurationManager._internal() {
19 DevelopEvent developType = DevelopEvent.dev; 21 DevelopEvent developType = DevelopEvent.dev;
20 - if(developType == DevelopEvent.dev) { 22 + if (developType == DevelopEvent.dev) {
21 baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/'; 23 baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/';
22 } else { 24 } else {
23 baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/'; 25 baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/';
lib/network/network_manager.dart renamed to lib/network/network_manager.dart.txt
1 -import 'dart:io';  
2 -  
3 import 'package:dio/dio.dart'; 1 import 'package:dio/dio.dart';
4 import 'package:flutter/foundation.dart'; 2 import 'package:flutter/foundation.dart';
5 -import 'package:flutter_easyloading/flutter_easyloading.dart';  
6 import 'package:wow_english/models/response_model.dart'; 3 import 'package:wow_english/models/response_model.dart';
7 -import 'package:wow_english/network/basic_configuration.dart';  
8 - 4 +import 'package:wow_english/network/basic_configuration.dart.txt';
9 5
10 enum HttpMethod { 6 enum HttpMethod {
11 get, 7 get,
@@ -27,24 +23,22 @@ class DioUtil { @@ -27,24 +23,22 @@ class DioUtil {
27 23
28 static BaseOptions getDefOptions() { 24 static BaseOptions getDefOptions() {
29 final BaseOptions options = BaseOptions(); 25 final BaseOptions options = BaseOptions();
30 - options.baseUrl = BasicConfigurationManager().baseUrl??''; 26 + options.baseUrl = BasicConfigurationManager().baseUrl ?? '';
31 options.connectTimeout = const Duration(milliseconds: 1000); 27 options.connectTimeout = const Duration(milliseconds: 1000);
32 options.receiveTimeout = const Duration(milliseconds: 1000); 28 options.receiveTimeout = const Duration(milliseconds: 1000);
33 - options.headers['content-type'] = 'application/x-www-form-urlencoded';  
34 return options; 29 return options;
35 } 30 }
36 31
37 Future<void> requestData<T>( 32 Future<void> requestData<T>(
38 - String path, {  
39 - data,  
40 - // HttpMethod method = HttpMethod.post,  
41 - Map<String, dynamic>? queryParameters,  
42 - ProgressCallback? onSendProgress,  
43 - ProgressCallback? onReceiveProgress,  
44 - required Function successCallBack,  
45 - required Function errorCallBack,  
46 - required HttpMethod method,  
47 - }) async{ 33 + HttpMethod method,
  34 + String path, {
  35 + data,
  36 + Function? successCallBack,
  37 + Function? errorCallBack,
  38 + Map<String, dynamic>? queryParameters,
  39 + ProgressCallback? onSendProgress,
  40 + ProgressCallback? onReceiveProgress,
  41 + }) async {
48 try { 42 try {
49 Map<String, dynamic> headers = <String, dynamic>{}; 43 Map<String, dynamic> headers = <String, dynamic>{};
50 44
@@ -52,32 +46,31 @@ class DioUtil { @@ -52,32 +46,31 @@ class DioUtil {
52 headers['content-type'] = 'application/json'; 46 headers['content-type'] = 'application/json';
53 } 47 }
54 Response<dynamic> response; 48 Response<dynamic> response;
55 - response = await _dio.request(  
56 - path,  
57 - data: data??{}, 49 + response = await _dio.request(path,
  50 + data: data ?? {},
58 queryParameters: queryParameters, 51 queryParameters: queryParameters,
59 - options: Options(method: method.name,headers: headers), 52 + options: Options(method: method.name, headers: headers),
60 onSendProgress: onSendProgress, 53 onSendProgress: onSendProgress,
61 onReceiveProgress: onReceiveProgress); 54 onReceiveProgress: onReceiveProgress);
62 - if (response.statusCode == HttpStatus.ok || response.statusCode == HttpStatus.created) { 55 + int statusCode = response.statusCode ?? 0;
  56 + if (statusCode >= 200 && statusCode < 300) {
63 if (kDebugMode) { 57 if (kDebugMode) {
64 print(response.data); 58 print(response.data);
65 } 59 }
66 final ResponseModel model = ResponseModel.fromJson(response.data); 60 final ResponseModel model = ResponseModel.fromJson(response.data);
67 - if (model.code != 200) {  
68 - errorCallBack(model.msg); 61 + if (model.code == 200) {
  62 + successCallBack?.call(response.data);
69 } else { 63 } else {
70 - successCallBack(response.data); 64 + errorCallBack?.call(model.msg);
71 } 65 }
72 } else { 66 } else {
73 - errorCallBack('请求失败'); 67 + errorCallBack?.call('请求失败');
74 } 68 }
75 - } on DioError catch(error) {  
76 - EasyLoading.dismiss(); 69 + } on DioException catch (error) {
77 if (kDebugMode) { 70 if (kDebugMode) {
78 print(error); 71 print(error);
79 } 72 }
80 - rethrow; 73 + errorCallBack?.call("网络错误: ${error.message}");
81 } 74 }
82 } 75 }
83 -}  
84 \ No newline at end of file 76 \ No newline at end of file
  77 +}
lib/utils/loading.dart 0 → 100644
  1 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  2 +
  3 +Future loading(Function block, {bool isShowLoading = true}) async {
  4 + if (isShowLoading) {
  5 + showLoading();
  6 + }
  7 + try {
  8 + await block();
  9 + } catch (e) {
  10 + rethrow;
  11 + } finally {
  12 + dismissLoading();
  13 + }
  14 + return;
  15 +}
  16 +
  17 +void showLoading() {
  18 + EasyLoading.show(status: "加载中...");
  19 +}
  20 +
  21 +void dismissLoading() {
  22 + EasyLoading.dismiss();
  23 +}
pubspec.yaml
@@ -37,6 +37,8 @@ dependencies: @@ -37,6 +37,8 @@ dependencies:
37 cupertino_icons: ^1.0.2 37 cupertino_icons: ^1.0.2
38 #网络请求 https://pub.dev/packages/dio 38 #网络请求 https://pub.dev/packages/dio
39 dio: ^5.1.2 39 dio: ^5.1.2
  40 + # https://pub.dev/packages/pretty_dio_logger
  41 + pretty_dio_logger: ^1.3.1
40 #谷歌字体 https://pub.dev/packages/google_fonts 42 #谷歌字体 https://pub.dev/packages/google_fonts
41 google_fonts: ^4.0.4 43 google_fonts: ^4.0.4
42 #状态管理 https://pub.dev/packages/flutter_bloc 44 #状态管理 https://pub.dev/packages/flutter_bloc
@@ -64,9 +66,9 @@ dependencies: @@ -64,9 +66,9 @@ dependencies:
64 # 拍照,从相册中选择 https://pub.flutter-io.cn/packages/image_picker 66 # 拍照,从相册中选择 https://pub.flutter-io.cn/packages/image_picker
65 image_picker: ^0.8.7+5 67 image_picker: ^0.8.7+5
66 # 支付宝支付SDK https://pub.flutter-io.cn/packages/tobias 68 # 支付宝支付SDK https://pub.flutter-io.cn/packages/tobias
67 -# tobias: ^3.1.0 69 + # tobias: ^3.1.0
68 # 微信SDK相关 https://pub.flutter-io.cn/packages/fluwx 70 # 微信SDK相关 https://pub.flutter-io.cn/packages/fluwx
69 -# fluwx: ^4.2.4+1 71 + # fluwx: ^4.2.4+1
70 # json数据解析 https://pub.flutter-io.cn/packages/json_annotation 72 # json数据解析 https://pub.flutter-io.cn/packages/json_annotation
71 json_annotation: ^4.8.1 73 json_annotation: ^4.8.1
72 # double丢失精度问题 https://pub.dev/packages/decimal 74 # double丢失精度问题 https://pub.dev/packages/decimal