Commit 68dd7ba80824d8c1cce795bf98c7caacff89955a
1 parent
56e2ae5a
feat:首页主题颜色+已知问题修改
Showing
34 changed files
with
449 additions
and
218 deletions
assets/images/back_study.png
0 → 100644
17.5 KB
assets/images/bacun.png
0 → 100644
11.4 KB
assets/images/blue_positive.png
0 → 100755
198 KB
assets/images/bronze_positive.png
0 → 100755
318 KB
assets/images/green_positive.png
0 → 100755
200 KB
assets/images/orange_positive.png
0 → 100755
199 KB
assets/images/photo_pause.png
0 → 100644
304 KB
assets/images/red_positive.png
0 → 100755
198 KB
assets/images/silver_positive.png
0 → 100755
252 KB
assets/images/yellow_positive.png
0 → 100755
190 KB
lib/common/dialogs/customer_dialog.dart
1 | 1 | import 'package:flutter/material.dart'; |
2 | 2 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
3 | +import 'package:wow_english/route/route.dart'; | |
3 | 4 | |
4 | 5 | class CustomerTwoActionDialog extends Dialog { |
5 | 6 | const CustomerTwoActionDialog( |
... | ... | @@ -25,7 +26,7 @@ class CustomerTwoActionDialog extends Dialog { |
25 | 26 | child: ConstrainedBox( |
26 | 27 | constraints: BoxConstraints( |
27 | 28 | maxHeight: 208.h, |
28 | - maxWidth: 247.w | |
29 | + maxWidth: 307.w | |
29 | 30 | ), |
30 | 31 | child: Container( |
31 | 32 | padding: EdgeInsets.symmetric(horizontal: 24.w,vertical: 15.h), | ... | ... |
lib/common/dialogs/show_dialog.dart
... | ... | @@ -18,6 +18,7 @@ void showTwoActionDialog(String title, String leftTitle, String rightTitle, Stri |
18 | 18 | {bool? barrierDismissible}) { |
19 | 19 | showDialog<CustomerTwoActionDialog>( |
20 | 20 | context: AppRouter.context, |
21 | + barrierDismissible: barrierDismissible ?? true, | |
21 | 22 | builder: (BuildContext context) { |
22 | 23 | return CustomerTwoActionDialog(title, leftTitle, rightTitle, content, leftTap, rightTap); |
23 | 24 | }); | ... | ... |
lib/common/request/apis.dart
... | ... | @@ -49,30 +49,30 @@ class Apis { |
49 | 49 | |
50 | 50 | /// 磨耳朵 |
51 | 51 | /// GET |
52 | - static const String ears = '/course/grinding/ears'; | |
52 | + static const String ears = 'course/grinding/ears'; | |
53 | 53 | |
54 | 54 | /// 视频跟读 |
55 | 55 | /// GET |
56 | - static const String followRead = '/course/video/follow/read'; | |
56 | + static const String followRead = 'course/video/follow/read'; | |
57 | 57 | |
58 | 58 | /// 视频跟读内容 |
59 | 59 | /// GET |
60 | - static const String readContent = '/course/video/follow/read/content'; | |
60 | + static const String readContent = 'course/video/follow/read/content'; | |
61 | 61 | |
62 | 62 | /// 视频跟读提交结果 |
63 | 63 | /// POST |
64 | - static const String followResult = '/course/submit/follow/result'; | |
64 | + static const String followResult = 'course/submit/follow/result'; | |
65 | 65 | |
66 | 66 | /// 获取课程内容 |
67 | 67 | /// GET |
68 | - static const String process = '/course/process'; | |
68 | + static const String process = 'course/process'; | |
69 | 69 | |
70 | 70 | /// 首页弹窗 |
71 | 71 | /// get |
72 | 72 | static const String homePopup = 'home/popup'; |
73 | 73 | |
74 | 74 | /// 兑换 |
75 | - static const String exchange = '/exchange'; | |
75 | + static const String exchange = 'exchange'; | |
76 | 76 | |
77 | 77 | /// 获取阿里云oss鉴权信息 |
78 | 78 | static const String aliyunOssSts = 'oss/sts/upload'; | ... | ... |
lib/common/request/dao/listen_dao.dart
... | ... | @@ -32,7 +32,7 @@ class ListenDao { |
32 | 32 | |
33 | 33 | ///视频跟读提交结果 |
34 | 34 | static Future followResult(frequency,videoFollowReadId) async { |
35 | - var data = await requestClient.post(Apis.followResult,data: {'frequency':frequency,'videoFollowReadId':videoFollowReadId}); | |
35 | + var data = await requestClient.post(Apis.followResult,data: {'frequency':frequency,'videoFollowReadContentId':videoFollowReadId}); | |
36 | 36 | return data; |
37 | 37 | } |
38 | 38 | ... | ... |
lib/common/widgets/we_app_bar.dart
... | ... | @@ -35,7 +35,13 @@ class WEAppBar extends StatelessWidget implements PreferredSizeWidget { |
35 | 35 | ), |
36 | 36 | leading: leading ?? |
37 | 37 | GestureDetector( |
38 | - onTap: () => onBack??Navigator.pop(context), | |
38 | + onTap: () { | |
39 | + if (onBack == null) { | |
40 | + Navigator.pop(context); | |
41 | + } else { | |
42 | + onBack!(); | |
43 | + } | |
44 | + }, | |
39 | 45 | child: Container( |
40 | 46 | alignment: Alignment.center, |
41 | 47 | child: Image.asset( | ... | ... |
lib/generated/json/course_entity.g.dart
... | ... | @@ -27,6 +27,10 @@ CourseEntity $CourseEntityFromJson(Map<String, dynamic> json) { |
27 | 27 | if (courseModuleThemeColor != null) { |
28 | 28 | courseEntity.courseModuleThemeColor = courseModuleThemeColor; |
29 | 29 | } |
30 | + final String? courseModuleCode = jsonConvert.convert<String>(json['courseModuleCode']); | |
31 | + if (courseModuleCode != null) { | |
32 | + courseEntity.courseModuleCode = courseModuleCode; | |
33 | + } | |
30 | 34 | return courseEntity; |
31 | 35 | } |
32 | 36 | |
... | ... | @@ -38,6 +42,7 @@ Map<String, dynamic> $CourseEntityToJson(CourseEntity entity) { |
38 | 42 | data['nowCourseModuleName'] = entity.nowCourseModuleName; |
39 | 43 | data['totalCourseLesson'] = entity.totalCourseLesson; |
40 | 44 | data['courseModuleThemeColor'] = entity.courseModuleThemeColor; |
45 | + data['courseModuleCode'] = entity.courseModuleCode; | |
41 | 46 | return data; |
42 | 47 | } |
43 | 48 | ... | ... |
lib/models/course_entity.dart
lib/pages/home/bloc/home_bloc.dart
... | ... | @@ -6,7 +6,6 @@ import 'package:wow_english/common/request/exception.dart'; |
6 | 6 | import 'package:wow_english/models/course_entity.dart'; |
7 | 7 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
8 | 8 | import 'package:wow_english/models/course_process_entity.dart'; |
9 | -// import 'package:wow_english/models/course_lesson_entity.dart'; | |
10 | 9 | import 'package:wow_english/utils/loading.dart'; |
11 | 10 | import 'package:wow_english/utils/toast_util.dart'; |
12 | 11 | ... | ... |
lib/pages/home/courese_module_model.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | |
2 | + | |
3 | +class CourseModuleModel { | |
4 | + Color get color => getCourseColor(); | |
5 | + String get courseModuleTitle => getCourseModuleTitle(); | |
6 | + String get courseModuleLogo => getCoureseImageName(); | |
7 | + | |
8 | + | |
9 | + String course; | |
10 | + | |
11 | + CourseModuleModel(this.course); | |
12 | + | |
13 | + Color getCourseColor() { | |
14 | + if (course == 'Phase-1') { | |
15 | + return Colors.yellow; | |
16 | + } | |
17 | + if (course == 'Phase-2') { | |
18 | + return Colors.red; | |
19 | + } | |
20 | + if (course == 'Phase-3') { | |
21 | + return Colors.blue; | |
22 | + } | |
23 | + if (course == 'Phase-4') { | |
24 | + return Colors.green; | |
25 | + } | |
26 | + if (course == 'Phase-5') { | |
27 | + return Colors.orange; | |
28 | + } | |
29 | + if (course == 'Phase-6') { | |
30 | + return const Color(0XFFC07347); | |
31 | + } | |
32 | + if (course == 'Phase-7') { | |
33 | + return const Color(0xFFA3A2A2); | |
34 | + } | |
35 | + return Colors.red; | |
36 | + } | |
37 | + | |
38 | + String getCourseModuleTitle() { | |
39 | + if (course == 'Phase-1') { | |
40 | + return 'learn wow! yellow'; | |
41 | + } | |
42 | + if (course == 'Phase-2') { | |
43 | + return 'learn wow! red'; | |
44 | + } | |
45 | + if (course == 'Phase-3') { | |
46 | + return 'learn wow! blue'; | |
47 | + } | |
48 | + if (course == 'Phase-4') { | |
49 | + return 'learn wow! green'; | |
50 | + } | |
51 | + if (course == 'Phase-5') { | |
52 | + return 'learn wow! orange'; | |
53 | + } | |
54 | + if (course == 'Phase-6') { | |
55 | + return 'learn wow! bronze'; | |
56 | + } | |
57 | + if (course == 'Phase-7') { | |
58 | + return 'learn wow! silver'; | |
59 | + } | |
60 | + return 'learn wow! red'; | |
61 | + } | |
62 | + | |
63 | + String getCoureseImageName() { | |
64 | + if (course == 'Phase-1') { | |
65 | + return 'yellow_positive'; | |
66 | + } | |
67 | + if (course == 'Phase-2') { | |
68 | + return 'red_positive'; | |
69 | + } | |
70 | + if (course == 'Phase-3') { | |
71 | + return 'blue_positive'; | |
72 | + } | |
73 | + if (course == 'Phase-4') { | |
74 | + return 'learn wow! green'; | |
75 | + } | |
76 | + if (course == 'Phase-5') { | |
77 | + return 'orange_positive'; | |
78 | + } | |
79 | + if (course == 'Phase-6') { | |
80 | + return 'bronze_positive'; | |
81 | + } | |
82 | + if (course == 'Phase-7') { | |
83 | + return 'silver_positive'; | |
84 | + } | |
85 | + return 'red_positive'; | |
86 | + } | |
87 | +} | |
0 | 88 | \ No newline at end of file | ... | ... |
lib/pages/home/home_page.dart
... | ... | @@ -8,10 +8,10 @@ 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 | 9 | import 'package:wow_english/pages/home/widgets/home_vidoe_item.dart'; |
10 | 10 | import 'package:wow_english/route/route.dart'; |
11 | -import 'package:wow_english/utils/color_util.dart'; | |
12 | 11 | import 'package:wow_english/utils/toast_util.dart'; |
13 | 12 | |
14 | 13 | import 'bloc/home_bloc.dart'; |
14 | +import 'courese_module_model.dart'; | |
15 | 15 | |
16 | 16 | class HomePage extends StatelessWidget { |
17 | 17 | const HomePage({super.key, this.moduleId}); |
... | ... | @@ -129,102 +129,103 @@ class _HomePageView extends StatelessWidget { |
129 | 129 | ); |
130 | 130 | } |
131 | 131 | |
132 | - Widget _homeView() => BlocBuilder<HomeBloc, HomeState>(builder: (context, state) { | |
133 | - final bloc = BlocProvider.of<HomeBloc>(context); | |
134 | - return Scaffold( | |
135 | - body: Container( | |
136 | - color: Colors.white, | |
137 | - child: Center( | |
138 | - child: Column( | |
139 | - mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
140 | - children: [ | |
141 | - HomeTabHeaderWidget( | |
142 | - themColor: bloc.modelData?.courseModuleThemeColor, | |
143 | - actionTap: (HeaderActionType type) { | |
144 | - _headerActionEvent(type); | |
145 | - }, | |
146 | - ), | |
147 | - Expanded( | |
148 | - child: ListView.builder( | |
149 | - itemCount: bloc.modelData?.totalCourseLesson??0, | |
150 | - scrollDirection: Axis.horizontal, | |
151 | - itemBuilder: (BuildContext context, int index) { | |
152 | - CourseCourseLessons? data = bloc.modelData?.courseLessons?[index]; | |
153 | - if (data?.courseType == 5) { | |
154 | - //彩蛋 | |
155 | - return GestureDetector( | |
156 | - onTap: () { | |
157 | - if(UserUtil.token.isEmpty) { | |
158 | - pushNamed(AppRouteName.login); | |
159 | - return; | |
160 | - } | |
161 | - if (data!.lock!) { | |
162 | - showToast('当前课程暂未解锁'); | |
163 | - return; | |
164 | - } | |
165 | - ///进入课堂 | |
166 | - bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); | |
167 | - }, | |
168 | - child: HomeBoundsItem( | |
169 | - imageUrl: data?.coverUrl, | |
132 | + Widget _homeView() => BlocBuilder<HomeBloc, HomeState>( | |
133 | + builder: (context, state) { | |
134 | + final bloc = BlocProvider.of<HomeBloc>(context); | |
135 | + return Scaffold( | |
136 | + body: Container( | |
137 | + color: Colors.white, | |
138 | + child: Center( | |
139 | + child: Column( | |
140 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
141 | + children: [ | |
142 | + HomeTabHeaderWidget( | |
143 | + entity: bloc.modelData, | |
144 | + actionTap: (HeaderActionType type) { | |
145 | + _headerActionEvent(type); | |
146 | + }, | |
147 | + ), | |
148 | + Expanded( | |
149 | + child: ListView.builder( | |
150 | + itemCount: bloc.modelData?.totalCourseLesson??0, | |
151 | + scrollDirection: Axis.horizontal, | |
152 | + itemBuilder: (BuildContext context, int index) { | |
153 | + CourseCourseLessons? data = bloc.modelData?.courseLessons?[index]; | |
154 | + if (data?.courseType == 5) { | |
155 | + //彩蛋 | |
156 | + return GestureDetector( | |
157 | + onTap: () { | |
158 | + if(UserUtil.token.isEmpty) { | |
159 | + pushNamed(AppRouteName.login); | |
160 | + return; | |
161 | + } | |
162 | + if (data!.lock!) { | |
163 | + showToast('当前课程暂未解锁'); | |
164 | + return; | |
165 | + } | |
166 | + ///进入课堂 | |
167 | + bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); | |
168 | + }, | |
169 | + child: HomeBoundsItem( | |
170 | + imageUrl: data?.coverUrl, | |
171 | + ), | |
172 | + ); | |
173 | + } else { | |
174 | + return GestureDetector( | |
175 | + onTap: () { | |
176 | + if(UserUtil.token.isEmpty) { | |
177 | + pushNamed(AppRouteName.login); | |
178 | + return; | |
179 | + } | |
180 | + if (data!.lock!) { | |
181 | + showToast('当前课程暂未解锁'); | |
182 | + return; | |
183 | + } | |
184 | + ///进入课堂 | |
185 | + bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); | |
186 | + }, | |
187 | + child: HomeVideoItem( | |
188 | + entity: bloc.modelData, | |
189 | + lessons: data, | |
190 | + ), | |
191 | + ); | |
192 | + } | |
193 | + })), | |
194 | + SafeArea( | |
195 | + child: Padding( | |
196 | + padding: EdgeInsets.symmetric(horizontal: 13.w), | |
197 | + child: Row( | |
198 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
199 | + children: [ | |
200 | + SizedBox( | |
201 | + height: 47.h, | |
202 | + width: 80.w, | |
203 | + ), | |
204 | + Container( | |
205 | + decoration: BoxDecoration( | |
206 | + color: CourseModuleModel(bloc.modelData?.courseModuleCode??'Phase-1').color, | |
207 | + borderRadius: BorderRadius.circular(14.5.r), | |
170 | 208 | ), |
171 | - ); | |
172 | - } else { | |
173 | - return GestureDetector( | |
174 | - onTap: () { | |
175 | - if(UserUtil.token.isEmpty) { | |
176 | - pushNamed(AppRouteName.login); | |
177 | - return; | |
178 | - } | |
179 | - if (data!.lock!) { | |
180 | - showToast('当前课程暂未解锁'); | |
181 | - return; | |
182 | - } | |
183 | - ///进入课堂 | |
184 | - bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); | |
185 | - }, | |
186 | - child: HomeVideoItem( | |
187 | - themColor: bloc.modelData?.courseModuleThemeColor, | |
188 | - lessons: data, | |
209 | + padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 24.w), | |
210 | + child: Text( | |
211 | + '${(bloc.modelData?.nowCourseLesson??0)}/${bloc.modelData?.totalCourseLesson??0}', | |
212 | + style: TextStyle(color: Colors.white, fontSize: 12.sp), | |
189 | 213 | ), |
190 | - ); | |
191 | - } | |
192 | - })), | |
193 | - SafeArea( | |
194 | - child: Padding( | |
195 | - padding: EdgeInsets.symmetric(horizontal: 13.w), | |
196 | - child: Row( | |
197 | - mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
198 | - children: [ | |
199 | - SizedBox( | |
200 | - height: 47.h, | |
201 | - width: 80.w, | |
202 | - ), | |
203 | - Container( | |
204 | - decoration: BoxDecoration( | |
205 | - color: HexColor(bloc.modelData?.courseModuleThemeColor??''), | |
206 | - borderRadius: BorderRadius.circular(14.5.r), | |
207 | - ), | |
208 | - padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 24.w), | |
209 | - child: Text( | |
210 | - '${(bloc.modelData?.nowCourseLesson??0)}/${bloc.modelData?.totalCourseLesson??0}', | |
211 | - style: TextStyle(color: Colors.white, fontSize: 12.sp), | |
212 | - ), | |
214 | + ), | |
215 | + Image.asset( | |
216 | + CourseModuleModel(bloc.modelData?.courseModuleCode??'Phase-1').courseModuleLogo.assetPng, | |
217 | + height: 47.h, | |
218 | + width: 80.w, | |
219 | + // color: Colors.red, | |
220 | + ), | |
221 | + ], | |
213 | 222 | ), |
214 | - Image.asset( | |
215 | - 'blue-positive'.assetPng, | |
216 | - height: 47.h, | |
217 | - width: 80.w, | |
218 | - // color: Colors.red, | |
219 | - ), | |
220 | - ], | |
221 | - ), | |
222 | - ), | |
223 | - ) | |
224 | - ], | |
223 | + ), | |
224 | + ) | |
225 | + ], | |
226 | + ), | |
227 | + ), | |
225 | 228 | ), |
226 | - ), | |
227 | - ), | |
228 | - ); | |
229 | - }); | |
229 | + ); | |
230 | + }); | |
230 | 231 | } | ... | ... |
lib/pages/home/widgets/home_tab_header_widget.dart
... | ... | @@ -4,9 +4,11 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; |
4 | 4 | import 'package:wow_english/common/core/user_util.dart'; |
5 | 5 | import 'package:wow_english/common/extension/string_extension.dart'; |
6 | 6 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
7 | -import 'package:wow_english/utils/color_util.dart'; | |
8 | 7 | import 'package:wow_english/utils/image_util.dart'; |
9 | 8 | |
9 | +import '../../../models/course_entity.dart'; | |
10 | +import '../courese_module_model.dart'; | |
11 | + | |
10 | 12 | enum HeaderActionType { |
11 | 13 | //视频跟读 |
12 | 14 | video, |
... | ... | @@ -21,9 +23,9 @@ enum HeaderActionType { |
21 | 23 | } |
22 | 24 | |
23 | 25 | class HomeTabHeaderWidget extends StatelessWidget { |
24 | - const HomeTabHeaderWidget({super.key, this.actionTap, this.themColor}); | |
26 | + const HomeTabHeaderWidget({super.key,this.entity, this.actionTap}); | |
25 | 27 | |
26 | - final String? themColor; | |
28 | + final CourseEntity? entity; | |
27 | 29 | final Function(HeaderActionType type)? actionTap; |
28 | 30 | |
29 | 31 | @override |
... | ... | @@ -33,7 +35,7 @@ class HomeTabHeaderWidget extends StatelessWidget { |
33 | 35 | return Container( |
34 | 36 | height: 45, |
35 | 37 | width: double.infinity, |
36 | - color: HexColor(themColor??''), | |
38 | + color: CourseModuleModel(entity?.courseModuleCode??'Phase-1').color, | |
37 | 39 | padding: EdgeInsets.symmetric(horizontal: 9.5.w), |
38 | 40 | child: Row( |
39 | 41 | children: [ |
... | ... | @@ -75,11 +77,11 @@ class HomeTabHeaderWidget extends StatelessWidget { |
75 | 77 | ), |
76 | 78 | ), |
77 | 79 | 20.horizontalSpace, |
78 | - const Expanded( | |
80 | + Expanded( | |
79 | 81 | child: Text( |
80 | - 'learn wow', | |
82 | + CourseModuleModel(entity?.courseModuleCode??'Phase-1').courseModuleTitle, | |
81 | 83 | textAlign: TextAlign.left, |
82 | - style: TextStyle(color: Colors.white, fontSize: 30.0), | |
84 | + style: const TextStyle(color: Colors.white, fontSize: 30.0), | |
83 | 85 | )), |
84 | 86 | IconButton( |
85 | 87 | onPressed: () { | ... | ... |
lib/pages/home/widgets/home_vidoe_item.dart
... | ... | @@ -3,12 +3,13 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; |
3 | 3 | import 'package:wow_english/common/extension/string_extension.dart'; |
4 | 4 | import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
5 | 5 | import 'package:wow_english/models/course_entity.dart'; |
6 | -import 'package:wow_english/utils/color_util.dart'; | |
6 | + | |
7 | +import '../courese_module_model.dart'; | |
7 | 8 | |
8 | 9 | class HomeVideoItem extends StatelessWidget { |
9 | - const HomeVideoItem({super.key, this.lessons, this.themColor}); | |
10 | + const HomeVideoItem({super.key, this.lessons, this.entity}); | |
10 | 11 | |
11 | - final String? themColor; | |
12 | + final CourseEntity? entity; | |
12 | 13 | final CourseCourseLessons? lessons; |
13 | 14 | |
14 | 15 | @override |
... | ... | @@ -20,8 +21,8 @@ class HomeVideoItem extends StatelessWidget { |
20 | 21 | padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 24.h), |
21 | 22 | decoration: BoxDecoration( |
22 | 23 | image: DecorationImage( |
23 | - image: AssetImage('gendubeij'.assetPng), | |
24 | - fit: BoxFit.fill | |
24 | + image: AssetImage('gendubeij'.assetPng), | |
25 | + fit: BoxFit.fill | |
25 | 26 | ), |
26 | 27 | ), |
27 | 28 | child: Column( |
... | ... | @@ -40,7 +41,8 @@ class HomeVideoItem extends StatelessWidget { |
40 | 41 | name: lessons?.coverUrl??'', |
41 | 42 | fit: BoxFit.fitHeight, |
42 | 43 | ), |
43 | - )), | |
44 | + ) | |
45 | + ), | |
44 | 46 | 24.verticalSpace, |
45 | 47 | Container( |
46 | 48 | decoration: BoxDecoration( |
... | ... | @@ -48,7 +50,7 @@ class HomeVideoItem extends StatelessWidget { |
48 | 50 | width: 2, |
49 | 51 | color: const Color(0xFF140C10), |
50 | 52 | ), |
51 | - color: HexColor(themColor??''), | |
53 | + color: CourseModuleModel(entity?.courseModuleCode??'Phase-1').color, | |
52 | 54 | borderRadius: BorderRadius.circular(6) |
53 | 55 | ), |
54 | 56 | padding: EdgeInsets.symmetric(horizontal: 10.w), | ... | ... |
lib/pages/lessons/widgets/lesson_item_widget.dart
... | ... | @@ -5,6 +5,8 @@ import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
5 | 5 | import 'package:wow_english/models/course_module_entity.dart'; |
6 | 6 | import 'package:wow_english/utils/color_util.dart'; |
7 | 7 | |
8 | +import '../../home/courese_module_model.dart'; | |
9 | + | |
8 | 10 | class LessonItemWidget extends StatelessWidget { |
9 | 11 | const LessonItemWidget({super.key, required this.isSelected, this.model, this.onClickEvent}); |
10 | 12 | ///是否被选中 |
... | ... | @@ -61,7 +63,7 @@ class LessonItemWidget extends StatelessWidget { |
61 | 63 | 10.verticalSpace, |
62 | 64 | Container( |
63 | 65 | decoration: BoxDecoration( |
64 | - color: HexColor(model?.courseModuleThemeColor??'#FFC0C3E7'), | |
66 | + color: CourseModuleModel(model?.code??'Phase-1').color, | |
65 | 67 | borderRadius: BorderRadius.circular(6.r), |
66 | 68 | border: Border.all( |
67 | 69 | color: const Color(0xFF333333), | ... | ... |
lib/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart
... | ... | @@ -171,10 +171,11 @@ class RepeatAfterContentBloc extends Bloc<RepeatAfterContentEvent, RepeatAfterCo |
171 | 171 | } |
172 | 172 | } |
173 | 173 | |
174 | - ///跟读结果 | |
174 | + ///提交跟读结果 | |
175 | 175 | void _postFollowReadContent(PostFollowReadContentEvent event,Emitter<RepeatAfterContentState> emitter) async { |
176 | 176 | try { |
177 | - await ListenDao.followResult(_recordNumber.toString(),courseLessonId); | |
177 | + ReadContentEntity entity = _entityList![_currentPlayIndex]!; | |
178 | + await ListenDao.followResult(_recordNumber.toString(),entity.id); | |
178 | 179 | } catch (e) { |
179 | 180 | if (e is ApiException) { |
180 | 181 | ... | ... |
lib/pages/repeataftercontent/repeat_after_content_page.dart
... | ... | @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; |
3 | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
4 | 4 | import 'package:wow_english/common/extension/string_extension.dart'; |
5 | 5 | import 'package:wow_english/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart'; |
6 | +import 'package:wow_english/pages/repeataftercontent/widgets/repeat_after_content_dialog.dart'; | |
6 | 7 | import 'package:wow_english/route/route.dart'; |
7 | 8 | |
8 | 9 | import '../../common/core/app_consts.dart'; |
... | ... | @@ -64,7 +65,16 @@ class _RepeatAfterContentPage extends StatelessWidget { |
64 | 65 | ///返回 |
65 | 66 | Positioned( |
66 | 67 | child: GestureDetector( |
67 | - onTap: () => popPage(), | |
68 | + onTap: () { | |
69 | + showDialog<RepeatAfterContentDialog>( | |
70 | + context: context, | |
71 | + builder: (context){ | |
72 | + return RepeatAfterContentDialog( (){ | |
73 | + popPage(); | |
74 | + }); | |
75 | + }); | |
76 | + // popPage(); | |
77 | + }, | |
68 | 78 | child: Image.asset( |
69 | 79 | 'back_around'.assetPng, |
70 | 80 | height: 40.h, |
... | ... | @@ -326,11 +336,11 @@ class _RepeatAfterContentPage extends StatelessWidget { |
326 | 336 | child: Container( |
327 | 337 | color: Colors.grey, |
328 | 338 | padding: EdgeInsets.symmetric( |
329 | - vertical: 50.h, | |
330 | - horizontal: 50.w | |
339 | + vertical: 50.h, | |
340 | + horizontal: 50.w | |
331 | 341 | ), |
332 | 342 | child: Text( |
333 | - bloc.voiceRecordState == VoiceRecordState.voiceRecording?'正在录音':'录音结束' | |
343 | + bloc.voiceRecordState == VoiceRecordState.voiceRecording?'正在录音':'录音结束' | |
334 | 344 | ), |
335 | 345 | ), |
336 | 346 | ), | ... | ... |
lib/pages/repeataftercontent/widgets/repeat_after_content_dialog.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/route/route.dart'; | |
5 | + | |
6 | +class RepeatAfterContentDialog extends Dialog { | |
7 | + const RepeatAfterContentDialog(this.onLeftTap, {super.key}); | |
8 | + final Function() onLeftTap; | |
9 | + @override | |
10 | + Widget build(BuildContext context) { | |
11 | + super.build(context); | |
12 | + return Center( | |
13 | + child: Column( | |
14 | + children: [ | |
15 | + 20.verticalSpace, | |
16 | + Image.asset( | |
17 | + 'photo_pause'.assetPng, | |
18 | + height: 202.h, | |
19 | + width: 321.w, | |
20 | + ), | |
21 | + Row( | |
22 | + mainAxisAlignment: MainAxisAlignment.center, | |
23 | + children: [ | |
24 | + GestureDetector( | |
25 | + onTap: () { | |
26 | + popPage(); | |
27 | + onLeftTap(); | |
28 | + }, | |
29 | + child: Container( | |
30 | + decoration: BoxDecoration( | |
31 | + image: DecorationImage( | |
32 | + image:AssetImage('bacun'.assetPng) | |
33 | + ) | |
34 | + ), | |
35 | + height: 44.h, | |
36 | + width: 137.w, | |
37 | + alignment: Alignment.center, | |
38 | + child: Text( | |
39 | + '保存并退出', | |
40 | + textAlign: TextAlign.center, | |
41 | + style: TextStyle( | |
42 | + color: const Color(0xFF333333), | |
43 | + fontSize: 17.sp | |
44 | + ), | |
45 | + ), | |
46 | + ), | |
47 | + ), | |
48 | + 33.horizontalSpace, | |
49 | + GestureDetector( | |
50 | + onTap: () { | |
51 | + popPage(); | |
52 | + }, | |
53 | + child: Container( | |
54 | + decoration: BoxDecoration( | |
55 | + image: DecorationImage( | |
56 | + image:AssetImage('back_study'.assetPng) | |
57 | + ) | |
58 | + ), | |
59 | + height: 44.h, | |
60 | + width: 137.w, | |
61 | + alignment: Alignment.center, | |
62 | + child: Text( | |
63 | + '返回继续学习', | |
64 | + textAlign: TextAlign.center, | |
65 | + style: TextStyle( | |
66 | + color: Colors.white, | |
67 | + fontSize: 17.sp | |
68 | + ), | |
69 | + ), | |
70 | + ), | |
71 | + ) | |
72 | + ], | |
73 | + ) | |
74 | + ], | |
75 | + ), | |
76 | + ); | |
77 | + } | |
78 | +} | |
0 | 79 | \ No newline at end of file | ... | ... |
lib/pages/user/information/user_information_page.dart
lib/pages/user/modify/modify_user_information_page.dart
... | ... | @@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; |
5 | 5 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
6 | 6 | import 'package:wow_english/common/core/assets_const.dart'; |
7 | 7 | import 'package:wow_english/common/core/user_util.dart'; |
8 | +import 'package:wow_english/common/dialogs/show_dialog.dart'; | |
8 | 9 | import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; |
9 | 10 | import 'package:wow_english/common/widgets/we_app_bar.dart'; |
10 | 11 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
... | ... | @@ -53,86 +54,100 @@ class ModifyUserInformationPage extends StatelessWidget { |
53 | 54 | } |
54 | 55 | }) |
55 | 56 | ], |
56 | - child: Scaffold( | |
57 | - backgroundColor: Colors.white, | |
58 | - appBar: WEAppBar( | |
59 | - titleText: '修改${type.title}', | |
60 | - ), | |
61 | - body: BlocBuilder<UserInfoBloc, UserInfoState>( | |
62 | - builder: (context, state) { | |
63 | - final bloc = BlocProvider.of<UserInfoBloc>(context); | |
64 | - return SingleChildScrollView( | |
65 | - child: Column( | |
66 | - children: [ | |
67 | - Padding( | |
68 | - padding: EdgeInsets.only(left: 65.w, right: 55.w, top: 38.h), | |
69 | - child: Row( | |
70 | - children: [ | |
71 | - Text( | |
72 | - type.title, | |
73 | - style: TextStyle( | |
74 | - fontWeight: FontWeight.w700, | |
75 | - color: const Color(0xFF333333), | |
76 | - fontSize: 21.sp, | |
77 | - ), | |
78 | - ), | |
79 | - 20.horizontalSpace, | |
80 | - // 输入框 or 选择框 | |
81 | - _buildTextFieldWidget(context), | |
82 | - // 占位 | |
83 | - Expanded( | |
84 | - child: Container(), | |
57 | + child: BlocBuilder<UserInfoBloc, UserInfoState>( | |
58 | + builder: (context, state) { | |
59 | + final bloc = BlocProvider.of<UserInfoBloc>(context); | |
60 | + return Scaffold( | |
61 | + backgroundColor: Colors.white, | |
62 | + appBar: WEAppBar( | |
63 | + titleText: '修改${type.title}', | |
64 | + onBack: () { | |
65 | + final bloc = BlocProvider.of<UserInfoBloc>(context); | |
66 | + if (bloc.isChangeInfo) { | |
67 | + showTwoActionDialog('提示', '确定离开', '继续修改', '您的信息尚未保存', () { | |
68 | + popPage(); | |
69 | + popPage(); | |
70 | + }, () { | |
71 | + popPage(); | |
72 | + }); | |
73 | + } else { | |
74 | + popPage(); | |
75 | + } | |
76 | + }, | |
77 | + ), | |
78 | + body: SingleChildScrollView( | |
79 | + child: Column( | |
80 | + children: [ | |
81 | + Padding( | |
82 | + padding: EdgeInsets.only(left: 65.w, right: 55.w, top: 38.h), | |
83 | + child: Row( | |
84 | + children: [ | |
85 | + Text( | |
86 | + type.title, | |
87 | + style: TextStyle( | |
88 | + fontWeight: FontWeight.w700, | |
89 | + color: const Color(0xFF333333), | |
90 | + fontSize: 21.sp, | |
85 | 91 | ), |
86 | - // 按钮 | |
87 | - GestureDetector( | |
88 | - onTap: () { | |
89 | - var text = ''; | |
90 | - if (type == ModifyUserInformationType.name || type == ModifyUserInformationType.age){ | |
91 | - if(bloc.modifyTextController.text.isEmpty) { | |
92 | - showToast('内容不能为空'); | |
93 | - return; | |
94 | - } | |
95 | - text = bloc.modifyTextController.text; | |
92 | + ), | |
93 | + 20.horizontalSpace, | |
94 | + // 输入框 or 选择框 | |
95 | + _buildTextFieldWidget(context), | |
96 | + // 占位 | |
97 | + Expanded( | |
98 | + child: Container(), | |
99 | + ), | |
100 | + // 按钮 | |
101 | + GestureDetector( | |
102 | + onTap: () { | |
103 | + var text = ''; | |
104 | + if (type == ModifyUserInformationType.name || type == ModifyUserInformationType.age){ | |
105 | + if(bloc.modifyTextController.text.isEmpty) { | |
106 | + showToast('内容不能为空'); | |
107 | + return; | |
96 | 108 | } |
109 | + text = bloc.modifyTextController.text; | |
110 | + } | |
97 | 111 | |
98 | - if (type == ModifyUserInformationType.gender) { | |
99 | - text = bloc.gender.toString(); | |
100 | - } | |
101 | - // 更新type类型的字段 | |
102 | - context.read<UserBloc>().add(UserUpdate(type,text)); | |
103 | - }, | |
104 | - child: Container( | |
105 | - alignment: Alignment.center, | |
106 | - width: 90.w, | |
107 | - height: 44.h, | |
108 | - decoration: const BoxDecoration( | |
109 | - image: DecorationImage(image: AssetImage(AssetsConst.bgButtonBlue), fit: BoxFit.fill), | |
110 | - ), | |
111 | - child: Text( | |
112 | - '确定', | |
113 | - style: TextStyle(fontSize: 17.sp, color: Colors.white), | |
114 | - ), | |
112 | + if (type == ModifyUserInformationType.gender) { | |
113 | + text = bloc.gender.toString(); | |
114 | + } | |
115 | + // 更新type类型的字段 | |
116 | + context.read<UserBloc>().add(UserUpdate(type,text)); | |
117 | + }, | |
118 | + child: Container( | |
119 | + alignment: Alignment.center, | |
120 | + width: 90.w, | |
121 | + height: 44.h, | |
122 | + decoration: const BoxDecoration( | |
123 | + image: DecorationImage(image: AssetImage(AssetsConst.bgButtonBlue), fit: BoxFit.fill), | |
124 | + ), | |
125 | + child: Text( | |
126 | + '确定', | |
127 | + style: TextStyle(fontSize: 17.sp, color: Colors.white), | |
115 | 128 | ), |
116 | - ) | |
117 | - ], | |
118 | - )), | |
119 | - Stack( | |
120 | - alignment: Alignment.topRight, | |
121 | - children: [ | |
122 | - Image.asset( | |
123 | - AssetsConst.bgEditUserInformation, | |
124 | - width: double.infinity, | |
125 | - ), | |
126 | - Positioned( | |
127 | - right: 125.w, | |
128 | - top: 10.h, | |
129 | - child: Image.asset(AssetsConst.bgIcSteveWrite, width: 161.w, height: 249.w), | |
130 | - ), | |
131 | - ], | |
132 | - ), | |
133 | - ], | |
134 | - )); | |
135 | - }), | |
129 | + ), | |
130 | + ) | |
131 | + ], | |
132 | + )), | |
133 | + Stack( | |
134 | + alignment: Alignment.topRight, | |
135 | + children: [ | |
136 | + Image.asset( | |
137 | + AssetsConst.bgEditUserInformation, | |
138 | + width: double.infinity, | |
139 | + ), | |
140 | + Positioned( | |
141 | + right: 125.w, | |
142 | + top: 10.h, | |
143 | + child: Image.asset(AssetsConst.bgIcSteveWrite, width: 161.w, height: 249.w), | |
144 | + ), | |
145 | + ], | |
146 | + ), | |
147 | + ], | |
148 | + )), | |
149 | + ); | |
150 | + }, | |
136 | 151 | ), |
137 | 152 | ), |
138 | 153 | ); |
... | ... | @@ -188,9 +203,9 @@ class ModifyUserInformationPage extends StatelessWidget { |
188 | 203 | textInputType: inputType, |
189 | 204 | inputFormatters: formatters, |
190 | 205 | controller: bloc.modifyTextController, |
191 | - /*onChangeValue: (String value) { | |
192 | - bloc.add(CodeNumberChangeEvent()); | |
193 | - },*/ | |
206 | + onChangeValue: (String value) { | |
207 | + bloc.add(ChangeTextFieldEvent(value)); | |
208 | + }, | |
194 | 209 | ); |
195 | 210 | }); |
196 | 211 | } | ... | ... |
lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart
... | ... | @@ -3,6 +3,7 @@ import 'dart:io'; |
3 | 3 | import 'package:device_info_plus/device_info_plus.dart'; |
4 | 4 | import 'package:flutter/cupertino.dart'; |
5 | 5 | import 'package:flutter_bloc/flutter_bloc.dart'; |
6 | +import 'package:flutter_easyloading/flutter_easyloading.dart'; | |
6 | 7 | import 'package:image_picker/image_picker.dart'; |
7 | 8 | import 'package:permission_handler/permission_handler.dart'; |
8 | 9 | import 'package:wow_english/common/core/assets_const.dart'; |
... | ... | @@ -38,10 +39,9 @@ class UserAvatarBloc extends Bloc<UserAvatarEvent, UserAvatarState> { |
38 | 39 | |
39 | 40 | Future<String> _uploadAvatar(String imagePath) async { |
40 | 41 | // todo 加个loading UI |
42 | + EasyLoading.showToast(''); | |
41 | 43 | String avatarUrl = await AliyunOssUtil.uploadFile(imagePath); |
42 | - debugPrint('>>>>>>>>>>阿里云图片地址$avatarUrl'); | |
43 | - // 上传服务器 | |
44 | - // await UserDao.updateUserInfoField(avatarUrl: avatarUrl); | |
44 | + EasyLoading.dismiss(); | |
45 | 45 | return avatarUrl; |
46 | 46 | } |
47 | 47 | ... | ... |
lib/pages/user/modify/user_info_bloc/user_info_bloc.dart
... | ... | @@ -12,17 +12,28 @@ class UserInfoBloc extends Bloc<UserInfoEvent, UserInfoState> { |
12 | 12 | |
13 | 13 | int get gender => _gender; |
14 | 14 | |
15 | + String _primitiveText = ''; | |
16 | + | |
17 | + bool isChangeInfo = false; | |
18 | + | |
15 | 19 | UserInfoBloc() : super(UserInfoInitial()) { |
16 | 20 | on<ChangeGenderEvent>(_changeGender); |
21 | + on<ChangeTextFieldEvent>(_changeTextField); | |
17 | 22 | on<InitControllerTextEvent>(_initControllerText); |
18 | 23 | } |
19 | 24 | |
20 | - _initControllerText(InitControllerTextEvent event,Emitter<UserInfoState> emitter) async { | |
25 | + void _initControllerText(InitControllerTextEvent event,Emitter<UserInfoState> emitter) async { | |
21 | 26 | modifyTextController.text = event.text; |
27 | + _primitiveText = event.text; | |
22 | 28 | } |
23 | 29 | |
24 | - _changeGender(ChangeGenderEvent event,Emitter<UserInfoState> emitter) async { | |
30 | + void _changeGender(ChangeGenderEvent event,Emitter<UserInfoState> emitter) async { | |
25 | 31 | _gender = event.gender; |
32 | + isChangeInfo = _gender != (UserUtil.getUser()!.gender??0); | |
26 | 33 | emitter(ChangeGenderState()); |
27 | 34 | } |
35 | + | |
36 | + void _changeTextField(ChangeTextFieldEvent event,Emitter<UserInfoState> emitter) async { | |
37 | + isChangeInfo = _primitiveText != event.text; | |
38 | + } | |
28 | 39 | } | ... | ... |
lib/pages/user/modify/user_info_bloc/user_info_event.dart
... | ... | @@ -8,6 +8,11 @@ class InitControllerTextEvent extends UserInfoEvent { |
8 | 8 | InitControllerTextEvent(this.text); |
9 | 9 | } |
10 | 10 | |
11 | +class ChangeTextFieldEvent extends UserInfoEvent { | |
12 | + final String text; | |
13 | + ChangeTextFieldEvent(this.text); | |
14 | +} | |
15 | + | |
11 | 16 | class ChangeGenderEvent extends UserInfoEvent { |
12 | 17 | final int gender; |
13 | 18 | ChangeGenderEvent(this.gender); | ... | ... |
lib/pages/user/user_page.dart
... | ... | @@ -29,9 +29,6 @@ class _UserView extends StatelessWidget { |
29 | 29 | } |
30 | 30 | |
31 | 31 | Widget _pageWidget() => BlocBuilder<UserBloc, UserState>( |
32 | - /*buildWhen: (previous, current) { | |
33 | - return current != previous; | |
34 | - },*/ | |
35 | 32 | builder: (context, state) { |
36 | 33 | UserEntity user = UserUtil.getUser()!; |
37 | 34 | final userBloc = BlocProvider.of<UserBloc>(context); |
... | ... | @@ -177,13 +174,20 @@ class _UserView extends StatelessWidget { |
177 | 174 | )), |
178 | 175 | 30.verticalSpace, |
179 | 176 | OutlinedButton( |
180 | - onPressed: () => userBloc.add(UserLogout()), | |
177 | + onPressed: () { | |
178 | + showTwoActionDialog(barrierDismissible:false,'提示', '取消', '确认', '您确认要退出Wow English吗?', () { | |
179 | + popPage(); | |
180 | + }, () { | |
181 | + popPage(); | |
182 | + userBloc.add(UserLogout()); | |
183 | + }); | |
184 | + }, | |
181 | 185 | style: ButtonStyle( |
182 | 186 | side: MaterialStateProperty.all(const BorderSide(color: Color(0xFF140C10), width: 1.5)), |
183 | 187 | shape: MaterialStateProperty.all( |
184 | 188 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))), |
185 | 189 | minimumSize: MaterialStateProperty.all(Size(295.w, 40.h)), |
186 | - backgroundColor: MaterialStateProperty.all(Color(0xFFFBB621)), | |
190 | + backgroundColor: MaterialStateProperty.all(const Color(0xFFFBB621)), | |
187 | 191 | ), |
188 | 192 | child: Text( |
189 | 193 | "退出登录", | ... | ... |
lib/utils/aliyun_oss_util.dart
pubspec.yaml
... | ... | @@ -88,7 +88,7 @@ dependencies: |
88 | 88 | # 富文本插件 https://pub.dev/packages/extended_text |
89 | 89 | extended_text: ^11.0.1 |
90 | 90 | # 视频播放 https://pub.dev/packages/video_player |
91 | - video_player: ^2.6.1 | |
91 | + video_player: ^2.7.0 | |
92 | 92 | # UI适配 https://pub.dev/packages/responsive_framework |
93 | 93 | responsive_framework: ^1.0.0 |
94 | 94 | # 音频播放 https://pub.dev/packages/audioplayers | ... | ... |