Commit 056970d81f6fc136aef89e88912071f87b2f4bc2
1 parent
725dc3f2
feat: api
Showing
30 changed files
with
762 additions
and
113 deletions
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
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
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 'login_state.dart'; | @@ -9,26 +14,35 @@ part 'login_state.dart'; | ||
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<LoginEvent, LoginState> { | @@ -40,22 +54,40 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> { | ||
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<LoginEvent, LoginState> { | @@ -65,10 +97,10 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> { | ||
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<LoginEvent, LoginState> { | @@ -79,7 +111,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> { | ||
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<LoginEvent, LoginState> { | @@ -99,7 +131,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> { | ||
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 'login_bloc.dart'; | @@ -4,18 +4,20 @@ part of 'login_bloc.dart'; | ||
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 |