Commit 2a3621f8408a29461f5101e8faa5999701a2d8f5

Authored by 吴启风
1 parent 258578de

feat:课程层级调整(增加unit层)

lib/common/request/apis.dart
@@ -42,6 +42,9 @@ class Apis { @@ -42,6 +42,9 @@ class Apis {
42 // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663 42 // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663
43 static const String courseModule = 'home/courseModule'; 43 static const String courseModule = 'home/courseModule';
44 44
  45 + /// 课程单元列表
  46 + static const String courseUnit = 'home/courseUnit';
  47 +
45 /// 课程列表 48 /// 课程列表
46 // GET /home/courseLesson 49 // GET /home/courseLesson
47 // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897662 50 // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897662
lib/common/request/dao/home_dao.dart
@@ -2,18 +2,27 @@ import 'package:wow_english/common/request/request_client.dart'; @@ -2,18 +2,27 @@ import 'package:wow_english/common/request/request_client.dart';
2 import 'package:wow_english/models/course_entity.dart'; 2 import 'package:wow_english/models/course_entity.dart';
3 3
4 import '../../../models/course_module_entity.dart'; 4 import '../../../models/course_module_entity.dart';
  5 +import '../../../models/course_unit_entity.dart';
5 6
6 class HomeDao { 7 class HomeDao {
7 - ///获取课程模块信息 8 + ///获取课程模块(列表)信息
8 static Future<List<CourseModuleEntity?>?> courseModule() async { 9 static Future<List<CourseModuleEntity?>?> courseModule() async {
9 var data = await requestClient.get<List<CourseModuleEntity>>(Apis.courseModule); 10 var data = await requestClient.get<List<CourseModuleEntity>>(Apis.courseModule);
10 return data; 11 return data;
11 } 12 }
12 13
  14 + ///课程单元列表
  15 + static Future<CourseUnitEntity?> courseUnit(int moduleId) async {
  16 + Map<String, dynamic> mapData = {};
  17 + mapData['moduleId'] = moduleId;
  18 + var data = await requestClient.get<CourseUnitEntity>(Apis.courseUnit, queryParameters: mapData);
  19 + return data;
  20 + }
  21 +
13 ///课程列表 22 ///课程列表
14 - static Future<CourseEntity?> courseLesson({String moduleId = ''}) async { 23 + static Future<CourseEntity?> courseLesson({int? moduleId}) async {
15 Map<String, dynamic> mapData = {}; 24 Map<String, dynamic> mapData = {};
16 - if (moduleId.isNotEmpty) { 25 + if (moduleId != null) {
17 mapData['moduleId'] = moduleId; 26 mapData['moduleId'] = moduleId;
18 } 27 }
19 var data = await requestClient.get<CourseEntity>(Apis.courseLesson, queryParameters: mapData); 28 var data = await requestClient.get<CourseEntity>(Apis.courseLesson, queryParameters: mapData);
lib/generated/json/app_config_entity.g.dart
1 import 'package:wow_english/generated/json/base/json_convert_content.dart'; 1 import 'package:wow_english/generated/json/base/json_convert_content.dart';
2 import 'package:wow_english/models/app_config_entity.dart'; 2 import 'package:wow_english/models/app_config_entity.dart';
3 3
4 -AppConfigEntity $AppConfigEntityEntityFromJson(  
5 - Map<String, dynamic> json) {  
6 - final AppConfigEntity appConfigEntityEntity = AppConfigEntity(); 4 +AppConfigEntity $AppConfigEntityFromJson(Map<String, dynamic> json) {
  5 + final AppConfigEntity appConfigEntity = AppConfigEntity();
7 final bool? androidForceUpdate = jsonConvert.convert<bool>( 6 final bool? androidForceUpdate = jsonConvert.convert<bool>(
8 json['androidForceUpdate']); 7 json['androidForceUpdate']);
9 if (androidForceUpdate != null) { 8 if (androidForceUpdate != null) {
10 - appConfigEntityEntity.androidForceUpdate = androidForceUpdate; 9 + appConfigEntity.androidForceUpdate = androidForceUpdate;
11 } 10 }
12 final bool? androidRecommendUpdate = jsonConvert.convert<bool>( 11 final bool? androidRecommendUpdate = jsonConvert.convert<bool>(
13 json['androidRecommendUpdate']); 12 json['androidRecommendUpdate']);
14 if (androidRecommendUpdate != null) { 13 if (androidRecommendUpdate != null) {
15 - appConfigEntityEntity.androidRecommendUpdate = androidRecommendUpdate; 14 + appConfigEntity.androidRecommendUpdate = androidRecommendUpdate;
16 } 15 }
17 final String? androidUpdatePackageUrl = jsonConvert.convert<String>( 16 final String? androidUpdatePackageUrl = jsonConvert.convert<String>(
18 json['androidUpdatePackageUrl']); 17 json['androidUpdatePackageUrl']);
19 if (androidUpdatePackageUrl != null) { 18 if (androidUpdatePackageUrl != null) {
20 - appConfigEntityEntity.androidUpdatePackageUrl = androidUpdatePackageUrl; 19 + appConfigEntity.androidUpdatePackageUrl = androidUpdatePackageUrl;
21 } 20 }
22 final int? androidVersion = jsonConvert.convert<int>(json['androidVersion']); 21 final int? androidVersion = jsonConvert.convert<int>(json['androidVersion']);
23 if (androidVersion != null) { 22 if (androidVersion != null) {
24 - appConfigEntityEntity.androidVersion = androidVersion; 23 + appConfigEntity.androidVersion = androidVersion;
25 } 24 }
26 final bool? iosForceUpdate = jsonConvert.convert<bool>( 25 final bool? iosForceUpdate = jsonConvert.convert<bool>(
27 json['iosForceUpdate']); 26 json['iosForceUpdate']);
28 if (iosForceUpdate != null) { 27 if (iosForceUpdate != null) {
29 - appConfigEntityEntity.iosForceUpdate = iosForceUpdate; 28 + appConfigEntity.iosForceUpdate = iosForceUpdate;
30 } 29 }
31 final bool? iosRecommendUpdate = jsonConvert.convert<bool>( 30 final bool? iosRecommendUpdate = jsonConvert.convert<bool>(
32 json['iosRecommendUpdate']); 31 json['iosRecommendUpdate']);
33 if (iosRecommendUpdate != null) { 32 if (iosRecommendUpdate != null) {
34 - appConfigEntityEntity.iosRecommendUpdate = iosRecommendUpdate; 33 + appConfigEntity.iosRecommendUpdate = iosRecommendUpdate;
35 } 34 }
36 final int? iosVersion = jsonConvert.convert<int>(json['iosVersion']); 35 final int? iosVersion = jsonConvert.convert<int>(json['iosVersion']);
37 if (iosVersion != null) { 36 if (iosVersion != null) {
38 - appConfigEntityEntity.iosVersion = iosVersion; 37 + appConfigEntity.iosVersion = iosVersion;
  38 + }
  39 + final String? updatePackageDescription = jsonConvert.convert<String>(
  40 + json['updatePackageDescription']);
  41 + if (updatePackageDescription != null) {
  42 + appConfigEntity.updatePackageDescription = updatePackageDescription;
39 } 43 }
40 final String? noticeBeforePurchaseUrl = jsonConvert.convert<String>( 44 final String? noticeBeforePurchaseUrl = jsonConvert.convert<String>(
41 json['noticeBeforePurchaseUrl']); 45 json['noticeBeforePurchaseUrl']);
42 if (noticeBeforePurchaseUrl != null) { 46 if (noticeBeforePurchaseUrl != null) {
43 - appConfigEntityEntity.noticeBeforePurchaseUrl = noticeBeforePurchaseUrl; 47 + appConfigEntity.noticeBeforePurchaseUrl = noticeBeforePurchaseUrl;
44 } 48 }
45 final String? safe = jsonConvert.convert<String>(json['safe']); 49 final String? safe = jsonConvert.convert<String>(json['safe']);
46 if (safe != null) { 50 if (safe != null) {
47 - appConfigEntityEntity.safe = safe; 51 + appConfigEntity.safe = safe;
48 } 52 }
49 - return appConfigEntityEntity; 53 + return appConfigEntity;
50 } 54 }
51 55
52 -Map<String, dynamic> $AppConfigEntityEntityToJson(  
53 - AppConfigEntity entity) { 56 +Map<String, dynamic> $AppConfigEntityToJson(AppConfigEntity entity) {
54 final Map<String, dynamic> data = <String, dynamic>{}; 57 final Map<String, dynamic> data = <String, dynamic>{};
55 data['androidForceUpdate'] = entity.androidForceUpdate; 58 data['androidForceUpdate'] = entity.androidForceUpdate;
56 data['androidRecommendUpdate'] = entity.androidRecommendUpdate; 59 data['androidRecommendUpdate'] = entity.androidRecommendUpdate;
@@ -59,12 +62,13 @@ Map&lt;String, dynamic&gt; $AppConfigEntityEntityToJson( @@ -59,12 +62,13 @@ Map&lt;String, dynamic&gt; $AppConfigEntityEntityToJson(
59 data['iosForceUpdate'] = entity.iosForceUpdate; 62 data['iosForceUpdate'] = entity.iosForceUpdate;
60 data['iosRecommendUpdate'] = entity.iosRecommendUpdate; 63 data['iosRecommendUpdate'] = entity.iosRecommendUpdate;
61 data['iosVersion'] = entity.iosVersion; 64 data['iosVersion'] = entity.iosVersion;
  65 + data['updatePackageDescription'] = entity.updatePackageDescription;
62 data['noticeBeforePurchaseUrl'] = entity.noticeBeforePurchaseUrl; 66 data['noticeBeforePurchaseUrl'] = entity.noticeBeforePurchaseUrl;
63 data['safe'] = entity.safe; 67 data['safe'] = entity.safe;
64 return data; 68 return data;
65 } 69 }
66 70
67 -extension AppConfigEntityEntityExtension on AppConfigEntity { 71 +extension AppConfigEntityExtension on AppConfigEntity {
68 AppConfigEntity copyWith({ 72 AppConfigEntity copyWith({
69 bool? androidForceUpdate, 73 bool? androidForceUpdate,
70 bool? androidRecommendUpdate, 74 bool? androidRecommendUpdate,
@@ -73,6 +77,7 @@ extension AppConfigEntityEntityExtension on AppConfigEntity { @@ -73,6 +77,7 @@ extension AppConfigEntityEntityExtension on AppConfigEntity {
73 bool? iosForceUpdate, 77 bool? iosForceUpdate,
74 bool? iosRecommendUpdate, 78 bool? iosRecommendUpdate,
75 int? iosVersion, 79 int? iosVersion,
  80 + String? updatePackageDescription,
76 String? noticeBeforePurchaseUrl, 81 String? noticeBeforePurchaseUrl,
77 String? safe, 82 String? safe,
78 }) { 83 }) {
@@ -86,6 +91,8 @@ extension AppConfigEntityEntityExtension on AppConfigEntity { @@ -86,6 +91,8 @@ extension AppConfigEntityEntityExtension on AppConfigEntity {
86 ..iosForceUpdate = iosForceUpdate ?? this.iosForceUpdate 91 ..iosForceUpdate = iosForceUpdate ?? this.iosForceUpdate
87 ..iosRecommendUpdate = iosRecommendUpdate ?? this.iosRecommendUpdate 92 ..iosRecommendUpdate = iosRecommendUpdate ?? this.iosRecommendUpdate
88 ..iosVersion = iosVersion ?? this.iosVersion 93 ..iosVersion = iosVersion ?? this.iosVersion
  94 + ..updatePackageDescription = updatePackageDescription ??
  95 + this.updatePackageDescription
89 ..noticeBeforePurchaseUrl = noticeBeforePurchaseUrl ?? 96 ..noticeBeforePurchaseUrl = noticeBeforePurchaseUrl ??
90 this.noticeBeforePurchaseUrl 97 this.noticeBeforePurchaseUrl
91 ..safe = safe ?? this.safe; 98 ..safe = safe ?? this.safe;
lib/generated/json/base/json_convert_content.dart
@@ -9,6 +9,7 @@ import &#39;package:wow_english/models/app_config_entity.dart&#39;; @@ -9,6 +9,7 @@ import &#39;package:wow_english/models/app_config_entity.dart&#39;;
9 import 'package:wow_english/models/course_entity.dart'; 9 import 'package:wow_english/models/course_entity.dart';
10 import 'package:wow_english/models/course_module_entity.dart'; 10 import 'package:wow_english/models/course_module_entity.dart';
11 import 'package:wow_english/models/course_process_entity.dart'; 11 import 'package:wow_english/models/course_process_entity.dart';
  12 +import 'package:wow_english/models/course_unit_entity.dart';
12 import 'package:wow_english/models/follow_read_entity.dart'; 13 import 'package:wow_english/models/follow_read_entity.dart';
13 import 'package:wow_english/models/listen_entity.dart'; 14 import 'package:wow_english/models/listen_entity.dart';
14 import 'package:wow_english/models/product_entity.dart'; 15 import 'package:wow_english/models/product_entity.dart';
@@ -192,6 +193,14 @@ class JsonConvert { @@ -192,6 +193,14 @@ class JsonConvert {
192 return data.map<CourseProcessVideos>((Map<String, dynamic> e) => 193 return data.map<CourseProcessVideos>((Map<String, dynamic> e) =>
193 CourseProcessVideos.fromJson(e)).toList() as M; 194 CourseProcessVideos.fromJson(e)).toList() as M;
194 } 195 }
  196 + if (<CourseUnitEntity>[] is M) {
  197 + return data.map<CourseUnitEntity>((Map<String, dynamic> e) =>
  198 + CourseUnitEntity.fromJson(e)).toList() as M;
  199 + }
  200 + if (<CourseUnitDetail>[] is M) {
  201 + return data.map<CourseUnitDetail>((Map<String, dynamic> e) =>
  202 + CourseUnitDetail.fromJson(e)).toList() as M;
  203 + }
195 if (<FollowReadEntity>[] is M) { 204 if (<FollowReadEntity>[] is M) {
196 return data.map<FollowReadEntity>((Map<String, dynamic> e) => 205 return data.map<FollowReadEntity>((Map<String, dynamic> e) =>
197 FollowReadEntity.fromJson(e)).toList() as M; 206 FollowReadEntity.fromJson(e)).toList() as M;
@@ -246,6 +255,8 @@ class JsonConvertClassCollection { @@ -246,6 +255,8 @@ class JsonConvertClassCollection {
246 (CourseProcessTopicsTopicAnswerList) 255 (CourseProcessTopicsTopicAnswerList)
247 .toString(): CourseProcessTopicsTopicAnswerList.fromJson, 256 .toString(): CourseProcessTopicsTopicAnswerList.fromJson,
248 (CourseProcessVideos).toString(): CourseProcessVideos.fromJson, 257 (CourseProcessVideos).toString(): CourseProcessVideos.fromJson,
  258 + (CourseUnitEntity).toString(): CourseUnitEntity.fromJson,
  259 + (CourseUnitDetail).toString(): CourseUnitDetail.fromJson,
249 (FollowReadEntity).toString(): FollowReadEntity.fromJson, 260 (FollowReadEntity).toString(): FollowReadEntity.fromJson,
250 (ListenEntity).toString(): ListenEntity.fromJson, 261 (ListenEntity).toString(): ListenEntity.fromJson,
251 (ProductEntity).toString(): ProductEntity.fromJson, 262 (ProductEntity).toString(): ProductEntity.fromJson,
lib/generated/json/course_module_entity.g.dart
@@ -3,7 +3,7 @@ import &#39;package:wow_english/models/course_module_entity.dart&#39;; @@ -3,7 +3,7 @@ import &#39;package:wow_english/models/course_module_entity.dart&#39;;
3 3
4 CourseModuleEntity $CourseModuleEntityFromJson(Map<String, dynamic> json) { 4 CourseModuleEntity $CourseModuleEntityFromJson(Map<String, dynamic> json) {
5 final CourseModuleEntity courseModuleEntity = CourseModuleEntity(); 5 final CourseModuleEntity courseModuleEntity = CourseModuleEntity();
6 - final String? id = jsonConvert.convert<String>(json['id']); 6 + final int? id = jsonConvert.convert<int>(json['id']);
7 if (id != null) { 7 if (id != null) {
8 courseModuleEntity.id = id; 8 courseModuleEntity.id = id;
9 } 9 }
@@ -90,7 +90,7 @@ Map&lt;String, dynamic&gt; $CourseModuleEntityToJson(CourseModuleEntity entity) { @@ -90,7 +90,7 @@ Map&lt;String, dynamic&gt; $CourseModuleEntityToJson(CourseModuleEntity entity) {
90 90
91 extension CourseModuleEntityExtension on CourseModuleEntity { 91 extension CourseModuleEntityExtension on CourseModuleEntity {
92 CourseModuleEntity copyWith({ 92 CourseModuleEntity copyWith({
93 - String? id, 93 + int? id,
94 String? code, 94 String? code,
95 int? courseModuleThemeId, 95 int? courseModuleThemeId,
96 int? courseTotal, 96 int? courseTotal,
lib/generated/json/course_unit_entity.g.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_convert_content.dart';
  2 +import 'package:wow_english/models/course_unit_entity.dart';
  3 +
  4 +CourseUnitEntity $CourseUnitEntityFromJson(Map<String, dynamic> json) {
  5 + final CourseUnitEntity courseUnitEntity = CourseUnitEntity();
  6 + final List<
  7 + CourseUnitDetail>? courseUnitVOList = (json['courseUnitVOList'] as List<
  8 + dynamic>?)
  9 + ?.map(
  10 + (e) => jsonConvert.convert<CourseUnitDetail>(e) as CourseUnitDetail)
  11 + .toList();
  12 + if (courseUnitVOList != null) {
  13 + courseUnitEntity.courseUnitVOList = courseUnitVOList;
  14 + }
  15 + final int? nowStep = jsonConvert.convert<int>(json['nowStep']);
  16 + if (nowStep != null) {
  17 + courseUnitEntity.nowStep = nowStep;
  18 + }
  19 + final int? total = jsonConvert.convert<int>(json['total']);
  20 + if (total != null) {
  21 + courseUnitEntity.total = total;
  22 + }
  23 + final int? nowCourseModuleId = jsonConvert.convert<int>(
  24 + json['nowCourseModuleId']);
  25 + if (nowCourseModuleId != null) {
  26 + courseUnitEntity.nowCourseModuleId = nowCourseModuleId;
  27 + }
  28 + final String? nowCourseModuleName = jsonConvert.convert<String>(
  29 + json['nowCourseModuleName']);
  30 + if (nowCourseModuleName != null) {
  31 + courseUnitEntity.nowCourseModuleName = nowCourseModuleName;
  32 + }
  33 + final String? courseModuleThemeColor = jsonConvert.convert<String>(
  34 + json['courseModuleThemeColor']);
  35 + if (courseModuleThemeColor != null) {
  36 + courseUnitEntity.courseModuleThemeColor = courseModuleThemeColor;
  37 + }
  38 + final String? courseModuleCode = jsonConvert.convert<String>(
  39 + json['courseModuleCode']);
  40 + if (courseModuleCode != null) {
  41 + courseUnitEntity.courseModuleCode = courseModuleCode;
  42 + }
  43 + return courseUnitEntity;
  44 +}
  45 +
  46 +Map<String, dynamic> $CourseUnitEntityToJson(CourseUnitEntity entity) {
  47 + final Map<String, dynamic> data = <String, dynamic>{};
  48 + data['courseUnitVOList'] =
  49 + entity.courseUnitVOList?.map((v) => v.toJson()).toList();
  50 + data['nowStep'] = entity.nowStep;
  51 + data['total'] = entity.total;
  52 + data['nowCourseModuleId'] = entity.nowCourseModuleId;
  53 + data['nowCourseModuleName'] = entity.nowCourseModuleName;
  54 + data['courseModuleThemeColor'] = entity.courseModuleThemeColor;
  55 + data['courseModuleCode'] = entity.courseModuleCode;
  56 + return data;
  57 +}
  58 +
  59 +extension CourseUnitEntityExtension on CourseUnitEntity {
  60 + CourseUnitEntity copyWith({
  61 + List<CourseUnitDetail>? courseUnitVOList,
  62 + int? nowStep,
  63 + int? total,
  64 + int? nowCourseModuleId,
  65 + String? nowCourseModuleName,
  66 + String? courseModuleThemeColor,
  67 + String? courseModuleCode,
  68 + }) {
  69 + return CourseUnitEntity()
  70 + ..courseUnitVOList = courseUnitVOList ?? this.courseUnitVOList
  71 + ..nowStep = nowStep ?? this.nowStep
  72 + ..total = total ?? this.total
  73 + ..nowCourseModuleId = nowCourseModuleId ?? this.nowCourseModuleId
  74 + ..nowCourseModuleName = nowCourseModuleName ?? this.nowCourseModuleName
  75 + ..courseModuleThemeColor = courseModuleThemeColor ??
  76 + this.courseModuleThemeColor
  77 + ..courseModuleCode = courseModuleCode ?? this.courseModuleCode;
  78 + }
  79 +}
  80 +
  81 +CourseUnitDetail $CourseUnitDetailFromJson(Map<String, dynamic> json) {
  82 + final CourseUnitDetail courseUnitDetail = CourseUnitDetail();
  83 + final int? courseModuleId = jsonConvert.convert<int>(json['courseModuleId']);
  84 + if (courseModuleId != null) {
  85 + courseUnitDetail.courseModuleId = courseModuleId;
  86 + }
  87 + final int? id = jsonConvert.convert<int>(json['id']);
  88 + if (id != null) {
  89 + courseUnitDetail.id = id;
  90 + }
  91 + final String? name = jsonConvert.convert<String>(json['name']);
  92 + if (name != null) {
  93 + courseUnitDetail.name = name;
  94 + }
  95 + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
  96 + if (coverUrl != null) {
  97 + courseUnitDetail.coverUrl = coverUrl;
  98 + }
  99 + final bool? lock = jsonConvert.convert<bool>(json['lock']);
  100 + if (lock != null) {
  101 + courseUnitDetail.lock = lock;
  102 + }
  103 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  104 + if (sortOrder != null) {
  105 + courseUnitDetail.sortOrder = sortOrder;
  106 + }
  107 + final int? status = jsonConvert.convert<int>(json['status']);
  108 + if (status != null) {
  109 + courseUnitDetail.status = status;
  110 + }
  111 + return courseUnitDetail;
  112 +}
  113 +
  114 +Map<String, dynamic> $CourseUnitDetailToJson(CourseUnitDetail entity) {
  115 + final Map<String, dynamic> data = <String, dynamic>{};
  116 + data['courseModuleId'] = entity.courseModuleId;
  117 + data['id'] = entity.id;
  118 + data['name'] = entity.name;
  119 + data['coverUrl'] = entity.coverUrl;
  120 + data['lock'] = entity.lock;
  121 + data['sortOrder'] = entity.sortOrder;
  122 + data['status'] = entity.status;
  123 + return data;
  124 +}
  125 +
  126 +extension CourseUnitDetailExtension on CourseUnitDetail {
  127 + CourseUnitDetail copyWith({
  128 + int? courseModuleId,
  129 + int? id,
  130 + String? name,
  131 + String? coverUrl,
  132 + bool? lock,
  133 + int? sortOrder,
  134 + int? status,
  135 + }) {
  136 + return CourseUnitDetail()
  137 + ..courseModuleId = courseModuleId ?? this.courseModuleId
  138 + ..id = id ?? this.id
  139 + ..name = name ?? this.name
  140 + ..coverUrl = coverUrl ?? this.coverUrl
  141 + ..lock = lock ?? this.lock
  142 + ..sortOrder = sortOrder ?? this.sortOrder
  143 + ..status = status ?? this.status;
  144 + }
  145 +}
0 \ No newline at end of file 146 \ No newline at end of file
lib/models/course_module_entity.dart
@@ -5,7 +5,7 @@ import &#39;package:wow_english/generated/json/course_module_entity.g.dart&#39;; @@ -5,7 +5,7 @@ import &#39;package:wow_english/generated/json/course_module_entity.g.dart&#39;;
5 5
6 @JsonSerializable() 6 @JsonSerializable()
7 class CourseModuleEntity { 7 class CourseModuleEntity {
8 - late String id; 8 + late int id;
9 String? code; 9 String? code;
10 int? courseModuleThemeId; 10 int? courseModuleThemeId;
11 int? courseTotal; 11 int? courseTotal;
lib/models/course_unit_entity.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_field.dart';
  2 +import 'package:wow_english/generated/json/course_unit_entity.g.dart';
  3 +import 'dart:convert';
  4 +
  5 +export 'package:wow_english/generated/json/course_unit_entity.g.dart';
  6 +
  7 +@JsonSerializable()
  8 +class CourseUnitEntity {
  9 +
  10 + // 课程详情列表
  11 + List<CourseUnitDetail>? courseUnitVOList;
  12 +
  13 + // 当前进行了多少节课程
  14 + int? nowStep;
  15 +
  16 + // 当前模块一共多少节课程
  17 + int? total;
  18 +
  19 + // 当前模块id
  20 + int? nowCourseModuleId;
  21 +
  22 + // 当前模块名
  23 + String? nowCourseModuleName;
  24 +
  25 + // 主题颜色值
  26 + String? courseModuleThemeColor;
  27 +
  28 + // 课程模块code
  29 + String? courseModuleCode;
  30 +
  31 + CourseUnitEntity();
  32 +
  33 + factory CourseUnitEntity.fromJson(Map<String, dynamic> json) => $CourseUnitEntityFromJson(json);
  34 +
  35 + Map<String, dynamic> toJson() => $CourseUnitEntityToJson(this);
  36 +
  37 + @override
  38 + String toString() {
  39 + return jsonEncode(this);
  40 + }
  41 +}
  42 +
  43 +
  44 +@JsonSerializable()
  45 +class CourseUnitDetail {
  46 +
  47 + // 模块id
  48 + int? courseModuleId;
  49 +
  50 + // 单元
  51 + int? id;
  52 +
  53 + // 单元名称
  54 + String? name;
  55 +
  56 + // 单元封面
  57 + String? coverUrl;
  58 +
  59 + bool? lock;
  60 +
  61 + int? sortOrder;
  62 +
  63 + int? status;
  64 +
  65 + CourseUnitDetail();
  66 +
  67 + factory CourseUnitDetail.fromJson(Map<String, dynamic> json) => $CourseUnitDetailFromJson(json);
  68 +
  69 + Map<String, dynamic> toJson() => $CourseUnitDetailToJson(this);
  70 +
  71 + @override
  72 + String toString() {
  73 + return jsonEncode(this);
  74 + }
  75 +}
0 \ No newline at end of file 76 \ No newline at end of file
lib/pages/home/bloc/home_bloc.dart
@@ -13,7 +13,7 @@ part &#39;home_event.dart&#39;; @@ -13,7 +13,7 @@ part &#39;home_event.dart&#39;;
13 part 'home_state.dart'; 13 part 'home_state.dart';
14 14
15 class HomeBloc extends Bloc<HomeEvent, HomeState> { 15 class HomeBloc extends Bloc<HomeEvent, HomeState> {
16 - final String? moduleId; 16 + final int? moduleId;
17 17
18 CourseEntity? _modelData; 18 CourseEntity? _modelData;
19 19
@@ -33,7 +33,7 @@ class HomeBloc extends Bloc&lt;HomeEvent, HomeState&gt; { @@ -33,7 +33,7 @@ class HomeBloc extends Bloc&lt;HomeEvent, HomeState&gt; {
33 void _requestData(RequestDataEvent event, Emitter<HomeState> emitter) async { 33 void _requestData(RequestDataEvent event, Emitter<HomeState> emitter) async {
34 try { 34 try {
35 await loading(() async { 35 await loading(() async {
36 - _modelData = await HomeDao.courseLesson(moduleId: moduleId ?? ''); 36 + _modelData = await HomeDao.courseLesson(moduleId: moduleId);
37 emitter(HomeDataLoadState()); 37 emitter(HomeDataLoadState());
38 }); 38 });
39 } catch (e) { 39 } catch (e) {
lib/pages/home/home_page.dart
@@ -6,7 +6,7 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;; @@ -6,7 +6,7 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;;
6 import 'package:wow_english/models/course_entity.dart'; 6 import 'package:wow_english/models/course_entity.dart';
7 import 'package:wow_english/pages/home/widgets/home_bouns_item.dart'; 7 import 'package:wow_english/pages/home/widgets/home_bouns_item.dart';
8 import 'package:wow_english/pages/home/widgets/home_tab_header_widget.dart'; 8 import 'package:wow_english/pages/home/widgets/home_tab_header_widget.dart';
9 -import 'package:wow_english/pages/home/widgets/home_vidoe_item.dart'; 9 +import 'package:wow_english/pages/home/widgets/home_video_item.dart';
10 import 'package:wow_english/route/route.dart'; 10 import 'package:wow_english/route/route.dart';
11 import 'package:wow_english/utils/toast_util.dart'; 11 import 'package:wow_english/utils/toast_util.dart';
12 12
@@ -17,7 +17,7 @@ class HomePage extends StatelessWidget { @@ -17,7 +17,7 @@ class HomePage extends StatelessWidget {
17 const HomePage({super.key, this.moduleId}); 17 const HomePage({super.key, this.moduleId});
18 18
19 /// 模块id 19 /// 模块id
20 - final String? moduleId; 20 + final int? moduleId;
21 21
22 @override 22 @override
23 Widget build(BuildContext context) { 23 Widget build(BuildContext context) {
lib/pages/home/widgets/home_vidoe_item.dart renamed to lib/pages/home/widgets/home_video_item.dart
lib/pages/lessons/lesson_page.dart
@@ -171,7 +171,7 @@ class _LessonPageView extends StatelessWidget { @@ -171,7 +171,7 @@ class _LessonPageView extends StatelessWidget {
171 model: model, 171 model: model,
172 isSelected: bloc.currentPageIndex == index, 172 isSelected: bloc.currentPageIndex == index,
173 onClickEvent: () { 173 onClickEvent: () {
174 - pushNamedAndRemoveUntil(AppRouteName.home, (route) => false,arguments: {'moduleId':model?.id}); 174 + pushNamed(AppRouteName.unit, arguments: {'courseModuleEntity':model});
175 }, 175 },
176 ), 176 ),
177 ), 177 ),
lib/pages/unit/bloc.dart 0 → 100644
  1 +import 'package:bloc/bloc.dart';
  2 +
  3 +import '../../common/request/dao/home_dao.dart';
  4 +import '../../common/request/exception.dart';
  5 +import '../../models/course_unit_entity.dart';
  6 +import '../../utils/loading.dart';
  7 +import '../../utils/toast_util.dart';
  8 +import 'event.dart';
  9 +import 'state.dart';
  10 +
  11 +class UnitBloc extends Bloc<UnitEvent, UnitState> {
  12 +
  13 + CourseUnitEntity? _modelData;
  14 +
  15 + CourseUnitEntity? get modelData => _modelData;
  16 +
  17 +
  18 + UnitBloc() : super(UnitState().init()) {
  19 + on<RequestUnitDataEvent>(_requestData);
  20 + }
  21 +
  22 + void _requestData(RequestUnitDataEvent event, Emitter<UnitState> emitter) async {
  23 + try {
  24 + await loading(() async {
  25 + _modelData = await HomeDao.courseUnit(event.moduleId);
  26 + emitter(UnitDataLoadState());
  27 + });
  28 + } catch (e) {
  29 + if (e is ApiException) {
  30 + showToast(e.message ?? '请求失败,请检查网络连接');
  31 + }
  32 + }
  33 + }
  34 +}
lib/pages/unit/event.dart 0 → 100644
  1 +abstract class UnitEvent {}
  2 +
  3 +// 获取课程单元数据
  4 +class RequestUnitDataEvent extends UnitEvent {
  5 + final int moduleId;
  6 +
  7 + RequestUnitDataEvent(this.moduleId);
  8 +}
lib/pages/unit/state.dart 0 → 100644
  1 +class UnitState {
  2 + UnitState init() {
  3 + return UnitState();
  4 + }
  5 +
  6 + UnitState clone() {
  7 + return UnitState();
  8 + }
  9 +}
  10 +
  11 +class UnitDataLoadState extends UnitState {}
0 \ No newline at end of file 12 \ No newline at end of file
lib/pages/unit/view.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/pages/unit/state.dart';
  5 +import 'package:wow_english/pages/unit/widget/course_unit_header_widget.dart';
  6 +import 'package:wow_english/pages/unit/widget/course_unit_item.dart';
  7 +import 'package:wow_english/route/route.dart';
  8 +
  9 +import '../../models/course_module_entity.dart';
  10 +import '../../models/course_unit_entity.dart';
  11 +import '../../utils/toast_util.dart';
  12 +import 'bloc.dart';
  13 +import 'event.dart';
  14 +
  15 +class UnitPage extends StatelessWidget {
  16 + const UnitPage({super.key, required this.courseEntity});
  17 +
  18 + /// 模块
  19 + final CourseModuleEntity courseEntity;
  20 +
  21 + @override
  22 + Widget build(BuildContext context) {
  23 + return BlocProvider(
  24 + create: (BuildContext context) =>
  25 + UnitBloc()..add(RequestUnitDataEvent(courseEntity.id)),
  26 + child: Builder(builder: (context) => _buildPage(context)),
  27 + );
  28 + }
  29 +
  30 + Widget _buildPage(BuildContext context) {
  31 + return BlocBuilder<UnitBloc, UnitState>(builder: (context, state) {
  32 + final bloc = BlocProvider.of<UnitBloc>(context);
  33 + return Scaffold(
  34 + body: Container(
  35 + color: Colors.white,
  36 + child: Center(
  37 + child: Column(
  38 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  39 + children: [
  40 + CourseUnitHeaderWidget(entity: courseEntity),
  41 + Expanded(
  42 + child: ListView.builder(
  43 + itemCount:
  44 + bloc.modelData?.courseUnitVOList?.length ?? 0,
  45 + scrollDirection: Axis.horizontal,
  46 + itemBuilder: (BuildContext context, int index) {
  47 + CourseUnitDetail? data =
  48 + bloc.modelData?.courseUnitVOList?[index];
  49 + return GestureDetector(
  50 + onTap: () {
  51 + if (data.lock == true) {
  52 + showToast('当前unit暂未解锁');
  53 + return;
  54 + }
  55 +
  56 + ///进入课堂
  57 + pushNamedAndRemoveUntil(
  58 + AppRouteName.home, (route) => route.isFirst,
  59 + arguments: {
  60 + 'moduleId': data.courseModuleId,
  61 + 'unitId': data.id
  62 + });
  63 + },
  64 + child: CourseUnitItem(
  65 + unitEntity: bloc.modelData!,
  66 + unitLesson: data!,
  67 + ),
  68 + );
  69 + })),
  70 + SafeArea(
  71 + child: Column(
  72 + children: [
  73 + 6.verticalSpace,
  74 + ],
  75 + ),
  76 + )
  77 + ],
  78 + ),
  79 + ),
  80 + ),
  81 + );
  82 + });
  83 + }
  84 +}
lib/pages/unit/widget/course_unit_header_widget.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/common/extension/string_extension.dart';
  5 +import 'package:wow_english/pages/user/bloc/user_bloc.dart';
  6 +
  7 +import '../../../models/course_module_entity.dart';
  8 +import '../../home/courese_module_model.dart';
  9 +
  10 +class CourseUnitHeaderWidget extends StatelessWidget {
  11 + const CourseUnitHeaderWidget({super.key, this.entity});
  12 +
  13 + final CourseModuleEntity? entity;
  14 +
  15 + @override
  16 + Widget build(BuildContext context) {
  17 + return BlocBuilder<UserBloc, UserState>(
  18 + builder: (context, state) {
  19 + return Container(
  20 + height: 45,
  21 + width: double.infinity,
  22 + color:
  23 + CourseModuleModel(entity?.code ?? 'Phase-1').color,
  24 + padding: EdgeInsets.symmetric(horizontal: 9.5.w),
  25 + child: Row(
  26 + children: [
  27 + ScreenUtil().bottomBarHeight.horizontalSpace,
  28 + GestureDetector(
  29 + onTap: () {
  30 + Navigator.pop(context);
  31 + },
  32 + child: Container(
  33 + alignment: Alignment.center,
  34 + child: Image.asset(
  35 + 'back_around'.assetPng,
  36 + height: 40.h,
  37 + width: 40.w,
  38 + ),
  39 + ),
  40 + ),
  41 + 20.horizontalSpace,
  42 + Expanded(
  43 + child: Text(entity?.name ??
  44 + CourseModuleModel(entity?.code ?? 'Phase-1')
  45 + .courseModuleTitle,
  46 + textAlign: TextAlign.left,
  47 + style: const TextStyle(color: Colors.white, fontSize: 30.0),
  48 + )),
  49 + ScreenUtil().bottomBarHeight.horizontalSpace,
  50 + ],
  51 + ));
  52 + },
  53 + );
  54 + }
  55 +}
lib/pages/unit/widget/course_unit_item.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
  5 +
  6 +import '../../../models/course_unit_entity.dart';
  7 +
  8 +class CourseUnitItem extends StatelessWidget {
  9 + const CourseUnitItem(
  10 + {super.key, required this.unitEntity, required this.unitLesson});
  11 +
  12 + final CourseUnitEntity unitEntity;
  13 + final CourseUnitDetail unitLesson;
  14 +
  15 + @override
  16 + Widget build(BuildContext context) {
  17 + return Padding(
  18 + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 24.h),
  19 + child: Container(
  20 + width: 165.w,
  21 + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 24.h),
  22 + decoration: BoxDecoration(
  23 + image: DecorationImage(
  24 + image: AssetImage('gendubeij'.assetPng), fit: BoxFit.fill),
  25 + ),
  26 + child: Column(
  27 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  28 + children: [
  29 + Expanded(
  30 + child: Container(
  31 + decoration: BoxDecoration(
  32 + border: Border.all(
  33 + width: 2,
  34 + color: const Color(0xFF140C10),
  35 + ),
  36 + borderRadius: BorderRadius.circular(6)),
  37 + child: OwImageWidget(
  38 + name: unitLesson.coverUrl ?? '',
  39 + fit: BoxFit.fitHeight,
  40 + ),
  41 + )),
  42 + 20.verticalSpace,
  43 + SizedBox(
  44 + height: 40.h,
  45 + child: Text(
  46 + unitLesson.name ?? '',
  47 + maxLines: 2,
  48 + overflow: TextOverflow.ellipsis,
  49 + style:
  50 + TextStyle(fontSize: 11.sp, color: const Color(0xFF140C10)),
  51 + ),
  52 + )
  53 + ],
  54 + ),
  55 + ),
  56 + );
  57 + }
  58 +}
lib/route/route.dart
@@ -26,11 +26,12 @@ import &#39;package:wow_english/pages/user/setting/setting_page.dart&#39;; @@ -26,11 +26,12 @@ import &#39;package:wow_english/pages/user/setting/setting_page.dart&#39;;
26 import 'package:wow_english/pages/user/user_page.dart'; 26 import 'package:wow_english/pages/user/user_page.dart';
27 import 'package:wow_english/pages/video/lookvideo/look_video_page.dart'; 27 import 'package:wow_english/pages/video/lookvideo/look_video_page.dart';
28 28
  29 +import '../models/course_module_entity.dart';
29 import '../pages/reading/reading_page.dart'; 30 import '../pages/reading/reading_page.dart';
30 import '../pages/shopping/view.dart'; 31 import '../pages/shopping/view.dart';
  32 +import '../pages/unit/view.dart';
31 import '../pages/user/setting/delete_account_page.dart'; 33 import '../pages/user/setting/delete_account_page.dart';
32 import '../pages/user/setting/reback_page.dart'; 34 import '../pages/user/setting/reback_page.dart';
33 -import '../utils/log_util.dart';  
34 35
35 class AppRouteName { 36 class AppRouteName {
36 static const String splash = 'splash'; 37 static const String splash = 'splash';
@@ -43,7 +44,8 @@ class AppRouteName { @@ -43,7 +44,8 @@ class AppRouteName {
43 /// 设置密码,修改密码;不要自己调用,使用[SetPassWordPage.push]方法,隐藏这种实现 44 /// 设置密码,修改密码;不要自己调用,使用[SetPassWordPage.push]方法,隐藏这种实现
44 //static const String setPwd = 'setPwd'; 45 //static const String setPwd = 'setPwd';
45 static const String webView = 'webView'; 46 static const String webView = 'webView';
46 - static const String lesson = 'lesson'; 47 + static const String unit = 'courseUnits';
  48 + static const String lesson = 'courseModules';
47 static const String listen = 'listen'; 49 static const String listen = 'listen';
48 static const String shop = 'shop'; 50 static const String shop = 'shop';
49 static const String exLesson = 'exLesson'; 51 static const String exLesson = 'exLesson';
@@ -100,9 +102,9 @@ class AppRouter { @@ -100,9 +102,9 @@ class AppRouter {
100 case AppRouteName.games: 102 case AppRouteName.games:
101 return CupertinoPageRoute(builder: (_) => const GamesPage()); 103 return CupertinoPageRoute(builder: (_) => const GamesPage());
102 case AppRouteName.home: 104 case AppRouteName.home:
103 - var moduleId = ''; 105 + int? moduleId;
104 if (settings.arguments != null) { 106 if (settings.arguments != null) {
105 - moduleId = (settings.arguments as Map)['moduleId'] as String; 107 + moduleId = (settings.arguments as Map).getOrNull('moduleId') as int?;
106 } 108 }
107 return CupertinoPageRoute( 109 return CupertinoPageRoute(
108 builder: (_) => HomePage( 110 builder: (_) => HomePage(
@@ -112,6 +114,12 @@ class AppRouter { @@ -112,6 +114,12 @@ class AppRouter {
112 return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage()); 114 return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage());
113 case AppRouteName.lesson: 115 case AppRouteName.lesson:
114 return CupertinoPageRoute(builder: (_) => const LessonPage()); 116 return CupertinoPageRoute(builder: (_) => const LessonPage());
  117 + case AppRouteName.unit:
  118 + CourseModuleEntity courseEntity = CourseModuleEntity();
  119 + if (settings.arguments != null) {
  120 + courseEntity = (settings.arguments as Map).getOrNull('courseModuleEntity') as CourseModuleEntity;
  121 + }
  122 + return CupertinoPageRoute(builder: (_) => UnitPage(courseEntity: courseEntity));
115 case AppRouteName.listen: 123 case AppRouteName.listen:
116 return CupertinoPageRoute(builder: (_) => const ListenPage()); 124 return CupertinoPageRoute(builder: (_) => const ListenPage());
117 case AppRouteName.shop: 125 case AppRouteName.shop: