Commit 2a3621f8408a29461f5101e8faa5999701a2d8f5
1 parent
258578de
feat:课程层级调整(增加unit层)
Showing
19 changed files
with
539 additions
and
31 deletions
lib/common/request/apis.dart
... | ... | @@ -42,6 +42,9 @@ class Apis { |
42 | 42 | // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663 |
43 | 43 | static const String courseModule = 'home/courseModule'; |
44 | 44 | |
45 | + /// 课程单元列表 | |
46 | + static const String courseUnit = 'home/courseUnit'; | |
47 | + | |
45 | 48 | /// 课程列表 |
46 | 49 | // GET /home/courseLesson |
47 | 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 | 2 | import 'package:wow_english/models/course_entity.dart'; |
3 | 3 | |
4 | 4 | import '../../../models/course_module_entity.dart'; |
5 | +import '../../../models/course_unit_entity.dart'; | |
5 | 6 | |
6 | 7 | class HomeDao { |
7 | - ///获取课程模块信息 | |
8 | + ///获取课程模块(列表)信息 | |
8 | 9 | static Future<List<CourseModuleEntity?>?> courseModule() async { |
9 | 10 | var data = await requestClient.get<List<CourseModuleEntity>>(Apis.courseModule); |
10 | 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 | 24 | Map<String, dynamic> mapData = {}; |
16 | - if (moduleId.isNotEmpty) { | |
25 | + if (moduleId != null) { | |
17 | 26 | mapData['moduleId'] = moduleId; |
18 | 27 | } |
19 | 28 | var data = await requestClient.get<CourseEntity>(Apis.courseLesson, queryParameters: mapData); | ... | ... |
lib/generated/json/app_config_entity.g.dart
1 | 1 | import 'package:wow_english/generated/json/base/json_convert_content.dart'; |
2 | 2 | import 'package:wow_english/models/app_config_entity.dart'; |
3 | 3 | |
4 | -AppConfigEntity $AppConfigEntityEntityFromJson( | |
5 | - Map<String, dynamic> json) { | |
6 | - final AppConfigEntity appConfigEntityEntity = AppConfigEntity(); | |
4 | +AppConfigEntity $AppConfigEntityFromJson(Map<String, dynamic> json) { | |
5 | + final AppConfigEntity appConfigEntity = AppConfigEntity(); | |
7 | 6 | final bool? androidForceUpdate = jsonConvert.convert<bool>( |
8 | 7 | json['androidForceUpdate']); |
9 | 8 | if (androidForceUpdate != null) { |
10 | - appConfigEntityEntity.androidForceUpdate = androidForceUpdate; | |
9 | + appConfigEntity.androidForceUpdate = androidForceUpdate; | |
11 | 10 | } |
12 | 11 | final bool? androidRecommendUpdate = jsonConvert.convert<bool>( |
13 | 12 | json['androidRecommendUpdate']); |
14 | 13 | if (androidRecommendUpdate != null) { |
15 | - appConfigEntityEntity.androidRecommendUpdate = androidRecommendUpdate; | |
14 | + appConfigEntity.androidRecommendUpdate = androidRecommendUpdate; | |
16 | 15 | } |
17 | 16 | final String? androidUpdatePackageUrl = jsonConvert.convert<String>( |
18 | 17 | json['androidUpdatePackageUrl']); |
19 | 18 | if (androidUpdatePackageUrl != null) { |
20 | - appConfigEntityEntity.androidUpdatePackageUrl = androidUpdatePackageUrl; | |
19 | + appConfigEntity.androidUpdatePackageUrl = androidUpdatePackageUrl; | |
21 | 20 | } |
22 | 21 | final int? androidVersion = jsonConvert.convert<int>(json['androidVersion']); |
23 | 22 | if (androidVersion != null) { |
24 | - appConfigEntityEntity.androidVersion = androidVersion; | |
23 | + appConfigEntity.androidVersion = androidVersion; | |
25 | 24 | } |
26 | 25 | final bool? iosForceUpdate = jsonConvert.convert<bool>( |
27 | 26 | json['iosForceUpdate']); |
28 | 27 | if (iosForceUpdate != null) { |
29 | - appConfigEntityEntity.iosForceUpdate = iosForceUpdate; | |
28 | + appConfigEntity.iosForceUpdate = iosForceUpdate; | |
30 | 29 | } |
31 | 30 | final bool? iosRecommendUpdate = jsonConvert.convert<bool>( |
32 | 31 | json['iosRecommendUpdate']); |
33 | 32 | if (iosRecommendUpdate != null) { |
34 | - appConfigEntityEntity.iosRecommendUpdate = iosRecommendUpdate; | |
33 | + appConfigEntity.iosRecommendUpdate = iosRecommendUpdate; | |
35 | 34 | } |
36 | 35 | final int? iosVersion = jsonConvert.convert<int>(json['iosVersion']); |
37 | 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 | 44 | final String? noticeBeforePurchaseUrl = jsonConvert.convert<String>( |
41 | 45 | json['noticeBeforePurchaseUrl']); |
42 | 46 | if (noticeBeforePurchaseUrl != null) { |
43 | - appConfigEntityEntity.noticeBeforePurchaseUrl = noticeBeforePurchaseUrl; | |
47 | + appConfigEntity.noticeBeforePurchaseUrl = noticeBeforePurchaseUrl; | |
44 | 48 | } |
45 | 49 | final String? safe = jsonConvert.convert<String>(json['safe']); |
46 | 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 | 57 | final Map<String, dynamic> data = <String, dynamic>{}; |
55 | 58 | data['androidForceUpdate'] = entity.androidForceUpdate; |
56 | 59 | data['androidRecommendUpdate'] = entity.androidRecommendUpdate; |
... | ... | @@ -59,12 +62,13 @@ Map<String, dynamic> $AppConfigEntityEntityToJson( |
59 | 62 | data['iosForceUpdate'] = entity.iosForceUpdate; |
60 | 63 | data['iosRecommendUpdate'] = entity.iosRecommendUpdate; |
61 | 64 | data['iosVersion'] = entity.iosVersion; |
65 | + data['updatePackageDescription'] = entity.updatePackageDescription; | |
62 | 66 | data['noticeBeforePurchaseUrl'] = entity.noticeBeforePurchaseUrl; |
63 | 67 | data['safe'] = entity.safe; |
64 | 68 | return data; |
65 | 69 | } |
66 | 70 | |
67 | -extension AppConfigEntityEntityExtension on AppConfigEntity { | |
71 | +extension AppConfigEntityExtension on AppConfigEntity { | |
68 | 72 | AppConfigEntity copyWith({ |
69 | 73 | bool? androidForceUpdate, |
70 | 74 | bool? androidRecommendUpdate, |
... | ... | @@ -73,6 +77,7 @@ extension AppConfigEntityEntityExtension on AppConfigEntity { |
73 | 77 | bool? iosForceUpdate, |
74 | 78 | bool? iosRecommendUpdate, |
75 | 79 | int? iosVersion, |
80 | + String? updatePackageDescription, | |
76 | 81 | String? noticeBeforePurchaseUrl, |
77 | 82 | String? safe, |
78 | 83 | }) { |
... | ... | @@ -86,6 +91,8 @@ extension AppConfigEntityEntityExtension on AppConfigEntity { |
86 | 91 | ..iosForceUpdate = iosForceUpdate ?? this.iosForceUpdate |
87 | 92 | ..iosRecommendUpdate = iosRecommendUpdate ?? this.iosRecommendUpdate |
88 | 93 | ..iosVersion = iosVersion ?? this.iosVersion |
94 | + ..updatePackageDescription = updatePackageDescription ?? | |
95 | + this.updatePackageDescription | |
89 | 96 | ..noticeBeforePurchaseUrl = noticeBeforePurchaseUrl ?? |
90 | 97 | this.noticeBeforePurchaseUrl |
91 | 98 | ..safe = safe ?? this.safe; | ... | ... |
lib/generated/json/base/json_convert_content.dart
... | ... | @@ -9,6 +9,7 @@ import 'package:wow_english/models/app_config_entity.dart'; |
9 | 9 | import 'package:wow_english/models/course_entity.dart'; |
10 | 10 | import 'package:wow_english/models/course_module_entity.dart'; |
11 | 11 | import 'package:wow_english/models/course_process_entity.dart'; |
12 | +import 'package:wow_english/models/course_unit_entity.dart'; | |
12 | 13 | import 'package:wow_english/models/follow_read_entity.dart'; |
13 | 14 | import 'package:wow_english/models/listen_entity.dart'; |
14 | 15 | import 'package:wow_english/models/product_entity.dart'; |
... | ... | @@ -192,6 +193,14 @@ class JsonConvert { |
192 | 193 | return data.map<CourseProcessVideos>((Map<String, dynamic> e) => |
193 | 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 | 204 | if (<FollowReadEntity>[] is M) { |
196 | 205 | return data.map<FollowReadEntity>((Map<String, dynamic> e) => |
197 | 206 | FollowReadEntity.fromJson(e)).toList() as M; |
... | ... | @@ -246,6 +255,8 @@ class JsonConvertClassCollection { |
246 | 255 | (CourseProcessTopicsTopicAnswerList) |
247 | 256 | .toString(): CourseProcessTopicsTopicAnswerList.fromJson, |
248 | 257 | (CourseProcessVideos).toString(): CourseProcessVideos.fromJson, |
258 | + (CourseUnitEntity).toString(): CourseUnitEntity.fromJson, | |
259 | + (CourseUnitDetail).toString(): CourseUnitDetail.fromJson, | |
249 | 260 | (FollowReadEntity).toString(): FollowReadEntity.fromJson, |
250 | 261 | (ListenEntity).toString(): ListenEntity.fromJson, |
251 | 262 | (ProductEntity).toString(): ProductEntity.fromJson, | ... | ... |
lib/generated/json/course_module_entity.g.dart
... | ... | @@ -3,7 +3,7 @@ import 'package:wow_english/models/course_module_entity.dart'; |
3 | 3 | |
4 | 4 | CourseModuleEntity $CourseModuleEntityFromJson(Map<String, dynamic> json) { |
5 | 5 | final CourseModuleEntity courseModuleEntity = CourseModuleEntity(); |
6 | - final String? id = jsonConvert.convert<String>(json['id']); | |
6 | + final int? id = jsonConvert.convert<int>(json['id']); | |
7 | 7 | if (id != null) { |
8 | 8 | courseModuleEntity.id = id; |
9 | 9 | } |
... | ... | @@ -90,7 +90,7 @@ Map<String, dynamic> $CourseModuleEntityToJson(CourseModuleEntity entity) { |
90 | 90 | |
91 | 91 | extension CourseModuleEntityExtension on CourseModuleEntity { |
92 | 92 | CourseModuleEntity copyWith({ |
93 | - String? id, | |
93 | + int? id, | |
94 | 94 | String? code, |
95 | 95 | int? courseModuleThemeId, |
96 | 96 | int? courseTotal, | ... | ... |
lib/generated/json/course_unit_entity.g.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_convert_content.dart'; | |
2 | +import 'package:wow_english/models/course_unit_entity.dart'; | |
3 | + | |
4 | +CourseUnitEntity $CourseUnitEntityFromJson(Map<String, dynamic> json) { | |
5 | + final CourseUnitEntity courseUnitEntity = CourseUnitEntity(); | |
6 | + final List< | |
7 | + CourseUnitDetail>? courseUnitVOList = (json['courseUnitVOList'] as List< | |
8 | + dynamic>?) | |
9 | + ?.map( | |
10 | + (e) => jsonConvert.convert<CourseUnitDetail>(e) as CourseUnitDetail) | |
11 | + .toList(); | |
12 | + if (courseUnitVOList != null) { | |
13 | + courseUnitEntity.courseUnitVOList = courseUnitVOList; | |
14 | + } | |
15 | + final int? nowStep = jsonConvert.convert<int>(json['nowStep']); | |
16 | + if (nowStep != null) { | |
17 | + courseUnitEntity.nowStep = nowStep; | |
18 | + } | |
19 | + final int? total = jsonConvert.convert<int>(json['total']); | |
20 | + if (total != null) { | |
21 | + courseUnitEntity.total = total; | |
22 | + } | |
23 | + final int? nowCourseModuleId = jsonConvert.convert<int>( | |
24 | + json['nowCourseModuleId']); | |
25 | + if (nowCourseModuleId != null) { | |
26 | + courseUnitEntity.nowCourseModuleId = nowCourseModuleId; | |
27 | + } | |
28 | + final String? nowCourseModuleName = jsonConvert.convert<String>( | |
29 | + json['nowCourseModuleName']); | |
30 | + if (nowCourseModuleName != null) { | |
31 | + courseUnitEntity.nowCourseModuleName = nowCourseModuleName; | |
32 | + } | |
33 | + final String? courseModuleThemeColor = jsonConvert.convert<String>( | |
34 | + json['courseModuleThemeColor']); | |
35 | + if (courseModuleThemeColor != null) { | |
36 | + courseUnitEntity.courseModuleThemeColor = courseModuleThemeColor; | |
37 | + } | |
38 | + final String? courseModuleCode = jsonConvert.convert<String>( | |
39 | + json['courseModuleCode']); | |
40 | + if (courseModuleCode != null) { | |
41 | + courseUnitEntity.courseModuleCode = courseModuleCode; | |
42 | + } | |
43 | + return courseUnitEntity; | |
44 | +} | |
45 | + | |
46 | +Map<String, dynamic> $CourseUnitEntityToJson(CourseUnitEntity entity) { | |
47 | + final Map<String, dynamic> data = <String, dynamic>{}; | |
48 | + data['courseUnitVOList'] = | |
49 | + entity.courseUnitVOList?.map((v) => v.toJson()).toList(); | |
50 | + data['nowStep'] = entity.nowStep; | |
51 | + data['total'] = entity.total; | |
52 | + data['nowCourseModuleId'] = entity.nowCourseModuleId; | |
53 | + data['nowCourseModuleName'] = entity.nowCourseModuleName; | |
54 | + data['courseModuleThemeColor'] = entity.courseModuleThemeColor; | |
55 | + data['courseModuleCode'] = entity.courseModuleCode; | |
56 | + return data; | |
57 | +} | |
58 | + | |
59 | +extension CourseUnitEntityExtension on CourseUnitEntity { | |
60 | + CourseUnitEntity copyWith({ | |
61 | + List<CourseUnitDetail>? courseUnitVOList, | |
62 | + int? nowStep, | |
63 | + int? total, | |
64 | + int? nowCourseModuleId, | |
65 | + String? nowCourseModuleName, | |
66 | + String? courseModuleThemeColor, | |
67 | + String? courseModuleCode, | |
68 | + }) { | |
69 | + return CourseUnitEntity() | |
70 | + ..courseUnitVOList = courseUnitVOList ?? this.courseUnitVOList | |
71 | + ..nowStep = nowStep ?? this.nowStep | |
72 | + ..total = total ?? this.total | |
73 | + ..nowCourseModuleId = nowCourseModuleId ?? this.nowCourseModuleId | |
74 | + ..nowCourseModuleName = nowCourseModuleName ?? this.nowCourseModuleName | |
75 | + ..courseModuleThemeColor = courseModuleThemeColor ?? | |
76 | + this.courseModuleThemeColor | |
77 | + ..courseModuleCode = courseModuleCode ?? this.courseModuleCode; | |
78 | + } | |
79 | +} | |
80 | + | |
81 | +CourseUnitDetail $CourseUnitDetailFromJson(Map<String, dynamic> json) { | |
82 | + final CourseUnitDetail courseUnitDetail = CourseUnitDetail(); | |
83 | + final int? courseModuleId = jsonConvert.convert<int>(json['courseModuleId']); | |
84 | + if (courseModuleId != null) { | |
85 | + courseUnitDetail.courseModuleId = courseModuleId; | |
86 | + } | |
87 | + final int? id = jsonConvert.convert<int>(json['id']); | |
88 | + if (id != null) { | |
89 | + courseUnitDetail.id = id; | |
90 | + } | |
91 | + final String? name = jsonConvert.convert<String>(json['name']); | |
92 | + if (name != null) { | |
93 | + courseUnitDetail.name = name; | |
94 | + } | |
95 | + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']); | |
96 | + if (coverUrl != null) { | |
97 | + courseUnitDetail.coverUrl = coverUrl; | |
98 | + } | |
99 | + final bool? lock = jsonConvert.convert<bool>(json['lock']); | |
100 | + if (lock != null) { | |
101 | + courseUnitDetail.lock = lock; | |
102 | + } | |
103 | + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']); | |
104 | + if (sortOrder != null) { | |
105 | + courseUnitDetail.sortOrder = sortOrder; | |
106 | + } | |
107 | + final int? status = jsonConvert.convert<int>(json['status']); | |
108 | + if (status != null) { | |
109 | + courseUnitDetail.status = status; | |
110 | + } | |
111 | + return courseUnitDetail; | |
112 | +} | |
113 | + | |
114 | +Map<String, dynamic> $CourseUnitDetailToJson(CourseUnitDetail entity) { | |
115 | + final Map<String, dynamic> data = <String, dynamic>{}; | |
116 | + data['courseModuleId'] = entity.courseModuleId; | |
117 | + data['id'] = entity.id; | |
118 | + data['name'] = entity.name; | |
119 | + data['coverUrl'] = entity.coverUrl; | |
120 | + data['lock'] = entity.lock; | |
121 | + data['sortOrder'] = entity.sortOrder; | |
122 | + data['status'] = entity.status; | |
123 | + return data; | |
124 | +} | |
125 | + | |
126 | +extension CourseUnitDetailExtension on CourseUnitDetail { | |
127 | + CourseUnitDetail copyWith({ | |
128 | + int? courseModuleId, | |
129 | + int? id, | |
130 | + String? name, | |
131 | + String? coverUrl, | |
132 | + bool? lock, | |
133 | + int? sortOrder, | |
134 | + int? status, | |
135 | + }) { | |
136 | + return CourseUnitDetail() | |
137 | + ..courseModuleId = courseModuleId ?? this.courseModuleId | |
138 | + ..id = id ?? this.id | |
139 | + ..name = name ?? this.name | |
140 | + ..coverUrl = coverUrl ?? this.coverUrl | |
141 | + ..lock = lock ?? this.lock | |
142 | + ..sortOrder = sortOrder ?? this.sortOrder | |
143 | + ..status = status ?? this.status; | |
144 | + } | |
145 | +} | |
0 | 146 | \ No newline at end of file | ... | ... |
lib/models/course_module_entity.dart
lib/models/course_unit_entity.dart
0 → 100644
1 | +import 'package:wow_english/generated/json/base/json_field.dart'; | |
2 | +import 'package:wow_english/generated/json/course_unit_entity.g.dart'; | |
3 | +import 'dart:convert'; | |
4 | + | |
5 | +export 'package:wow_english/generated/json/course_unit_entity.g.dart'; | |
6 | + | |
7 | +@JsonSerializable() | |
8 | +class CourseUnitEntity { | |
9 | + | |
10 | + // 课程详情列表 | |
11 | + List<CourseUnitDetail>? courseUnitVOList; | |
12 | + | |
13 | + // 当前进行了多少节课程 | |
14 | + int? nowStep; | |
15 | + | |
16 | + // 当前模块一共多少节课程 | |
17 | + int? total; | |
18 | + | |
19 | + // 当前模块id | |
20 | + int? nowCourseModuleId; | |
21 | + | |
22 | + // 当前模块名 | |
23 | + String? nowCourseModuleName; | |
24 | + | |
25 | + // 主题颜色值 | |
26 | + String? courseModuleThemeColor; | |
27 | + | |
28 | + // 课程模块code | |
29 | + String? courseModuleCode; | |
30 | + | |
31 | + CourseUnitEntity(); | |
32 | + | |
33 | + factory CourseUnitEntity.fromJson(Map<String, dynamic> json) => $CourseUnitEntityFromJson(json); | |
34 | + | |
35 | + Map<String, dynamic> toJson() => $CourseUnitEntityToJson(this); | |
36 | + | |
37 | + @override | |
38 | + String toString() { | |
39 | + return jsonEncode(this); | |
40 | + } | |
41 | +} | |
42 | + | |
43 | + | |
44 | +@JsonSerializable() | |
45 | +class CourseUnitDetail { | |
46 | + | |
47 | + // 模块id | |
48 | + int? courseModuleId; | |
49 | + | |
50 | + // 单元 | |
51 | + int? id; | |
52 | + | |
53 | + // 单元名称 | |
54 | + String? name; | |
55 | + | |
56 | + // 单元封面 | |
57 | + String? coverUrl; | |
58 | + | |
59 | + bool? lock; | |
60 | + | |
61 | + int? sortOrder; | |
62 | + | |
63 | + int? status; | |
64 | + | |
65 | + CourseUnitDetail(); | |
66 | + | |
67 | + factory CourseUnitDetail.fromJson(Map<String, dynamic> json) => $CourseUnitDetailFromJson(json); | |
68 | + | |
69 | + Map<String, dynamic> toJson() => $CourseUnitDetailToJson(this); | |
70 | + | |
71 | + @override | |
72 | + String toString() { | |
73 | + return jsonEncode(this); | |
74 | + } | |
75 | +} | |
0 | 76 | \ No newline at end of file | ... | ... |
lib/pages/home/bloc/home_bloc.dart
... | ... | @@ -13,7 +13,7 @@ part 'home_event.dart'; |
13 | 13 | part 'home_state.dart'; |
14 | 14 | |
15 | 15 | class HomeBloc extends Bloc<HomeEvent, HomeState> { |
16 | - final String? moduleId; | |
16 | + final int? moduleId; | |
17 | 17 | |
18 | 18 | CourseEntity? _modelData; |
19 | 19 | |
... | ... | @@ -33,7 +33,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { |
33 | 33 | void _requestData(RequestDataEvent event, Emitter<HomeState> emitter) async { |
34 | 34 | try { |
35 | 35 | await loading(() async { |
36 | - _modelData = await HomeDao.courseLesson(moduleId: moduleId ?? ''); | |
36 | + _modelData = await HomeDao.courseLesson(moduleId: moduleId); | |
37 | 37 | emitter(HomeDataLoadState()); |
38 | 38 | }); |
39 | 39 | } catch (e) { | ... | ... |
lib/pages/home/home_page.dart
... | ... | @@ -6,7 +6,7 @@ import 'package:wow_english/common/extension/string_extension.dart'; |
6 | 6 | import 'package:wow_english/models/course_entity.dart'; |
7 | 7 | import 'package:wow_english/pages/home/widgets/home_bouns_item.dart'; |
8 | 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 | 10 | import 'package:wow_english/route/route.dart'; |
11 | 11 | import 'package:wow_english/utils/toast_util.dart'; |
12 | 12 | |
... | ... | @@ -17,7 +17,7 @@ class HomePage extends StatelessWidget { |
17 | 17 | const HomePage({super.key, this.moduleId}); |
18 | 18 | |
19 | 19 | /// 模块id |
20 | - final String? moduleId; | |
20 | + final int? moduleId; | |
21 | 21 | |
22 | 22 | @override |
23 | 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 | 171 | model: model, |
172 | 172 | isSelected: bloc.currentPageIndex == index, |
173 | 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
lib/pages/unit/state.dart
0 → 100644
lib/pages/unit/view.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | |
2 | +import 'package:flutter_bloc/flutter_bloc.dart'; | |
3 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | |
4 | +import 'package:wow_english/pages/unit/state.dart'; | |
5 | +import 'package:wow_english/pages/unit/widget/course_unit_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 'package:wow_english/pages/user/setting/setting_page.dart'; |
26 | 26 | import 'package:wow_english/pages/user/user_page.dart'; |
27 | 27 | import 'package:wow_english/pages/video/lookvideo/look_video_page.dart'; |
28 | 28 | |
29 | +import '../models/course_module_entity.dart'; | |
29 | 30 | import '../pages/reading/reading_page.dart'; |
30 | 31 | import '../pages/shopping/view.dart'; |
32 | +import '../pages/unit/view.dart'; | |
31 | 33 | import '../pages/user/setting/delete_account_page.dart'; |
32 | 34 | import '../pages/user/setting/reback_page.dart'; |
33 | -import '../utils/log_util.dart'; | |
34 | 35 | |
35 | 36 | class AppRouteName { |
36 | 37 | static const String splash = 'splash'; |
... | ... | @@ -43,7 +44,8 @@ class AppRouteName { |
43 | 44 | /// 设置密码,修改密码;不要自己调用,使用[SetPassWordPage.push]方法,隐藏这种实现 |
44 | 45 | //static const String setPwd = 'setPwd'; |
45 | 46 | static const String webView = 'webView'; |
46 | - static const String lesson = 'lesson'; | |
47 | + static const String unit = 'courseUnits'; | |
48 | + static const String lesson = 'courseModules'; | |
47 | 49 | static const String listen = 'listen'; |
48 | 50 | static const String shop = 'shop'; |
49 | 51 | static const String exLesson = 'exLesson'; |
... | ... | @@ -100,9 +102,9 @@ class AppRouter { |
100 | 102 | case AppRouteName.games: |
101 | 103 | return CupertinoPageRoute(builder: (_) => const GamesPage()); |
102 | 104 | case AppRouteName.home: |
103 | - var moduleId = ''; | |
105 | + int? moduleId; | |
104 | 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 | 109 | return CupertinoPageRoute( |
108 | 110 | builder: (_) => HomePage( |
... | ... | @@ -112,6 +114,12 @@ class AppRouter { |
112 | 114 | return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage()); |
113 | 115 | case AppRouteName.lesson: |
114 | 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 | 123 | case AppRouteName.listen: |
116 | 124 | return CupertinoPageRoute(builder: (_) => const ListenPage()); |
117 | 125 | case AppRouteName.shop: | ... | ... |