Commit 68dd7ba80824d8c1cce795bf98c7caacff89955a

Authored by liangchengyou
1 parent 56e2ae5a

feat:首页主题颜色+已知问题修改

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&lt;String, dynamic&gt; 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&lt;String, dynamic&gt; $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
... ... @@ -10,6 +10,7 @@ class CourseEntity {
10 10 String? nowCourseModuleName;
11 11 int? totalCourseLesson;
12 12 String? courseModuleThemeColor;
  13 + String? courseModuleCode;
13 14  
14 15 CourseEntity();
15 16  
... ...
lib/pages/home/bloc/home_bloc.dart
... ... @@ -6,7 +6,6 @@ import &#39;package:wow_english/common/request/exception.dart&#39;;
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 &#39;package:wow_english/pages/home/widgets/home_bouns_item.dart&#39;;
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 &#39;package:flutter_screenutil/flutter_screenutil.dart&#39;;
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 &#39;package:flutter_screenutil/flutter_screenutil.dart&#39;;
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 &#39;package:wow_english/common/widgets/ow_image_widget.dart&#39;;
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&lt;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 &#39;package:flutter_bloc/flutter_bloc.dart&#39;;
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
... ... @@ -72,7 +72,7 @@ class _UserInformationContentView extends StatelessWidget {
72 72 _buildContentRow(
73 73 '年龄',
74 74 Text(
75   - user.age.toString(),
  75 + (user.age??0).toString(),
76 76 style: TextStyle(
77 77 fontWeight: FontWeight.w500,
78 78 color: const Color(0xFF333333),
... ...
lib/pages/user/modify/modify_user_information_page.dart
... ... @@ -5,6 +5,7 @@ import &#39;package:flutter_bloc/flutter_bloc.dart&#39;;
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 &#39;dart:io&#39;;
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&lt;UserAvatarEvent, UserAvatarState&gt; {
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&lt;UserInfoEvent, UserInfoState&gt; {
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
... ... @@ -27,7 +27,7 @@ class AliyunOssUtil {
27 27 );
28 28  
29 29 // 上传文件
30   - final Response<dynamic> resp = await Client().putObjectFile(
  30 + await Client().putObjectFile(
31 31 filePath,
32 32 fileKey: stsEntity.fileKey,
33 33 option: PutRequestOption(
... ...
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
... ...