Commit c95453ce5bcaf94dde4967788c29dec4fa8e2264
1 parent
6f617434
feat: User界面完善
Showing
18 changed files
with
300 additions
and
271 deletions
android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt
1 | package com.kouyuxingqiu.wow_english | 1 | package com.kouyuxingqiu.wow_english |
2 | 2 | ||
3 | +import android.graphics.Color | ||
4 | +import android.os.Build | ||
5 | +import android.os.Bundle | ||
6 | +import android.util.Log | ||
7 | +import android.view.View | ||
8 | +import androidx.core.view.WindowCompat | ||
9 | +import androidx.core.view.WindowInsetsCompat | ||
10 | +import androidx.core.view.WindowInsetsControllerCompat | ||
3 | import io.flutter.embedding.android.FlutterActivity | 11 | import io.flutter.embedding.android.FlutterActivity |
4 | 12 | ||
5 | class MainActivity : FlutterActivity() { | 13 | class MainActivity : FlutterActivity() { |
6 | - // 测试有效 | ||
7 | - /*override fun onCreate(savedInstanceState: Bundle?) { | 14 | + override fun onCreate(savedInstanceState: Bundle?) { |
8 | super.onCreate(savedInstanceState) | 15 | super.onCreate(savedInstanceState) |
9 | - Toast.makeText(this, "onCreate", Toast.LENGTH_SHORT).show() | ||
10 | - }*/ | 16 | + Log.i("WowEnglish", "MainActivity onCreate") |
17 | + } | ||
18 | + | ||
19 | + override fun onResume() { | ||
20 | + super.onResume() | ||
21 | + //setFullScreen() | ||
22 | + } | ||
23 | + | ||
24 | + private fun setFullScreen() { | ||
25 | + WindowInsetsControllerCompat(window, window.decorView).let { | ||
26 | + it.hide(WindowInsetsCompat.Type.statusBars()) | ||
27 | + it.hide(WindowInsetsCompat.Type.navigationBars()) | ||
28 | + it.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE | ||
29 | + } | ||
30 | + // 导航栏横线的颜色 | ||
31 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { | ||
32 | + window.navigationBarDividerColor = Color.TRANSPARENT | ||
33 | + } | ||
34 | + | ||
35 | + /*window.statusBarColor = Color.TRANSPARENT | ||
36 | + val controller = WindowInsetsControllerCompat(window, window.decorView) | ||
37 | + // 黑色状态栏字体 | ||
38 | + controller.isAppearanceLightStatusBars = false | ||
39 | + // 状态栏隐藏 | ||
40 | + controller.hide(WindowInsetsCompat.Type.statusBars()) | ||
41 | + // 导航栏隐藏 | ||
42 | + controller.hide(WindowInsetsCompat.Type.navigationBars()) | ||
43 | + //window.navigationBarColor = Color.TRANSPARENT | ||
44 | + // 打开沉浸式 | ||
45 | + WindowCompat.setDecorFitsSystemWindows(window, false)*/ | ||
46 | + } | ||
11 | } | 47 | } |
lib/common/core/assets_const.dart
1 | class AssetsConst { | 1 | class AssetsConst { |
2 | - static const String _assetImagePrefix = "assets/images/"; | ||
3 | - static const String wowLogo = "wow_logo.png"; | ||
4 | - static const String icVip = "ic_vip.png"; | 2 | + static const String _assetImagePrefix = 'assets/images/'; |
3 | + static const String wowLogo = '${_assetImagePrefix}wow_logo.png'; | ||
4 | + static const String icVip = '${_assetImagePrefix}ic_vip.png'; | ||
5 | +//static String get icVip2 =>'ic_vip.png'.assetImg; | ||
5 | } | 6 | } |
lib/common/pages/wow_web_page.dart
1 | -import 'dart:io'; | ||
2 | - | ||
3 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
4 | -import 'package:flutter/services.dart'; | ||
5 | import 'package:flutter_easyloading/flutter_easyloading.dart'; | 2 | import 'package:flutter_easyloading/flutter_easyloading.dart'; |
6 | -import 'package:limiting_direction_csx/limiting_direction_csx.dart'; | ||
7 | import 'package:webview_flutter/webview_flutter.dart'; | 3 | import 'package:webview_flutter/webview_flutter.dart'; |
8 | import 'package:wow_english/common/widgets/we_app_bar.dart'; | 4 | import 'package:wow_english/common/widgets/we_app_bar.dart'; |
9 | 5 | ||
@@ -26,12 +22,11 @@ class _WowWebViewPageState extends State<WowWebViewPage> { | @@ -26,12 +22,11 @@ class _WowWebViewPageState extends State<WowWebViewPage> { | ||
26 | @override | 22 | @override |
27 | void initState() { | 23 | void initState() { |
28 | super.initState(); | 24 | super.initState(); |
29 | - | ||
30 | - if (Platform.isIOS) { | 25 | + /*if (Platform.isIOS) { |
31 | LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.PortraitUpsideDown); | 26 | LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.PortraitUpsideDown); |
32 | } else { | 27 | } else { |
33 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); | 28 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); |
34 | - } | 29 | + }*/ |
35 | 30 | ||
36 | final WebViewController controller =WebViewController() | 31 | final WebViewController controller =WebViewController() |
37 | ..setJavaScriptMode(JavaScriptMode.unrestricted) | 32 | ..setJavaScriptMode(JavaScriptMode.unrestricted) |
@@ -69,14 +64,4 @@ class _WowWebViewPageState extends State<WowWebViewPage> { | @@ -69,14 +64,4 @@ class _WowWebViewPageState extends State<WowWebViewPage> { | ||
69 | body: WebViewWidget(controller: _controller,), | 64 | body: WebViewWidget(controller: _controller,), |
70 | ); | 65 | ); |
71 | } | 66 | } |
72 | - | ||
73 | - @override | ||
74 | - void deactivate() { | ||
75 | - super.deactivate(); | ||
76 | - if (Platform.isIOS) { | ||
77 | - LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.Landscape); | ||
78 | - } else { | ||
79 | - SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight]); | ||
80 | - } | ||
81 | - } | ||
82 | -} | ||
83 | \ No newline at end of file | 67 | \ No newline at end of file |
68 | +} |
lib/common/request/apis.dart
@@ -10,6 +10,12 @@ class Apis { | @@ -10,6 +10,12 @@ class Apis { | ||
10 | /// 登出 | 10 | /// 登出 |
11 | static const String logout = 'logout'; | 11 | static const String logout = 'logout'; |
12 | 12 | ||
13 | + /// 获取用户信息 | ||
14 | + static const String getUserInfo = 'student/info'; | ||
15 | + | ||
16 | + /// 更新用户信息 | ||
17 | + static const String setUserInfo = 'student/update/info'; | ||
18 | + | ||
13 | /// 发送验证码 | 19 | /// 发送验证码 |
14 | static const String sendSmsCode = 'system/send/code'; | 20 | static const String sendSmsCode = 'system/send/code'; |
15 | 21 |
lib/common/request/dao/user_dao.dart
@@ -5,6 +5,7 @@ import '../apis.dart'; | @@ -5,6 +5,7 @@ import '../apis.dart'; | ||
5 | import '../request_client.dart'; | 5 | import '../request_client.dart'; |
6 | 6 | ||
7 | class UserDao { | 7 | class UserDao { |
8 | + /// 登录 | ||
8 | static Future<UserEntity?> login(phoneNumber, type, checkKey, checkNumber) async { | 9 | static Future<UserEntity?> login(phoneNumber, type, checkKey, checkNumber) async { |
9 | var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber}; | 10 | var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber}; |
10 | var data = await requestClient.post<UserEntity>( | 11 | var data = await requestClient.post<UserEntity>( |
@@ -17,10 +18,27 @@ class UserDao { | @@ -17,10 +18,27 @@ class UserDao { | ||
17 | return data; | 18 | return data; |
18 | } | 19 | } |
19 | 20 | ||
20 | - static Future sendCode(phoneNumber,{smsType ='login'}) async { | ||
21 | - final params = {'phoneNum':phoneNumber,'smsType':smsType}; | ||
22 | - await requestClient.post( | ||
23 | - Apis.sendSmsCode,data: params | ||
24 | - ); | 21 | + /// 登出 |
22 | + static Future logout() async { | ||
23 | + var result = await requestClient.post(Apis.logout); | ||
24 | + print('logout result=$result'); | ||
25 | + UserUtil.logout(); | ||
26 | + return result; | ||
27 | + } | ||
28 | + | ||
29 | + /// 发送验证码 | ||
30 | + static Future sendCode(phoneNumber, {smsType = 'login'}) async { | ||
31 | + final params = {'phoneNum': phoneNumber, 'smsType': smsType}; | ||
32 | + await requestClient.post(Apis.sendSmsCode, data: params); | ||
33 | + } | ||
34 | + | ||
35 | + /// 获取用户信息 | ||
36 | + static Future<UserEntity?> getUserInfo() async { | ||
37 | + return await requestClient.post(Apis.getUserInfo); | ||
38 | + } | ||
39 | + | ||
40 | + /// 更新用户信息,返回即成功,无body | ||
41 | + static Future updateUserInfo(UserEntity userEntity) async { | ||
42 | + return await requestClient.put(Apis.setUserInfo, data: userEntity.toUpdateJson()); | ||
25 | } | 43 | } |
26 | } | 44 | } |
lib/common/widgets/ow_image_widget.dart
@@ -16,7 +16,7 @@ class OwImageWidget extends StatelessWidget { | @@ -16,7 +16,7 @@ class OwImageWidget extends StatelessWidget { | ||
16 | width: width, | 16 | width: width, |
17 | ); | 17 | ); |
18 | } | 18 | } |
19 | - return name.contains('http')? | 19 | + return name.startsWith('http')? |
20 | CachedNetworkImage( | 20 | CachedNetworkImage( |
21 | imageUrl: name, | 21 | imageUrl: name, |
22 | height: height, | 22 | height: height, |
@@ -29,4 +29,4 @@ class OwImageWidget extends StatelessWidget { | @@ -29,4 +29,4 @@ class OwImageWidget extends StatelessWidget { | ||
29 | fit: fit, | 29 | fit: fit, |
30 | ); | 30 | ); |
31 | } | 31 | } |
32 | -} | ||
33 | \ No newline at end of file | 32 | \ No newline at end of file |
33 | +} |
lib/generated/json/user_entity.g.dart
@@ -11,6 +11,10 @@ UserEntity $UserEntityFromJson(Map<String, dynamic> json) { | @@ -11,6 +11,10 @@ UserEntity $UserEntityFromJson(Map<String, dynamic> json) { | ||
11 | if (name != null) { | 11 | if (name != null) { |
12 | userEntity.name = name; | 12 | userEntity.name = name; |
13 | } | 13 | } |
14 | + final String? token = jsonConvert.convert<String>(json['token']); | ||
15 | + if (token != null) { | ||
16 | + userEntity.token = token; | ||
17 | + } | ||
14 | final int? age = jsonConvert.convert<int>(json['age']); | 18 | final int? age = jsonConvert.convert<int>(json['age']); |
15 | if (age != null) { | 19 | if (age != null) { |
16 | userEntity.age = age; | 20 | userEntity.age = age; |
@@ -27,13 +31,17 @@ UserEntity $UserEntityFromJson(Map<String, dynamic> json) { | @@ -27,13 +31,17 @@ UserEntity $UserEntityFromJson(Map<String, dynamic> json) { | ||
27 | if (phoneNum != null) { | 31 | if (phoneNum != null) { |
28 | userEntity.phoneNum = phoneNum; | 32 | userEntity.phoneNum = phoneNum; |
29 | } | 33 | } |
30 | - final String? token = jsonConvert.convert<String>(json['token']); | ||
31 | - if (token != null) { | ||
32 | - userEntity.token = token; | 34 | + final int? fillUserInfo = jsonConvert.convert<int>(json['fillUserInfo']); |
35 | + if (fillUserInfo != null) { | ||
36 | + userEntity.fillUserInfo = fillUserInfo; | ||
37 | + } | ||
38 | + final int? nowCourseModuleId = jsonConvert.convert<int>(json['nowCourseModuleId']); | ||
39 | + if (nowCourseModuleId != null) { | ||
40 | + userEntity.nowCourseModuleId = nowCourseModuleId; | ||
33 | } | 41 | } |
34 | - final int? expireTime = jsonConvert.convert<int>(json['expireTime']); | ||
35 | - if (expireTime != null) { | ||
36 | - userEntity.expireTime = expireTime; | 42 | + final String? effectiveDate = jsonConvert.convert<String>(json['effectiveDate']); |
43 | + if (effectiveDate != null) { | ||
44 | + userEntity.effectiveDate = effectiveDate; | ||
37 | } | 45 | } |
38 | return userEntity; | 46 | return userEntity; |
39 | } | 47 | } |
@@ -42,11 +50,13 @@ Map<String, dynamic> $UserEntityToJson(UserEntity entity) { | @@ -42,11 +50,13 @@ Map<String, dynamic> $UserEntityToJson(UserEntity entity) { | ||
42 | final Map<String, dynamic> data = <String, dynamic>{}; | 50 | final Map<String, dynamic> data = <String, dynamic>{}; |
43 | data['id'] = entity.id; | 51 | data['id'] = entity.id; |
44 | data['name'] = entity.name; | 52 | data['name'] = entity.name; |
53 | + data['token'] = entity.token; | ||
45 | data['age'] = entity.age; | 54 | data['age'] = entity.age; |
46 | data['gender'] = entity.gender; | 55 | data['gender'] = entity.gender; |
47 | data['avatarUrl'] = entity.avatarUrl; | 56 | data['avatarUrl'] = entity.avatarUrl; |
48 | data['phoneNum'] = entity.phoneNum; | 57 | data['phoneNum'] = entity.phoneNum; |
49 | - data['token'] = entity.token; | ||
50 | - data['expireTime'] = entity.expireTime; | 58 | + data['fillUserInfo'] = entity.fillUserInfo; |
59 | + data['nowCourseModuleId'] = entity.nowCourseModuleId; | ||
60 | + data['effectiveDate'] = entity.effectiveDate; | ||
51 | return data; | 61 | return data; |
52 | -} | ||
53 | \ No newline at end of file | 62 | \ No newline at end of file |
63 | +} |
lib/models/response_model.dart.txt deleted
1 | -import 'package:json_annotation/json_annotation.dart'; | ||
2 | - | ||
3 | -part 'response_model.g.dart'; | ||
4 | - | ||
5 | -@JsonSerializable() | ||
6 | -class ResponseModel { | ||
7 | - int? code; | ||
8 | - dynamic data; | ||
9 | - String? msg; | ||
10 | - | ||
11 | - ResponseModel(this.code,this.data,this.msg); | ||
12 | - | ||
13 | - factory ResponseModel.fromJson(Map<String, dynamic> json) => _$ResponseModelFromJson(json); | ||
14 | - | ||
15 | - Map<String, dynamic> toJson() => _$ResponseModelToJson(this); | ||
16 | -} |
lib/models/response_model.g.dart.txt deleted
1 | -// GENERATED CODE - DO NOT MODIFY BY HAND | ||
2 | - | ||
3 | -part of 'response_model.dart.txt'; | ||
4 | - | ||
5 | -// ************************************************************************** | ||
6 | -// JsonSerializableGenerator | ||
7 | -// ************************************************************************** | ||
8 | - | ||
9 | -ResponseModel _$ResponseModelFromJson(Map<String, dynamic> json) => | ||
10 | - ResponseModel( | ||
11 | - json['code'] as int?, | ||
12 | - json['data'], | ||
13 | - json['msg'] as String?, | ||
14 | - ); | ||
15 | - | ||
16 | -Map<String, dynamic> _$ResponseModelToJson(ResponseModel instance) => | ||
17 | - <String, dynamic>{ | ||
18 | - 'code': instance.code, | ||
19 | - 'data': instance.data, | ||
20 | - 'msg': instance.msg, | ||
21 | - }; |
lib/models/user_entity.dart
@@ -7,14 +7,27 @@ import 'package:wow_english/generated/json/user_entity.g.dart'; | @@ -7,14 +7,27 @@ import 'package:wow_english/generated/json/user_entity.g.dart'; | ||
7 | class UserEntity { | 7 | class UserEntity { |
8 | late int id; | 8 | late int id; |
9 | late String name; | 9 | late String name; |
10 | + | ||
11 | + /// 一定有也必须要有 | ||
12 | + late String token; | ||
13 | + | ||
14 | + //late int expireTime; | ||
15 | + | ||
10 | int? age; | 16 | int? age; |
11 | 17 | ||
12 | /// 性别:0, 1 | 18 | /// 性别:0, 1 |
13 | int? gender; | 19 | int? gender; |
14 | String? avatarUrl; | 20 | String? avatarUrl; |
15 | - late String phoneNum; | ||
16 | - late String token; | ||
17 | - late int expireTime; | 21 | + String? phoneNum; |
22 | + | ||
23 | + /// 用户信息是否填写 0.未填写 1.已经填写 | ||
24 | + int? fillUserInfo; | ||
25 | + | ||
26 | + /// 当前模块Id | ||
27 | + int? nowCourseModuleId; | ||
28 | + | ||
29 | + /// 有效时间,VIP,为null没有 | ||
30 | + String? effectiveDate; | ||
18 | 31 | ||
19 | UserEntity(); | 32 | UserEntity(); |
20 | 33 | ||
@@ -26,4 +39,21 @@ class UserEntity { | @@ -26,4 +39,21 @@ class UserEntity { | ||
26 | String toString() { | 39 | String toString() { |
27 | return jsonEncode(this); | 40 | return jsonEncode(this); |
28 | } | 41 | } |
42 | + | ||
43 | + Map<String, dynamic> toUpdateJson() { | ||
44 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
45 | + data['name'] = name; | ||
46 | + data['age'] = age; | ||
47 | + data['gender'] = gender; | ||
48 | + data['avatarUrl'] = avatarUrl; | ||
49 | + return data; | ||
50 | + } | ||
51 | + | ||
52 | + String getGenderString() { | ||
53 | + return gender == null | ||
54 | + ? '' | ||
55 | + : gender == 0 | ||
56 | + ? '男' | ||
57 | + : '女'; | ||
58 | + } | ||
29 | } | 59 | } |
lib/network/api.dart.txt deleted
1 | -class Api { | ||
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/network/basic_configuration.dart.txt deleted
1 | -enum DevelopEvent { | ||
2 | - ///开发环境 | ||
3 | - dev, | ||
4 | - | ||
5 | - ///正式环境 | ||
6 | - formal | ||
7 | -} | ||
8 | - | ||
9 | -class BasicConfigurationManager { | ||
10 | - factory BasicConfigurationManager() => _getInstance(); | ||
11 | - | ||
12 | - static BasicConfigurationManager? _instance; | ||
13 | - | ||
14 | - //服务器地址 | ||
15 | - String? baseUrl; | ||
16 | - | ||
17 | - //SessionId | ||
18 | - String? sessionId; | ||
19 | - | ||
20 | - BasicConfigurationManager._internal() { | ||
21 | - DevelopEvent developType = DevelopEvent.dev; | ||
22 | - if (developType == DevelopEvent.dev) { | ||
23 | - baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/'; | ||
24 | - } else { | ||
25 | - baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/'; | ||
26 | - } | ||
27 | - sessionId = ''; | ||
28 | - } | ||
29 | - | ||
30 | - static BasicConfigurationManager _getInstance() { | ||
31 | - _instance ??= BasicConfigurationManager._internal(); | ||
32 | - return _instance!; | ||
33 | - } | ||
34 | -} |
lib/network/network_manager.dart.txt deleted
1 | -import 'package:dio/dio.dart'; | ||
2 | -import 'package:flutter/foundation.dart'; | ||
3 | -import 'package:wow_english/models/response_model.dart'; | ||
4 | -import 'package:wow_english/network/basic_configuration.dart.txt'; | ||
5 | - | ||
6 | -enum HttpMethod { | ||
7 | - get, | ||
8 | - put, | ||
9 | - post, | ||
10 | - head, | ||
11 | - patch, | ||
12 | - delete, | ||
13 | -} | ||
14 | - | ||
15 | -class DioUtil { | ||
16 | - static final Dio _dio = getDefDio(); | ||
17 | - | ||
18 | - static Dio getDefDio() { | ||
19 | - Dio dio = Dio(); | ||
20 | - dio.options = getDefOptions(); | ||
21 | - return dio; | ||
22 | - } | ||
23 | - | ||
24 | - static BaseOptions getDefOptions() { | ||
25 | - final BaseOptions options = BaseOptions(); | ||
26 | - options.baseUrl = BasicConfigurationManager().baseUrl ?? ''; | ||
27 | - options.connectTimeout = const Duration(milliseconds: 1000); | ||
28 | - options.receiveTimeout = const Duration(milliseconds: 1000); | ||
29 | - return options; | ||
30 | - } | ||
31 | - | ||
32 | - Future<void> requestData<T>( | ||
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 { | ||
42 | - try { | ||
43 | - Map<String, dynamic> headers = <String, dynamic>{}; | ||
44 | - | ||
45 | - if (method == HttpMethod.post) { | ||
46 | - headers['content-type'] = 'application/json'; | ||
47 | - } | ||
48 | - Response<dynamic> response; | ||
49 | - response = await _dio.request(path, | ||
50 | - data: data ?? {}, | ||
51 | - queryParameters: queryParameters, | ||
52 | - options: Options(method: method.name, headers: headers), | ||
53 | - onSendProgress: onSendProgress, | ||
54 | - onReceiveProgress: onReceiveProgress); | ||
55 | - int statusCode = response.statusCode ?? 0; | ||
56 | - if (statusCode >= 200 && statusCode < 300) { | ||
57 | - if (kDebugMode) { | ||
58 | - print(response.data); | ||
59 | - } | ||
60 | - final ResponseModel model = ResponseModel.fromJson(response.data); | ||
61 | - if (model.code == 200) { | ||
62 | - successCallBack?.call(response.data); | ||
63 | - } else { | ||
64 | - errorCallBack?.call(model.msg); | ||
65 | - } | ||
66 | - } else { | ||
67 | - errorCallBack?.call('请求失败'); | ||
68 | - } | ||
69 | - } on DioException catch (error) { | ||
70 | - if (kDebugMode) { | ||
71 | - print(error); | ||
72 | - } | ||
73 | - errorCallBack?.call("网络错误: ${error.message}"); | ||
74 | - } | ||
75 | - } | ||
76 | -} |
lib/pages/login/loginpage/login_page.dart
@@ -104,7 +104,7 @@ class _LoginPageView extends StatelessWidget { | @@ -104,7 +104,7 @@ class _LoginPageView extends StatelessWidget { | ||
104 | recognizer: TapGestureRecognizer() | 104 | recognizer: TapGestureRecognizer() |
105 | ..onTap = () { | 105 | ..onTap = () { |
106 | Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | 106 | Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { |
107 | - 'urlStr': 'https://www.zhihu.com', | 107 | + 'urlStr': 'http://page.kouyuxingqiu.com/%E7%94%A8%E6%88%B7%E6%B3%A8%E5%86%8C%E5%8F%8A%E4%BD%BF%E7%94%A8APP%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE.html', |
108 | 'webViewTitle': '用户隐私协议' | 108 | 'webViewTitle': '用户隐私协议' |
109 | }); | 109 | }); |
110 | }), | 110 | }), |
@@ -116,7 +116,7 @@ class _LoginPageView extends StatelessWidget { | @@ -116,7 +116,7 @@ class _LoginPageView extends StatelessWidget { | ||
116 | recognizer: TapGestureRecognizer() | 116 | recognizer: TapGestureRecognizer() |
117 | ..onTap = () { | 117 | ..onTap = () { |
118 | Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | 118 | Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { |
119 | - 'urlStr': 'https://www.zhihu.com', | 119 | + 'urlStr': 'https://ishowedu-public-images.ishowedu.com/%E5%8F%A3%E8%AF%AD%E6%98%9F%E7%90%83%E5%84%BF%E7%AB%A5%E9%9A%90%E7%A7%81%E4%BF%9D%E6%8A%A4%E6%94%BF%E7%AD%96_iShowLD%E4%BF%AE%E8%AE%A2_20210913%281%29.html', |
120 | 'webViewTitle': '儿童隐私协议' | 120 | 'webViewTitle': '儿童隐私协议' |
121 | }); | 121 | }); |
122 | }) | 122 | }) |
lib/pages/user/bloc/user_bloc.dart
1 | import 'package:bloc/bloc.dart'; | 1 | import 'package:bloc/bloc.dart'; |
2 | import 'package:meta/meta.dart'; | 2 | import 'package:meta/meta.dart'; |
3 | +import 'package:wow_english/common/request/dao/user_dao.dart'; | ||
3 | 4 | ||
4 | part 'user_event.dart'; | 5 | part 'user_event.dart'; |
5 | part 'user_state.dart'; | 6 | part 'user_state.dart'; |
6 | 7 | ||
7 | class UserBloc extends Bloc<UserEvent, UserState> { | 8 | class UserBloc extends Bloc<UserEvent, UserState> { |
8 | UserBloc() : super(UserInitial()) { | 9 | UserBloc() : super(UserInitial()) { |
10 | + on<UserLogout>(_test); | ||
9 | on<UserEvent>((event, emit) { | 11 | on<UserEvent>((event, emit) { |
10 | // TODO: implement event handler | 12 | // TODO: implement event handler |
11 | }); | 13 | }); |
12 | } | 14 | } |
15 | + | ||
16 | + void _test(UserLogout event, Emitter<UserState> emitter) async { | ||
17 | + print('UserBloc._test, event: $event, emitter: $emitter'); | ||
18 | + await UserDao.logout(); | ||
19 | + } | ||
13 | } | 20 | } |
lib/pages/user/bloc/user_event.dart
lib/pages/user/user_page.dart
@@ -3,10 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart'; | @@ -3,10 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart'; | ||
3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
4 | import 'package:wow_english/common/blocs/cachebloc/cache_bloc.dart'; | 4 | import 'package:wow_english/common/blocs/cachebloc/cache_bloc.dart'; |
5 | import 'package:wow_english/common/core/assets_const.dart'; | 5 | import 'package:wow_english/common/core/assets_const.dart'; |
6 | -import 'package:wow_english/common/extension/string_extension.dart'; | 6 | +import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
7 | import 'package:wow_english/common/widgets/we_app_bar.dart'; | 7 | import 'package:wow_english/common/widgets/we_app_bar.dart'; |
8 | import 'package:wow_english/models/user_entity.dart'; | 8 | import 'package:wow_english/models/user_entity.dart'; |
9 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; | 9 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
10 | +import 'package:wow_english/route/route.dart'; | ||
10 | 11 | ||
11 | class UserPage extends StatelessWidget { | 12 | class UserPage extends StatelessWidget { |
12 | const UserPage({super.key}); | 13 | const UserPage({super.key}); |
@@ -15,7 +16,7 @@ class UserPage extends StatelessWidget { | @@ -15,7 +16,7 @@ class UserPage extends StatelessWidget { | ||
15 | Widget build(BuildContext context) { | 16 | Widget build(BuildContext context) { |
16 | return BlocProvider( | 17 | return BlocProvider( |
17 | create: (context) => UserBloc(), | 18 | create: (context) => UserBloc(), |
18 | - child: _UserView(), | 19 | + child: const _UserView(), |
19 | ); | 20 | ); |
20 | } | 21 | } |
21 | } | 22 | } |
@@ -25,65 +26,152 @@ class _UserView extends StatelessWidget { | @@ -25,65 +26,152 @@ class _UserView extends StatelessWidget { | ||
25 | 26 | ||
26 | @override | 27 | @override |
27 | Widget build(BuildContext context) { | 28 | Widget build(BuildContext context) { |
28 | - UserEntity? user = context.read<CacheBloc>().userEntity; | 29 | + final cacheBloc = BlocProvider.of<CacheBloc>(context); |
30 | + final userBloc = BlocProvider.of<UserBloc>(context); | ||
31 | + UserEntity user = cacheBloc.userEntity!; | ||
32 | + | ||
33 | + // 常规按钮的字体样式 | ||
34 | + final textStyle21sp = TextStyle( | ||
35 | + //fontWeight: FontWeight.w600, | ||
36 | + color: const Color(0xFF333333), | ||
37 | + fontSize: 21.sp, | ||
38 | + ); | ||
39 | + | ||
40 | + // 常规按钮的样式 | ||
41 | + var normalButtonStyle = ButtonStyle( | ||
42 | + side: MaterialStateProperty.all(BorderSide(color: const Color(0xFF140C10), width: 1.5)), | ||
43 | + shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))), | ||
44 | + minimumSize: MaterialStateProperty.all(Size(double.infinity, 58.h)), | ||
45 | + backgroundColor: MaterialStateProperty.all(Colors.white), | ||
46 | + ); | ||
29 | return Scaffold( | 47 | return Scaffold( |
30 | backgroundColor: Colors.white, | 48 | backgroundColor: Colors.white, |
31 | - appBar: WEAppBar( | ||
32 | - // 测试用的 | ||
33 | - titleText: user?.name ?? '个人中心', | ||
34 | - ), | 49 | + appBar: const WEAppBar(), |
35 | body: SingleChildScrollView( | 50 | body: SingleChildScrollView( |
51 | + //padding: EdgeInsets.symmetric(horizontal: 17.w), | ||
52 | + padding: EdgeInsets.only(left: 17.w, right: 17.w, top: 10.h, bottom: 22.h), | ||
36 | child: Column( | 53 | child: Column( |
37 | mainAxisAlignment: MainAxisAlignment.center, | 54 | mainAxisAlignment: MainAxisAlignment.center, |
38 | children: <Widget>[ | 55 | children: <Widget>[ |
39 | - Container( | ||
40 | - child: Image.asset(AssetsConst.wowLogo.assetImg), constraints: BoxConstraints(maxHeight: 196.h)), | ||
41 | - _userInfo(context), | 56 | + Container(child: Image.asset(AssetsConst.wowLogo), constraints: BoxConstraints(maxHeight: 196.h)), |
57 | + 30.verticalSpace, | ||
58 | + Row( | ||
59 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
60 | + children: [ | ||
61 | + CircleAvatar( | ||
62 | + radius: 40.r, | ||
63 | + backgroundColor: Color(0xFF140C10), | ||
64 | + /*child: CircleAvatar( | ||
65 | + radius: 38.5.r, | ||
66 | + backgroundImage: ImageUtil.getImageProviderOnDefault(user.avatarUrl), | ||
67 | + ),*/ | ||
68 | + child: ClipOval( | ||
69 | + child: OwImageWidget(name: user.avatarUrl ?? AssetsConst.wowLogo), | ||
70 | + )), | ||
71 | + 32.horizontalSpace, | ||
72 | + Expanded( | ||
73 | + child: Column( | ||
74 | + children: [ | ||
75 | + Row( | ||
76 | + children: [ | ||
77 | + LimitedBox( | ||
78 | + maxWidth: 220.w, | ||
79 | + child: Text( | ||
80 | + user.name, | ||
81 | + //'1231231231312312312312312312312312312312312312312', | ||
82 | + style: textStyle21sp, | ||
83 | + overflow: TextOverflow.ellipsis, | ||
84 | + ), | ||
85 | + ), | ||
86 | + 14.horizontalSpace, | ||
87 | + Text( | ||
88 | + user.getGenderString(), | ||
89 | + style: textStyle21sp, | ||
90 | + ), | ||
91 | + 14.horizontalSpace, | ||
92 | + Offstage( | ||
93 | + offstage: user.effectiveDate == null, | ||
94 | + child: Image.asset( | ||
95 | + AssetsConst.icVip, | ||
96 | + height: 18.h, | ||
97 | + ), | ||
98 | + ) | ||
99 | + ], | ||
100 | + ), | ||
101 | + Offstage( | ||
102 | + offstage: user.effectiveDate == null, | ||
103 | + child: Row( | ||
104 | + children: [ | ||
105 | + Text( | ||
106 | + "${user.effectiveDate} 到期", | ||
107 | + style: TextStyle( | ||
108 | + color: const Color(0xFFE11212), | ||
109 | + fontSize: 17.sp, | ||
110 | + ), | ||
111 | + ) | ||
112 | + ], | ||
113 | + ), | ||
114 | + ) | ||
115 | + ], | ||
116 | + )), | ||
117 | + TextButton( | ||
118 | + child: Text( | ||
119 | + "修改个人信息>", | ||
120 | + style: textStyle21sp, | ||
121 | + ), | ||
122 | + onPressed: () {}, | ||
123 | + ) | ||
124 | + ], | ||
125 | + ), | ||
126 | + 30.verticalSpace, | ||
127 | + OutlinedButton( | ||
128 | + onPressed: () => {}, | ||
129 | + style: normalButtonStyle, | ||
130 | + child: Text( | ||
131 | + "修改密码", | ||
132 | + style: textStyle21sp, | ||
133 | + ), | ||
134 | + ), | ||
135 | + 12.verticalSpace, | ||
136 | + OutlinedButton( | ||
137 | + onPressed: () => {}, | ||
138 | + style: normalButtonStyle, | ||
139 | + child: Text( | ||
140 | + "兑换课程", | ||
141 | + style: textStyle21sp, | ||
142 | + )), | ||
143 | + 12.verticalSpace, | ||
144 | + OutlinedButton( | ||
145 | + onPressed: () => { | ||
146 | + Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | ||
147 | + 'urlStr': 'http://page.kouyuxingqiu.com/%E7%94%A8%E6%88%B7%E6%B3%A8%E5%86%8C%E5%8F%8A%E4%BD%BF%E7%94%A8APP%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE.html', | ||
148 | + 'webViewTitle': '隐私协议' | ||
149 | + }) | ||
150 | + }, | ||
151 | + style: normalButtonStyle, | ||
152 | + child: Text( | ||
153 | + "隐私协议", | ||
154 | + style: textStyle21sp, | ||
155 | + )), | ||
156 | + 30.verticalSpace, | ||
157 | + OutlinedButton( | ||
158 | + onPressed: () => {userBloc.add(UserLogout())}, | ||
159 | + style: ButtonStyle( | ||
160 | + side: MaterialStateProperty.all(BorderSide(color: const Color(0xFF140C10), width: 1.5)), | ||
161 | + shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))), | ||
162 | + minimumSize: MaterialStateProperty.all(Size(295.w, 40.h)), | ||
163 | + backgroundColor: MaterialStateProperty.all(Color(0xFFFBB621)), | ||
164 | + ), | ||
165 | + child: Text( | ||
166 | + "退出登陆", | ||
167 | + style: TextStyle( | ||
168 | + //fontWeight: FontWeight.w600, | ||
169 | + color: Colors.white, | ||
170 | + fontSize: 17.sp, | ||
171 | + ), | ||
172 | + )), | ||
42 | ], | 173 | ], |
43 | ), | 174 | ), |
44 | )); | 175 | )); |
45 | } | 176 | } |
46 | - | ||
47 | - Widget _userInfo(BuildContext context) { | ||
48 | - return Row( | ||
49 | - children: [ | ||
50 | - Image.asset( | ||
51 | - AssetsConst.wowLogo.assetImg, | ||
52 | - width: 80, | ||
53 | - height: 80, | ||
54 | - ), | ||
55 | - Column( | ||
56 | - children: [ | ||
57 | - Row( | ||
58 | - children: [ | ||
59 | - Text( | ||
60 | - context.read<CacheBloc>().userEntity?.name ?? '----', | ||
61 | - style: TextStyle( | ||
62 | - color: const Color(0xFF333333), | ||
63 | - fontSize: 21.sp, | ||
64 | - ), | ||
65 | - ), | ||
66 | - //Text(context.read<CacheBloc>().userEntity?.gender ?? '--'), | ||
67 | - Image.asset( | ||
68 | - AssetsConst.wowLogo.assetImg, | ||
69 | - height: 18.h, | ||
70 | - ), | ||
71 | - ], | ||
72 | - ), | ||
73 | - Row( | ||
74 | - children: [ | ||
75 | - Text( | ||
76 | - "什么时候到期", | ||
77 | - style: TextStyle( | ||
78 | - color: const Color(0xFFE11212), | ||
79 | - fontSize: 17.sp, | ||
80 | - ), | ||
81 | - ) | ||
82 | - ], | ||
83 | - ) | ||
84 | - ], | ||
85 | - ), | ||
86 | - ], | ||
87 | - ); | ||
88 | - } | ||
89 | } | 177 | } |
lib/utils/image_util.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | ||
2 | +import 'package:wow_english/common/core/assets_const.dart'; | ||
3 | + | ||
4 | +class ImageUtil { | ||
5 | + static ImageProvider getImageProviderOnDefault(String? uri, {scale = 1.0}) { | ||
6 | + if (uri == null || uri.isEmpty) { | ||
7 | + return ExactAssetImage(AssetsConst.wowLogo, scale: scale); | ||
8 | + } | ||
9 | + if (uri.startsWith('http')) { | ||
10 | + return NetworkImage(uri); | ||
11 | + } else { | ||
12 | + return ExactAssetImage(uri, scale: scale); | ||
13 | + } | ||
14 | + //return uri.startsWith('http') ? NetworkImage(uri) : ExactAssetImage(uri, scale: 0.5) as ImageProvider?; | ||
15 | + } | ||
16 | +} |