Commit 6f61743479801b967bad9cbdad2f4daaab64484f

Authored by liangchengyou
1 parent 2a427e12

feat:磨耳朵/视频跟读列表页接口调整

lib/common/request/dao/home_dao.dart
... ... @@ -22,9 +22,6 @@ class HomeDao {
22 22 Apis.courseLesson,
23 23 queryParameters: mapData
24 24 );
25   - if (kDebugMode) {
26   - print('>>>>>>>>>${data.runtimeType}');
27   - }
28 25 return data;
29 26 }
30 27 }
... ...
lib/common/request/dao/listen_dao.dart
1 1 import 'package:wow_english/common/request/apis.dart';
2 2 import 'package:wow_english/common/request/request_client.dart';
  3 +import 'package:wow_english/models/follow_read_entity.dart';
  4 +import 'package:wow_english/models/listen_entity.dart';
3 5  
4 6 class ListenDao {
5 7 /// 磨耳朵
6   - static Future listen() async {
7   - var data = await requestClient.get(Apis.ears);
  8 + static Future<List<ListenEntity?>?> listen() async {
  9 + var data = await requestClient.get<List<ListenEntity?>>(Apis.ears);
  10 + return data;
  11 + }
  12 +
  13 + ///视频跟读
  14 + static Future<List<FollowReadEntity?>?> followRead() async {
  15 + var data = await requestClient.get<List<FollowReadEntity?>>(Apis.followRead);
8 16 return data;
9 17 }
10 18 }
11 19 \ No newline at end of file
... ...
lib/common/widgets/ow_image_widget.dart 0 → 100644
  1 +import 'package:cached_network_image/cached_network_image.dart';
  2 +import 'package:flutter/material.dart';
  3 +
  4 +class OwImageWidget extends StatelessWidget {
  5 + const OwImageWidget({super.key, this.width, this.height, required this.name, this.fit});
  6 + final double? width;
  7 + final double? height;
  8 + final BoxFit? fit;
  9 + final String name;
  10 +
  11 + @override
  12 + Widget build(BuildContext context) {
  13 + if (name.isEmpty) {
  14 + return SizedBox(
  15 + height: height,
  16 + width: width,
  17 + );
  18 + }
  19 + return name.contains('http')?
  20 + CachedNetworkImage(
  21 + imageUrl: name,
  22 + height: height,
  23 + width: width,
  24 + fit: fit,
  25 + ):Image.asset(
  26 + name,
  27 + height: height,
  28 + width: width,
  29 + fit: fit,
  30 + );
  31 + }
  32 +}
0 33 \ No newline at end of file
... ...
lib/generated/json/base/json_convert_content.dart
... ... @@ -4,6 +4,7 @@
4 4  
5 5 // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
6 6 import 'package:flutter/material.dart' show debugPrint;
  7 +import 'package:wow_english/models/follow_read_entity.dart';
7 8 import 'package:wow_english/models/course_entity.dart';
8 9 import 'package:wow_english/models/course_module_entity.dart';
9 10 import 'package:wow_english/models/listen_entity.dart';
... ... @@ -15,6 +16,7 @@ typedef EnumConvertFunction&lt;T&gt; = T Function(String value);
15 16  
16 17 class JsonConvert {
17 18 static final Map<String, JsonConvertFunction> convertFuncMap = {
  19 + (FollowReadEntity).toString(): FollowReadEntity.fromJson,
18 20 (CourseEntity).toString(): CourseEntity.fromJson,
19 21 (CourseCourseLessons).toString(): CourseCourseLessons.fromJson,
20 22 (CourseModuleEntity).toString(): CourseModuleEntity.fromJson,
... ... @@ -98,6 +100,9 @@ List&lt;T&gt;? convertListNotNull&lt;T&gt;(dynamic value, {EnumConvertFunction? enumConvert}
98 100  
99 101 //list is returned by type
100 102 static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
  103 + if(<FollowReadEntity>[] is M){
  104 + return data.map<FollowReadEntity>((Map<String, dynamic> e) => FollowReadEntity.fromJson(e)).toList() as M;
  105 + }
101 106 if(<CourseEntity>[] is M){
102 107 return data.map<CourseEntity>((Map<String, dynamic> e) => CourseEntity.fromJson(e)).toList() as M;
103 108 }
... ...
lib/generated/json/follow_read_entity.g.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_convert_content.dart';
  2 +import 'package:wow_english/models/follow_read_entity.dart';
  3 +
  4 +FollowReadEntity $FollowReadEntityFromJson(Map<String, dynamic> json) {
  5 + final FollowReadEntity followReadEntity = FollowReadEntity();
  6 + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
  7 + if (coverUrl != null) {
  8 + followReadEntity.coverUrl = coverUrl;
  9 + }
  10 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  11 + if (createTime != null) {
  12 + followReadEntity.createTime = createTime;
  13 + }
  14 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  15 + if (deleted != null) {
  16 + followReadEntity.deleted = deleted;
  17 + }
  18 + final String? id = jsonConvert.convert<String>(json['id']);
  19 + if (id != null) {
  20 + followReadEntity.id = id;
  21 + }
  22 + final bool? lock = jsonConvert.convert<bool>(json['lock']);
  23 + if (lock != null) {
  24 + followReadEntity.lock = lock;
  25 + }
  26 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  27 + if (modifyTime != null) {
  28 + followReadEntity.modifyTime = modifyTime;
  29 + }
  30 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  31 + if (sortOrder != null) {
  32 + followReadEntity.sortOrder = sortOrder;
  33 + }
  34 + final int? star = jsonConvert.convert<int>(json['star']);
  35 + if (star != null) {
  36 + followReadEntity.star = star;
  37 + }
  38 + final int? status = jsonConvert.convert<int>(json['status']);
  39 + if (status != null) {
  40 + followReadEntity.status = status;
  41 + }
  42 + final String? title = jsonConvert.convert<String>(json['title']);
  43 + if (title != null) {
  44 + followReadEntity.title = title;
  45 + }
  46 + final int? videoTotal = jsonConvert.convert<int>(json['videoTotal']);
  47 + if (videoTotal != null) {
  48 + followReadEntity.videoTotal = videoTotal;
  49 + }
  50 + return followReadEntity;
  51 +}
  52 +
  53 +Map<String, dynamic> $FollowReadEntityToJson(FollowReadEntity entity) {
  54 + final Map<String, dynamic> data = <String, dynamic>{};
  55 + data['coverUrl'] = entity.coverUrl;
  56 + data['createTime'] = entity.createTime;
  57 + data['deleted'] = entity.deleted;
  58 + data['id'] = entity.id;
  59 + data['lock'] = entity.lock;
  60 + data['modifyTime'] = entity.modifyTime;
  61 + data['sortOrder'] = entity.sortOrder;
  62 + data['star'] = entity.star;
  63 + data['status'] = entity.status;
  64 + data['title'] = entity.title;
  65 + data['videoTotal'] = entity.videoTotal;
  66 + return data;
  67 +}
0 68 \ No newline at end of file
... ...
lib/models/follow_read_entity.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_field.dart';
  2 +import 'package:wow_english/generated/json/follow_read_entity.g.dart';
  3 +import 'dart:convert';
  4 +
  5 +@JsonSerializable()
  6 +class FollowReadEntity {
  7 + String? coverUrl;
  8 + String? createTime;
  9 + String? deleted;
  10 + String? id;
  11 + bool? lock;
  12 + String? modifyTime;
  13 + int? sortOrder;
  14 + int? star;
  15 + int? status;
  16 + String? title;
  17 + int? videoTotal;
  18 +
  19 + FollowReadEntity();
  20 +
  21 + factory FollowReadEntity.fromJson(Map<String, dynamic> json) => $FollowReadEntityFromJson(json);
  22 +
  23 + Map<String, dynamic> toJson() => $FollowReadEntityToJson(this);
  24 +
  25 + @override
  26 + String toString() {
  27 + return jsonEncode(this);
  28 + }
  29 +}
0 30 \ No newline at end of file
... ...
lib/pages/home/home_page.dart
1 1 import 'package:flutter/material.dart';
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_easyloading/flutter_easyloading.dart';
3 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
4 5 import 'package:wow_english/common/extension/string_extension.dart';
5 6 import 'package:wow_english/models/course_entity.dart';
... ... @@ -75,15 +76,30 @@ class _HomePageView extends StatelessWidget {
75 76 itemCount: bloc.modelData?.totalCourseLesson,
76 77 scrollDirection: Axis.horizontal,
77 78 itemBuilder: (BuildContext context, int index){
78   - String? title = bloc.modelData?.courseLessons?[index]?.name;
79 79 CourseCourseLessons? data = bloc.modelData?.courseLessons?[index];
80 80 if (data?.courseType == 5) {//彩蛋
81   - return HomeBoundsItem(
82   - imageUrl: data?.coverUrl,
  81 + return GestureDetector(
  82 + onTap: (){
  83 + if (data!.lock!) {
  84 + return;
  85 + }
  86 + EasyLoading.showToast('点击事件');
  87 + },
  88 + child: HomeBoundsItem(
  89 + imageUrl: data?.coverUrl,
  90 + ),
83 91 );
84 92 } else {
85   - return HomeVideoItem(
86   - lessons: data,
  93 + return GestureDetector(
  94 + onTap: () {
  95 + if (data!.lock!) {
  96 + return;
  97 + }
  98 + EasyLoading.showToast('点击事件');
  99 + },
  100 + child: HomeVideoItem(
  101 + lessons: data,
  102 + ),
87 103 );
88 104 }
89 105 })
... ...
lib/pages/home/widgets/home_bouns_item.dart
1 1 import 'package:flutter/cupertino.dart';
2 2 import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
3 4  
4 5 class HomeBoundsItem extends StatelessWidget {
5 6 const HomeBoundsItem({super.key, this.imageUrl});
... ... @@ -11,7 +12,7 @@ class HomeBoundsItem extends StatelessWidget {
11 12 return SizedBox(
12 13 height: 207.h,
13 14 width: 169.w,
14   - child: Image.network(imageUrl??''),
  15 + child: OwImageWidget(name:imageUrl??''),
15 16 );
16 17 }
17 18 }
18 19 \ No newline at end of file
... ...
lib/pages/home/widgets/home_lesson_item_widget.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:flutter_screenutil/flutter_screenutil.dart';
3   -
4   -class HomeLessonItem extends StatelessWidget {
5   - const HomeLessonItem({super.key});
6   -
7   - @override
8   - Widget build(BuildContext context) {
9   - return SizedBox(
10   - width: 200,
11   - child: ListView.builder(
12   - itemCount: 5,
13   - scrollDirection: Axis.horizontal,
14   - physics: const NeverScrollableScrollPhysics(),
15   - itemBuilder: (BuildContext context,int index){
16   - return Padding(
17   - padding: EdgeInsets.symmetric(horizontal: 4.w),
18   - child: Image.network(
19   - 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032',
20   - width: 40,
21   - fit: BoxFit.fitHeight,
22   - ),
23   - );
24   - }),
25   - );
26   - }
27   -}
28 0 \ No newline at end of file
lib/pages/home/widgets/home_tab_header_widget.dart
... ... @@ -117,14 +117,14 @@ class HomeTabHeaderWidget extends StatelessWidget {
117 117 },
118 118 icon: Image.asset('listen'.assetPng)
119 119 ),
120   - IconButton(
121   - onPressed: (){
122   - if(actionTap != null) {
123   - actionTap!(HeaderActionType.shop);
124   - }
125   - },
126   - icon: Image.asset('shop'.assetPng)
127   - ),
  120 + // IconButton(
  121 + // onPressed: (){
  122 + // if(actionTap != null) {
  123 + // actionTap!(HeaderActionType.shop);
  124 + // }
  125 + // },
  126 + // icon: Image.asset('shop'.assetPng)
  127 + // ),
128 128 ScreenUtil().bottomBarHeight.horizontalSpace,
129 129 ],
130 130 ),
... ...
lib/pages/home/widgets/home_vidoe_item.dart
1 1 import 'package:flutter/material.dart';
2 2 import 'package:flutter_screenutil/flutter_screenutil.dart';
3 3 import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
4 5 import 'package:wow_english/models/course_entity.dart';
5 6  
6 7 class HomeVideoItem extends StatelessWidget {
... ... @@ -16,9 +17,9 @@ class HomeVideoItem extends StatelessWidget {
16 17 width: 165.w,
17 18 padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 24.h),
18 19 decoration: BoxDecoration(
19   - image: DecorationImage(
20   - image: AssetImage('gendubeij'.assetPng),
21   - ),
  20 + image: DecorationImage(
  21 + image: AssetImage('gendubeij'.assetPng),
  22 + ),
22 23 ),
23 24 child: Column(
24 25 mainAxisAlignment: MainAxisAlignment.spaceAround,
... ... @@ -26,17 +27,17 @@ class HomeVideoItem extends StatelessWidget {
26 27 Expanded(
27 28 child: Container(
28 29 decoration: BoxDecoration(
29   - border: Border.all(
30   - width: 2,
31   - color: const Color(0xFF140C10),
  30 + border: Border.all(
  31 + width: 2,
  32 + color: const Color(0xFF140C10),
  33 + ),
  34 + borderRadius: BorderRadius.circular(6)
32 35 ),
33   - borderRadius: BorderRadius.circular(6)
34   - ),
35   - child: Image.network(
36   - lessons?.coverUrl??'',
  36 + child: OwImageWidget(
  37 + name: lessons?.coverUrl??'',
37 38 fit: BoxFit.fill,
38 39 ),
39   - )),
  40 + )),
40 41 24.verticalSpace,
41 42 Container(
42 43 decoration: BoxDecoration(
... ...
lib/pages/lessons/lesson_page.dart
... ... @@ -52,15 +52,15 @@ class _LessonPageView extends StatelessWidget {
52 52 width: 43,
53 53 )
54 54 ),
55   - actions: <Widget>[
56   - IconButton(
57   - icon: Image.asset('shop'.assetPng),
58   - color: Colors.white,
59   - onPressed: () {
60   - EasyLoading.showToast('购买');
61   - },
62   - )
63   - ],
  55 + // actions: <Widget>[
  56 + // IconButton(
  57 + // icon: Image.asset('shop'.assetPng),
  58 + // color: Colors.white,
  59 + // onPressed: () {
  60 + // EasyLoading.showToast('购买');
  61 + // },
  62 + // )
  63 + // ],
64 64 ),
65 65 body: _lessViewWidget(),
66 66 ),
... ... @@ -88,7 +88,7 @@ class _LessonPageView extends StatelessWidget {
88 88 32.verticalSpace,
89 89 SizedBox(
90 90 height: 32.h,
91   - width: double.infinity,
  91 + width: 66.w * bloc.listData.length,
92 92 child: ListView.builder(
93 93 itemCount: bloc.listData.length,
94 94 scrollDirection: Axis.horizontal,
... ... @@ -109,6 +109,7 @@ class _LessonPageView extends StatelessWidget {
109 109 height: bloc.currentPageIndex == index ? 32:20,
110 110 decoration: BoxDecoration(
111 111 color: bloc.currentPageIndex == index ? Colors.red:Colors.white,
  112 + borderRadius: BorderRadius.circular(5.r),
112 113 border: Border.all(
113 114 width: 0.5,
114 115 color: Colors.black,
... ...
lib/pages/lessons/widgets/lesson_item_widget.dart
1 1 import 'package:flutter/material.dart';
2 2 import 'package:flutter_screenutil/flutter_screenutil.dart';
3 3 import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
4 5 import 'package:wow_english/models/course_module_entity.dart';
5 6  
6 7 class LessonItemWidget extends StatelessWidget {
... ... @@ -30,8 +31,8 @@ class LessonItemWidget extends StatelessWidget {
30 31 image: AssetImage('gendubeij'.assetPng)
31 32 )
32 33 ),
33   - child: Image.network(
34   - model?.picUrl??'',
  34 + child: OwImageWidget(
  35 + name: model?.picUrl??'',
35 36 ),
36 37 );
37 38 }
... ... @@ -40,29 +41,48 @@ class LessonItemWidget extends StatelessWidget {
40 41 return Container(
41 42 padding: const EdgeInsets.all(10),
42 43 decoration: BoxDecoration(
43   - image: DecorationImage(
44   - image: AssetImage('gendubeij'.assetPng)
45   - )
  44 + image: DecorationImage(
  45 + image: AssetImage(
  46 + 'gendubeij'.assetPng,
  47 + ),
  48 + fit: BoxFit.fill
  49 + ),
46 50 ),
47 51 child: Column(
48 52 mainAxisAlignment: MainAxisAlignment.spaceBetween,
49 53 children: [
50 54 Expanded(
51   - child: Image.network(
52   - model?.picUrl??'',
53   - fit: BoxFit.contain
  55 + child: OwImageWidget(
  56 + name: model?.picUrl??'',
54 57 ),
55 58 ),
56 59 10.verticalSpace,
57 60 Container(
58   - color: Colors.red,
  61 + decoration: BoxDecoration(
  62 + color: Colors.red,
  63 + borderRadius: BorderRadius.circular(6.r),
  64 + border: Border.all(
  65 + color: const Color(0xFF333333),
  66 + width: 1.0
  67 + )
  68 + ),
59 69 padding: EdgeInsets.symmetric(horizontal: 10.w),
60 70 child: Column(
61 71 children: [
62   - Text(model?.name??''),
  72 + Text(
  73 + model?.name??'',
  74 + style: TextStyle(
  75 + color: Colors.white,
  76 + fontSize: 12.sp
  77 + ),
  78 + ),
63 79 Text(
64 80 model?.des??'',
65 81 maxLines: 1,
  82 + style: TextStyle(
  83 + color: Colors.white,
  84 + fontSize: 12.sp
  85 + ),
66 86 )
67 87 ],
68 88 ),
... ...
lib/pages/listen/bloc/listen_bloc.dart
... ... @@ -13,8 +13,8 @@ part &#39;listen_state.dart&#39;;
13 13  
14 14 class ListenBloc extends Bloc<ListenEvent, ListenState> {
15 15  
16   - final List<ListenEntity?> _listData = [];
17   - List<ListenEntity?> get listData => _listData;
  16 + List<ListenEntity?>? _listData;
  17 + List<ListenEntity?>? get listData => _listData;
18 18  
19 19 ListenBloc() : super(ListenInitial()) {
20 20 on<ListenEvent>((event, emit) {
... ... @@ -25,13 +25,7 @@ class ListenBloc extends Bloc&lt;ListenEvent, ListenState&gt; {
25 25 Future<void> requestData() async {
26 26 try {
27 27 await loading(() async {
28   - List<String> list = await ListenDao.listen()??[];
29   - if (list.isNotEmpty) {
30   - for (String jsonStr in list) {
31   - ListenEntity? data = ListenEntity.fromJson(jsonDecode(jsonStr));
32   - _listData.add(data);
33   - }
34   - }
  28 + _listData = await ListenDao.listen()??[];
35 29 emit(RequestListenDataState());
36 30 });
37 31 } catch (e) {
... ...
lib/pages/listen/listen_page.dart
... ... @@ -40,12 +40,12 @@ class _ListenPageView extends StatelessWidget {
40 40 builder: (context, state) {
41 41 final bloc = BlocProvider.of<ListenBloc>(context);
42 42 return ListView.builder(
43   - itemCount: bloc.listData.length,
  43 + itemCount: bloc.listData?.length,
44 44 scrollDirection: Axis.horizontal,
45 45 padding: EdgeInsets.symmetric(horizontal: 30.w,vertical: 36.h),
46 46 itemBuilder: (BuildContext context,int index){
47 47 return ListenItemWidget(
48   - isLock: (index > 5),
  48 + entity: bloc.listData?[index],
49 49 clickEvent: (){
50 50 Navigator.of(context).pushNamed(AppRouteName.lookVideo,arguments: {'videoUrl':'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4'});
51 51 });
... ...
lib/pages/listen/widgets/listen_item_widget.dart
  1 +import 'package:cached_network_image/cached_network_image.dart';
1 2 import 'package:flutter/material.dart';
2 3 import 'package:flutter_screenutil/flutter_screenutil.dart';
3 4 import 'package:wow_english/common/extension/string_extension.dart';
  5 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
  6 +import 'package:wow_english/models/listen_entity.dart';
4 7  
5 8 class ListenItemWidget extends StatelessWidget {
6   - const ListenItemWidget({super.key, this.isLock = false, required this.clickEvent});
  9 + const ListenItemWidget({super.key, required this.clickEvent, this.entity});
7 10  
8 11 final Function() clickEvent;
9 12  
10   - final bool isLock;
  13 + final ListenEntity? entity;
11 14  
12 15 @override
13 16 Widget build(BuildContext context) {
... ... @@ -17,23 +20,24 @@ class ListenItemWidget extends StatelessWidget {
17 20 children: [
18 21 GestureDetector(
19 22 onTap: () {
20   - if (!isLock) {
21   - clickEvent();
  23 + if (entity?.lock??false) {
  24 + return;
22 25 }
  26 + clickEvent?.call();
23 27 },
24 28 child: ClipRRect(
25 29 borderRadius:BorderRadius.circular(90.r),
26 30 child: Stack(
27 31 alignment:Alignment.center,
28 32 children: [
29   - Image.network(
30   - 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032',
31   - height: 180.h,
  33 + OwImageWidget(
32 34 width: 180.h,
  35 + height: 180.h,
33 36 fit: BoxFit.fill,
  37 + name:entity?.coverUrl??'',
34 38 ),
35 39 Visibility(
36   - visible: isLock,
  40 + visible: entity?.lock??false,
37 41 child: Container(
38 42 height: 180.h,
39 43 width: 180.h,
... ... @@ -41,7 +45,7 @@ class ListenItemWidget extends StatelessWidget {
41 45 ),
42 46 ),
43 47 Visibility(
44   - visible: isLock,
  48 + visible: entity?.lock??false,
45 49 child: Image.asset(
46 50 'listen_lock'.assetPng,
47 51 height: 36.h,
... ... @@ -66,7 +70,7 @@ class ListenItemWidget extends StatelessWidget {
66 70 ),
67 71 alignment: Alignment.center,
68 72 child: Text(
69   - 'listen title',
  73 + entity?.title??'',
70 74 style: TextStyle(
71 75 fontSize: 20.sp,
72 76 color: const Color(0xFF333333)
... ...
lib/pages/repeatafter/bloc/repeat_after_bloc.dart
1 1 import 'package:flutter/cupertino.dart';
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
3 3 import 'package:flutter_easyloading/flutter_easyloading.dart';
  4 +import 'package:wow_english/common/request/dao/listen_dao.dart';
  5 +import 'package:wow_english/common/request/exception.dart';
  6 +import 'package:wow_english/models/follow_read_entity.dart';
  7 +import 'package:wow_english/utils/loading.dart';
4 8  
5 9 part 'repeat_after_event.dart';
6 10 part 'repeat_after_state.dart';
7 11  
8 12 class RepeatAfterBloc extends Bloc<RepeatAfterEvent, RepeatAfterState> {
  13 +
  14 + List<FollowReadEntity?> _listData = [];
  15 + List<FollowReadEntity?> get listData => _listData;
  16 +
9 17 RepeatAfterBloc() : super(RepeatAfterInitial()) {
10 18 on<RepeatAfterEvent>((event, emit) {
11 19 // TODO: implement event handler
... ... @@ -14,10 +22,15 @@ class RepeatAfterBloc extends Bloc&lt;RepeatAfterEvent, RepeatAfterState&gt; {
14 22  
15 23  
16 24 Future<void> requestData() async {
17   - EasyLoading.show();
18   - Future.delayed(const Duration(milliseconds: 2000),(){
19   - EasyLoading.dismiss();
20   - emit(RequestDataState());
21   - });
  25 + try {
  26 + await loading(() async {
  27 + _listData = await ListenDao.followRead()??[];
  28 + emit(RequestDataState());
  29 + });
  30 + } catch (e) {
  31 + if (e is ApiException) {
  32 + EasyLoading.showToast(e.message??'请求失败,请检查网络连接');
  33 + }
  34 + }
22 35 }
23 36 }
... ...
lib/pages/repeatafter/repeat_after_page.dart
1   -import 'dart:math';
2   -
3 1 import 'package:flutter/material.dart';
4 2 import 'package:flutter_bloc/flutter_bloc.dart';
5 3 import 'package:flutter_easyloading/flutter_easyloading.dart';
6 4 import 'package:wow_english/common/widgets/we_app_bar.dart';
  5 +import 'package:wow_english/models/follow_read_entity.dart';
7 6 import 'package:wow_english/pages/repeatafter/widgets/repeat_after_item.dart';
8 7  
9 8 import 'bloc/repeat_after_bloc.dart';
... ... @@ -35,6 +34,7 @@ class _RepeatAfterPageView extends StatelessWidget {
35 34  
36 35 Widget _repeatAfterView() => BlocBuilder<RepeatAfterBloc, RepeatAfterState>(
37 36 builder: (context, state) {
  37 + final bloc = BlocProvider.of<RepeatAfterBloc>(context);
38 38 return Scaffold(
39 39 appBar: const WEAppBar(
40 40 titleText: '视频跟读',
... ... @@ -44,16 +44,15 @@ class _RepeatAfterPageView extends StatelessWidget {
44 44 child: Container(
45 45 alignment: Alignment.center,
46 46 child: ListView.builder(
47   - itemCount: 10,
  47 + itemCount: bloc.listData.length,
48 48 scrollDirection: Axis.horizontal,
49 49 itemBuilder: (BuildContext context,int index){
50   - bool unLock = index%3==0;
  50 + FollowReadEntity? entity = bloc.listData[index];
51 51 return RepeatAfterItem(
52   - unLock: unLock,
53 52 tapEvent: () {
54 53  
55 54 },
56   - starNumber: !unLock?0:Random().nextInt(5)
  55 + entity: entity,
57 56 );
58 57 }),
59 58 ),
... ...
lib/pages/repeatafter/widgets/repeat_after_item.dart
1 1 import 'package:flutter/material.dart';
2 2 import 'package:flutter_screenutil/flutter_screenutil.dart';
3 3 import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
  5 +import 'package:wow_english/models/follow_read_entity.dart';
4 6  
5 7 class RepeatAfterItem extends StatelessWidget {
6   - const RepeatAfterItem({super.key, required this.starNumber, required this.unLock, required this.tapEvent});
7   - //分数
8   - final int starNumber;
9   - //是否解锁
10   - final bool unLock;
  8 + const RepeatAfterItem({super.key, required this.tapEvent, this.entity});
  9 +
  10 + final FollowReadEntity? entity;
11 11  
12 12 final Function() tapEvent;
13 13  
... ... @@ -19,8 +19,10 @@ class RepeatAfterItem extends StatelessWidget {
19 19 ),
20 20 child: GestureDetector(
21 21 onTap: (){
22   - if(unLock) {
23   - tapEvent();
  22 + if (entity != null) {
  23 + if (entity?.lock??false) {
  24 + tapEvent();
  25 + }
24 26 }
25 27 },
26 28 child: Stack(
... ... @@ -50,8 +52,8 @@ class RepeatAfterItem extends StatelessWidget {
50 52 child: Column(
51 53 mainAxisAlignment: MainAxisAlignment.spaceBetween,
52 54 children: [
53   - Image.network(
54   - 'https://img.liblibai.com/web/648331d033b41.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp',
  55 + OwImageWidget(
  56 + name:entity?.coverUrl??'',
55 57 height: 100.h,
56 58 width: 140.w,
57 59 fit: BoxFit.fitWidth,
... ... @@ -60,27 +62,27 @@ class RepeatAfterItem extends StatelessWidget {
60 62 mainAxisAlignment: MainAxisAlignment.spaceBetween,
61 63 children: [
62 64 Image.asset(
63   - starNumber >= 1 ? 'star_light'.assetPng:'star_dark'.assetPng,
  65 + (entity?.star??0) >= 1 ? 'star_light'.assetPng:'star_dark'.assetPng,
64 66 width: 23.w,
65 67 height: 21.h,
66 68 ),
67 69 Image.asset(
68   - starNumber >= 2 ? 'star_light'.assetPng:'star_dark'.assetPng,
  70 + (entity?.star??0) >= 2 ? 'star_light'.assetPng:'star_dark'.assetPng,
69 71 width: 23.w,
70 72 height: 21.h,
71 73 ),
72 74 Image.asset(
73   - starNumber >= 3 ? 'star_light'.assetPng:'star_dark'.assetPng,
  75 + (entity?.star??0) >= 3 ? 'star_light'.assetPng:'star_dark'.assetPng,
74 76 width: 23.w,
75 77 height: 21.h,
76 78 ),
77 79 Image.asset(
78   - starNumber >= 4 ? 'star_light'.assetPng:'star_dark'.assetPng,
  80 + (entity?.star??0) >= 4 ? 'star_light'.assetPng:'star_dark'.assetPng,
79 81 width: 23.w,
80 82 height: 21.h,
81 83 ),
82 84 Image.asset(
83   - starNumber >= 5 ? 'star_light'.assetPng:'star_dark'.assetPng,
  85 + (entity?.star??0) >= 5 ? 'star_light'.assetPng:'star_dark'.assetPng,
84 86 width: 23.w,
85 87 height: 21.h,
86 88 ),
... ... @@ -99,7 +101,7 @@ class RepeatAfterItem extends StatelessWidget {
99 101 ),
100 102 alignment: Alignment.center,
101 103 child: Text(
102   - 'video title',
  104 + entity?.title??'',
103 105 style: TextStyle(
104 106 fontSize: 16.sp,
105 107 color: const Color(0xFF333333)
... ... @@ -112,8 +114,8 @@ class RepeatAfterItem extends StatelessWidget {
112 114 }
113 115  
114 116 Widget _lockWidget() {
115   - return Offstage(
116   - offstage: unLock,
  117 + return Visibility(
  118 + visible: entity?.lock??false,
117 119 child: Container(
118 120 width: 162.w,
119 121 height: 235.h,
... ...