Commit 9ebefc69b3f2cb7f85d42d6a85dd19fe2001d885
Merge remote-tracking branch 'origin/feat-wqf-payment' into xiaoyu_cocossteve
# Conflicts: # pubspec.yaml
Showing
53 changed files
with
1270 additions
and
469 deletions
lib/app/splash_page.dart
... | ... | @@ -77,7 +77,7 @@ class _TransitionViewState extends State<TransitionView> { |
77 | 77 | }*/ |
78 | 78 | bool isAggreementAccepted = AppConfigHelper.getAgreementAccepted(); |
79 | 79 | if (isAggreementAccepted) { |
80 | - pushNamedAndRemoveUntil(AppRouteName.moduleSelect, (route) => false); | |
80 | + pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); | |
81 | 81 | } else { |
82 | 82 | showDialog( |
83 | 83 | context: context, |
... | ... | @@ -91,11 +91,11 @@ class _TransitionViewState extends State<TransitionView> { |
91 | 91 | leftTap: () { |
92 | 92 | AppConfigHelper.saveAgreementAccepted(true); |
93 | 93 | pushNamedAndRemoveUntil( |
94 | - AppRouteName.moduleSelect, (route) => false); | |
94 | + AppRouteName.home, (route) => false); | |
95 | 95 | }, |
96 | 96 | rightTap: () { |
97 | 97 | // 退出应用 |
98 | - SystemNavigator.pop(); | |
98 | + AppConfigHelper.exitApp(); | |
99 | 99 | }, |
100 | 100 | ), |
101 | 101 | ); | ... | ... |
lib/common/core/app_config_helper.dart
... | ... | @@ -2,6 +2,8 @@ import 'dart:ffi'; |
2 | 2 | import 'dart:io'; |
3 | 3 | |
4 | 4 | import 'package:flutter/cupertino.dart'; |
5 | +import 'package:flutter/foundation.dart'; | |
6 | +import 'package:flutter/services.dart'; | |
5 | 7 | import 'package:package_info_plus/package_info_plus.dart'; |
6 | 8 | import 'package:wow_english/common/core/sp_const.dart'; |
7 | 9 | import 'package:wow_english/common/core/user_util.dart'; |
... | ... | @@ -16,6 +18,9 @@ class AppConfigHelper { |
16 | 18 | |
17 | 19 | static String _versionCode = ''; |
18 | 20 | |
21 | + // 是否检测过更新,因为路由混乱导致首页会多次启动,避免重复检测更新,先临时处理 | |
22 | + static bool checkedUpdate = false; | |
23 | + | |
19 | 24 | // 获取用户信息 |
20 | 25 | static Future<AppConfigEntity?> getAppConfig() async { |
21 | 26 | if (configEntityEntity != null) { |
... | ... | @@ -25,9 +30,15 @@ class AppConfigHelper { |
25 | 30 | return configEntityEntity; |
26 | 31 | } |
27 | 32 | |
33 | + // 是否是iOS平台 | |
34 | + static bool isIosPlatform() { | |
35 | + return defaultTargetPlatform == TargetPlatform.iOS; | |
36 | + } | |
37 | + | |
28 | 38 | // 是否需要隐藏... |
29 | 39 | static bool shouldHidePay() { |
30 | - return configEntityEntity?.isAppReviewing() == true || UserUtil.getUser()?.phoneNum == "17730280759"; | |
40 | + return isIosPlatform() && | |
41 | + (configEntityEntity?.isAppReviewing() == true || UserUtil.getUser()?.phoneNum == "17730280759"); | |
31 | 42 | } |
32 | 43 | |
33 | 44 | // 获取app版本号 |
... | ... | @@ -55,4 +66,13 @@ class AppConfigHelper { |
55 | 66 | static void _clearUserData() { |
56 | 67 | SpUtil.getInstance().remove(SpConst.prefsKeyAgreementAccepted); |
57 | 68 | } |
69 | + | |
70 | + static void exitApp() { | |
71 | + if (Platform.isIOS) { | |
72 | + exit(0); | |
73 | + } else { | |
74 | + //此种方式在IOS上不生效 | |
75 | + SystemNavigator.pop(); | |
76 | + } | |
77 | + } | |
58 | 78 | } | ... | ... |
lib/common/core/user_util.dart
... | ... | @@ -60,12 +60,11 @@ class UserUtil { |
60 | 60 | if (currentPageName != AppRouteName.splash) { |
61 | 61 | Navigator.of(AppRouter.context).pushNamedAndRemoveUntil(AppRouteName.login, (route) => false); |
62 | 62 | }*/ |
63 | - Navigator.of(AppRouter.context).pushNamedAndRemoveUntil(AppRouteName.login, (route) => false, arguments: {'showPasswordPage': showPasswordLoginPage}); | |
63 | + pushNamedAndRemoveUntil(AppRouteName.login, (route) => false, arguments: {'showPasswordPage': showPasswordLoginPage}); | |
64 | 64 | } |
65 | 65 | |
66 | 66 | // 是否有游戏权限 |
67 | 67 | static bool hasGamePermission() { |
68 | - debugPrint('hasGamePermission: ${_userEntity}'); | |
69 | 68 | return _userEntity?.valid ?? false; |
70 | 69 | } |
71 | 70 | ... | ... |
lib/common/permission/permissionRequestPage.dart
1 | 1 | import 'dart:io'; |
2 | 2 | import 'package:flutter/material.dart'; |
3 | -import 'package:flutter/services.dart'; | |
4 | 3 | import 'package:permission_handler/permission_handler.dart'; |
4 | +import 'package:wow_english/common/core/app_config_helper.dart'; | |
5 | 5 | |
6 | 6 | import '../../utils/log_util.dart'; |
7 | 7 | |
... | ... | @@ -167,7 +167,7 @@ class _PermissionRequestPageState extends State<PermissionRequestPage> |
167 | 167 | |
168 | 168 | /// 退出应用程序 |
169 | 169 | void _quitApp() { |
170 | - SystemChannels.platform.invokeMethod("SystemNavigator.pop"); | |
170 | + AppConfigHelper.exitApp(); | |
171 | 171 | } |
172 | 172 | |
173 | 173 | /// 关闭整个权限申请页面 | ... | ... |
lib/common/request/apis.dart
... | ... | @@ -6,6 +6,9 @@ class Apis { |
6 | 6 | /// 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897678 |
7 | 7 | static const String appConfig = 'system/app/config'; |
8 | 8 | |
9 | + /// app版本信息 | |
10 | + static const String appVersion = 'system/app/version'; | |
11 | + | |
9 | 12 | /// 登录 |
10 | 13 | static const String login = 'login'; |
11 | 14 | |
... | ... | @@ -42,11 +45,17 @@ class Apis { |
42 | 45 | // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663 |
43 | 46 | static const String courseModule = 'home/courseModule'; |
44 | 47 | |
48 | + /// 课程单元列表 | |
49 | + static const String courseUnit = 'home/courseUnit'; | |
50 | + | |
45 | 51 | /// 课程列表 |
46 | 52 | // GET /home/courseLesson |
47 | 53 | // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897662 |
48 | 54 | static const String courseLesson = 'home/courseLesson'; |
49 | 55 | |
56 | + // 课程环节列表 | |
57 | + static const String courseSection = 'course/courseLesson'; | |
58 | + | |
50 | 59 | /// 磨耳朵 |
51 | 60 | /// GET |
52 | 61 | static const String ears = 'course/grinding/ears'; | ... | ... |
lib/common/request/dao/home_dao.dart renamed to lib/common/request/dao/lesson_dao.dart
1 | 1 | import 'package:wow_english/common/request/request_client.dart'; |
2 | 2 | import 'package:wow_english/models/course_entity.dart'; |
3 | +import 'package:wow_english/models/course_section_entity.dart'; | |
3 | 4 | |
4 | 5 | import '../../../models/course_module_entity.dart'; |
6 | +import '../../../models/course_unit_entity.dart'; | |
5 | 7 | |
6 | -class HomeDao { | |
7 | - ///获取课程模块信息 | |
8 | +class LessonDao { | |
9 | + ///获取课程模块(列表)信息 | |
8 | 10 | static Future<List<CourseModuleEntity?>?> courseModule() async { |
9 | 11 | var data = await requestClient.get<List<CourseModuleEntity>>(Apis.courseModule); |
10 | 12 | return data; |
11 | 13 | } |
12 | 14 | |
13 | - ///课程列表 | |
14 | - static Future<CourseEntity?> courseLesson({String moduleId = ''}) async { | |
15 | + ///课程单元列表 | |
16 | + static Future<CourseUnitEntity?> courseUnit(int? moduleId) async { | |
15 | 17 | Map<String, dynamic> mapData = {}; |
16 | - if (moduleId.isNotEmpty) { | |
18 | + if (moduleId != null) { | |
17 | 19 | mapData['moduleId'] = moduleId; |
18 | 20 | } |
21 | + var data = await requestClient.get<CourseUnitEntity>(Apis.courseUnit, queryParameters: mapData); | |
22 | + return data; | |
23 | + } | |
24 | + | |
25 | + ///课程列表 | |
26 | + static Future<CourseEntity?> courseLesson({int? courseUnitId}) async { | |
27 | + Map<String, dynamic> mapData = {}; | |
28 | + if (courseUnitId != null) { | |
29 | + mapData['courseUnitId'] = courseUnitId; | |
30 | + } | |
19 | 31 | var data = await requestClient.get<CourseEntity>(Apis.courseLesson, queryParameters: mapData); |
20 | 32 | return data; |
21 | 33 | } |
34 | + | |
35 | + ///课程(单元)列表 | |
36 | + static Future<List<CourseSectionEntity>?> courseSection({required int courseUnitId}) async { | |
37 | + Map<String, dynamic> mapData = {}; | |
38 | + mapData['courseUnitId'] = courseUnitId; | |
39 | + var data = await requestClient.get<List<CourseSectionEntity>?>(Apis.courseSection, queryParameters: mapData); | |
40 | + return data; | |
41 | + } | |
22 | 42 | } | ... | ... |
lib/common/request/dao/system_dao.dart
1 | 1 | import '../../../models/app_config_entity.dart'; |
2 | +import '../../../models/app_version_entity.dart'; | |
2 | 3 | import '../request_client.dart'; |
3 | 4 | |
4 | 5 | class SystemDao { |
... | ... | @@ -7,4 +8,9 @@ class SystemDao { |
7 | 8 | static Future<AppConfigEntity?> getAppConfig() async { |
8 | 9 | return await requestClient.get(Apis.appConfig); |
9 | 10 | } |
11 | + | |
12 | + // 获取app版本信息 | |
13 | + static Future<AppVersionEntity?> getVersionInfo() async { | |
14 | + return await requestClient.get(Apis.appVersion); | |
15 | + } | |
10 | 16 | } | ... | ... |
lib/common/request/token_interceptor.dart
1 | 1 | import 'package:dio/dio.dart'; |
2 | +import 'package:flutter/foundation.dart'; | |
2 | 3 | import 'package:wow_english/common/core/user_util.dart'; |
3 | 4 | |
4 | 5 | import '../core/app_config_helper.dart'; |
... | ... | @@ -13,6 +14,7 @@ class TokenInterceptor extends Interceptor { |
13 | 14 | // 在发送请求之前获取版本号 |
14 | 15 | String version = await AppConfigHelper.getAppVersion(); |
15 | 16 | options.headers["version"] = version; |
17 | + options.headers["User-Agent"] = AppConfigHelper.isIosPlatform() ? "ios" : "android"; | |
16 | 18 | super.onRequest(options, handler); |
17 | 19 | } |
18 | 20 | } | ... | ... |
lib/common/widgets/webview_dialog.dart
... | ... | @@ -41,21 +41,26 @@ class WebviewDialog extends StatelessWidget { |
41 | 41 | } |
42 | 42 | })), |
43 | 43 | actions: <Widget>[ |
44 | - TextButton( | |
45 | - child: | |
44 | + Row( | |
45 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
46 | + children: [ | |
47 | + TextButton( | |
48 | + child: | |
46 | 49 | const Text('同意并继续', style: TextStyle(color: Color(0xFFFBB621))), |
47 | - onPressed: () { | |
48 | - // 处理接受按钮的点击事件 | |
49 | - leftTap(); // 关闭对话框 | |
50 | - }, | |
51 | - ), | |
52 | - TextButton( | |
53 | - child: const Text('不同意,退出应用'), | |
54 | - onPressed: () { | |
55 | - // 处理拒绝按钮的点击事件 | |
56 | - rightTap(); // 关闭对话框 | |
57 | - }, | |
58 | - ), | |
50 | + onPressed: () { | |
51 | + // 处理接受按钮的点击事件 | |
52 | + leftTap(); // 关闭对话框 | |
53 | + }, | |
54 | + ), | |
55 | + TextButton( | |
56 | + child: const Text('不同意,退出应用'), | |
57 | + onPressed: () { | |
58 | + // 处理拒绝按钮的点击事件 | |
59 | + rightTap(); // 关闭对话框 | |
60 | + }, | |
61 | + ), | |
62 | + ], | |
63 | + ) | |
59 | 64 | ], |
60 | 65 | ); |
61 | 66 | } | ... | ... |
lib/generated/json/app_config_entity.g.dart
1 | 1 | import 'package:wow_english/generated/json/base/json_convert_content.dart'; |
2 | 2 | import 'package:wow_english/models/app_config_entity.dart'; |
3 | 3 | |
4 | -AppConfigEntity $AppConfigEntityEntityFromJson( | |
5 | - Map<String, dynamic> json) { | |
6 | - final AppConfigEntity appConfigEntityEntity = AppConfigEntity(); | |
7 | - final bool? androidForceUpdate = jsonConvert.convert<bool>( | |
8 | - json['androidForceUpdate']); | |
9 | - if (androidForceUpdate != null) { | |
10 | - appConfigEntityEntity.androidForceUpdate = androidForceUpdate; | |
11 | - } | |
12 | - final bool? androidRecommendUpdate = jsonConvert.convert<bool>( | |
13 | - json['androidRecommendUpdate']); | |
14 | - if (androidRecommendUpdate != null) { | |
15 | - appConfigEntityEntity.androidRecommendUpdate = androidRecommendUpdate; | |
16 | - } | |
17 | - final String? androidUpdatePackageUrl = jsonConvert.convert<String>( | |
18 | - json['androidUpdatePackageUrl']); | |
19 | - if (androidUpdatePackageUrl != null) { | |
20 | - appConfigEntityEntity.androidUpdatePackageUrl = androidUpdatePackageUrl; | |
21 | - } | |
22 | - final int? androidVersion = jsonConvert.convert<int>(json['androidVersion']); | |
23 | - if (androidVersion != null) { | |
24 | - appConfigEntityEntity.androidVersion = androidVersion; | |
25 | - } | |
26 | - final bool? iosForceUpdate = jsonConvert.convert<bool>( | |
27 | - json['iosForceUpdate']); | |
28 | - if (iosForceUpdate != null) { | |
29 | - appConfigEntityEntity.iosForceUpdate = iosForceUpdate; | |
30 | - } | |
31 | - final bool? iosRecommendUpdate = jsonConvert.convert<bool>( | |
32 | - json['iosRecommendUpdate']); | |
33 | - if (iosRecommendUpdate != null) { | |
34 | - appConfigEntityEntity.iosRecommendUpdate = iosRecommendUpdate; | |
35 | - } | |
36 | - final int? iosVersion = jsonConvert.convert<int>(json['iosVersion']); | |
37 | - if (iosVersion != null) { | |
38 | - appConfigEntityEntity.iosVersion = iosVersion; | |
39 | - } | |
40 | - final String? noticeBeforePurchaseUrl = jsonConvert.convert<String>( | |
41 | - json['noticeBeforePurchaseUrl']); | |
42 | - if (noticeBeforePurchaseUrl != null) { | |
43 | - appConfigEntityEntity.noticeBeforePurchaseUrl = noticeBeforePurchaseUrl; | |
44 | - } | |
4 | +AppConfigEntity $AppConfigEntityFromJson(Map<String, dynamic> json) { | |
5 | + final AppConfigEntity appConfigEntity = AppConfigEntity(); | |
45 | 6 | final String? safe = jsonConvert.convert<String>(json['safe']); |
46 | 7 | if (safe != null) { |
47 | - appConfigEntityEntity.safe = safe; | |
8 | + appConfigEntity.safe = safe; | |
48 | 9 | } |
49 | - return appConfigEntityEntity; | |
10 | + return appConfigEntity; | |
50 | 11 | } |
51 | 12 | |
52 | -Map<String, dynamic> $AppConfigEntityEntityToJson( | |
53 | - AppConfigEntity entity) { | |
13 | +Map<String, dynamic> $AppConfigEntityToJson(AppConfigEntity entity) { | |
54 | 14 | final Map<String, dynamic> data = <String, dynamic>{}; |
55 | - data['androidForceUpdate'] = entity.androidForceUpdate; | |
56 | - data['androidRecommendUpdate'] = entity.androidRecommendUpdate; | |
57 | - data['androidUpdatePackageUrl'] = entity.androidUpdatePackageUrl; | |
58 | - data['androidVersion'] = entity.androidVersion; | |
59 | - data['iosForceUpdate'] = entity.iosForceUpdate; | |
60 | - data['iosRecommendUpdate'] = entity.iosRecommendUpdate; | |
61 | - data['iosVersion'] = entity.iosVersion; | |
62 | - data['noticeBeforePurchaseUrl'] = entity.noticeBeforePurchaseUrl; | |
63 | 15 | data['safe'] = entity.safe; |
64 | 16 | return data; |
65 | 17 | } |
66 | 18 | |
67 | -extension AppConfigEntityEntityExtension on AppConfigEntity { | |
19 | +extension AppConfigEntityExtension on AppConfigEntity { | |
68 | 20 | AppConfigEntity copyWith({ |
69 | - bool? androidForceUpdate, | |
70 | - bool? androidRecommendUpdate, | |
71 | - String? androidUpdatePackageUrl, | |
72 | - int? androidVersion, | |
73 | - bool? iosForceUpdate, | |
74 | - bool? iosRecommendUpdate, | |
75 | - int? iosVersion, | |
76 | - String? noticeBeforePurchaseUrl, | |
77 | 21 | String? safe, |
78 | 22 | }) { |
79 | 23 | return AppConfigEntity() |
80 | - ..androidForceUpdate = androidForceUpdate ?? this.androidForceUpdate | |
81 | - ..androidRecommendUpdate = androidRecommendUpdate ?? | |
82 | - this.androidRecommendUpdate | |
83 | - ..androidUpdatePackageUrl = androidUpdatePackageUrl ?? | |
84 | - this.androidUpdatePackageUrl | |
85 | - ..androidVersion = androidVersion ?? this.androidVersion | |
86 | - ..iosForceUpdate = iosForceUpdate ?? this.iosForceUpdate | |
87 | - ..iosRecommendUpdate = iosRecommendUpdate ?? this.iosRecommendUpdate | |
88 | - ..iosVersion = iosVersion ?? this.iosVersion | |
89 | - ..noticeBeforePurchaseUrl = noticeBeforePurchaseUrl ?? | |
90 | - this.noticeBeforePurchaseUrl | |
91 | 24 | ..safe = safe ?? this.safe; |
92 | 25 | } |
93 | 26 | } |
94 | 27 | \ No newline at end of file | ... | ... |
lib/generated/json/app_version_entity.g.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_convert_content.dart'; | |
2 | +import 'package:wow_english/models/app_version_entity.dart'; | |
3 | + | |
4 | +AppVersionEntity $AppVersionEntityFromJson(Map<String, dynamic> json) { | |
5 | + final AppVersionEntity appVersionEntity = AppVersionEntity(); | |
6 | + final String? packageUrl = jsonConvert.convert<String>(json['packageUrl']); | |
7 | + if (packageUrl != null) { | |
8 | + appVersionEntity.packageUrl = packageUrl; | |
9 | + } | |
10 | + final String? packageName = jsonConvert.convert<String>(json['packageName']); | |
11 | + if (packageName != null) { | |
12 | + appVersionEntity.packageName = packageName; | |
13 | + } | |
14 | + final String? packageSize = jsonConvert.convert<String>(json['packageSize']); | |
15 | + if (packageSize != null) { | |
16 | + appVersionEntity.packageSize = packageSize; | |
17 | + } | |
18 | + final String? platformType = jsonConvert.convert<String>( | |
19 | + json['platformType']); | |
20 | + if (platformType != null) { | |
21 | + appVersionEntity.platformType = platformType; | |
22 | + } | |
23 | + final String? remark = jsonConvert.convert<String>(json['remark']); | |
24 | + if (remark != null) { | |
25 | + appVersionEntity.remark = remark; | |
26 | + } | |
27 | + final String? status = jsonConvert.convert<String>(json['status']); | |
28 | + if (status != null) { | |
29 | + appVersionEntity.status = status; | |
30 | + } | |
31 | + final String? version = jsonConvert.convert<String>(json['version']); | |
32 | + if (version != null) { | |
33 | + appVersionEntity.version = version; | |
34 | + } | |
35 | + final String? volType = jsonConvert.convert<String>(json['volType']); | |
36 | + if (volType != null) { | |
37 | + appVersionEntity.volType = volType; | |
38 | + } | |
39 | + return appVersionEntity; | |
40 | +} | |
41 | + | |
42 | +Map<String, dynamic> $AppVersionEntityToJson(AppVersionEntity entity) { | |
43 | + final Map<String, dynamic> data = <String, dynamic>{}; | |
44 | + data['packageUrl'] = entity.packageUrl; | |
45 | + data['packageName'] = entity.packageName; | |
46 | + data['packageSize'] = entity.packageSize; | |
47 | + data['platformType'] = entity.platformType; | |
48 | + data['remark'] = entity.remark; | |
49 | + data['status'] = entity.status; | |
50 | + data['version'] = entity.version; | |
51 | + data['volType'] = entity.volType; | |
52 | + return data; | |
53 | +} | |
54 | + | |
55 | +extension AppVersionEntityExtension on AppVersionEntity { | |
56 | + AppVersionEntity copyWith({ | |
57 | + String? packageUrl, | |
58 | + String? packageName, | |
59 | + String? packageSize, | |
60 | + String? platformType, | |
61 | + String? remark, | |
62 | + String? status, | |
63 | + String? version, | |
64 | + String? volType, | |
65 | + }) { | |
66 | + return AppVersionEntity() | |
67 | + ..packageUrl = packageUrl ?? this.packageUrl | |
68 | + ..packageName = packageName ?? this.packageName | |
69 | + ..packageSize = packageSize ?? this.packageSize | |
70 | + ..platformType = platformType ?? this.platformType | |
71 | + ..remark = remark ?? this.remark | |
72 | + ..status = status ?? this.status | |
73 | + ..version = version ?? this.version | |
74 | + ..volType = volType ?? this.volType; | |
75 | + } | |
76 | +} | |
0 | 77 | \ No newline at end of file | ... | ... |
lib/generated/json/base/json_convert_content.dart
... | ... | @@ -6,9 +6,12 @@ |
6 | 6 | import 'package:flutter/material.dart' show debugPrint; |
7 | 7 | import 'package:wow_english/models/aliyun_oss_upload_sts_entity.dart'; |
8 | 8 | import 'package:wow_english/models/app_config_entity.dart'; |
9 | +import 'package:wow_english/models/app_version_entity.dart'; | |
9 | 10 | import 'package:wow_english/models/course_entity.dart'; |
10 | 11 | import 'package:wow_english/models/course_module_entity.dart'; |
11 | 12 | import 'package:wow_english/models/course_process_entity.dart'; |
13 | +import 'package:wow_english/models/course_section_entity.dart'; | |
14 | +import 'package:wow_english/models/course_unit_entity.dart'; | |
12 | 15 | import 'package:wow_english/models/follow_read_entity.dart'; |
13 | 16 | import 'package:wow_english/models/listen_entity.dart'; |
14 | 17 | import 'package:wow_english/models/product_entity.dart'; |
... | ... | @@ -159,6 +162,10 @@ class JsonConvert { |
159 | 162 | return data.map<AppConfigEntity>((Map<String, dynamic> e) => |
160 | 163 | AppConfigEntity.fromJson(e)).toList() as M; |
161 | 164 | } |
165 | + if (<AppVersionEntity>[] is M) { | |
166 | + return data.map<AppVersionEntity>((Map<String, dynamic> e) => | |
167 | + AppVersionEntity.fromJson(e)).toList() as M; | |
168 | + } | |
162 | 169 | if (<CourseEntity>[] is M) { |
163 | 170 | return data.map<CourseEntity>((Map<String, dynamic> e) => |
164 | 171 | CourseEntity.fromJson(e)).toList() as M; |
... | ... | @@ -192,6 +199,18 @@ class JsonConvert { |
192 | 199 | return data.map<CourseProcessVideos>((Map<String, dynamic> e) => |
193 | 200 | CourseProcessVideos.fromJson(e)).toList() as M; |
194 | 201 | } |
202 | + if (<CourseSectionEntity>[] is M) { | |
203 | + return data.map<CourseSectionEntity>((Map<String, dynamic> e) => | |
204 | + CourseSectionEntity.fromJson(e)).toList() as M; | |
205 | + } | |
206 | + if (<CourseUnitEntity>[] is M) { | |
207 | + return data.map<CourseUnitEntity>((Map<String, dynamic> e) => | |
208 | + CourseUnitEntity.fromJson(e)).toList() as M; | |
209 | + } | |
210 | + if (<CourseUnitDetail>[] is M) { | |
211 | + return data.map<CourseUnitDetail>((Map<String, dynamic> e) => | |
212 | + CourseUnitDetail.fromJson(e)).toList() as M; | |
213 | + } | |
195 | 214 | if (<FollowReadEntity>[] is M) { |
196 | 215 | return data.map<FollowReadEntity>((Map<String, dynamic> e) => |
197 | 216 | FollowReadEntity.fromJson(e)).toList() as M; |
... | ... | @@ -237,6 +256,7 @@ class JsonConvertClassCollection { |
237 | 256 | (AliyunOssUploadStsCallbackParam) |
238 | 257 | .toString(): AliyunOssUploadStsCallbackParam.fromJson, |
239 | 258 | (AppConfigEntity).toString(): AppConfigEntity.fromJson, |
259 | + (AppVersionEntity).toString(): AppVersionEntity.fromJson, | |
240 | 260 | (CourseEntity).toString(): CourseEntity.fromJson, |
241 | 261 | (CourseCourseLessons).toString(): CourseCourseLessons.fromJson, |
242 | 262 | (CourseModuleEntity).toString(): CourseModuleEntity.fromJson, |
... | ... | @@ -246,6 +266,9 @@ class JsonConvertClassCollection { |
246 | 266 | (CourseProcessTopicsTopicAnswerList) |
247 | 267 | .toString(): CourseProcessTopicsTopicAnswerList.fromJson, |
248 | 268 | (CourseProcessVideos).toString(): CourseProcessVideos.fromJson, |
269 | + (CourseSectionEntity).toString(): CourseSectionEntity.fromJson, | |
270 | + (CourseUnitEntity).toString(): CourseUnitEntity.fromJson, | |
271 | + (CourseUnitDetail).toString(): CourseUnitDetail.fromJson, | |
249 | 272 | (FollowReadEntity).toString(): FollowReadEntity.fromJson, |
250 | 273 | (ListenEntity).toString(): ListenEntity.fromJson, |
251 | 274 | (ProductEntity).toString(): ProductEntity.fromJson, | ... | ... |
lib/generated/json/course_module_entity.g.dart
... | ... | @@ -3,7 +3,7 @@ import 'package:wow_english/models/course_module_entity.dart'; |
3 | 3 | |
4 | 4 | CourseModuleEntity $CourseModuleEntityFromJson(Map<String, dynamic> json) { |
5 | 5 | final CourseModuleEntity courseModuleEntity = CourseModuleEntity(); |
6 | - final String? id = jsonConvert.convert<String>(json['id']); | |
6 | + final int? id = jsonConvert.convert<int>(json['id']); | |
7 | 7 | if (id != null) { |
8 | 8 | courseModuleEntity.id = id; |
9 | 9 | } |
... | ... | @@ -90,7 +90,7 @@ Map<String, dynamic> $CourseModuleEntityToJson(CourseModuleEntity entity) { |
90 | 90 | |
91 | 91 | extension CourseModuleEntityExtension on CourseModuleEntity { |
92 | 92 | CourseModuleEntity copyWith({ |
93 | - String? id, | |
93 | + int? id, | |
94 | 94 | String? code, |
95 | 95 | int? courseModuleThemeId, |
96 | 96 | int? courseTotal, | ... | ... |
lib/generated/json/course_section_entity.g.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_convert_content.dart'; | |
2 | +import 'package:wow_english/models/course_section_entity.dart'; | |
3 | + | |
4 | +CourseSectionEntity $CourseSectionEntityFromJson(Map<String, dynamic> json) { | |
5 | + final CourseSectionEntity courseSectionEntity = CourseSectionEntity(); | |
6 | + final int? id = jsonConvert.convert<int>(json['id']); | |
7 | + if (id != null) { | |
8 | + courseSectionEntity.id = id; | |
9 | + } | |
10 | + final int? courseUnitId = jsonConvert.convert<int>(json['courseUnitId']); | |
11 | + if (courseUnitId != null) { | |
12 | + courseSectionEntity.courseUnitId = courseUnitId; | |
13 | + } | |
14 | + final int? courseModuleId = jsonConvert.convert<int>(json['courseModuleId']); | |
15 | + if (courseModuleId != null) { | |
16 | + courseSectionEntity.courseModuleId = courseModuleId; | |
17 | + } | |
18 | + final String? name = jsonConvert.convert<String>(json['name']); | |
19 | + if (name != null) { | |
20 | + courseSectionEntity.name = name; | |
21 | + } | |
22 | + final dynamic des = json['des']; | |
23 | + if (des != null) { | |
24 | + courseSectionEntity.des = des; | |
25 | + } | |
26 | + final int? courseType = jsonConvert.convert<int>(json['courseType']); | |
27 | + if (courseType != null) { | |
28 | + courseSectionEntity.courseType = courseType; | |
29 | + } | |
30 | + final dynamic coverUrl = json['coverUrl']; | |
31 | + if (coverUrl != null) { | |
32 | + courseSectionEntity.coverUrl = coverUrl; | |
33 | + } | |
34 | + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']); | |
35 | + if (sortOrder != null) { | |
36 | + courseSectionEntity.sortOrder = sortOrder; | |
37 | + } | |
38 | + final int? status = jsonConvert.convert<int>(json['status']); | |
39 | + if (status != null) { | |
40 | + courseSectionEntity.status = status; | |
41 | + } | |
42 | + final bool? lock = jsonConvert.convert<bool>(json['lock']); | |
43 | + if (lock != null) { | |
44 | + courseSectionEntity.lock = lock; | |
45 | + } | |
46 | + return courseSectionEntity; | |
47 | +} | |
48 | + | |
49 | +Map<String, dynamic> $CourseSectionEntityToJson(CourseSectionEntity entity) { | |
50 | + final Map<String, dynamic> data = <String, dynamic>{}; | |
51 | + data['id'] = entity.id; | |
52 | + data['courseUnitId'] = entity.courseUnitId; | |
53 | + data['courseModuleId'] = entity.courseModuleId; | |
54 | + data['name'] = entity.name; | |
55 | + data['des'] = entity.des; | |
56 | + data['courseType'] = entity.courseType; | |
57 | + data['coverUrl'] = entity.coverUrl; | |
58 | + data['sortOrder'] = entity.sortOrder; | |
59 | + data['status'] = entity.status; | |
60 | + data['lock'] = entity.lock; | |
61 | + return data; | |
62 | +} | |
63 | + | |
64 | +extension CourseSectionEntityExtension on CourseSectionEntity { | |
65 | + CourseSectionEntity copyWith({ | |
66 | + int? id, | |
67 | + int? courseUnitId, | |
68 | + int? courseModuleId, | |
69 | + String? name, | |
70 | + dynamic des, | |
71 | + int? courseType, | |
72 | + dynamic coverUrl, | |
73 | + int? sortOrder, | |
74 | + int? status, | |
75 | + bool? lock, | |
76 | + }) { | |
77 | + return CourseSectionEntity() | |
78 | + ..id = id ?? this.id | |
79 | + ..courseUnitId = courseUnitId ?? this.courseUnitId | |
80 | + ..courseModuleId = courseModuleId ?? this.courseModuleId | |
81 | + ..name = name ?? this.name | |
82 | + ..des = des ?? this.des | |
83 | + ..courseType = courseType ?? this.courseType | |
84 | + ..coverUrl = coverUrl ?? this.coverUrl | |
85 | + ..sortOrder = sortOrder ?? this.sortOrder | |
86 | + ..status = status ?? this.status | |
87 | + ..lock = lock ?? this.lock; | |
88 | + } | |
89 | +} | |
0 | 90 | \ No newline at end of file | ... | ... |
lib/generated/json/course_unit_entity.g.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_convert_content.dart'; | |
2 | +import 'package:wow_english/models/course_unit_entity.dart'; | |
3 | + | |
4 | +CourseUnitEntity $CourseUnitEntityFromJson(Map<String, dynamic> json) { | |
5 | + final CourseUnitEntity courseUnitEntity = CourseUnitEntity(); | |
6 | + final List< | |
7 | + CourseUnitDetail>? courseUnitVOList = (json['courseUnitVOList'] as List< | |
8 | + dynamic>?) | |
9 | + ?.map( | |
10 | + (e) => jsonConvert.convert<CourseUnitDetail>(e) as CourseUnitDetail) | |
11 | + .toList(); | |
12 | + if (courseUnitVOList != null) { | |
13 | + courseUnitEntity.courseUnitVOList = courseUnitVOList; | |
14 | + } | |
15 | + final int? nowStep = jsonConvert.convert<int>(json['nowStep']); | |
16 | + if (nowStep != null) { | |
17 | + courseUnitEntity.nowStep = nowStep; | |
18 | + } | |
19 | + final int? total = jsonConvert.convert<int>(json['total']); | |
20 | + if (total != null) { | |
21 | + courseUnitEntity.total = total; | |
22 | + } | |
23 | + final int? nowCourseModuleId = jsonConvert.convert<int>( | |
24 | + json['nowCourseModuleId']); | |
25 | + if (nowCourseModuleId != null) { | |
26 | + courseUnitEntity.nowCourseModuleId = nowCourseModuleId; | |
27 | + } | |
28 | + final String? nowCourseModuleName = jsonConvert.convert<String>( | |
29 | + json['nowCourseModuleName']); | |
30 | + if (nowCourseModuleName != null) { | |
31 | + courseUnitEntity.nowCourseModuleName = nowCourseModuleName; | |
32 | + } | |
33 | + final String? courseModuleThemeColor = jsonConvert.convert<String>( | |
34 | + json['courseModuleThemeColor']); | |
35 | + if (courseModuleThemeColor != null) { | |
36 | + courseUnitEntity.courseModuleThemeColor = courseModuleThemeColor; | |
37 | + } | |
38 | + final String? courseModuleCode = jsonConvert.convert<String>( | |
39 | + json['courseModuleCode']); | |
40 | + if (courseModuleCode != null) { | |
41 | + courseUnitEntity.courseModuleCode = courseModuleCode; | |
42 | + } | |
43 | + return courseUnitEntity; | |
44 | +} | |
45 | + | |
46 | +Map<String, dynamic> $CourseUnitEntityToJson(CourseUnitEntity entity) { | |
47 | + final Map<String, dynamic> data = <String, dynamic>{}; | |
48 | + data['courseUnitVOList'] = | |
49 | + entity.courseUnitVOList?.map((v) => v.toJson()).toList(); | |
50 | + data['nowStep'] = entity.nowStep; | |
51 | + data['total'] = entity.total; | |
52 | + data['nowCourseModuleId'] = entity.nowCourseModuleId; | |
53 | + data['nowCourseModuleName'] = entity.nowCourseModuleName; | |
54 | + data['courseModuleThemeColor'] = entity.courseModuleThemeColor; | |
55 | + data['courseModuleCode'] = entity.courseModuleCode; | |
56 | + return data; | |
57 | +} | |
58 | + | |
59 | +extension CourseUnitEntityExtension on CourseUnitEntity { | |
60 | + CourseUnitEntity copyWith({ | |
61 | + List<CourseUnitDetail>? courseUnitVOList, | |
62 | + int? nowStep, | |
63 | + int? total, | |
64 | + int? nowCourseModuleId, | |
65 | + String? nowCourseModuleName, | |
66 | + String? courseModuleThemeColor, | |
67 | + String? courseModuleCode, | |
68 | + }) { | |
69 | + return CourseUnitEntity() | |
70 | + ..courseUnitVOList = courseUnitVOList ?? this.courseUnitVOList | |
71 | + ..nowStep = nowStep ?? this.nowStep | |
72 | + ..total = total ?? this.total | |
73 | + ..nowCourseModuleId = nowCourseModuleId ?? this.nowCourseModuleId | |
74 | + ..nowCourseModuleName = nowCourseModuleName ?? this.nowCourseModuleName | |
75 | + ..courseModuleThemeColor = courseModuleThemeColor ?? | |
76 | + this.courseModuleThemeColor | |
77 | + ..courseModuleCode = courseModuleCode ?? this.courseModuleCode; | |
78 | + } | |
79 | +} | |
80 | + | |
81 | +CourseUnitDetail $CourseUnitDetailFromJson(Map<String, dynamic> json) { | |
82 | + final CourseUnitDetail courseUnitDetail = CourseUnitDetail(); | |
83 | + final int? courseModuleId = jsonConvert.convert<int>(json['courseModuleId']); | |
84 | + if (courseModuleId != null) { | |
85 | + courseUnitDetail.courseModuleId = courseModuleId; | |
86 | + } | |
87 | + final int? id = jsonConvert.convert<int>(json['id']); | |
88 | + if (id != null) { | |
89 | + courseUnitDetail.id = id; | |
90 | + } | |
91 | + final String? name = jsonConvert.convert<String>(json['name']); | |
92 | + if (name != null) { | |
93 | + courseUnitDetail.name = name; | |
94 | + } | |
95 | + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']); | |
96 | + if (coverUrl != null) { | |
97 | + courseUnitDetail.coverUrl = coverUrl; | |
98 | + } | |
99 | + final bool? lock = jsonConvert.convert<bool>(json['lock']); | |
100 | + if (lock != null) { | |
101 | + courseUnitDetail.lock = lock; | |
102 | + } | |
103 | + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']); | |
104 | + if (sortOrder != null) { | |
105 | + courseUnitDetail.sortOrder = sortOrder; | |
106 | + } | |
107 | + final int? status = jsonConvert.convert<int>(json['status']); | |
108 | + if (status != null) { | |
109 | + courseUnitDetail.status = status; | |
110 | + } | |
111 | + return courseUnitDetail; | |
112 | +} | |
113 | + | |
114 | +Map<String, dynamic> $CourseUnitDetailToJson(CourseUnitDetail entity) { | |
115 | + final Map<String, dynamic> data = <String, dynamic>{}; | |
116 | + data['courseModuleId'] = entity.courseModuleId; | |
117 | + data['id'] = entity.id; | |
118 | + data['name'] = entity.name; | |
119 | + data['coverUrl'] = entity.coverUrl; | |
120 | + data['lock'] = entity.lock; | |
121 | + data['sortOrder'] = entity.sortOrder; | |
122 | + data['status'] = entity.status; | |
123 | + return data; | |
124 | +} | |
125 | + | |
126 | +extension CourseUnitDetailExtension on CourseUnitDetail { | |
127 | + CourseUnitDetail copyWith({ | |
128 | + int? courseModuleId, | |
129 | + int? id, | |
130 | + String? name, | |
131 | + String? coverUrl, | |
132 | + bool? lock, | |
133 | + int? sortOrder, | |
134 | + int? status, | |
135 | + }) { | |
136 | + return CourseUnitDetail() | |
137 | + ..courseModuleId = courseModuleId ?? this.courseModuleId | |
138 | + ..id = id ?? this.id | |
139 | + ..name = name ?? this.name | |
140 | + ..coverUrl = coverUrl ?? this.coverUrl | |
141 | + ..lock = lock ?? this.lock | |
142 | + ..sortOrder = sortOrder ?? this.sortOrder | |
143 | + ..status = status ?? this.status; | |
144 | + } | |
145 | +} | |
0 | 146 | \ No newline at end of file | ... | ... |
lib/models/app_config_entity.dart
... | ... | @@ -7,40 +7,15 @@ import '../generated/json/app_config_entity.g.dart'; |
7 | 7 | @JsonSerializable() |
8 | 8 | class AppConfigEntity { |
9 | 9 | |
10 | - // 安卓是否强制更新 | |
11 | - bool? androidForceUpdate; | |
12 | - | |
13 | - // 安卓是否推荐更新 | |
14 | - bool? androidRecommendUpdate; | |
15 | - | |
16 | - // 安卓更新包地址 | |
17 | - String? androidUpdatePackageUrl; | |
18 | - | |
19 | - // 安卓当前版本号 | |
20 | - late int androidVersion; | |
21 | - | |
22 | - bool? iosForceUpdate; | |
23 | - | |
24 | - bool? iosRecommendUpdate; | |
25 | - | |
26 | - // ios版本 | |
27 | - late int iosVersion; | |
28 | - | |
29 | - // 更新说明 | |
30 | - String? updatePackageDescription; | |
31 | - | |
32 | - // 购前须知图片 | |
33 | - String? noticeBeforePurchaseUrl; | |
34 | - | |
35 | 10 | // 当前是否安全,safe-安全 otherwise-隐藏pay |
36 | 11 | String? safe; |
37 | 12 | |
38 | 13 | |
39 | 14 | AppConfigEntity(); |
40 | 15 | |
41 | - factory AppConfigEntity.fromJson(Map<String, dynamic> json) => $AppConfigEntityEntityFromJson(json); | |
16 | + factory AppConfigEntity.fromJson(Map<String, dynamic> json) => $AppConfigEntityFromJson(json); | |
42 | 17 | |
43 | - Map<String, dynamic> toJson() => $AppConfigEntityEntityToJson(this); | |
18 | + Map<String, dynamic> toJson() => $AppConfigEntityToJson(this); | |
44 | 19 | |
45 | 20 | @override |
46 | 21 | String toString() { | ... | ... |
lib/models/app_version_entity.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_field.dart'; | |
2 | +import 'package:wow_english/generated/json/app_version_entity.g.dart'; | |
3 | +import 'dart:convert'; | |
4 | +export 'package:wow_english/generated/json/app_version_entity.g.dart'; | |
5 | + | |
6 | +@JsonSerializable() | |
7 | +class AppVersionEntity { | |
8 | + | |
9 | + // 更新包地址 | |
10 | + String? packageUrl; | |
11 | + | |
12 | + // 更新包名 | |
13 | + String? packageName; | |
14 | + | |
15 | + // 更新包大小 | |
16 | + String? packageSize; | |
17 | + | |
18 | + // 平台类型 | |
19 | + String? platformType; | |
20 | + | |
21 | + // 更新说明 | |
22 | + String? remark; | |
23 | + | |
24 | + // 状态 | |
25 | + String? status; | |
26 | + | |
27 | + // app版本号 | |
28 | + String? version; | |
29 | + | |
30 | + // 强更类型 | |
31 | + String? volType; | |
32 | + | |
33 | + | |
34 | + AppVersionEntity(); | |
35 | + | |
36 | + factory AppVersionEntity.fromJson(Map<String, dynamic> json) => $AppVersionEntityFromJson(json); | |
37 | + | |
38 | + Map<String, dynamic> toJson() => $AppVersionEntityToJson(this); | |
39 | + | |
40 | + @override | |
41 | + String toString() { | |
42 | + return jsonEncode(this); | |
43 | + } | |
44 | +} | |
45 | + | |
46 | +enum UpdateStrategy { | |
47 | + SUGGEST("suggest", "建议更新"), | |
48 | + FORCE("force", "强制更新"); | |
49 | + | |
50 | + const UpdateStrategy(this.name, this.chineseName); | |
51 | + | |
52 | + final String name; | |
53 | + | |
54 | + final String chineseName; | |
55 | +} | |
0 | 56 | \ No newline at end of file | ... | ... |
lib/models/course_module_entity.dart
lib/models/course_section_entity.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_field.dart'; | |
2 | +import 'package:wow_english/generated/json/course_section_entity.g.dart'; | |
3 | +import 'dart:convert'; | |
4 | +export 'package:wow_english/generated/json/course_section_entity.g.dart'; | |
5 | + | |
6 | +@JsonSerializable() | |
7 | +class CourseSectionEntity { | |
8 | + late int id; | |
9 | + late int courseUnitId; | |
10 | + late int courseModuleId; | |
11 | + late String name; | |
12 | + dynamic des; | |
13 | + late int courseType; | |
14 | + dynamic coverUrl; | |
15 | + late int sortOrder; | |
16 | + late int status; | |
17 | + late bool lock; | |
18 | + | |
19 | + CourseSectionEntity(); | |
20 | + | |
21 | + factory CourseSectionEntity.fromJson(Map<String, dynamic> json) => $CourseSectionEntityFromJson(json); | |
22 | + | |
23 | + Map<String, dynamic> toJson() => $CourseSectionEntityToJson(this); | |
24 | + | |
25 | + @override | |
26 | + String toString() { | |
27 | + return jsonEncode(this); | |
28 | + } | |
29 | +} | |
0 | 30 | \ No newline at end of file | ... | ... |
lib/models/course_unit_entity.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_field.dart'; | |
2 | +import 'package:wow_english/generated/json/course_unit_entity.g.dart'; | |
3 | +import 'dart:convert'; | |
4 | + | |
5 | +export 'package:wow_english/generated/json/course_unit_entity.g.dart'; | |
6 | + | |
7 | +@JsonSerializable() | |
8 | +class CourseUnitEntity { | |
9 | + | |
10 | + // 课程详情列表 | |
11 | + List<CourseUnitDetail>? courseUnitVOList; | |
12 | + | |
13 | + // 当前进行了多少节课程 | |
14 | + int? nowStep; | |
15 | + | |
16 | + // 当前模块一共多少节课程 | |
17 | + int? total; | |
18 | + | |
19 | + // 当前模块id | |
20 | + int? nowCourseModuleId; | |
21 | + | |
22 | + // 当前模块名 | |
23 | + String? nowCourseModuleName; | |
24 | + | |
25 | + // 主题颜色值 | |
26 | + String? courseModuleThemeColor; | |
27 | + | |
28 | + // 课程模块code | |
29 | + String? courseModuleCode; | |
30 | + | |
31 | + CourseUnitEntity(); | |
32 | + | |
33 | + factory CourseUnitEntity.fromJson(Map<String, dynamic> json) => $CourseUnitEntityFromJson(json); | |
34 | + | |
35 | + Map<String, dynamic> toJson() => $CourseUnitEntityToJson(this); | |
36 | + | |
37 | + @override | |
38 | + String toString() { | |
39 | + return jsonEncode(this); | |
40 | + } | |
41 | +} | |
42 | + | |
43 | + | |
44 | +@JsonSerializable() | |
45 | +class CourseUnitDetail { | |
46 | + | |
47 | + // 模块id | |
48 | + int? courseModuleId; | |
49 | + | |
50 | + // 单元 | |
51 | + int? id; | |
52 | + | |
53 | + // 单元名称 | |
54 | + String? name; | |
55 | + | |
56 | + // 单元封面 | |
57 | + String? coverUrl; | |
58 | + | |
59 | + bool? lock; | |
60 | + | |
61 | + int? sortOrder; | |
62 | + | |
63 | + int? status; | |
64 | + | |
65 | + CourseUnitDetail(); | |
66 | + | |
67 | + factory CourseUnitDetail.fromJson(Map<String, dynamic> json) => $CourseUnitDetailFromJson(json); | |
68 | + | |
69 | + Map<String, dynamic> toJson() => $CourseUnitDetailToJson(this); | |
70 | + | |
71 | + @override | |
72 | + String toString() { | |
73 | + return jsonEncode(this); | |
74 | + } | |
75 | +} | |
0 | 76 | \ No newline at end of file | ... | ... |
lib/pages/moduleSelect/bloc.dart renamed to lib/pages/home/bloc.dart
1 | 1 | import 'package:bloc/bloc.dart'; |
2 | 2 | import 'package:flutter/cupertino.dart'; |
3 | 3 | import 'package:flutter/foundation.dart'; |
4 | -import 'package:wow_english/models/app_config_entity.dart'; | |
5 | 4 | |
6 | 5 | import '../../common/core/app_config_helper.dart'; |
6 | +import '../../common/request/dao/system_dao.dart'; | |
7 | +import '../../models/app_version_entity.dart'; | |
8 | +import '../../utils/log_util.dart'; | |
7 | 9 | import 'event.dart'; |
8 | 10 | import 'state.dart'; |
9 | 11 | |
10 | -class ModuleSelectBloc extends Bloc<ModuleSelectEvent, ModuleSelectState> { | |
11 | - ModuleSelectBloc() : super(ModuleSelectState().init()) { | |
12 | +class ModuleSelectBloc extends Bloc<HomeEvent, HomeState> { | |
13 | + ModuleSelectBloc() : super(HomeState().init()) { | |
12 | 14 | on<InitEvent>(_init); |
13 | 15 | } |
14 | 16 | |
15 | - void _init(InitEvent event, Emitter<ModuleSelectState> emit) async { | |
17 | + void _init(InitEvent event, Emitter<HomeState> emit) async { | |
16 | 18 | await _checkUpdate(emit); |
17 | 19 | debugPrint('WQF ModuleSelectBloc _init'); |
18 | 20 | } |
19 | 21 | |
20 | - Future<void> _checkUpdate(Emitter<ModuleSelectState> emit) async { | |
22 | + Future<void> _checkUpdate(Emitter<HomeState> emit) async { | |
23 | + if (AppConfigHelper.checkedUpdate) { | |
24 | + return; | |
25 | + } | |
21 | 26 | int localVersion = int.parse(await AppConfigHelper.getAppVersion()); |
22 | - AppConfigEntity? appConfigEntity = await AppConfigHelper.getAppConfig(); | |
23 | - if (appConfigEntity == null) { | |
27 | + AppVersionEntity? appVersionEntity = await SystemDao.getVersionInfo(); | |
28 | + AppConfigHelper.checkedUpdate = true; | |
29 | + if (appVersionEntity == null) { | |
24 | 30 | return; |
25 | 31 | } |
26 | - debugPrint('WQF _checkUpdate'); | |
27 | - if (defaultTargetPlatform == TargetPlatform.iOS) { | |
28 | - if (localVersion < appConfigEntity.iosVersion && | |
29 | - appConfigEntity.iosRecommendUpdate == true) { | |
30 | - emit(UpdateDialogState( | |
31 | - appConfigEntity.iosForceUpdate ?? false, appConfigEntity)); | |
32 | - } | |
33 | - } else { | |
34 | - if (localVersion < appConfigEntity.androidVersion && | |
35 | - appConfigEntity.androidRecommendUpdate == true) { | |
36 | - emit(UpdateDialogState( | |
37 | - appConfigEntity.androidForceUpdate ?? false, appConfigEntity, | |
38 | - )); | |
39 | - } | |
32 | + Log.d("WQF _checkUpdate appVersionEntity: $appVersionEntity localVersion=$localVersion"); | |
33 | + if (localVersion < int.parse(appVersionEntity.version ?? '0')) { | |
34 | + emit(UpdateDialogState( | |
35 | + appVersionEntity.volType == UpdateStrategy.FORCE.name, appVersionEntity)); | |
40 | 36 | } |
41 | 37 | } |
42 | 38 | } | ... | ... |
lib/pages/home/event.dart
0 → 100644
lib/pages/home/state.dart
0 → 100644
1 | +import 'package:wow_english/models/app_version_entity.dart'; | |
2 | + | |
3 | +class HomeState { | |
4 | + HomeState init() { | |
5 | + return HomeState(); | |
6 | + } | |
7 | + | |
8 | + HomeState clone() { | |
9 | + return HomeState(); | |
10 | + } | |
11 | +} | |
12 | + | |
13 | +class UpdateDialogState extends HomeState { | |
14 | + | |
15 | + final AppVersionEntity appVersionEntity; | |
16 | + | |
17 | + final bool forceUpdate; | |
18 | + | |
19 | + UpdateDialogState(this.forceUpdate, this.appVersionEntity); | |
20 | +} | ... | ... |
lib/pages/moduleSelect/view.dart renamed to lib/pages/home/view.dart
... | ... | @@ -8,20 +8,21 @@ import 'package:flutter_bloc/flutter_bloc.dart'; |
8 | 8 | import 'package:url_launcher/url_launcher.dart'; |
9 | 9 | import 'package:wow_english/common/core/app_config_helper.dart'; |
10 | 10 | import 'package:wow_english/common/extension/string_extension.dart'; |
11 | -import 'package:wow_english/pages/moduleSelect/state.dart'; | |
12 | -import 'package:wow_english/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart'; | |
11 | +import 'package:wow_english/models/app_version_entity.dart'; | |
12 | +import 'package:wow_english/pages/home/state.dart'; | |
13 | +import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; | |
13 | 14 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
14 | 15 | |
15 | 16 | import '../../common/core/user_util.dart'; |
16 | 17 | import '../../common/dialogs/show_dialog.dart'; |
17 | -import '../../models/app_config_entity.dart'; | |
18 | +import '../../utils/log_util.dart'; | |
18 | 19 | import 'bloc.dart'; |
19 | 20 | import 'event.dart'; |
20 | 21 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
21 | 22 | import 'package:wow_english/route/route.dart'; |
22 | 23 | |
23 | -class ModuleSelectPage extends StatelessWidget { | |
24 | - const ModuleSelectPage({super.key}); | |
24 | +class HomePage extends StatelessWidget { | |
25 | + const HomePage({super.key}); | |
25 | 26 | |
26 | 27 | @override |
27 | 28 | Widget build(BuildContext context) { |
... | ... | @@ -41,10 +42,11 @@ class _HomePageView extends StatelessWidget { |
41 | 42 | BlocListener<UserBloc, UserState>(listener: (context, state) { |
42 | 43 | debugPrint('WQF ModuleSelectPage BlocListener state: $state'); |
43 | 44 | }), |
44 | - BlocListener<ModuleSelectBloc, ModuleSelectState>( | |
45 | + BlocListener<ModuleSelectBloc, HomeState>( | |
45 | 46 | listener: (context, state) { |
47 | + Log.d("WQF HomePage listener state: $state"); | |
46 | 48 | if (state is UpdateDialogState) { |
47 | - _showUpdateDialog(context, state.forceUpdate, state.appConfigEntity); | |
49 | + _showUpdateDialog(context, state.forceUpdate, state.appVersionEntity); | |
48 | 50 | } |
49 | 51 | }, |
50 | 52 | ), |
... | ... | @@ -52,7 +54,7 @@ class _HomePageView extends StatelessWidget { |
52 | 54 | } |
53 | 55 | |
54 | 56 | Widget _homeView() => |
55 | - BlocBuilder<ModuleSelectBloc, ModuleSelectState>( | |
57 | + BlocBuilder<ModuleSelectBloc, HomeState>( | |
56 | 58 | builder: (context, state) { |
57 | 59 | return Scaffold( |
58 | 60 | body: Container( |
... | ... | @@ -68,7 +70,7 @@ class _HomePageView extends StatelessWidget { |
68 | 70 | child: GestureDetector( |
69 | 71 | onTap: () { |
70 | 72 | if (UserUtil.isLogined()) { |
71 | - pushNamed(AppRouteName.home); | |
73 | + pushNamed(AppRouteName.courseUnit); | |
72 | 74 | } else { |
73 | 75 | pushNamed(AppRouteName.login); |
74 | 76 | } |
... | ... | @@ -169,7 +171,7 @@ class _HomePageView extends StatelessWidget { |
169 | 171 | ///Flutter侧处理升级对话框 |
170 | 172 | ///[forcedUpgrade] 是否强制升级 |
171 | 173 | _showUpdateDialog(BuildContext context, bool forcedUpgrade, |
172 | - AppConfigEntity appConfigEntity) { | |
174 | + AppVersionEntity appVersionEntity) { | |
173 | 175 | showDialog( |
174 | 176 | context: context, |
175 | 177 | // 当我们点击除开对话框内容以外的区域是否关闭对话需用用到barrierDismissible参数 . 这个参数默认值是true ,但不能为null . |
... | ... | @@ -180,7 +182,7 @@ class _HomePageView extends StatelessWidget { |
180 | 182 | child: AlertDialog( |
181 | 183 | title: const Text('发现新版本'), |
182 | 184 | content: Text( |
183 | - appConfigEntity.updatePackageDescription ?? | |
185 | + appVersionEntity.remark ?? | |
184 | 186 | '修复了一些已知问题'), |
185 | 187 | actions: <Widget>[ |
186 | 188 | TextButton( |
... | ... | @@ -188,7 +190,7 @@ class _HomePageView extends StatelessWidget { |
188 | 190 | onPressed: () => |
189 | 191 | { |
190 | 192 | if (forcedUpgrade) { |
191 | - SystemNavigator.pop() | |
193 | + AppConfigHelper.exitApp() | |
192 | 194 | } else |
193 | 195 | { |
194 | 196 | Navigator.of(context).pop() |
... | ... | @@ -198,11 +200,11 @@ class _HomePageView extends StatelessWidget { |
198 | 200 | TextButton( |
199 | 201 | child: const Text('升级'), |
200 | 202 | onPressed: () async { |
201 | - if (defaultTargetPlatform == TargetPlatform.iOS) { | |
203 | + if (AppConfigHelper.isIosPlatform()) { | |
202 | 204 | _launchAppStore("6450870731"); |
203 | 205 | return; |
204 | 206 | } |
205 | - final String? apkUrl = appConfigEntity.androidUpdatePackageUrl; | |
207 | + final String? apkUrl = appVersionEntity.packageUrl; | |
206 | 208 | if (apkUrl == null || apkUrl.isEmpty) { |
207 | 209 | return; |
208 | 210 | } | ... | ... |
lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart renamed to lib/pages/home/widgets/BaseHomeHeaderWidget.dart
... | ... | @@ -78,8 +78,8 @@ class BaseHomeHeaderWidget extends StatelessWidget { |
78 | 78 | textAlign: TextAlign.left, |
79 | 79 | style: TextStyle(color: Colors.white, fontSize: 30.0), |
80 | 80 | )), |
81 | - Visibility( | |
82 | - visible: !AppConfigHelper.shouldHidePay(), | |
81 | + Offstage( | |
82 | + offstage: AppConfigHelper.shouldHidePay(), | |
83 | 83 | child: Row(children: <Widget>[ |
84 | 84 | Image( |
85 | 85 | width: 20.0.w, | ... | ... |
lib/pages/lessons/bloc/lesson_state.dart deleted
lib/pages/login/loginpage/login_page.dart
... | ... | @@ -34,7 +34,7 @@ class _LoginPageView extends StatelessWidget { |
34 | 34 | if (state is LoginResultChangeState) { |
35 | 35 | // 调试用 |
36 | 36 | // Navigator.of(context).pushNamed(AppRouteName.home); |
37 | - pushNamedAndRemoveUntil(AppRouteName.moduleSelect, (route) => false); | |
37 | + pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); | |
38 | 38 | } |
39 | 39 | }, |
40 | 40 | child: _buildLoginViewWidget(), | ... | ... |
lib/pages/lessons/bloc/lesson_bloc.dart renamed to lib/pages/module/bloc/module_bloc.dart
1 | 1 | import 'package:flutter/cupertino.dart'; |
2 | 2 | import 'package:flutter_bloc/flutter_bloc.dart'; |
3 | -import 'package:wow_english/common/request/dao/home_dao.dart'; | |
3 | +import 'package:wow_english/common/request/dao/lesson_dao.dart'; | |
4 | 4 | import 'package:wow_english/common/request/exception.dart'; |
5 | 5 | import 'package:wow_english/models/course_module_entity.dart'; |
6 | 6 | import 'package:wow_english/utils/loading.dart'; |
7 | 7 | import 'package:wow_english/utils/toast_util.dart'; |
8 | 8 | |
9 | -part 'lesson_event.dart'; | |
10 | -part 'lesson_state.dart'; | |
9 | +part 'module_event.dart'; | |
10 | +part 'module_state.dart'; | |
11 | 11 | |
12 | -class LessonBloc extends Bloc<LessonEvent, LessonState> { | |
12 | +class ModuleBloc extends Bloc<ModuleEvent, ModuleState> { | |
13 | 13 | final int pageIndex; |
14 | 14 | |
15 | 15 | final PageController pageController; |
... | ... | @@ -22,22 +22,22 @@ class LessonBloc extends Bloc<LessonEvent, LessonState> { |
22 | 22 | |
23 | 23 | List<CourseModuleEntity?> get listData => _listData; |
24 | 24 | |
25 | - LessonBloc(this.pageIndex, this.pageController) : super(LessonInitial()) { | |
25 | + ModuleBloc(this.pageIndex, this.pageController) : super(ModuleInitial()) { | |
26 | 26 | _currentPageIndex = pageIndex; |
27 | 27 | on<PageViewChangeIndexEvent>(_pageIndexChange); |
28 | 28 | on<RequestDataEvent>(_requestData); |
29 | 29 | } |
30 | 30 | |
31 | - void _pageIndexChange(PageViewChangeIndexEvent event, Emitter<LessonState> emitter) async { | |
31 | + void _pageIndexChange(PageViewChangeIndexEvent event, Emitter<ModuleState> emitter) async { | |
32 | 32 | _currentPageIndex = event.index; |
33 | 33 | emitter(PageIndexChangeState()); |
34 | 34 | } |
35 | 35 | |
36 | - void _requestData(RequestDataEvent event, Emitter<LessonState> emitter) async { | |
36 | + void _requestData(RequestDataEvent event, Emitter<ModuleState> emitter) async { | |
37 | 37 | try { |
38 | 38 | await loading(() async { |
39 | - _listData = await HomeDao.courseModule() ?? []; | |
40 | - emitter(LessonDataLoadState()); | |
39 | + _listData = await LessonDao.courseModule() ?? []; | |
40 | + emitter(ModuleDataLoadState()); | |
41 | 41 | }); |
42 | 42 | } catch (e) { |
43 | 43 | if (e is ApiException) { | ... | ... |
lib/pages/lessons/bloc/lesson_event.dart renamed to lib/pages/module/bloc/module_event.dart
1 | -part of 'lesson_bloc.dart'; | |
1 | +part of 'module_bloc.dart'; | |
2 | 2 | |
3 | 3 | @immutable |
4 | -abstract class LessonEvent {} | |
4 | +abstract class ModuleEvent {} | |
5 | 5 | |
6 | -class PageViewChangeIndexEvent extends LessonEvent { | |
6 | +class PageViewChangeIndexEvent extends ModuleEvent { | |
7 | 7 | final int index; |
8 | 8 | PageViewChangeIndexEvent(this.index); |
9 | 9 | } |
10 | 10 | |
11 | -class RequestDataEvent extends LessonEvent {} | |
11 | +class RequestDataEvent extends ModuleEvent {} | ... | ... |
lib/pages/module/bloc/module_state.dart
0 → 100644
lib/pages/lessons/lesson_page.dart renamed to lib/pages/module/module_page.dart
... | ... | @@ -6,23 +6,21 @@ import 'package:wow_english/common/widgets/we_app_bar.dart'; |
6 | 6 | import 'package:wow_english/models/course_module_entity.dart'; |
7 | 7 | import 'package:wow_english/route/route.dart'; |
8 | 8 | |
9 | -import 'bloc/lesson_bloc.dart'; | |
10 | -import 'widgets/lesson_item_widget.dart'; | |
9 | +import 'bloc/module_bloc.dart'; | |
10 | +import 'widgets/module_item_widget.dart'; | |
11 | 11 | |
12 | -class LessonPage extends StatelessWidget { | |
13 | - const LessonPage({super.key, this.starPageIndex}); | |
12 | +// 阶段(模块)列表页 | |
13 | +class ModulePage extends StatelessWidget { | |
14 | + const ModulePage({super.key, this.starPageIndex}); | |
14 | 15 | |
15 | 16 | final int? starPageIndex; |
16 | 17 | |
17 | 18 | @override |
18 | 19 | Widget build(BuildContext context) { |
19 | 20 | return BlocProvider( |
20 | - create: (context) => LessonBloc( | |
21 | - starPageIndex??0, | |
22 | - PageController( | |
23 | - initialPage: starPageIndex??0, | |
24 | - viewportFraction: 0.3 | |
25 | - ), | |
21 | + create: (context) => ModuleBloc( | |
22 | + starPageIndex ?? 0, | |
23 | + PageController(initialPage: starPageIndex ?? 0, viewportFraction: 0.3), | |
26 | 24 | )..add(RequestDataEvent()), |
27 | 25 | child: _LessonPageView(), |
28 | 26 | ); |
... | ... | @@ -30,27 +28,25 @@ class LessonPage extends StatelessWidget { |
30 | 28 | } |
31 | 29 | |
32 | 30 | class _LessonPageView extends StatelessWidget { |
33 | - | |
34 | 31 | final double _cardHeight = 240.h; |
35 | 32 | |
36 | 33 | final double _scale = 0.8; |
37 | 34 | |
38 | 35 | @override |
39 | 36 | Widget build(BuildContext context) { |
40 | - return BlocListener<LessonBloc,LessonState>( | |
41 | - listener: (context, state){}, | |
37 | + return BlocListener<ModuleBloc, ModuleState>( | |
38 | + listener: (context, state) {}, | |
42 | 39 | child: Scaffold( |
43 | 40 | appBar: WEAppBar( |
44 | 41 | leading: IconButton( |
45 | - onPressed: (){ | |
46 | - popPage(); | |
42 | + onPressed: () { | |
43 | + popPage(); | |
47 | 44 | }, |
48 | 45 | icon: Image.asset( |
49 | 46 | 'back'.assetPng, |
50 | 47 | height: 43, |
51 | 48 | width: 43, |
52 | - ) | |
53 | - ), | |
49 | + )), | |
54 | 50 | // actions: <Widget>[ |
55 | 51 | // IconButton( |
56 | 52 | // icon: Image.asset('shop'.assetPng), |
... | ... | @@ -66,9 +62,9 @@ class _LessonPageView extends StatelessWidget { |
66 | 62 | ); |
67 | 63 | } |
68 | 64 | |
69 | - Widget _lessViewWidget() => BlocBuilder<LessonBloc,LessonState>( | |
70 | - builder: (context, state){ | |
71 | - final bloc = BlocProvider.of<LessonBloc>(context); | |
65 | + Widget _lessViewWidget() => | |
66 | + BlocBuilder<ModuleBloc, ModuleState>(builder: (context, state) { | |
67 | + final bloc = BlocProvider.of<ModuleBloc>(context); | |
72 | 68 | return Center( |
73 | 69 | child: SafeArea( |
74 | 70 | child: Column( |
... | ... | @@ -81,8 +77,7 @@ class _LessonPageView extends StatelessWidget { |
81 | 77 | onPageChanged: (int index) { |
82 | 78 | bloc.add(PageViewChangeIndexEvent(index)); |
83 | 79 | }, |
84 | - itemBuilder: (context,index) => _itemTransCard(index) | |
85 | - ), | |
80 | + itemBuilder: (context, index) => _itemTransCard(index)), | |
86 | 81 | ), |
87 | 82 | 32.verticalSpace, |
88 | 83 | SizedBox( |
... | ... | @@ -91,7 +86,7 @@ class _LessonPageView extends StatelessWidget { |
91 | 86 | child: ListView.builder( |
92 | 87 | itemCount: bloc.listData.length, |
93 | 88 | scrollDirection: Axis.horizontal, |
94 | - itemBuilder: (BuildContext context,int index){ | |
89 | + itemBuilder: (BuildContext context, int index) { | |
95 | 90 | return Container( |
96 | 91 | height: 32.h, |
97 | 92 | width: 66.w, |
... | ... | @@ -101,13 +96,19 @@ class _LessonPageView extends StatelessWidget { |
101 | 96 | if (index == bloc.currentPageIndex) { |
102 | 97 | return; |
103 | 98 | } |
104 | - int mill = (index - bloc.currentPageIndex) > 0 ? 100 * (index - bloc.currentPageIndex):100 * (bloc.currentPageIndex-index); | |
105 | - bloc.pageController.animateToPage(index, duration: Duration(milliseconds: mill), curve: Curves.ease); | |
99 | + int mill = (index - bloc.currentPageIndex) > 0 | |
100 | + ? 100 * (index - bloc.currentPageIndex) | |
101 | + : 100 * (bloc.currentPageIndex - index); | |
102 | + bloc.pageController.animateToPage(index, | |
103 | + duration: Duration(milliseconds: mill), | |
104 | + curve: Curves.ease); | |
106 | 105 | }, |
107 | 106 | child: Container( |
108 | - height: bloc.currentPageIndex == index ? 32:20, | |
107 | + height: bloc.currentPageIndex == index ? 32 : 20, | |
109 | 108 | decoration: BoxDecoration( |
110 | - color: bloc.currentPageIndex == index ? Colors.red:Colors.white, | |
109 | + color: bloc.currentPageIndex == index | |
110 | + ? Colors.red | |
111 | + : Colors.white, | |
111 | 112 | borderRadius: BorderRadius.circular(5.r), |
112 | 113 | border: Border.all( |
113 | 114 | width: 0.5, |
... | ... | @@ -116,10 +117,11 @@ class _LessonPageView extends StatelessWidget { |
116 | 117 | ), |
117 | 118 | alignment: Alignment.center, |
118 | 119 | child: Text( |
119 | - (index+1).toString(), | |
120 | + (index + 1).toString(), | |
120 | 121 | style: TextStyle( |
121 | - color: bloc.currentPageIndex == index ? Colors.white:Colors.black | |
122 | - ), | |
122 | + color: bloc.currentPageIndex == index | |
123 | + ? Colors.white | |
124 | + : Colors.black), | |
123 | 125 | ), |
124 | 126 | ), |
125 | 127 | ), |
... | ... | @@ -132,49 +134,54 @@ class _LessonPageView extends StatelessWidget { |
132 | 134 | ); |
133 | 135 | }); |
134 | 136 | |
135 | - Widget _itemTransCard(int index) => BlocBuilder<LessonBloc,LessonState>( | |
136 | - builder: (context, state) { | |
137 | - final bloc = BlocProvider.of<LessonBloc>(context); | |
138 | - Matrix4 matrix4 = Matrix4.identity(); | |
139 | - if (index == bloc.currentPageIndex.floor()) { | |
140 | - //当前的item | |
141 | - double currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); | |
142 | - var currTrans = _cardHeight * (1 - currScale) / 2; | |
137 | + Widget _itemTransCard(int index) => | |
138 | + BlocBuilder<ModuleBloc, ModuleState>(builder: (context, state) { | |
139 | + final bloc = BlocProvider.of<ModuleBloc>(context); | |
140 | + Matrix4 matrix4 = Matrix4.identity(); | |
141 | + if (index == bloc.currentPageIndex.floor()) { | |
142 | + //当前的item | |
143 | + double currScale = | |
144 | + (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); | |
145 | + var currTrans = _cardHeight * (1 - currScale) / 2; | |
143 | 146 | |
144 | - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) | |
145 | - ..setTranslationRaw(0.0, currTrans, 0.0); | |
146 | - } else if (index == bloc.currentPageIndex.floor() + 1) { | |
147 | - //右边的item | |
148 | - var currScale = _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale); | |
149 | - var currTrans = _cardHeight * (1 - currScale) / 2; | |
147 | + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) | |
148 | + ..setTranslationRaw(0.0, currTrans, 0.0); | |
149 | + } else if (index == bloc.currentPageIndex.floor() + 1) { | |
150 | + //右边的item | |
151 | + var currScale = | |
152 | + _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale); | |
153 | + var currTrans = _cardHeight * (1 - currScale) / 2; | |
150 | 154 | |
151 | - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) | |
152 | - ..setTranslationRaw(0.0, currTrans, 0.0); | |
153 | - } else if (index == bloc.currentPageIndex - 1) { | |
154 | - //左边 | |
155 | - var currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); | |
156 | - var currTrans = _cardHeight * (1 - currScale) / 2; | |
155 | + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) | |
156 | + ..setTranslationRaw(0.0, currTrans, 0.0); | |
157 | + } else if (index == bloc.currentPageIndex - 1) { | |
158 | + //左边 | |
159 | + var currScale = | |
160 | + (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); | |
161 | + var currTrans = _cardHeight * (1 - currScale) / 2; | |
157 | 162 | |
158 | - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) | |
159 | - ..setTranslationRaw(0.0, currTrans, 0.0); | |
160 | - } else { | |
161 | - //其他,不在屏幕显示的item | |
162 | - matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0) | |
163 | - ..setTranslationRaw(0.0, _cardHeight * (1 - _scale) / 2, 0.0); | |
164 | - } | |
165 | - CourseModuleEntity? model = bloc.listData[index]; | |
166 | - return Transform( | |
167 | - transform: matrix4, | |
168 | - child: Padding( | |
169 | - padding: const EdgeInsets.symmetric(horizontal: 10), | |
170 | - child: LessonItemWidget( | |
171 | - model: model, | |
172 | - isSelected: bloc.currentPageIndex == index, | |
173 | - onClickEvent: () { | |
174 | - pushNamedAndRemoveUntil(AppRouteName.home, (route) => false,arguments: {'moduleId':model?.id}); | |
175 | - }, | |
163 | + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) | |
164 | + ..setTranslationRaw(0.0, currTrans, 0.0); | |
165 | + } else { | |
166 | + //其他,不在屏幕显示的item | |
167 | + matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0) | |
168 | + ..setTranslationRaw(0.0, _cardHeight * (1 - _scale) / 2, 0.0); | |
169 | + } | |
170 | + CourseModuleEntity? model = bloc.listData[index]; | |
171 | + return Transform( | |
172 | + transform: matrix4, | |
173 | + child: Padding( | |
174 | + padding: const EdgeInsets.symmetric(horizontal: 10), | |
175 | + child: ModuleItemWidget( | |
176 | + model: model, | |
177 | + isSelected: bloc.currentPageIndex == index, | |
178 | + onClickEvent: () { | |
179 | + pushNamedAndRemoveUntil( | |
180 | + AppRouteName.courseUnit, (route) => route.isFirst, | |
181 | + arguments: {'courseModuleEntity': model}); | |
182 | + }, | |
183 | + ), | |
176 | 184 | ), |
177 | - ), | |
178 | - ); | |
179 | - }); | |
185 | + ); | |
186 | + }); | |
180 | 187 | } | ... | ... |
lib/pages/lessons/widgets/lesson_item_widget.dart renamed to lib/pages/module/widgets/module_item_widget.dart
... | ... | @@ -4,10 +4,10 @@ import 'package:wow_english/common/extension/string_extension.dart'; |
4 | 4 | import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
5 | 5 | import 'package:wow_english/models/course_module_entity.dart'; |
6 | 6 | |
7 | -import '../../home/courese_module_model.dart'; | |
7 | +import '../../section/courese_module_model.dart'; | |
8 | 8 | |
9 | -class LessonItemWidget extends StatelessWidget { | |
10 | - const LessonItemWidget({super.key, required this.isSelected, this.model, this.onClickEvent}); | |
9 | +class ModuleItemWidget extends StatelessWidget { | |
10 | + const ModuleItemWidget({super.key, required this.isSelected, this.model, this.onClickEvent}); | |
11 | 11 | ///是否被选中 |
12 | 12 | final bool isSelected; |
13 | 13 | final CourseModuleEntity? model; | ... | ... |
lib/pages/moduleSelect/event.dart deleted
lib/pages/moduleSelect/state.dart deleted
1 | -import '../../models/app_config_entity.dart'; | |
2 | - | |
3 | -class ModuleSelectState { | |
4 | - ModuleSelectState init() { | |
5 | - return ModuleSelectState(); | |
6 | - } | |
7 | - | |
8 | - ModuleSelectState clone() { | |
9 | - return ModuleSelectState(); | |
10 | - } | |
11 | -} | |
12 | - | |
13 | -class UpdateDialogState extends ModuleSelectState { | |
14 | - | |
15 | - final AppConfigEntity appConfigEntity; | |
16 | - | |
17 | - final bool forceUpdate; | |
18 | - | |
19 | - UpdateDialogState(this.forceUpdate, this.appConfigEntity); | |
20 | -} |
lib/pages/home/bloc/home_bloc.dart renamed to lib/pages/section/bloc/section_bloc.dart
1 | 1 | import 'package:flutter/cupertino.dart'; |
2 | 2 | import 'package:flutter/foundation.dart'; |
3 | 3 | import 'package:flutter_bloc/flutter_bloc.dart'; |
4 | -import 'package:wow_english/common/request/dao/home_dao.dart'; | |
4 | +import 'package:wow_english/common/request/dao/lesson_dao.dart'; | |
5 | 5 | import 'package:wow_english/common/request/exception.dart'; |
6 | -import 'package:wow_english/models/course_entity.dart'; | |
7 | 6 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
8 | 7 | import 'package:wow_english/models/course_process_entity.dart'; |
9 | 8 | import 'package:wow_english/utils/loading.dart'; |
10 | 9 | import 'package:wow_english/utils/toast_util.dart'; |
11 | 10 | |
12 | -part 'home_event.dart'; | |
13 | -part 'home_state.dart'; | |
11 | +import '../../../models/course_section_entity.dart'; | |
12 | +import '../../../models/course_unit_entity.dart'; | |
14 | 13 | |
15 | -class HomeBloc extends Bloc<HomeEvent, HomeState> { | |
16 | - final String? moduleId; | |
14 | +part 'section_event.dart'; | |
15 | +part 'section_state.dart'; | |
17 | 16 | |
18 | - CourseEntity? _modelData; | |
17 | +class SectionBloc extends Bloc<SectionEvent, SectionState> { | |
19 | 18 | |
20 | - CourseEntity? get modelData => _modelData; | |
19 | + CourseUnitEntity _courseUnitEntity; | |
20 | + | |
21 | + CourseUnitEntity get courseUnitEntity => _courseUnitEntity; | |
22 | + | |
23 | + CourseUnitDetail _courseUnitDetail; | |
24 | + | |
25 | + CourseUnitDetail get courseUnitDetail => _courseUnitDetail; | |
26 | + | |
27 | + List<CourseSectionEntity>? _courseSectionDatas; | |
28 | + | |
29 | + List<CourseSectionEntity>? get courseSectionDatas => _courseSectionDatas; | |
21 | 30 | |
22 | 31 | CourseProcessEntity? _processEntity; |
23 | 32 | |
24 | 33 | CourseProcessEntity? get processEntity => _processEntity; |
25 | 34 | |
26 | - HomeBloc(this.moduleId) : super(HomeInitial()) { | |
35 | + SectionBloc(this._courseUnitEntity, this._courseUnitDetail) : super(LessonInitial()) { | |
27 | 36 | on<RequestDataEvent>(_requestData); |
28 | 37 | on<RequestExitClassEvent>(_requestExitClass); |
29 | 38 | on<RequestEnterClassEvent>(_requestEnterClass); |
30 | 39 | on<RequestVideoLessonEvent>(_requestVideoLesson); |
31 | 40 | } |
32 | 41 | |
33 | - void _requestData(RequestDataEvent event, Emitter<HomeState> emitter) async { | |
42 | + void _requestData(RequestDataEvent event, Emitter<SectionState> emitter) async { | |
34 | 43 | try { |
35 | 44 | await loading(() async { |
36 | - _modelData = await HomeDao.courseLesson(moduleId: moduleId ?? ''); | |
37 | - emitter(HomeDataLoadState()); | |
45 | + _courseSectionDatas = await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!); | |
46 | + emitter(LessonDataLoadState()); | |
38 | 47 | }); |
39 | 48 | } catch (e) { |
40 | 49 | if (e is ApiException) { |
... | ... | @@ -43,7 +52,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { |
43 | 52 | } |
44 | 53 | } |
45 | 54 | |
46 | - void _requestVideoLesson(RequestVideoLessonEvent event, Emitter<HomeState> emitter) async { | |
55 | + void _requestVideoLesson(RequestVideoLessonEvent event, Emitter<SectionState> emitter) async { | |
47 | 56 | try { |
48 | 57 | await loading(() async { |
49 | 58 | _processEntity = await ListenDao.process(event.courseLessonId); |
... | ... | @@ -57,7 +66,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { |
57 | 66 | } |
58 | 67 | |
59 | 68 | |
60 | - void _requestEnterClass(RequestEnterClassEvent event,Emitter<HomeState> emitter) async { | |
69 | + void _requestEnterClass(RequestEnterClassEvent event,Emitter<SectionState> emitter) async { | |
61 | 70 | try { |
62 | 71 | await loading(() async { |
63 | 72 | await ListenDao.enterClass(event.courseLessonId); |
... | ... | @@ -70,7 +79,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { |
70 | 79 | } |
71 | 80 | } |
72 | 81 | |
73 | - void _requestExitClass(RequestExitClassEvent event,Emitter<HomeState> emitter) async { | |
82 | + void _requestExitClass(RequestExitClassEvent event,Emitter<SectionState> emitter) async { | |
74 | 83 | await ListenDao.exitClass(event.courseLessonId,event.currentStep,event.currentTime); |
75 | 84 | } |
76 | 85 | } | ... | ... |
lib/pages/home/bloc/home_event.dart renamed to lib/pages/section/bloc/section_event.dart
1 | -part of 'home_bloc.dart'; | |
1 | +part of 'section_bloc.dart'; | |
2 | 2 | |
3 | 3 | @immutable |
4 | -abstract class HomeEvent {} | |
4 | +abstract class SectionEvent {} | |
5 | 5 | |
6 | -class RequestDataEvent extends HomeEvent {} | |
6 | +class RequestDataEvent extends SectionEvent {} | |
7 | 7 | |
8 | 8 | ///获取视频课程内容 |
9 | -class RequestVideoLessonEvent extends HomeEvent { | |
9 | +class RequestVideoLessonEvent extends SectionEvent { | |
10 | 10 | final String courseLessonId; |
11 | 11 | final int courseType; |
12 | 12 | RequestVideoLessonEvent(this.courseLessonId, this.courseType); |
13 | 13 | } |
14 | 14 | |
15 | 15 | ///进入课堂 |
16 | -class RequestEnterClassEvent extends HomeEvent { | |
16 | +class RequestEnterClassEvent extends SectionEvent { | |
17 | 17 | final String courseLessonId; |
18 | 18 | final int courseType; |
19 | 19 | RequestEnterClassEvent(this.courseLessonId,this.courseType); |
20 | 20 | } |
21 | 21 | |
22 | 22 | ///退出课堂 |
23 | -class RequestExitClassEvent extends HomeEvent { | |
23 | +class RequestExitClassEvent extends SectionEvent { | |
24 | 24 | final String courseLessonId; |
25 | 25 | final String currentStep; |
26 | 26 | final String currentTime; | ... | ... |
lib/pages/home/bloc/home_state.dart renamed to lib/pages/section/bloc/section_state.dart
1 | -part of 'home_bloc.dart'; | |
1 | +part of 'section_bloc.dart'; | |
2 | 2 | |
3 | 3 | @immutable |
4 | -abstract class HomeState {} | |
4 | +abstract class SectionState {} | |
5 | 5 | |
6 | -class HomeInitial extends HomeState {} | |
6 | +class LessonInitial extends SectionState {} | |
7 | 7 | |
8 | -class HomeDataLoadState extends HomeState {} | |
8 | +class LessonDataLoadState extends SectionState {} | |
9 | 9 | |
10 | -class RequestVideoLessonState extends HomeState { | |
10 | +class RequestVideoLessonState extends SectionState { | |
11 | 11 | final String courseLessonId; |
12 | 12 | final int type; |
13 | 13 | RequestVideoLessonState(this.courseLessonId,this.type); |
14 | 14 | } |
15 | 15 | |
16 | -class RequestEnterClassState extends HomeState{ | |
16 | +class RequestEnterClassState extends SectionState{ | |
17 | 17 | final String courseLessonId; |
18 | 18 | final int courseType; |
19 | 19 | RequestEnterClassState(this.courseLessonId,this.courseType); | ... | ... |
lib/pages/home/courese_module_model.dart renamed to lib/pages/section/courese_module_model.dart
... | ... | @@ -2,9 +2,10 @@ import 'package:flutter/material.dart'; |
2 | 2 | |
3 | 3 | class CourseModuleModel { |
4 | 4 | Color get color => getCourseColor(); |
5 | - String get courseModuleTitle => getCourseModuleTitle(); | |
6 | - String get courseModuleLogo => getCoureseImageName(); | |
7 | 5 | |
6 | + String get courseModuleTitle => getCourseModuleTitle(); | |
7 | + | |
8 | + String get courseModuleLogo => getCoureseImageName(); | |
8 | 9 | |
9 | 10 | String course; |
10 | 11 | |
... | ... | @@ -84,4 +85,4 @@ class CourseModuleModel { |
84 | 85 | } |
85 | 86 | return 'red_positive'; |
86 | 87 | } |
87 | -} | |
88 | 88 | \ No newline at end of file |
89 | +} | ... | ... |
lib/pages/home/home_page.dart renamed to lib/pages/section/section_page.dart
... | ... | @@ -3,60 +3,47 @@ import 'package:flutter_bloc/flutter_bloc.dart'; |
3 | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
4 | 4 | import 'package:wow_english/common/core/user_util.dart'; |
5 | 5 | import 'package:wow_english/common/extension/string_extension.dart'; |
6 | -import 'package:wow_english/models/course_entity.dart'; | |
7 | -import 'package:wow_english/pages/home/widgets/home_bouns_item.dart'; | |
8 | -import 'package:wow_english/pages/home/widgets/home_tab_header_widget.dart'; | |
9 | -import 'package:wow_english/pages/home/widgets/home_vidoe_item.dart'; | |
6 | +import 'package:wow_english/models/course_unit_entity.dart'; | |
7 | +import 'package:wow_english/pages/section/widgets/home_video_item.dart'; | |
8 | +import 'package:wow_english/pages/section/widgets/section_bouns_item.dart'; | |
9 | +import 'package:wow_english/pages/section/widgets/section_header_widget.dart'; | |
10 | 10 | import 'package:wow_english/route/route.dart'; |
11 | 11 | import 'package:wow_english/utils/toast_util.dart'; |
12 | 12 | |
13 | -import 'bloc/home_bloc.dart'; | |
13 | +import '../../models/course_section_entity.dart'; | |
14 | +import 'bloc/section_bloc.dart'; | |
14 | 15 | import 'courese_module_model.dart'; |
15 | 16 | |
16 | -class HomePage extends StatelessWidget { | |
17 | - const HomePage({super.key, this.moduleId}); | |
17 | +/// 环节列表页 | |
18 | +class SectionPage extends StatelessWidget { | |
19 | + const SectionPage({super.key, required this.courseUnitEntity, required this.courseUnitDetail}); | |
18 | 20 | |
19 | - /// 模块id | |
20 | - final String? moduleId; | |
21 | + final CourseUnitEntity courseUnitEntity; | |
22 | + | |
23 | + /// unitId | |
24 | + final CourseUnitDetail courseUnitDetail; | |
21 | 25 | |
22 | 26 | @override |
23 | 27 | Widget build(BuildContext context) { |
24 | 28 | return BlocProvider( |
25 | - create: (context) => HomeBloc(moduleId)..add(RequestDataEvent()), | |
26 | - child: _HomePageView(context), | |
29 | + create: (context) => SectionBloc(courseUnitEntity, courseUnitDetail)..add(RequestDataEvent()), | |
30 | + child: _SectionPageView(context), | |
27 | 31 | ); |
28 | 32 | } |
29 | 33 | } |
30 | 34 | |
31 | -class _HomePageView extends StatelessWidget { | |
32 | - | |
33 | - const _HomePageView(this.context); | |
35 | +class _SectionPageView extends StatelessWidget { | |
36 | + const _SectionPageView(this.context); | |
34 | 37 | |
35 | 38 | final BuildContext context; |
36 | 39 | |
37 | - void _headerActionEvent(HeaderActionType type) { | |
38 | - if (type == HeaderActionType.video) { | |
39 | - pushNamed(AppRouteName.reAfter); | |
40 | - } else if (type == HeaderActionType.phase) { | |
41 | - pushNamed(AppRouteName.lesson); | |
42 | - } else if (type == HeaderActionType.listen) { | |
43 | - pushNamed(AppRouteName.listen); | |
44 | - } else if (type == HeaderActionType.shop) { | |
45 | - pushNamed(AppRouteName.shop); | |
46 | - } else if (type == HeaderActionType.user) { | |
47 | - pushNamed(AppRouteName.user); | |
48 | - } else if (type == HeaderActionType.home) { | |
49 | - Navigator.pop(context); | |
50 | - } | |
51 | - } | |
52 | - | |
53 | 40 | @override |
54 | 41 | Widget build(BuildContext context) { |
55 | - final bloc = BlocProvider.of<HomeBloc>(context); | |
56 | - return BlocListener<HomeBloc, HomeState>( | |
42 | + final bloc = BlocProvider.of<SectionBloc>(context); | |
43 | + return BlocListener<SectionBloc, SectionState>( | |
57 | 44 | listener: (context, state) { |
58 | 45 | if (state is RequestVideoLessonState) { |
59 | - final videoUrl = bloc.processEntity?.videos?.videoUrl??''; | |
46 | + final videoUrl = bloc.processEntity?.videos?.videoUrl ?? ''; | |
60 | 47 | var title = ''; |
61 | 48 | if (state.type == 1) { |
62 | 49 | title = 'song'; |
... | ... | @@ -73,9 +60,13 @@ class _HomePageView extends StatelessWidget { |
73 | 60 | if (videoUrl.isEmpty || !videoUrl.contains('http')) { |
74 | 61 | return; |
75 | 62 | } |
76 | - pushNamed(AppRouteName.lookVideo,arguments: {'videoUrl':videoUrl,'title':title,'courseLessonId':state.courseLessonId}).then((value) { | |
63 | + pushNamed(AppRouteName.lookVideo, arguments: { | |
64 | + 'videoUrl': videoUrl, | |
65 | + 'title': title, | |
66 | + 'courseLessonId': state.courseLessonId | |
67 | + }).then((value) { | |
77 | 68 | if (value != null) { |
78 | - Map<String,String> dataMap = value as Map<String,String>; | |
69 | + Map<String, String> dataMap = value as Map<String, String>; | |
79 | 70 | bloc.add(RequestExitClassEvent( |
80 | 71 | dataMap['courseLessonId']!, |
81 | 72 | '0', |
... | ... | @@ -87,35 +78,37 @@ class _HomePageView extends StatelessWidget { |
87 | 78 | } |
88 | 79 | |
89 | 80 | if (state is RequestEnterClassState) { |
90 | - if (state.courseType != 3 && state.courseType != 4) {///视频类型 | |
81 | + if (state.courseType != 3 && state.courseType != 4) { | |
82 | + ///视频类型 | |
91 | 83 | ///获取视频课程内容 |
92 | - bloc.add(RequestVideoLessonEvent(state.courseLessonId,state.courseType)); | |
84 | + bloc.add(RequestVideoLessonEvent( | |
85 | + state.courseLessonId, state.courseType)); | |
93 | 86 | return; |
94 | 87 | } |
95 | 88 | |
96 | - if (state.courseType == 4) {//绘本 | |
97 | - pushNamed(AppRouteName.reading, arguments: {'courseLessonId':state.courseLessonId}).then((value) { | |
89 | + if (state.courseType == 4) { | |
90 | + //绘本 | |
91 | + pushNamed(AppRouteName.reading, | |
92 | + arguments: {'courseLessonId': state.courseLessonId}) | |
93 | + .then((value) { | |
98 | 94 | if (value != null) { |
99 | - Map<String,String> dataMap = value as Map<String,String>; | |
95 | + Map<String, String> dataMap = value as Map<String, String>; | |
100 | 96 | bloc.add(RequestExitClassEvent( |
101 | - dataMap['courseLessonId']!, | |
102 | - dataMap['currentStep']!, | |
103 | - '0' | |
104 | - )); | |
97 | + dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); | |
105 | 98 | } |
106 | 99 | }); |
107 | 100 | return; |
108 | 101 | } |
109 | 102 | |
110 | - if (state.courseType == 3) {//练习 | |
111 | - pushNamed(AppRouteName.topicPic,arguments: {'courseLessonId':state.courseLessonId}).then((value) { | |
103 | + if (state.courseType == 3) { | |
104 | + //练习 | |
105 | + pushNamed(AppRouteName.topicPic, | |
106 | + arguments: {'courseLessonId': state.courseLessonId}) | |
107 | + .then((value) { | |
112 | 108 | if (value != null) { |
113 | - Map<String,String> dataMap = value as Map<String,String>; | |
109 | + Map<String, String> dataMap = value as Map<String, String>; | |
114 | 110 | bloc.add(RequestExitClassEvent( |
115 | - dataMap['courseLessonId']!, | |
116 | - dataMap['currentStep']!, | |
117 | - '0' | |
118 | - )); | |
111 | + dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); | |
119 | 112 | } |
120 | 113 | }); |
121 | 114 | return; |
... | ... | @@ -126,9 +119,9 @@ class _HomePageView extends StatelessWidget { |
126 | 119 | ); |
127 | 120 | } |
128 | 121 | |
129 | - Widget _homeView() => BlocBuilder<HomeBloc, HomeState>( | |
130 | - builder: (context, state) { | |
131 | - final bloc = BlocProvider.of<HomeBloc>(context); | |
122 | + Widget _homeView() => | |
123 | + BlocBuilder<SectionBloc, SectionState>(builder: (context, state) { | |
124 | + final bloc = BlocProvider.of<SectionBloc>(context); | |
132 | 125 | return Scaffold( |
133 | 126 | body: Container( |
134 | 127 | color: Colors.white, |
... | ... | @@ -136,19 +129,17 @@ class _HomePageView extends StatelessWidget { |
136 | 129 | child: Column( |
137 | 130 | mainAxisAlignment: MainAxisAlignment.spaceBetween, |
138 | 131 | children: [ |
139 | - HomeTabHeaderWidget( | |
140 | - entity: bloc.modelData, | |
141 | - actionTap: (HeaderActionType type) { | |
142 | - _headerActionEvent(type); | |
143 | - }, | |
144 | - ), | |
132 | + SectionHeaderWidget( | |
133 | + title: bloc.courseUnitDetail.name, | |
134 | + courseModuleCode: bloc.courseUnitEntity.courseModuleCode), | |
145 | 135 | Expanded( |
146 | 136 | child: ListView.builder( |
147 | - itemCount: bloc.modelData?.totalCourseLesson??0, | |
137 | + itemCount: bloc.courseSectionDatas?.length ?? 0, | |
148 | 138 | scrollDirection: Axis.horizontal, |
149 | 139 | itemBuilder: (BuildContext context, int index) { |
150 | - CourseCourseLessons? data = bloc.modelData?.courseLessons?[index]; | |
151 | - if (data?.courseType == 5) { | |
140 | + CourseSectionEntity sectionData = | |
141 | + bloc.courseSectionDatas![index]; | |
142 | + if (sectionData.courseType == 5) { | |
152 | 143 | //彩蛋 |
153 | 144 | return GestureDetector( |
154 | 145 | onTap: () { |
... | ... | @@ -156,15 +147,17 @@ class _HomePageView extends StatelessWidget { |
156 | 147 | pushNamed(AppRouteName.login); |
157 | 148 | return; |
158 | 149 | } |
159 | - if (data!.lock!) { | |
150 | + if (sectionData.lock == true) { | |
160 | 151 | showToast('当前课程暂未解锁'); |
161 | 152 | return; |
162 | 153 | } |
154 | + | |
163 | 155 | ///进入课堂 |
164 | - bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); | |
156 | + bloc.add(RequestEnterClassEvent( | |
157 | + sectionData.id.toString(), sectionData.courseType)); | |
165 | 158 | }, |
166 | - child: HomeBoundsItem( | |
167 | - imageUrl: data?.coverUrl, | |
159 | + child: SectionBoundsItem( | |
160 | + imageUrl: sectionData.coverUrl, | |
168 | 161 | ), |
169 | 162 | ); |
170 | 163 | } else { |
... | ... | @@ -174,16 +167,18 @@ class _HomePageView extends StatelessWidget { |
174 | 167 | pushNamed(AppRouteName.login); |
175 | 168 | return; |
176 | 169 | } |
177 | - if (data!.lock!) { | |
170 | + if (sectionData.lock == true) { | |
178 | 171 | showToast('当前课程暂未解锁'); |
179 | 172 | return; |
180 | 173 | } |
174 | + | |
181 | 175 | ///进入课堂 |
182 | - bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); | |
176 | + bloc.add(RequestEnterClassEvent( | |
177 | + sectionData.id.toString(), sectionData.courseType)); | |
183 | 178 | }, |
184 | - child: HomeVideoItem( | |
185 | - entity: bloc.modelData, | |
186 | - lessons: data, | |
179 | + child: SectionVideoItem( | |
180 | + unitEntity: bloc.courseUnitEntity, | |
181 | + lessons: sectionData, | |
187 | 182 | ), |
188 | 183 | ); |
189 | 184 | } |
... | ... | @@ -200,17 +195,26 @@ class _HomePageView extends StatelessWidget { |
200 | 195 | ), |
201 | 196 | Container( |
202 | 197 | decoration: BoxDecoration( |
203 | - color: CourseModuleModel(bloc.modelData?.courseModuleCode??'Phase-1').color, | |
198 | + color: CourseModuleModel( | |
199 | + bloc.courseUnitEntity.courseModuleCode ?? | |
200 | + 'Phase-1') | |
201 | + .color, | |
204 | 202 | borderRadius: BorderRadius.circular(14.5.r), |
205 | 203 | ), |
206 | - padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 24.w), | |
204 | + padding: EdgeInsets.symmetric( | |
205 | + vertical: 8.h, horizontal: 24.w), | |
207 | 206 | child: Text( |
208 | - '${(bloc.modelData?.nowCourseLesson??0)}/${bloc.modelData?.totalCourseLesson??0}', | |
209 | - style: TextStyle(color: Colors.white, fontSize: 12.sp), | |
207 | + '${(bloc.courseUnitEntity.nowStep ?? 0)}/${bloc.courseUnitEntity.total ?? 0}', | |
208 | + style: TextStyle( | |
209 | + color: Colors.white, fontSize: 12.sp), | |
210 | 210 | ), |
211 | 211 | ), |
212 | 212 | Image.asset( |
213 | - CourseModuleModel(bloc.modelData?.courseModuleCode??'Phase-1').courseModuleLogo.assetPng, | |
213 | + CourseModuleModel( | |
214 | + bloc.courseUnitEntity.courseModuleCode ?? | |
215 | + 'Phase-1') | |
216 | + .courseModuleLogo | |
217 | + .assetPng, | |
214 | 218 | height: 47.h, |
215 | 219 | width: 80.w, |
216 | 220 | // color: Colors.red, | ... | ... |
lib/pages/home/widgets/home_vidoe_item.dart renamed to lib/pages/section/widgets/home_video_item.dart
... | ... | @@ -2,15 +2,16 @@ import 'package:flutter/material.dart'; |
2 | 2 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
3 | 3 | import 'package:wow_english/common/extension/string_extension.dart'; |
4 | 4 | import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
5 | -import 'package:wow_english/models/course_entity.dart'; | |
6 | 5 | |
6 | +import '../../../models/course_section_entity.dart'; | |
7 | +import '../../../models/course_unit_entity.dart'; | |
7 | 8 | import '../courese_module_model.dart'; |
8 | 9 | |
9 | -class HomeVideoItem extends StatelessWidget { | |
10 | - const HomeVideoItem({super.key, this.lessons, this.entity}); | |
10 | +class SectionVideoItem extends StatelessWidget { | |
11 | + const SectionVideoItem({super.key, this.lessons, this.unitEntity}); | |
11 | 12 | |
12 | - final CourseEntity? entity; | |
13 | - final CourseCourseLessons? lessons; | |
13 | + final CourseUnitEntity? unitEntity; | |
14 | + final CourseSectionEntity? lessons; | |
14 | 15 | |
15 | 16 | @override |
16 | 17 | Widget build(BuildContext context) { |
... | ... | @@ -50,7 +51,7 @@ class HomeVideoItem extends StatelessWidget { |
50 | 51 | width: 2, |
51 | 52 | color: const Color(0xFF140C10), |
52 | 53 | ), |
53 | - color: CourseModuleModel(entity?.courseModuleCode??'Phase-1').color, | |
54 | + color: CourseModuleModel(unitEntity?.courseModuleCode??'Phase-1').color, | |
54 | 55 | borderRadius: BorderRadius.circular(6) |
55 | 56 | ), |
56 | 57 | padding: EdgeInsets.symmetric(horizontal: 10.w), | ... | ... |
lib/pages/home/widgets/home_bouns_item.dart renamed to lib/pages/section/widgets/section_bouns_item.dart
... | ... | @@ -2,8 +2,8 @@ import 'package:flutter/cupertino.dart'; |
2 | 2 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
3 | 3 | import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
4 | 4 | |
5 | -class HomeBoundsItem extends StatelessWidget { | |
6 | - const HomeBoundsItem({super.key, this.imageUrl}); | |
5 | +class SectionBoundsItem extends StatelessWidget { | |
6 | + const SectionBoundsItem({super.key, this.imageUrl}); | |
7 | 7 | |
8 | 8 | final String? imageUrl; |
9 | 9 | ... | ... |
lib/pages/section/widgets/section_header_widget.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | |
2 | +import 'package:flutter_bloc/flutter_bloc.dart'; | |
3 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | |
4 | +import 'package:wow_english/common/extension/string_extension.dart'; | |
5 | +import 'package:wow_english/pages/user/bloc/user_bloc.dart'; | |
6 | + | |
7 | +import '../courese_module_model.dart'; | |
8 | + | |
9 | +class SectionHeaderWidget extends StatelessWidget { | |
10 | + const SectionHeaderWidget({super.key, this.title, this.courseModuleCode}); | |
11 | + | |
12 | + final String? title; | |
13 | + | |
14 | + final String? courseModuleCode; | |
15 | + | |
16 | + @override | |
17 | + Widget build(BuildContext context) { | |
18 | + return BlocBuilder<UserBloc, UserState>( | |
19 | + builder: (context, state) { | |
20 | + return Container( | |
21 | + height: 45, | |
22 | + width: double.infinity, | |
23 | + color: CourseModuleModel(courseModuleCode ?? 'Phase-1').color, | |
24 | + padding: EdgeInsets.symmetric(horizontal: 9.5.w), | |
25 | + child: Row( | |
26 | + children: [ | |
27 | + ScreenUtil().bottomBarHeight.horizontalSpace, | |
28 | + GestureDetector( | |
29 | + onTap: () { | |
30 | + Navigator.pop(context); | |
31 | + }, | |
32 | + child: Container( | |
33 | + alignment: Alignment.center, | |
34 | + child: Image.asset( | |
35 | + 'back_around'.assetPng, | |
36 | + height: 40.h, | |
37 | + width: 40.w, | |
38 | + ), | |
39 | + ), | |
40 | + ), | |
41 | + 20.horizontalSpace, | |
42 | + Expanded( | |
43 | + child: Text( | |
44 | + title ?? | |
45 | + CourseModuleModel(courseModuleCode ?? 'Phase-1') | |
46 | + .courseModuleTitle, | |
47 | + textAlign: TextAlign.left, | |
48 | + style: const TextStyle(color: Colors.white, fontSize: 30.0), | |
49 | + )), | |
50 | + ScreenUtil().bottomBarHeight.horizontalSpace, | |
51 | + ], | |
52 | + )); | |
53 | + }, | |
54 | + ); | |
55 | + } | |
56 | +} | ... | ... |
lib/pages/shopping/bloc.dart
... | ... | @@ -80,10 +80,9 @@ class ShoppingBloc extends Bloc<ShoppingEvent, ShoppingState> { |
80 | 80 | await fluwx?.registerApi(appId: "wx365e5a79956a450a", |
81 | 81 | universalLink: "https://app-api.wowenglish.com.cn/app/"); |
82 | 82 | wxPayResponseListener = (WeChatResponse response) { |
83 | - debugPrint("WqfPay wxPayResponseListener $response"); | |
83 | + debugPrint("wxPayResponseListener $response"); | |
84 | 84 | if (response is WeChatPaymentResponse) { |
85 | 85 | if (response.errCode == 0) { |
86 | - debugPrint("WqfPay wxPayResponseListener response=${response.errCode}"); | |
87 | 86 | showToast("支付成功"); |
88 | 87 | // Log.d("emitter isDone=${emitter.isDone}"); |
89 | 88 | ... | ... |
lib/pages/tab/tab_page.dart
1 | 1 | import 'package:flutter/material.dart'; |
2 | 2 | import 'package:flutter_bloc/flutter_bloc.dart'; |
3 | -import 'package:wow_english/pages/home/home_page.dart'; | |
4 | -import 'package:wow_english/pages/lessons/lesson_page.dart'; | |
3 | +import 'package:wow_english/pages/module/module_page.dart'; | |
5 | 4 | |
5 | +import '../unit/view.dart'; | |
6 | 6 | import 'blocs/tab_bloc.dart'; |
7 | 7 | |
8 | 8 | class TabPage extends StatelessWidget { |
9 | 9 | const TabPage({super.key}); |
10 | 10 | |
11 | 11 | final _pages =const <Widget>[ |
12 | - HomePage(), | |
13 | - LessonPage() | |
12 | + UnitPage(), | |
13 | + ModulePage() | |
14 | 14 | ]; |
15 | 15 | |
16 | 16 | final _tabIcons = const <Icon>[ | ... | ... |
lib/pages/unit/bloc.dart
0 → 100644
1 | +import 'package:bloc/bloc.dart'; | |
2 | +import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; | |
3 | + | |
4 | +import '../../common/request/dao/lesson_dao.dart'; | |
5 | +import '../../common/request/exception.dart'; | |
6 | +import '../../models/course_module_entity.dart'; | |
7 | +import '../../models/course_unit_entity.dart'; | |
8 | +import '../../route/route.dart'; | |
9 | +import '../../utils/loading.dart'; | |
10 | +import '../../utils/toast_util.dart'; | |
11 | +import 'event.dart'; | |
12 | +import 'state.dart'; | |
13 | + | |
14 | +class UnitBloc extends Bloc<UnitEvent, UnitState> { | |
15 | + | |
16 | + CourseModuleEntity? _moduleEntity; | |
17 | + | |
18 | + CourseModuleEntity? get moduleEntity => _moduleEntity; | |
19 | + | |
20 | + CourseUnitEntity? _unitData; | |
21 | + | |
22 | + CourseUnitEntity? get unitData => _unitData; | |
23 | + | |
24 | + | |
25 | + UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { | |
26 | + on<RequestUnitDataEvent>(_requestData); | |
27 | + } | |
28 | + | |
29 | + void _requestData(RequestUnitDataEvent event, Emitter<UnitState> emitter) async { | |
30 | + try { | |
31 | + await loading(() async { | |
32 | + _unitData = await LessonDao.courseUnit(event.moduleId); | |
33 | + emitter(UnitDataLoadState()); | |
34 | + }); | |
35 | + } catch (e) { | |
36 | + if (e is ApiException) { | |
37 | + showToast(e.message ?? '请求失败,请检查网络连接'); | |
38 | + } | |
39 | + } | |
40 | + } | |
41 | + | |
42 | + String? getCourseModuleCode() { | |
43 | + return _moduleEntity?.code ?? _unitData?.courseModuleCode; | |
44 | + } | |
45 | + | |
46 | + void headerActionEvent(HeaderActionType type) { | |
47 | + if (type == HeaderActionType.video) { | |
48 | + pushNamed(AppRouteName.reAfter); | |
49 | + } else if (type == HeaderActionType.phase) { | |
50 | + pushNamed(AppRouteName.courseModule); | |
51 | + } else if (type == HeaderActionType.listen) { | |
52 | + pushNamed(AppRouteName.listen); | |
53 | + } else if (type == HeaderActionType.shop) { | |
54 | + pushNamed(AppRouteName.shop); | |
55 | + } else if (type == HeaderActionType.user) { | |
56 | + pushNamed(AppRouteName.user); | |
57 | + } | |
58 | + } | |
59 | +} | ... | ... |
lib/pages/unit/event.dart
0 → 100644
lib/pages/unit/state.dart
0 → 100644
lib/pages/unit/view.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | |
2 | +import 'package:flutter_bloc/flutter_bloc.dart'; | |
3 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | |
4 | +import 'package:wow_english/pages/unit/state.dart'; | |
5 | +import 'package:wow_english/pages/unit/widget/course_unit_item.dart'; | |
6 | +import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; | |
7 | +import 'package:wow_english/route/route.dart'; | |
8 | + | |
9 | +import '../../models/course_module_entity.dart'; | |
10 | +import '../../models/course_unit_entity.dart'; | |
11 | +import '../../utils/toast_util.dart'; | |
12 | +import 'bloc.dart'; | |
13 | +import 'event.dart'; | |
14 | + | |
15 | +// 课程列表页(多unit,参考口语星球的框或分割标志) | |
16 | +class UnitPage extends StatelessWidget { | |
17 | + const UnitPage({super.key, this.courseModuleEntity}); | |
18 | + | |
19 | + /// 模块 | |
20 | + final CourseModuleEntity? courseModuleEntity; | |
21 | + | |
22 | + @override | |
23 | + Widget build(BuildContext context) { | |
24 | + return BlocProvider( | |
25 | + create: (BuildContext context) => UnitBloc(courseModuleEntity) | |
26 | + ..add(RequestUnitDataEvent(courseModuleEntity?.id)), | |
27 | + child: Builder(builder: (context) => _buildPage(context)), | |
28 | + ); | |
29 | + } | |
30 | + | |
31 | + Widget _buildPage(BuildContext context) { | |
32 | + return BlocBuilder<UnitBloc, UnitState>(builder: (context, state) { | |
33 | + final bloc = BlocProvider.of<UnitBloc>(context); | |
34 | + return Scaffold( | |
35 | + body: Container( | |
36 | + color: Colors.white, | |
37 | + child: Center( | |
38 | + child: Column( | |
39 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
40 | + children: [ | |
41 | + HomeTabHeaderWidget( | |
42 | + courseModuleCode: bloc.getCourseModuleCode(), | |
43 | + actionTap: (HeaderActionType type) { | |
44 | + bloc.headerActionEvent(type); | |
45 | + }, | |
46 | + ), | |
47 | + Expanded( | |
48 | + child: Container( | |
49 | + margin: EdgeInsets.symmetric(horizontal: 12.w), | |
50 | + child: ListView.builder( | |
51 | + itemCount: | |
52 | + bloc.unitData?.courseUnitVOList?.length ?? 0, | |
53 | + scrollDirection: Axis.horizontal, | |
54 | + itemBuilder: (BuildContext context, int index) { | |
55 | + CourseUnitDetail? data = | |
56 | + bloc.unitData?.courseUnitVOList?[index]; | |
57 | + return GestureDetector( | |
58 | + onTap: () { | |
59 | + if (data.lock == true) { | |
60 | + showToast('当前unit暂未解锁'); | |
61 | + return; | |
62 | + } | |
63 | + | |
64 | + pushNamed(AppRouteName.courseSection, | |
65 | + arguments: { | |
66 | + 'courseUnitEntity': bloc.unitData, | |
67 | + 'courseUnitDetail': data | |
68 | + }); | |
69 | + }, | |
70 | + child: CourseUnitItem( | |
71 | + unitEntity: bloc.unitData!, | |
72 | + unitLesson: data!, | |
73 | + ), | |
74 | + ); | |
75 | + })), | |
76 | + ), | |
77 | + SafeArea( | |
78 | + child: Column( | |
79 | + children: [ | |
80 | + 6.verticalSpace, | |
81 | + ], | |
82 | + ), | |
83 | + ) | |
84 | + ], | |
85 | + ), | |
86 | + ), | |
87 | + ), | |
88 | + ); | |
89 | + }); | |
90 | + } | |
91 | +} | ... | ... |
lib/pages/unit/widget/course_unit_item.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | |
2 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | |
3 | +import 'package:wow_english/common/extension/string_extension.dart'; | |
4 | +import 'package:wow_english/common/widgets/ow_image_widget.dart'; | |
5 | + | |
6 | +import '../../../models/course_unit_entity.dart'; | |
7 | + | |
8 | +class CourseUnitItem extends StatelessWidget { | |
9 | + const CourseUnitItem( | |
10 | + {super.key, required this.unitEntity, required this.unitLesson}); | |
11 | + | |
12 | + final CourseUnitEntity unitEntity; | |
13 | + final CourseUnitDetail unitLesson; | |
14 | + | |
15 | + @override | |
16 | + Widget build(BuildContext context) { | |
17 | + return Padding( | |
18 | + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 24.h), | |
19 | + child: Container( | |
20 | + width: 165.w, | |
21 | + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 24.h), | |
22 | + decoration: BoxDecoration( | |
23 | + image: DecorationImage( | |
24 | + image: AssetImage('gendubeij'.assetPng), fit: BoxFit.fill), | |
25 | + ), | |
26 | + child: Column( | |
27 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
28 | + children: [ | |
29 | + Expanded( | |
30 | + child: Container( | |
31 | + decoration: BoxDecoration( | |
32 | + border: Border.all( | |
33 | + width: 2, | |
34 | + color: const Color(0xFF140C10), | |
35 | + ), | |
36 | + borderRadius: BorderRadius.circular(6)), | |
37 | + child: OwImageWidget( | |
38 | + name: unitLesson.coverUrl ?? '', | |
39 | + fit: BoxFit.fitHeight, | |
40 | + ), | |
41 | + )), | |
42 | + 20.verticalSpace, | |
43 | + SizedBox( | |
44 | + height: 40.h, | |
45 | + child: Text( | |
46 | + unitLesson.name ?? '', | |
47 | + maxLines: 2, | |
48 | + overflow: TextOverflow.ellipsis, | |
49 | + style: | |
50 | + TextStyle(fontSize: 11.sp, color: const Color(0xFF140C10)), | |
51 | + ), | |
52 | + ) | |
53 | + ], | |
54 | + ), | |
55 | + ), | |
56 | + ); | |
57 | + } | |
58 | +} | ... | ... |
lib/pages/home/widgets/home_tab_header_widget.dart renamed to lib/pages/unit/widget/home_tab_header_widget.dart
... | ... | @@ -5,8 +5,7 @@ import 'package:wow_english/common/extension/string_extension.dart'; |
5 | 5 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
6 | 6 | |
7 | 7 | import '../../../common/core/app_config_helper.dart'; |
8 | -import '../../../models/course_entity.dart'; | |
9 | -import '../courese_module_model.dart'; | |
8 | +import '../../section/courese_module_model.dart'; | |
10 | 9 | |
11 | 10 | enum HeaderActionType { |
12 | 11 | //视频跟读 |
... | ... | @@ -19,14 +18,13 @@ enum HeaderActionType { |
19 | 18 | shop, |
20 | 19 | //个人信息 |
21 | 20 | user, |
22 | - //返回到(模块选择)首页 | |
23 | - home, | |
24 | 21 | } |
25 | 22 | |
26 | 23 | class HomeTabHeaderWidget extends StatelessWidget { |
27 | - const HomeTabHeaderWidget({super.key, this.entity, this.actionTap}); | |
24 | + const HomeTabHeaderWidget({super.key, this.courseModuleCode, this.actionTap}); | |
25 | + | |
26 | + final String? courseModuleCode; | |
28 | 27 | |
29 | - final CourseEntity? entity; | |
30 | 28 | final Function(HeaderActionType type)? actionTap; |
31 | 29 | |
32 | 30 | @override |
... | ... | @@ -37,16 +35,14 @@ class HomeTabHeaderWidget extends StatelessWidget { |
37 | 35 | height: 45, |
38 | 36 | width: double.infinity, |
39 | 37 | color: |
40 | - CourseModuleModel(entity?.courseModuleCode ?? 'Phase-1').color, | |
38 | + CourseModuleModel(courseModuleCode ?? 'Phase-1').color, | |
41 | 39 | padding: EdgeInsets.symmetric(horizontal: 9.5.w), |
42 | 40 | child: Row( |
43 | 41 | children: [ |
44 | 42 | ScreenUtil().bottomBarHeight.horizontalSpace, |
45 | 43 | GestureDetector( |
46 | 44 | onTap: () { |
47 | - if (actionTap != null) { | |
48 | - actionTap!(HeaderActionType.home); | |
49 | - } | |
45 | + Navigator.pop(context); | |
50 | 46 | }, |
51 | 47 | child: Container( |
52 | 48 | alignment: Alignment.center, |
... | ... | @@ -96,7 +92,7 @@ class HomeTabHeaderWidget extends StatelessWidget { |
96 | 92 | 20.horizontalSpace, |
97 | 93 | Expanded( |
98 | 94 | child: Text( |
99 | - CourseModuleModel(entity?.courseModuleCode ?? 'Phase-1') | |
95 | + CourseModuleModel(courseModuleCode ?? 'Phase-1') | |
100 | 96 | .courseModuleTitle, |
101 | 97 | textAlign: TextAlign.left, |
102 | 98 | style: const TextStyle(color: Colors.white, fontSize: 30.0), |
... | ... | @@ -122,8 +118,8 @@ class HomeTabHeaderWidget extends StatelessWidget { |
122 | 118 | } |
123 | 119 | }, |
124 | 120 | icon: Image.asset('listen'.assetPng)), |
125 | - Visibility( | |
126 | - visible: !AppConfigHelper.shouldHidePay(), | |
121 | + Offstage( | |
122 | + offstage: AppConfigHelper.shouldHidePay(), | |
127 | 123 | child: IconButton( |
128 | 124 | onPressed: () { |
129 | 125 | if (actionTap != null) { | ... | ... |
lib/pages/user/user_page.dart
... | ... | @@ -4,6 +4,7 @@ import 'package:flutter/services.dart'; |
4 | 4 | import 'package:flutter/material.dart'; |
5 | 5 | import 'package:flutter_bloc/flutter_bloc.dart'; |
6 | 6 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
7 | +import 'package:wow_english/common/core/app_config_helper.dart'; | |
7 | 8 | import 'package:wow_english/common/core/app_consts.dart'; |
8 | 9 | import 'package:wow_english/common/core/assets_const.dart'; |
9 | 10 | import 'package:wow_english/common/core/user_util.dart'; |
... | ... | @@ -163,9 +164,8 @@ class _UserView extends StatelessWidget { |
163 | 164 | ), |
164 | 165 | ), |
165 | 166 | 12.verticalSpace, |
166 | - // todo 为了过审,把测试账号兑换功能下掉 | |
167 | 167 | Offstage( |
168 | - offstage: UserUtil.getUser()?.phoneNum == '17730280759', | |
168 | + offstage: AppConfigHelper.shouldHidePay(), | |
169 | 169 | child: OutlinedButton( |
170 | 170 | onPressed: () => pushNamed(AppRouteName.exLesson), |
171 | 171 | style: normalButtonStyle, |
... | ... | @@ -175,7 +175,7 @@ class _UserView extends StatelessWidget { |
175 | 175 | )), |
176 | 176 | ), |
177 | 177 | Offstage( |
178 | - offstage: UserUtil.getUser()?.phoneNum == '17730280759', | |
178 | + offstage: AppConfigHelper.shouldHidePay(), | |
179 | 179 | child: 12.verticalSpace, |
180 | 180 | ), |
181 | 181 | OutlinedButton( | ... | ... |
lib/route/route.dart
... | ... | @@ -3,22 +3,21 @@ import 'package:flutter/material.dart'; |
3 | 3 | import 'package:wow_english/app/splash_page.dart'; |
4 | 4 | import 'package:wow_english/common/pages/wow_web_page.dart'; |
5 | 5 | import 'package:wow_english/generated/json/base/json_convert_content.dart'; |
6 | +import 'package:wow_english/models/course_unit_entity.dart'; | |
6 | 7 | import 'package:wow_english/models/product_entity.dart'; |
7 | 8 | import 'package:wow_english/pages/games/view.dart'; |
8 | -import 'package:wow_english/pages/home/home_page.dart'; | |
9 | -import 'package:wow_english/pages/lessons/lesson_page.dart'; | |
9 | +import 'package:wow_english/pages/home/view.dart'; | |
10 | 10 | import 'package:wow_english/pages/listen/listen_page.dart'; |
11 | 11 | import 'package:wow_english/pages/login/forgetpwd/forget_password_home_page.dart'; |
12 | 12 | import 'package:wow_english/pages/login/loginpage/login_page.dart'; |
13 | 13 | import 'package:wow_english/pages/login/setpwd/set_pwd_page.dart'; |
14 | -import 'package:wow_english/pages/moduleSelect/view.dart'; | |
14 | +import 'package:wow_english/pages/module/module_page.dart'; | |
15 | 15 | import 'package:wow_english/pages/practice/topic_picture_page.dart'; |
16 | 16 | import 'package:wow_english/pages/repeatafter/repeat_after_page.dart'; |
17 | 17 | import 'package:wow_english/pages/repeataftercontent/repeat_after_content_page.dart'; |
18 | 18 | import 'package:wow_english/pages/shop/exchane/exchange_lesson_page.dart'; |
19 | 19 | import 'package:wow_english/pages/shop/exchangelist/exchange_lesson_list_page.dart'; |
20 | 20 | import 'package:wow_english/pages/shop/home/shop_home_page.dart'; |
21 | -import 'package:wow_english/pages/tab/tab_page.dart'; | |
22 | 21 | import 'package:wow_english/pages/user/information/user_information_page.dart'; |
23 | 22 | import 'package:wow_english/pages/user/modify/modify_user_avatar_page.dart'; |
24 | 23 | import 'package:wow_english/pages/user/modify/modify_user_information_page.dart'; |
... | ... | @@ -26,24 +25,28 @@ import 'package:wow_english/pages/user/setting/setting_page.dart'; |
26 | 25 | import 'package:wow_english/pages/user/user_page.dart'; |
27 | 26 | import 'package:wow_english/pages/video/lookvideo/look_video_page.dart'; |
28 | 27 | |
28 | +import '../models/course_module_entity.dart'; | |
29 | 29 | import '../pages/reading/reading_page.dart'; |
30 | +import '../pages/section/section_page.dart'; | |
30 | 31 | import '../pages/shopping/view.dart'; |
32 | +import '../pages/tab/tab_page.dart'; | |
33 | +import '../pages/unit/view.dart'; | |
31 | 34 | import '../pages/user/setting/delete_account_page.dart'; |
32 | 35 | import '../pages/user/setting/reback_page.dart'; |
33 | -import '../utils/log_util.dart'; | |
34 | 36 | |
35 | 37 | class AppRouteName { |
36 | 38 | static const String splash = 'splash'; |
37 | 39 | static const String login = 'login'; |
38 | - static const String moduleSelect = 'moduleSelect'; | |
39 | - static const String games = 'games'; | |
40 | 40 | static const String home = 'home'; |
41 | + static const String games = 'games'; | |
41 | 42 | static const String fogPwd = 'fogPwd'; |
42 | 43 | |
43 | 44 | /// 设置密码,修改密码;不要自己调用,使用[SetPassWordPage.push]方法,隐藏这种实现 |
44 | 45 | //static const String setPwd = 'setPwd'; |
45 | 46 | static const String webView = 'webView'; |
46 | - static const String lesson = 'lesson'; | |
47 | + static const String courseModule = 'courseModules'; | |
48 | + static const String courseUnit = 'courseUnits'; | |
49 | + static const String courseSection = 'courseSections'; | |
47 | 50 | static const String listen = 'listen'; |
48 | 51 | static const String shop = 'shop'; |
49 | 52 | static const String exLesson = 'exLesson'; |
... | ... | @@ -55,6 +58,7 @@ class AppRouteName { |
55 | 58 | |
56 | 59 | /// 用户详细信息页 |
57 | 60 | static const String userInformation = 'userInformation'; |
61 | + | |
58 | 62 | /// 修改用户头像 |
59 | 63 | static const String userAvatar = 'userAvatar'; |
60 | 64 | |
... | ... | @@ -62,15 +66,19 @@ class AppRouteName { |
62 | 66 | //static const String userModifyInformation = 'userModifyInformation'; |
63 | 67 | ///看视频 |
64 | 68 | static const String lookVideo = 'lookVideo'; |
69 | + | |
65 | 70 | ///绘本 |
66 | 71 | static const String reading = 'reading'; |
72 | + | |
67 | 73 | ///视频跟读详情 |
68 | 74 | static const String readAfterContent = 'readAfterContent'; |
69 | 75 | |
70 | 76 | ///设置 |
71 | 77 | static const String setting = 'setting'; |
78 | + | |
72 | 79 | ///注销账号 |
73 | 80 | static const String deleteAccount = 'deleteAccount'; |
81 | + | |
74 | 82 | ///帮助与反馈 |
75 | 83 | static const String reBack = 'reBack'; |
76 | 84 | |
... | ... | @@ -93,25 +101,42 @@ class AppRouter { |
93 | 101 | transitionsBuilder: (_, __, ___, child) => child); |
94 | 102 | case AppRouteName.login: |
95 | 103 | // 是否默认密码登录,修改密码后跳登录页,优先密码登录体验好点 |
96 | - final bool showPasswordPage = (settings.arguments as Map?)?.getOrNull('showPasswordPage') as bool? ?? false; | |
97 | - return CupertinoPageRoute(builder: (_) => LoginPage(preferencesPasswordLogin: showPasswordPage)); | |
98 | - case AppRouteName.moduleSelect: | |
99 | - return CupertinoPageRoute(builder: (_) => const ModuleSelectPage()); | |
104 | + final bool showPasswordPage = (settings.arguments as Map?) | |
105 | + ?.getOrNull('showPasswordPage') as bool? ?? | |
106 | + false; | |
107 | + return CupertinoPageRoute( | |
108 | + builder: (_) => | |
109 | + LoginPage(preferencesPasswordLogin: showPasswordPage)); | |
110 | + case AppRouteName.home: | |
111 | + return CupertinoPageRoute(builder: (_) => const HomePage()); | |
100 | 112 | case AppRouteName.games: |
101 | 113 | return CupertinoPageRoute(builder: (_) => const GamesPage()); |
102 | - case AppRouteName.home: | |
103 | - var moduleId = ''; | |
114 | + case AppRouteName.fogPwd: | |
115 | + return CupertinoPageRoute( | |
116 | + builder: (_) => const ForgetPasswordHomePage()); | |
117 | + case AppRouteName.courseModule: | |
118 | + return CupertinoPageRoute(builder: (_) => const ModulePage()); | |
119 | + case AppRouteName.courseUnit: | |
120 | + CourseModuleEntity courseModuleEntity = CourseModuleEntity(); | |
104 | 121 | if (settings.arguments != null) { |
105 | - moduleId = (settings.arguments as Map)['moduleId'] as String; | |
122 | + courseModuleEntity = (settings.arguments as Map) | |
123 | + .getOrNull('courseModuleEntity') as CourseModuleEntity; | |
106 | 124 | } |
107 | 125 | return CupertinoPageRoute( |
108 | - builder: (_) => HomePage( | |
109 | - moduleId: moduleId, | |
110 | - )); | |
111 | - case AppRouteName.fogPwd: | |
112 | - return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage()); | |
113 | - case AppRouteName.lesson: | |
114 | - return CupertinoPageRoute(builder: (_) => const LessonPage()); | |
126 | + builder: (_) => UnitPage(courseModuleEntity: courseModuleEntity)); | |
127 | + case AppRouteName.courseSection: | |
128 | + CourseUnitEntity courseUnitEntity = CourseUnitEntity(); | |
129 | + CourseUnitDetail courseUnitDetail = CourseUnitDetail(); | |
130 | + if (settings.arguments != null) { | |
131 | + courseUnitEntity = (settings.arguments as Map) | |
132 | + .getOrNull('courseUnitEntity') as CourseUnitEntity; | |
133 | + courseUnitDetail = (settings.arguments as Map) | |
134 | + .getOrNull('courseUnitDetail') as CourseUnitDetail; | |
135 | + } | |
136 | + return CupertinoPageRoute( | |
137 | + builder: (_) => SectionPage( | |
138 | + courseUnitEntity: courseUnitEntity, | |
139 | + courseUnitDetail: courseUnitDetail)); | |
115 | 140 | case AppRouteName.listen: |
116 | 141 | return CupertinoPageRoute(builder: (_) => const ListenPage()); |
117 | 142 | case AppRouteName.shop: |
... | ... | @@ -121,11 +146,13 @@ class AppRouter { |
121 | 146 | if (settings.arguments != null && settings.arguments is ProductEntity) { |
122 | 147 | productEntity = settings.arguments as ProductEntity; |
123 | 148 | } |
124 | - return CupertinoPageRoute(builder: (_) => ShoppingPage(productEntity: productEntity)); | |
149 | + return CupertinoPageRoute( | |
150 | + builder: (_) => ShoppingPage(productEntity: productEntity)); | |
125 | 151 | case AppRouteName.exLesson: |
126 | 152 | return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage()); |
127 | 153 | case AppRouteName.exList: |
128 | - return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage()); | |
154 | + return CupertinoPageRoute( | |
155 | + builder: (_) => const ExchangeLessonListPage()); | |
129 | 156 | case AppRouteName.reAfter: |
130 | 157 | return CupertinoPageRoute(builder: (_) => const RepeatAfterPage()); |
131 | 158 | case AppRouteName.user: |
... | ... | @@ -153,19 +180,22 @@ class AppRouter { |
153 | 180 | case AppRouteName.topicPic: |
154 | 181 | var courseLessonId = ''; |
155 | 182 | if (settings.arguments != null) { |
156 | - courseLessonId = (settings.arguments as Map)['courseLessonId'] as String; | |
183 | + courseLessonId = | |
184 | + (settings.arguments as Map)['courseLessonId'] as String; | |
157 | 185 | } |
158 | - return CupertinoPageRoute(builder: (_) => TopicPicturePage(courseLessonId: courseLessonId)); | |
186 | + return CupertinoPageRoute( | |
187 | + builder: (_) => TopicPicturePage(courseLessonId: courseLessonId)); | |
159 | 188 | case AppRouteName.lookVideo: |
160 | 189 | final videoUrl = (settings.arguments as Map)['videoUrl'] as String; |
161 | 190 | final title = (settings.arguments as Map)['title'] as String?; |
162 | - final courseLessonId = (settings.arguments as Map)['courseLessonId'] as String?; | |
191 | + final courseLessonId = | |
192 | + (settings.arguments as Map)['courseLessonId'] as String?; | |
163 | 193 | return CupertinoPageRoute( |
164 | 194 | builder: (_) => LookVideoPage( |
165 | - videoUrl: videoUrl, | |
166 | - typeTitle: title, | |
167 | - courseLessonId: courseLessonId, | |
168 | - )); | |
195 | + videoUrl: videoUrl, | |
196 | + typeTitle: title, | |
197 | + courseLessonId: courseLessonId, | |
198 | + )); | |
169 | 199 | /*case AppRouteName.setPwd: |
170 | 200 | case AppRouteName.setPwd: |
171 | 201 | phoneNum: phoneNum, |
... | ... | @@ -174,7 +204,8 @@ class AppRouter { |
174 | 204 | ));*/ |
175 | 205 | case AppRouteName.webView: |
176 | 206 | final urlStr = (settings.arguments as Map)['urlStr'] as String; |
177 | - final webViewTitle = (settings.arguments as Map)['webViewTitle'] as String; | |
207 | + final webViewTitle = | |
208 | + (settings.arguments as Map)['webViewTitle'] as String; | |
178 | 209 | return CupertinoPageRoute( |
179 | 210 | builder: (_) => WowWebViewPage( |
180 | 211 | urlStr: urlStr, |
... | ... | @@ -183,13 +214,16 @@ class AppRouter { |
183 | 214 | case AppRouteName.readAfterContent: |
184 | 215 | var videoFollowReadId = ''; |
185 | 216 | if (settings.arguments != null) { |
186 | - videoFollowReadId = (settings.arguments as Map)['videoFollowReadId'] as String; | |
217 | + videoFollowReadId = | |
218 | + (settings.arguments as Map)['videoFollowReadId'] as String; | |
187 | 219 | } |
188 | - return CupertinoPageRoute(builder: (_) => RepeatAfterContentPage(videoFollowReadId: videoFollowReadId)); | |
220 | + return CupertinoPageRoute( | |
221 | + builder: (_) => | |
222 | + RepeatAfterContentPage(videoFollowReadId: videoFollowReadId)); | |
189 | 223 | case AppRouteName.setting: |
190 | - return CupertinoPageRoute(builder: (_) => const SettingPage()); | |
224 | + return CupertinoPageRoute(builder: (_) => const SettingPage()); | |
191 | 225 | case AppRouteName.deleteAccount: |
192 | - return CupertinoPageRoute(builder: (_) => const DeleteAccountPage()); | |
226 | + return CupertinoPageRoute(builder: (_) => const DeleteAccountPage()); | |
193 | 227 | case AppRouteName.reBack: |
194 | 228 | return CupertinoPageRoute(builder: (_) => const ReBackPage()); |
195 | 229 | case AppRouteName.tab: |
... | ... | @@ -202,26 +236,34 @@ class AppRouter { |
202 | 236 | case AppRouteName.reading: |
203 | 237 | var courseLessonId = ''; |
204 | 238 | if (settings.arguments != null) { |
205 | - courseLessonId = (settings.arguments as Map)['courseLessonId'] as String; | |
239 | + courseLessonId = | |
240 | + (settings.arguments as Map)['courseLessonId'] as String; | |
206 | 241 | } |
207 | - return CupertinoPageRoute(builder: (_) => ReadingPage(courseLessonId: courseLessonId)); | |
242 | + return CupertinoPageRoute( | |
243 | + builder: (_) => ReadingPage(courseLessonId: courseLessonId)); | |
208 | 244 | default: |
209 | 245 | return CupertinoPageRoute( |
210 | - builder: (_) => Scaffold(body: Center(child: Text('No route defined for ${settings.name}')))); | |
246 | + builder: (_) => Scaffold( | |
247 | + body: Center( | |
248 | + child: Text('No route defined for ${settings.name}')))); | |
211 | 249 | } |
212 | 250 | } |
213 | 251 | } |
214 | 252 | |
215 | 253 | Future pushNamed(String routeName, {Object? arguments}) { |
216 | - return Navigator.of(AppRouter.context).pushNamed(routeName, arguments: arguments).then((value) { | |
254 | + return Navigator.of(AppRouter.context) | |
255 | + .pushNamed(routeName, arguments: arguments) | |
256 | + .then((value) { | |
217 | 257 | return value; |
218 | 258 | }); |
219 | 259 | } |
220 | 260 | |
221 | -Future pushNamedAndRemoveUntil(String routeName, RoutePredicate predicate, {Object? arguments}) { | |
222 | - return Navigator.of(AppRouter.context).pushNamedAndRemoveUntil(routeName, predicate, arguments: arguments); | |
261 | +Future pushNamedAndRemoveUntil(String routeName, RoutePredicate predicate, | |
262 | + {Object? arguments}) { | |
263 | + return Navigator.of(AppRouter.context) | |
264 | + .pushNamedAndRemoveUntil(routeName, predicate, arguments: arguments); | |
223 | 265 | } |
224 | 266 | |
225 | 267 | void popPage({dynamic data}) { |
226 | - Navigator.of(AppRouter.context).pop(data); | |
268 | + Navigator.of(AppRouter.context).pop(data); | |
227 | 269 | } | ... | ... |
pubspec.yaml
... | ... | @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev |
16 | 16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html |
17 | 17 | # In Windows, build-name is used as the major, minor, and patch parts |
18 | 18 | # of the product and file versions while build-number is used as the build suffix. |
19 | -version: 1.0.3+2 | |
19 | +version: 1.0.3+3 | |
20 | 20 | |
21 | 21 | environment: |
22 | 22 | sdk: '>=3.0.0 <4.0.0' | ... | ... |