Commit 42f15f6c1954d7adc8d5c7ad9908c6b99953ca7f

Authored by 吴启风
1 parent 8616f94b

feat:模块选择持久化&模块主题色从缓存获取

lib/app/app.dart
@@ -32,6 +32,8 @@ class App extends StatelessWidget { @@ -32,6 +32,8 @@ class App extends StatelessWidget {
32 fontFamily: 'HannotateSC', 32 fontFamily: 'HannotateSC',
33 colorScheme: ColorScheme.fromSeed(seedColor: Colors.white), 33 colorScheme: ColorScheme.fromSeed(seedColor: Colors.white),
34 useMaterial3: true, 34 useMaterial3: true,
  35 + ///系统主题色
  36 + primaryColor: const Color(0xFF00B6F1)
35 ), 37 ),
36 builder: EasyLoading.init( 38 builder: EasyLoading.init(
37 builder: (context, child) => ResponsiveBreakpoints(breakpoints: const [ 39 builder: (context, child) => ResponsiveBreakpoints(breakpoints: const [
lib/app/splash_page.dart
@@ -19,6 +19,7 @@ import 'package:wow_english/utils/log_util.dart'; @@ -19,6 +19,7 @@ import 'package:wow_english/utils/log_util.dart';
19 import 'package:wow_english/utils/sp_util.dart'; 19 import 'package:wow_english/utils/sp_util.dart';
20 20
21 import '../common/core/app_consts.dart'; 21 import '../common/core/app_consts.dart';
  22 +import '../common/core/module_cache.dart';
22 import '../common/widgets/webview_dialog.dart'; 23 import '../common/widgets/webview_dialog.dart';
23 24
24 class SplashPage extends StatelessWidget { 25 class SplashPage extends StatelessWidget {
@@ -167,6 +168,7 @@ class _TransitionViewState extends State<TransitionView> { @@ -167,6 +168,7 @@ class _TransitionViewState extends State<TransitionView> {
167 void init() async { 168 void init() async {
168 changeDevice(); 169 changeDevice();
169 await SpUtil.preInit(); 170 await SpUtil.preInit();
  171 + ModuleCache.instance.init();
170 AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.welcomeToWow); 172 AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.welcomeToWow);
171 startTime(); 173 startTime();
172 } 174 }
lib/common/core/module_cache.dart 0 → 100644
  1 +import 'dart:convert';
  2 +import 'dart:ui';
  3 +
  4 +import '../../models/course_module_entity.dart';
  5 +import '../../utils/sp_util.dart';
  6 +import '../utils/color_parser.dart';
  7 +
  8 +///模块缓存类
  9 +class ModuleCache {
  10 + // Private constructor
  11 + ModuleCache._privateConstructor();
  12 +
  13 + // Singleton instance
  14 + static final ModuleCache _instance = ModuleCache._privateConstructor();
  15 +
  16 + // Public accessor for the singleton instance
  17 + static ModuleCache get instance => _instance;
  18 +
  19 + // Variable to store the current module entity
  20 + CourseModuleEntity? _currentModule;
  21 +
  22 + // Key for SharedPreferences
  23 + static const String _moduleKey = "courseModule";
  24 +
  25 + // Initialize the cache by loading data from SharedPreferences
  26 + Future<void> init() async {
  27 + String? jsonString = SpUtil.getInstance().get<String>(_moduleKey);
  28 + if (jsonString != null) {
  29 + _currentModule = CourseModuleEntity.fromJson(json.decode(jsonString));
  30 + }
  31 + }
  32 +
  33 + // Getter and setter for the current module
  34 + CourseModuleEntity? get currentModule => _currentModule;
  35 + set currentModule(CourseModuleEntity? value) {
  36 + _currentModule = value;
  37 + _saveToPrefs(value);
  38 + }
  39 +
  40 + // Method to clear the cached module data
  41 + void clear() {
  42 + _currentModule = null;
  43 + _clearPrefs();
  44 + }
  45 +
  46 + // Save module data to SharedPreferences
  47 + void _saveToPrefs(CourseModuleEntity? module) {
  48 + if (module != null) {
  49 + String jsonString = json.encode(module.toJson());
  50 + SpUtil.getInstance().setData(_moduleKey, jsonString);
  51 + } else {
  52 + SpUtil.getInstance().remove(_moduleKey);
  53 + }
  54 + }
  55 +
  56 + String getCurrentThemeColorStr({String? colorStr}) {
  57 + return colorStr ?? _currentModule.getSafeThemeColor();
  58 + }
  59 +
  60 + ///根据当前课程阶段获取系统主题色
  61 + Color getCurrentThemeColor({String? colorStr}) {
  62 + return parseColor(getCurrentThemeColorStr(colorStr: colorStr));
  63 + }
  64 +
  65 + ///根据当前课程阶段获取系统主题名称
  66 + String getCurrentThemeName({String? name}) {
  67 + return name ?? _currentModule.getSafeName();
  68 + }
  69 +
  70 + // Clear all data from SharedPreferences
  71 + void _clearPrefs() async {
  72 + SpUtil.getInstance().remove(_moduleKey);
  73 + }
  74 +}
0 \ No newline at end of file 75 \ No newline at end of file
lib/common/utils/color_parser.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +
  3 +/// 将"#80FFFF00"字符串类型的颜色值转成Color对象类型
  4 +Color parseColor(String color) {
  5 + // Remove the '#' character from the beginning of the string
  6 + String hexColor = color.replaceAll("#", "");
  7 +
  8 + // Check if the color is in the correct length (6 or 8)
  9 + if (hexColor.length == 6) {
  10 + // Add 'FF' for the alpha value if not provided
  11 + hexColor = "FF$hexColor";
  12 + } else if (hexColor.length != 8) {
  13 + ///如果数据异常,返回主题色兜底
  14 + // throw const FormatException("Invalid color format");
  15 + hexColor = "FF00B6F1";
  16 + }
  17 +
  18 + // Convert the hex string to an integer and create a Color object
  19 + return Color(int.parse(hexColor, radix: 16));
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
lib/generated/json/base/json_convert_content.dart
@@ -139,7 +139,12 @@ class JsonConvert { @@ -139,7 +139,12 @@ class JsonConvert {
139 if (value == null) { 139 if (value == null) {
140 return null; 140 return null;
141 } 141 }
142 - return convertFuncMap[type]!(value as Map<String, dynamic>) as T; 142 + var covertFunc = convertFuncMap[type]!;
  143 + if (covertFunc is Map<String, dynamic>) {
  144 + return covertFunc(value as Map<String, dynamic>) as T;
  145 + } else {
  146 + return covertFunc(Map<String, dynamic>.from(value)) as T;
  147 + }
143 } else { 148 } else {
144 throw UnimplementedError( 149 throw UnimplementedError(
145 '$type unimplemented,you can try running the app again'); 150 '$type unimplemented,you can try running the app again');
lib/models/course_module_entity.dart
@@ -21,14 +21,49 @@ class CourseModuleEntity { @@ -21,14 +21,49 @@ class CourseModuleEntity {
21 int? status; 21 int? status;
22 String? courseModuleThemeColor; 22 String? courseModuleThemeColor;
23 23
24 - CourseModuleEntity(); 24 + // 无参构造函数
  25 + CourseModuleEntity.empty();
25 26
26 - factory CourseModuleEntity.fromJson(Map<String, dynamic> json) => $CourseModuleEntityFromJson(json); 27 + // 命名构造函数
  28 + CourseModuleEntity(
  29 + {int? id,
  30 + String? code,
  31 + String? courseModuleName,
  32 + String? courseModuleThemeColor});
  33 +
  34 + factory CourseModuleEntity.fromJson(Map<String, dynamic> json) =>
  35 + $CourseModuleEntityFromJson(json);
27 36
28 Map<String, dynamic> toJson() => $CourseModuleEntityToJson(this); 37 Map<String, dynamic> toJson() => $CourseModuleEntityToJson(this);
29 38
  39 + // Factory constructor for creating an instance with only three parameters
  40 + factory CourseModuleEntity.of(int? courseModuleId, String? courseModuleCode,
  41 + String? courseModuleName, String? courseModuleThemeColor) {
  42 + return CourseModuleEntity(
  43 + id: courseModuleId,
  44 + code: courseModuleCode,
  45 + courseModuleName: courseModuleName,
  46 + courseModuleThemeColor: courseModuleThemeColor,
  47 + // Set default values or leave other fields null
  48 + );
  49 + }
  50 +
30 @override 51 @override
31 String toString() { 52 String toString() {
32 return jsonEncode(this); 53 return jsonEncode(this);
33 } 54 }
34 } 55 }
  56 +
  57 +///对可空的CourseModuleEntity对象扩展
  58 +extension PersonSafeExt on CourseModuleEntity? {
  59 +
  60 + ///获取非空的主题色,系统主题色0xFF00B6F1兜底
  61 + String getSafeThemeColor() {
  62 + return this?.courseModuleThemeColor ?? '0xFF00B6F1';
  63 + }
  64 +
  65 + ///获取非空的阶段名称
  66 + String getSafeName() {
  67 + return this?.name ?? 'learn wow!';
  68 + }
  69 +}
lib/pages/module/course_module_page.dart
@@ -5,9 +5,10 @@ import &#39;package:wow_english/common/widgets/we_app_bar.dart&#39;; @@ -5,9 +5,10 @@ import &#39;package:wow_english/common/widgets/we_app_bar.dart&#39;;
5 import 'package:wow_english/models/course_module_entity.dart'; 5 import 'package:wow_english/models/course_module_entity.dart';
6 import 'package:wow_english/route/route.dart'; 6 import 'package:wow_english/route/route.dart';
7 7
  8 +import '../../common/core/module_cache.dart';
8 import '../../common/utils/click_with_music_controller.dart'; 9 import '../../common/utils/click_with_music_controller.dart';
  10 +import '../../common/utils/color_parser.dart';
9 import '../../utils/audio_player_util.dart'; 11 import '../../utils/audio_player_util.dart';
10 -import '../section/courese_module_model.dart';  
11 import 'bloc/module_bloc.dart'; 12 import 'bloc/module_bloc.dart';
12 import 'widgets/module_item_widget.dart'; 13 import 'widgets/module_item_widget.dart';
13 14
@@ -94,12 +95,11 @@ class _LessonPageView extends StatelessWidget { @@ -94,12 +95,11 @@ class _LessonPageView extends StatelessWidget {
94 // ? Colors.red 95 // ? Colors.red
95 // : Colors.white, 96 // : Colors.white,
96 color: 97 color:
97 - CourseModuleModel(model?.code ?? 'Phase-1')  
98 - .color 98 + parseColor(model.getSafeThemeColor())
99 .withOpacity( 99 .withOpacity(
100 bloc.currentPageIndex == index 100 bloc.currentPageIndex == index
101 ? 1 101 ? 1
102 - : 0.35), 102 + : 0.15),
103 borderRadius: BorderRadius.circular(5.r), 103 borderRadius: BorderRadius.circular(5.r),
104 border: Border.all( 104 border: Border.all(
105 width: 0.5, 105 width: 0.5,
@@ -167,6 +167,7 @@ class _LessonPageView extends StatelessWidget { @@ -167,6 +167,7 @@ class _LessonPageView extends StatelessWidget {
167 model: model, 167 model: model,
168 isSelected: bloc.currentPageIndex == index, 168 isSelected: bloc.currentPageIndex == index,
169 onClickEvent: () { 169 onClickEvent: () {
  170 + ModuleCache.instance.currentModule = model;
170 ///todo 不同阶段音乐文件待提供 171 ///todo 不同阶段音乐文件待提供
171 ClickWithMusicController.instance.playMusicAndPerformAction( 172 ClickWithMusicController.instance.playMusicAndPerformAction(
172 context, 173 context,
lib/pages/module/widgets/module_item_widget.dart
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:flutter_screenutil/flutter_screenutil.dart'; 2 import 'package:flutter_screenutil/flutter_screenutil.dart';
3 import 'package:wow_english/common/extension/string_extension.dart'; 3 import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/common/utils/color_parser.dart';
4 import 'package:wow_english/common/widgets/ow_image_widget.dart'; 5 import 'package:wow_english/common/widgets/ow_image_widget.dart';
5 import 'package:wow_english/models/course_module_entity.dart'; 6 import 'package:wow_english/models/course_module_entity.dart';
6 7
7 -import '../../section/courese_module_model.dart';  
8 -  
9 ///阶段(模块)item布局 8 ///阶段(模块)item布局
10 class ModuleItemWidget extends StatelessWidget { 9 class ModuleItemWidget extends StatelessWidget {
11 - const ModuleItemWidget({super.key, required this.isSelected, this.model, this.onClickEvent}); 10 + const ModuleItemWidget(
  11 + {super.key, required this.isSelected, this.model, this.onClickEvent});
  12 +
12 ///是否被选中 13 ///是否被选中
13 final bool isSelected; 14 final bool isSelected;
14 final CourseModuleEntity? model; 15 final CourseModuleEntity? model;
@@ -23,7 +24,7 @@ class ModuleItemWidget extends StatelessWidget { @@ -23,7 +24,7 @@ class ModuleItemWidget extends StatelessWidget {
23 } 24 }
24 onClickEvent?.call(); 25 onClickEvent?.call();
25 }, 26 },
26 - child: isSelected?_selectWidget():_unSelectWidget(), 27 + child: isSelected ? _selectWidget() : _unSelectWidget(),
27 ); 28 );
28 } 29 }
29 30
@@ -31,12 +32,9 @@ class ModuleItemWidget extends StatelessWidget { @@ -31,12 +32,9 @@ class ModuleItemWidget extends StatelessWidget {
31 return Container( 32 return Container(
32 padding: const EdgeInsets.all(20), 33 padding: const EdgeInsets.all(20),
33 decoration: BoxDecoration( 34 decoration: BoxDecoration(
34 - image: DecorationImage(  
35 - image: AssetImage('gendubeij'.assetPng)  
36 - )  
37 - ), 35 + image: DecorationImage(image: AssetImage('gendubeij'.assetPng))),
38 child: OwImageWidget( 36 child: OwImageWidget(
39 - name: model?.picUrl??'', 37 + name: model?.picUrl ?? '',
40 ), 38 ),
41 ); 39 );
42 } 40 }
@@ -45,48 +43,37 @@ class ModuleItemWidget extends StatelessWidget { @@ -45,48 +43,37 @@ class ModuleItemWidget extends StatelessWidget {
45 return Container( 43 return Container(
46 padding: const EdgeInsets.all(10), 44 padding: const EdgeInsets.all(10),
47 decoration: BoxDecoration( 45 decoration: BoxDecoration(
48 - image: DecorationImage(  
49 - image: AssetImage(  
50 - 'gendubeij'.assetPng,  
51 - ),  
52 - fit: BoxFit.fill  
53 - ), 46 + image: DecorationImage(
  47 + image: AssetImage(
  48 + 'gendubeij'.assetPng,
  49 + ),
  50 + fit: BoxFit.fill),
54 ), 51 ),
55 - child: Column( 52 + child: Column(
56 mainAxisAlignment: MainAxisAlignment.spaceBetween, 53 mainAxisAlignment: MainAxisAlignment.spaceBetween,
57 children: [ 54 children: [
58 Expanded( 55 Expanded(
59 child: OwImageWidget( 56 child: OwImageWidget(
60 - name: model?.picUrl??'', 57 + name: model?.picUrl ?? '',
61 ), 58 ),
62 ), 59 ),
63 10.verticalSpace, 60 10.verticalSpace,
64 Container( 61 Container(
65 decoration: BoxDecoration( 62 decoration: BoxDecoration(
66 - color: CourseModuleModel(model?.code??'Phase-1').color,  
67 - borderRadius: BorderRadius.circular(6.r),  
68 - border: Border.all(  
69 - color: const Color(0xFF333333),  
70 - width: 1.0  
71 - )  
72 - ), 63 + color: parseColor(model.getSafeThemeColor()),
  64 + borderRadius: BorderRadius.circular(6.r),
  65 + border: Border.all(color: const Color(0xFF333333), width: 1.0)),
73 padding: EdgeInsets.symmetric(horizontal: 10.w), 66 padding: EdgeInsets.symmetric(horizontal: 10.w),
74 child: Column( 67 child: Column(
75 children: [ 68 children: [
76 Text( 69 Text(
77 - model?.name??'',  
78 - style: TextStyle(  
79 - color: Colors.white,  
80 - fontSize: 12.sp  
81 - ), 70 + model?.getSafeName() ?? '',
  71 + style: TextStyle(color: Colors.white, fontSize: 12.sp),
82 ), 72 ),
83 Text( 73 Text(
84 - model?.des??'', 74 + model?.des ?? '',
85 maxLines: 1, 75 maxLines: 1,
86 - style: TextStyle(  
87 - color: Colors.white,  
88 - fontSize: 12.sp  
89 - ), 76 + style: TextStyle(color: Colors.white, fontSize: 12.sp),
90 ) 77 )
91 ], 78 ],
92 ), 79 ),
@@ -95,4 +82,4 @@ class ModuleItemWidget extends StatelessWidget { @@ -95,4 +82,4 @@ class ModuleItemWidget extends StatelessWidget {
95 ), 82 ),
96 ); 83 );
97 } 84 }
98 -}  
99 \ No newline at end of file 85 \ No newline at end of file
  86 +}
lib/pages/section/bloc/section_bloc.dart
@@ -38,6 +38,7 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; { @@ -38,6 +38,7 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; {
38 38
39 ScrollController get indicatorSrollController => _indicatorSrollController; 39 ScrollController get indicatorSrollController => _indicatorSrollController;
40 40
  41 + ///之前传进来是用于根据courseModuleCode获取主题色的,现在不用了。参数还是先留着,预防后面需要
41 CourseUnitEntity _courseUnitEntity; 42 CourseUnitEntity _courseUnitEntity;
42 43
43 CourseUnitEntity get courseUnitEntity => _courseUnitEntity; 44 CourseUnitEntity get courseUnitEntity => _courseUnitEntity;
lib/pages/section/section_page.dart
@@ -3,6 +3,7 @@ import &#39;package:flutter/material.dart&#39;; @@ -3,6 +3,7 @@ import &#39;package:flutter/material.dart&#39;;
3 import 'package:flutter_bloc/flutter_bloc.dart'; 3 import 'package:flutter_bloc/flutter_bloc.dart';
4 import 'package:flutter_screenutil/flutter_screenutil.dart'; 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
5 import 'package:nested_scroll_views/material.dart'; 5 import 'package:nested_scroll_views/material.dart';
  6 +import 'package:wow_english/common/core/module_cache.dart';
6 import 'package:wow_english/common/core/user_util.dart'; 7 import 'package:wow_english/common/core/user_util.dart';
7 import 'package:wow_english/common/utils/click_with_music_controller.dart'; 8 import 'package:wow_english/common/utils/click_with_music_controller.dart';
8 import 'package:wow_english/models/course_unit_entity.dart'; 9 import 'package:wow_english/models/course_unit_entity.dart';
@@ -138,9 +139,7 @@ class _SectionPageView extends StatelessWidget { @@ -138,9 +139,7 @@ class _SectionPageView extends StatelessWidget {
138 await bloc.requestEnterClass(courseLessonId, () { 139 await bloc.requestEnterClass(courseLessonId, () {
139 pushNamed(AppRouteName.topicPic, arguments: { 140 pushNamed(AppRouteName.topicPic, arguments: {
140 'courseLessonId': courseLessonId, 141 'courseLessonId': courseLessonId,
141 - 'moduleColor': CourseModuleModel(  
142 - bloc.courseUnitEntity.courseModuleCode ?? 'Phase-1')  
143 - .color 142 + 'moduleColor': ModuleCache.instance.getCurrentThemeColor()
144 }).then((value) { 143 }).then((value) {
145 if (value != null) { 144 if (value != null) {
146 Map<String, dynamic> dataMap = 145 Map<String, dynamic> dataMap =
@@ -175,7 +174,6 @@ class _SectionPageView extends StatelessWidget { @@ -175,7 +174,6 @@ class _SectionPageView extends StatelessWidget {
175 children: [ 174 children: [
176 SectionHeaderWidget( 175 SectionHeaderWidget(
177 title: bloc.getCourseUnitDetail().name, 176 title: bloc.getCourseUnitDetail().name,
178 - courseModuleCode: bloc.courseUnitEntity.courseModuleCode,  
179 onBack: () { 177 onBack: () {
180 popPage(data: { 178 popPage(data: {
181 'needRefresh': bloc.courseUnitEntityChanged, 179 'needRefresh': bloc.courseUnitEntityChanged,
@@ -281,9 +279,7 @@ Widget _itemTransCard( @@ -281,9 +279,7 @@ Widget _itemTransCard(
281 const SizedBox(height: 16.0), 279 const SizedBox(height: 16.0),
282 // 间距 280 // 间距
283 CircularProgressIndicator( 281 CircularProgressIndicator(
284 - color: CourseModuleModel(  
285 - bloc.courseUnitEntity.courseModuleCode ?? 'Phase-1')  
286 - .color), 282 + color: ModuleCache.instance.getCurrentThemeColor()),
287 // 加载动画 283 // 加载动画
288 ], 284 ],
289 ), 285 ),
@@ -332,7 +328,6 @@ Widget _itemTransCard( @@ -332,7 +328,6 @@ Widget _itemTransCard(
332 sectionData.id.toString(), sectionData.courseType)); 328 sectionData.id.toString(), sectionData.courseType));
333 }, 329 },
334 child: SectionItem( 330 child: SectionItem(
335 - courseModuleId: bloc.courseUnitEntity.courseModuleCode,  
336 lessons: sectionData, 331 lessons: sectionData,
337 ), 332 ),
338 ); 333 );
lib/pages/section/widgets/section_header_widget.dart
@@ -4,17 +4,15 @@ import &#39;package:flutter_screenutil/flutter_screenutil.dart&#39;; @@ -4,17 +4,15 @@ import &#39;package:flutter_screenutil/flutter_screenutil.dart&#39;;
4 import 'package:wow_english/common/extension/string_extension.dart'; 4 import 'package:wow_english/common/extension/string_extension.dart';
5 import 'package:wow_english/pages/user/bloc/user_bloc.dart'; 5 import 'package:wow_english/pages/user/bloc/user_bloc.dart';
6 6
7 -import '../courese_module_model.dart'; 7 +import '../../../common/core/module_cache.dart';
8 8
9 /// 环节(课程)列表页标题栏 9 /// 环节(课程)列表页标题栏
10 class SectionHeaderWidget extends StatelessWidget { 10 class SectionHeaderWidget extends StatelessWidget {
11 const SectionHeaderWidget( 11 const SectionHeaderWidget(
12 - {super.key, this.title, this.courseModuleCode, this.onBack}); 12 + {super.key, this.title, this.onBack});
13 13
14 final String? title; 14 final String? title;
15 15
16 - final String? courseModuleCode;  
17 -  
18 final VoidCallback? onBack; 16 final VoidCallback? onBack;
19 17
20 @override 18 @override
@@ -24,7 +22,7 @@ class SectionHeaderWidget extends StatelessWidget { @@ -24,7 +22,7 @@ class SectionHeaderWidget extends StatelessWidget {
24 return Container( 22 return Container(
25 height: 45, 23 height: 45,
26 width: double.infinity, 24 width: double.infinity,
27 - color: CourseModuleModel(courseModuleCode ?? 'Phase-1').color, 25 + color: ModuleCache.instance.getCurrentThemeColor(),
28 padding: EdgeInsets.symmetric(horizontal: 9.5.w), 26 padding: EdgeInsets.symmetric(horizontal: 9.5.w),
29 child: Row( 27 child: Row(
30 children: [ 28 children: [
@@ -49,9 +47,7 @@ class SectionHeaderWidget extends StatelessWidget { @@ -49,9 +47,7 @@ class SectionHeaderWidget extends StatelessWidget {
49 20.horizontalSpace, 47 20.horizontalSpace,
50 Expanded( 48 Expanded(
51 child: Text( 49 child: Text(
52 - title ??  
53 - CourseModuleModel(courseModuleCode ?? 'Phase-1')  
54 - .courseModuleTitle, 50 + title ?? ModuleCache.instance.getCurrentThemeName(),
55 textAlign: TextAlign.left, 51 textAlign: TextAlign.left,
56 style: const TextStyle(color: Colors.white, fontSize: 30.0), 52 style: const TextStyle(color: Colors.white, fontSize: 30.0),
57 )), 53 )),
lib/pages/section/widgets/section_item.dart
@@ -3,15 +3,13 @@ import &#39;package:flutter_screenutil/flutter_screenutil.dart&#39;; @@ -3,15 +3,13 @@ import &#39;package:flutter_screenutil/flutter_screenutil.dart&#39;;
3 import 'package:wow_english/common/extension/string_extension.dart'; 3 import 'package:wow_english/common/extension/string_extension.dart';
4 import 'package:wow_english/common/widgets/ow_image_widget.dart'; 4 import 'package:wow_english/common/widgets/ow_image_widget.dart';
5 5
  6 +import '../../../common/core/module_cache.dart';
6 import '../../../models/course_section_entity.dart'; 7 import '../../../models/course_section_entity.dart';
7 -import '../../../models/course_unit_entity.dart';  
8 -import '../courese_module_model.dart';  
9 8
10 ///环节item布局 9 ///环节item布局
11 class SectionItem extends StatelessWidget { 10 class SectionItem extends StatelessWidget {
12 - const SectionItem({super.key, this.lessons, this.courseModuleId}); 11 + const SectionItem({super.key, this.lessons});
13 12
14 - final String? courseModuleId;  
15 final CourseSectionEntity? lessons; 13 final CourseSectionEntity? lessons;
16 14
17 @override 15 @override
@@ -62,7 +60,7 @@ class SectionItem extends StatelessWidget { @@ -62,7 +60,7 @@ class SectionItem extends StatelessWidget {
62 width: 2, 60 width: 2,
63 color: const Color(0xFF140C10), 61 color: const Color(0xFF140C10),
64 ), 62 ),
65 - color: CourseModuleModel(courseModuleId ?? 'Phase-1').color, 63 + color: ModuleCache.instance.getCurrentThemeColor(),
66 borderRadius: BorderRadius.circular(6) 64 borderRadius: BorderRadius.circular(6)
67 ), 65 ),
68 padding: EdgeInsets.symmetric(horizontal: 10.w), 66 padding: EdgeInsets.symmetric(horizontal: 10.w),
lib/pages/unit/bloc.dart
@@ -2,6 +2,7 @@ import &#39;package:bloc/bloc.dart&#39;; @@ -2,6 +2,7 @@ import &#39;package:bloc/bloc.dart&#39;;
2 import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; 2 import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart';
3 import 'package:wow_english/utils/audio_player_util.dart'; 3 import 'package:wow_english/utils/audio_player_util.dart';
4 4
  5 +import '../../common/core/module_cache.dart';
5 import '../../common/request/dao/lesson_dao.dart'; 6 import '../../common/request/dao/lesson_dao.dart';
6 import '../../common/request/exception.dart'; 7 import '../../common/request/exception.dart';
7 import '../../models/course_module_entity.dart'; 8 import '../../models/course_module_entity.dart';
@@ -24,6 +25,8 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; { @@ -24,6 +25,8 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; {
24 bool exchangeResult = false; 25 bool exchangeResult = false;
25 26
26 UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { 27 UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) {
  28 + ///缓存当前模块信息
  29 + setIfNotNull(courseEntity);
27 on<RequestUnitDataEvent>(_requestUnitDatas); 30 on<RequestUnitDataEvent>(_requestUnitDatas);
28 on<UnitInitEvent>((event, emit) { 31 on<UnitInitEvent>((event, emit) {
29 AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.inMyTummy); 32 AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.inMyTummy);
@@ -35,6 +38,7 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; { @@ -35,6 +38,7 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; {
35 try { 38 try {
36 await loading(() async { 39 await loading(() async {
37 _unitData = await LessonDao.courseUnit(event.moduleId); 40 _unitData = await LessonDao.courseUnit(event.moduleId);
  41 + setIfNull(_unitData);
38 emitter(UnitDataLoadState()); 42 emitter(UnitDataLoadState());
39 }); 43 });
40 } catch (e) { 44 } catch (e) {
@@ -44,6 +48,27 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; { @@ -44,6 +48,27 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; {
44 } 48 }
45 } 49 }
46 50
  51 + ///如果从模块页选择回来,则刷新缓存,否则认为是从
  52 + void setIfNotNull(CourseModuleEntity? courseModuleEntity) {
  53 + if (courseModuleEntity != null) {
  54 + _moduleEntity = courseModuleEntity;
  55 + } else {
  56 + _moduleEntity = ModuleCache.instance.currentModule;
  57 + }
  58 + }
  59 +
  60 + ///理论上只有没有缓存的情况下首次进入单元列表,数据请求成功后构建第一次缓存
  61 + void setIfNull(CourseUnitEntity? courseUnitData) {
  62 + if (_moduleEntity == null && courseUnitData != null) {
  63 + _moduleEntity = CourseModuleEntity.of(
  64 + courseUnitData.nowCourseModuleId,
  65 + courseUnitData.courseModuleCode,
  66 + courseUnitData.nowCourseModuleName,
  67 + courseUnitData.courseModuleThemeColor);
  68 + ModuleCache.instance.currentModule = _moduleEntity;
  69 + }
  70 + }
  71 +
47 String? getCourseModuleCode() { 72 String? getCourseModuleCode() {
48 return _moduleEntity?.code ?? _unitData?.courseModuleCode; 73 return _moduleEntity?.code ?? _unitData?.courseModuleCode;
49 } 74 }
lib/pages/unit/widget/home_tab_header_widget.dart
@@ -5,7 +5,7 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;; @@ -5,7 +5,7 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;;
5 import 'package:wow_english/pages/user/bloc/user_bloc.dart'; 5 import 'package:wow_english/pages/user/bloc/user_bloc.dart';
6 6
7 import '../../../common/core/app_config_helper.dart'; 7 import '../../../common/core/app_config_helper.dart';
8 -import '../../section/courese_module_model.dart'; 8 +import '../../../common/core/module_cache.dart';
9 9
10 enum HeaderActionType { 10 enum HeaderActionType {
11 //视频跟读 11 //视频跟读
@@ -35,7 +35,7 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -35,7 +35,7 @@ class HomeTabHeaderWidget extends StatelessWidget {
35 return Container( 35 return Container(
36 height: 45, 36 height: 45,
37 width: double.infinity, 37 width: double.infinity,
38 - color: CourseModuleModel(courseModuleCode ?? 'Phase-1').color, 38 + color: ModuleCache.instance.getCurrentThemeColor(),
39 padding: EdgeInsets.symmetric(horizontal: 9.5.w), 39 padding: EdgeInsets.symmetric(horizontal: 9.5.w),
40 child: Row( 40 child: Row(
41 children: [ 41 children: [
@@ -60,8 +60,7 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -60,8 +60,7 @@ class HomeTabHeaderWidget extends StatelessWidget {
60 20.horizontalSpace, 60 20.horizontalSpace,
61 Expanded( 61 Expanded(
62 child: Text( 62 child: Text(
63 - CourseModuleModel(courseModuleCode ?? 'Phase-1')  
64 - .courseModuleTitle, 63 + ModuleCache.instance.getCurrentThemeName(),
65 textAlign: TextAlign.left, 64 textAlign: TextAlign.left,
66 style: const TextStyle(color: Colors.white, fontSize: 30.0), 65 style: const TextStyle(color: Colors.white, fontSize: 30.0),
67 )), 66 )),
lib/route/route.dart
@@ -119,7 +119,7 @@ class AppRouter { @@ -119,7 +119,7 @@ class AppRouter {
119 case AppRouteName.courseModule: 119 case AppRouteName.courseModule:
120 return CupertinoPageRoute(builder: (_) => const CourseModulePage()); 120 return CupertinoPageRoute(builder: (_) => const CourseModulePage());
121 case AppRouteName.courseUnit: 121 case AppRouteName.courseUnit:
122 - CourseModuleEntity courseModuleEntity = CourseModuleEntity(); 122 + CourseModuleEntity? courseModuleEntity;
123 if (settings.arguments != null) { 123 if (settings.arguments != null) {
124 courseModuleEntity = (settings.arguments as Map) 124 courseModuleEntity = (settings.arguments as Map)
125 .getOrNull('courseModuleEntity') as CourseModuleEntity; 125 .getOrNull('courseModuleEntity') as CourseModuleEntity;