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