After Width: | Height: | Size: 867 B |
After Width: | Height: | Size: 700 B |
After Width: | Height: | Size: 483 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 795 B |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 350 B |
After Width: | Height: | Size: 284 B |
@ -0,0 +1,234 @@ |
|||||||
|
import 'package:dio/dio.dart'; |
||||||
|
import 'package:flutter/cupertino.dart'; |
||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:flutter/rendering.dart'; |
||||||
|
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||||
|
import 'package:huixiang/main.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/banner.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/base_data.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/brand.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/brand_data.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/category_select_list.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/course_list.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/page.dart'; |
||||||
|
import 'package:huixiang/retrofit/retrofit_api.dart'; |
||||||
|
import 'package:huixiang/utils/event_type.dart'; |
||||||
|
import 'package:huixiang/view_widget/classic_header.dart'; |
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||||
|
import 'package:huixiang/view_widget/login_tips_dialog.dart'; |
||||||
|
import 'package:huixiang/view_widget/store_title_tab.dart'; |
||||||
|
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||||
|
import 'package:shared_preferences/shared_preferences.dart'; |
||||||
|
|
||||||
|
import 'community_view/class_list_view.dart'; |
||||||
|
import 'community_view/class_title_tab.dart'; |
||||||
|
import 'community_view/course_banner.dart'; |
||||||
|
import 'community_view/home_class.dart'; |
||||||
|
|
||||||
|
class CommunityCourse extends StatefulWidget { |
||||||
|
@override |
||||||
|
State<StatefulWidget> createState() { |
||||||
|
return _CommunityCourse(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class _CommunityCourse extends State<CommunityCourse> |
||||||
|
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { |
||||||
|
final ScrollController scrollController = ScrollController(); |
||||||
|
final RefreshController refreshController = RefreshController(); |
||||||
|
|
||||||
|
ApiService apiService; |
||||||
|
List<Brand> brands = []; |
||||||
|
BrandData brandData; |
||||||
|
List<GlobalKey> globaKeys = []; |
||||||
|
List<BannerData> bannerData = []; |
||||||
|
List<CategorySelectList> classSelectList = []; |
||||||
|
List<CourseList> classList = []; |
||||||
|
List<CourseList> classTabList = []; |
||||||
|
int checkIndex = 0; |
||||||
|
|
||||||
|
@override |
||||||
|
void initState() { |
||||||
|
super.initState(); |
||||||
|
|
||||||
|
eventBus.on<EventType>().listen((event) { |
||||||
|
print("object: CommunityCourse"); |
||||||
|
if (event.type < 3) { |
||||||
|
setState(() {}); |
||||||
|
} |
||||||
|
}); |
||||||
|
classListAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
///课程分类列表 |
||||||
|
classListAsync() async { |
||||||
|
if (apiService == null) { |
||||||
|
SharedPreferences value = await SharedPreferences.getInstance(); |
||||||
|
apiService = ApiService( |
||||||
|
Dio(), |
||||||
|
context: context, |
||||||
|
token: value.getString("token"), |
||||||
|
); |
||||||
|
} |
||||||
|
BaseData<List<CategorySelectList>> baseData = await apiService.categoryList().catchError((onError) {}); |
||||||
|
if (baseData != null && baseData.isSuccess) { |
||||||
|
setState(() { |
||||||
|
classSelectList = baseData.data; |
||||||
|
}); |
||||||
|
queryClassList(""); |
||||||
|
} |
||||||
|
EasyLoading.dismiss(); |
||||||
|
} |
||||||
|
|
||||||
|
///课程列表 |
||||||
|
queryClassList(categoryId) async { |
||||||
|
if (apiService == null) { |
||||||
|
SharedPreferences value = await SharedPreferences.getInstance(); |
||||||
|
apiService = ApiService( |
||||||
|
Dio(), |
||||||
|
context: context, |
||||||
|
token: value.getString("token"), |
||||||
|
); |
||||||
|
} |
||||||
|
BaseData<PageInfo<CourseList>> baseData = await apiService.courseList({ |
||||||
|
"categoryId":categoryId, |
||||||
|
"pageNum": 1, |
||||||
|
"pageSize":10, |
||||||
|
"searchKey": "", |
||||||
|
"state":0 |
||||||
|
}).catchError((error) { |
||||||
|
if(categoryId == ""){ |
||||||
|
refreshController.refreshFailed(); |
||||||
|
refreshController.loadFailed(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
if (baseData.isSuccess) { |
||||||
|
if(categoryId == "") { |
||||||
|
refreshController.refreshCompleted(); |
||||||
|
refreshController.loadComplete(); |
||||||
|
setState(() { |
||||||
|
classList.clear(); |
||||||
|
classList.addAll(baseData.data.list); |
||||||
|
}); |
||||||
|
if(classSelectList.length > 0) |
||||||
|
queryClassList(classSelectList[checkIndex].id); |
||||||
|
}else{ |
||||||
|
setState(() { |
||||||
|
classTabList.clear(); |
||||||
|
classTabList.addAll(baseData.data.list); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
_onRefresh(){ |
||||||
|
classListAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
super.build(context); |
||||||
|
return |
||||||
|
Stack( |
||||||
|
children: [ |
||||||
|
Positioned( |
||||||
|
child: Container( |
||||||
|
child: SmartRefresher( |
||||||
|
controller: refreshController, |
||||||
|
enablePullDown: true, |
||||||
|
enablePullUp: false, |
||||||
|
header: MyHeader(), |
||||||
|
physics: ClampingScrollPhysics(), |
||||||
|
onRefresh: _onRefresh, |
||||||
|
scrollController: scrollController, |
||||||
|
child: Container( |
||||||
|
child: SingleChildScrollView( |
||||||
|
physics: NeverScrollableScrollPhysics(), |
||||||
|
child: Container( |
||||||
|
color: Color(0xFFF7F7F7), |
||||||
|
margin: EdgeInsets.only(top: 16.h), |
||||||
|
child: Column( |
||||||
|
children: classChildItem(), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
bottom:0, |
||||||
|
top: 0, |
||||||
|
left: 0, |
||||||
|
right: 0, |
||||||
|
), |
||||||
|
if (brands != null && brands.length > 0) |
||||||
|
Positioned( |
||||||
|
child: Container( |
||||||
|
color: Colors.white, |
||||||
|
child: StoreTitleTab( |
||||||
|
brands, |
||||||
|
globaKeys, |
||||||
|
scrollController, |
||||||
|
isScroll: true, |
||||||
|
), |
||||||
|
), |
||||||
|
top: 0, |
||||||
|
left: 0, |
||||||
|
right: 0, |
||||||
|
), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
List<Widget> classChildItem() { |
||||||
|
var widgets = <Widget>[ |
||||||
|
///课程banner |
||||||
|
CourseBanner(bannerData), |
||||||
|
|
||||||
|
SizedBox(height: 28), |
||||||
|
|
||||||
|
///回乡小课堂 |
||||||
|
HomeClass(classList), |
||||||
|
|
||||||
|
SizedBox(height: 28), |
||||||
|
|
||||||
|
///课程导航栏 |
||||||
|
ClassTitleTab(classSelectList,(index){ |
||||||
|
checkIndex = index; |
||||||
|
queryClassList(classSelectList[index].id); |
||||||
|
}), |
||||||
|
|
||||||
|
///课程列表 |
||||||
|
ClassListView(classTabList), |
||||||
|
|
||||||
|
]; |
||||||
|
|
||||||
|
// if (brands == null) return widgets; |
||||||
|
// brands.forEach((value) { |
||||||
|
// widgets.add( |
||||||
|
// Container( |
||||||
|
// key: globaKeys[brands.indexOf(value)], |
||||||
|
// child: Container( |
||||||
|
// child: Html( |
||||||
|
// data: value.content, |
||||||
|
// customImageRenders: { |
||||||
|
// assetUriMatcher(): assetImageRender(), |
||||||
|
// networkSourceMatcher(extension: "svg"): svgNetworkImageRender(), |
||||||
|
// networkSourceMatcher(): networkImageRender( |
||||||
|
// loadingWidget: () { |
||||||
|
// return Container(); |
||||||
|
// }, |
||||||
|
// ), |
||||||
|
// }, |
||||||
|
// ), |
||||||
|
// ), |
||||||
|
// ), |
||||||
|
// ); |
||||||
|
// }); |
||||||
|
return widgets; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@override |
||||||
|
bool get wantKeepAlive => true; |
||||||
|
} |
@ -0,0 +1,165 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/course_list.dart'; |
||||||
|
import 'package:huixiang/utils/flutter_utils.dart'; |
||||||
|
import 'package:huixiang/utils/font_weight.dart'; |
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||||
|
import 'package:huixiang/view_widget/custom_image.dart'; |
||||||
|
|
||||||
|
class ClassListView extends StatefulWidget { |
||||||
|
final List<CourseList> classList; |
||||||
|
|
||||||
|
ClassListView(this.classList); |
||||||
|
|
||||||
|
@override |
||||||
|
State<StatefulWidget> createState() { |
||||||
|
return _ClassListView(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class _ClassListView extends State<ClassListView> { |
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return GridView.builder( |
||||||
|
itemCount:widget.classList == null ? 0 : widget.classList.length, |
||||||
|
padding: EdgeInsets.only( |
||||||
|
left: 16.w, |
||||||
|
right: 16.w, |
||||||
|
top: 13.h, |
||||||
|
bottom: 16.h, |
||||||
|
), |
||||||
|
shrinkWrap: true, |
||||||
|
physics: NeverScrollableScrollPhysics(), |
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
||||||
|
//一行的Widget数量 |
||||||
|
crossAxisCount: 3, |
||||||
|
//水平子Widget之间间距 |
||||||
|
crossAxisSpacing: 11.w, |
||||||
|
//垂直子Widget之间间距 |
||||||
|
mainAxisSpacing: 16.w, |
||||||
|
//子Widget宽高比例 0.59 |
||||||
|
childAspectRatio: |
||||||
|
166 / (281 / 2 + (281 / 2) * AppUtils.textScale(context)), |
||||||
|
), |
||||||
|
itemBuilder: (context, index) { |
||||||
|
return GestureDetector( |
||||||
|
onTap: () { |
||||||
|
Navigator.of(context).pushNamed('/router/class_details',arguments: {"id": widget.classList[index].id}); |
||||||
|
}, |
||||||
|
child: classListItem(widget.classList[index]), |
||||||
|
); |
||||||
|
}, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Widget classListItem(CourseList classList) { |
||||||
|
return Container( |
||||||
|
width: 106, |
||||||
|
height: 189, |
||||||
|
margin: EdgeInsets.symmetric( |
||||||
|
// horizontal: 6.w, |
||||||
|
vertical: 3, |
||||||
|
), |
||||||
|
color: Colors.white, |
||||||
|
child: Column( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Stack( |
||||||
|
alignment: Alignment(0.9, 0.9), |
||||||
|
children: [ |
||||||
|
Container( |
||||||
|
color: Color.fromARGB(80, 0, 0, 0), |
||||||
|
child: ClipRRect( |
||||||
|
child: MImage( |
||||||
|
classList.coverImg, |
||||||
|
width: double.infinity, |
||||||
|
height: 120, |
||||||
|
fit: BoxFit.cover, |
||||||
|
errorSrc: "assets/image/default_1.png", |
||||||
|
fadeSrc: "assets/image/default_1.png", |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.vertical( |
||||||
|
top: Radius.circular(4), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
Container( |
||||||
|
padding: EdgeInsets.only(left: 4), |
||||||
|
child: Row( |
||||||
|
children: [ |
||||||
|
Row( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Image.asset( |
||||||
|
"assets/image/ketang_like.png", |
||||||
|
width: 16.w, |
||||||
|
height: 16.h, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
SizedBox(width: 5), |
||||||
|
Text( |
||||||
|
classList.likes.toString(), |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
SizedBox(width: 8), |
||||||
|
Row( |
||||||
|
children: [ |
||||||
|
Image.asset( |
||||||
|
"assets/image/ketang_message.png", |
||||||
|
width: 16.w, |
||||||
|
height: 16.h, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
SizedBox(width: 5), |
||||||
|
Text( |
||||||
|
classList.viewers.toString(), |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
Container( |
||||||
|
padding: EdgeInsets.only(left: 4, top: 3), |
||||||
|
child: Column( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Text( |
||||||
|
classList.subject, |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 14.sp, |
||||||
|
fontWeight: MyFontWeight.medium, |
||||||
|
color: Colors.black, |
||||||
|
), |
||||||
|
), |
||||||
|
SizedBox(height: 2), |
||||||
|
Text( |
||||||
|
"讲师:${classList.author.name}", |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
color: Colors.black, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:huixiang/generated/l10n.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/category_select_list.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/goods_category.dart'; |
||||||
|
import 'package:huixiang/utils/font_weight.dart'; |
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||||
|
import 'package:huixiang/view_widget/my_tab.dart'; |
||||||
|
|
||||||
|
class ClassTitleTab extends StatefulWidget { |
||||||
|
final List<CategorySelectList> classSelectList; |
||||||
|
final Function notifyClassSelectList; |
||||||
|
|
||||||
|
ClassTitleTab(this.classSelectList,this.notifyClassSelectList); |
||||||
|
|
||||||
|
@override |
||||||
|
State<StatefulWidget> createState() { |
||||||
|
return _ClassTitleTab(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class _ClassTitleTab extends State<ClassTitleTab> |
||||||
|
with SingleTickerProviderStateMixin { |
||||||
|
TabController tabController; |
||||||
|
|
||||||
|
@override |
||||||
|
void initState() { |
||||||
|
super.initState(); |
||||||
|
if (widget.classSelectList != null && widget.classSelectList.length > 0) |
||||||
|
tabController = TabController(length: widget.classSelectList.length, vsync: this ); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Container( |
||||||
|
alignment: Alignment.centerLeft, |
||||||
|
child: DefaultTabController( |
||||||
|
length:widget.classSelectList == null |
||||||
|
? 0 |
||||||
|
: widget.classSelectList.length, |
||||||
|
child: TabBar( |
||||||
|
isScrollable: true, |
||||||
|
//可滚动 |
||||||
|
indicatorColor: Color(0xff39B54A), |
||||||
|
labelColor: Color(0xff32A060), |
||||||
|
labelStyle: TextStyle( |
||||||
|
fontSize: 14.sp, |
||||||
|
fontWeight: FontWeight.bold, |
||||||
|
), |
||||||
|
unselectedLabelStyle: TextStyle( |
||||||
|
fontSize: 14.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
), |
||||||
|
controller: tabController, |
||||||
|
//未选中文字颜色 |
||||||
|
unselectedLabelColor: Color(0xff4D4D4D), |
||||||
|
indicatorSize: TabBarIndicatorSize.label, |
||||||
|
onTap: (index){ |
||||||
|
widget.notifyClassSelectList(index); |
||||||
|
}, |
||||||
|
//指示器与文字等宽 |
||||||
|
tabs:widget.classSelectList == null |
||||||
|
? [] |
||||||
|
: widget.classSelectList |
||||||
|
.map((e) => MyTab(text: e.name)) |
||||||
|
.toList(), |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,106 @@ |
|||||||
|
|
||||||
|
import 'dart:convert'; |
||||||
|
|
||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:flutter_swiper/flutter_swiper.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/banner.dart'; |
||||||
|
import 'package:huixiang/view_widget/custom_image.dart'; |
||||||
|
|
||||||
|
class CourseBanner extends StatefulWidget { |
||||||
|
|
||||||
|
final List<BannerData> bannerData; |
||||||
|
|
||||||
|
CourseBanner(this.bannerData); |
||||||
|
|
||||||
|
@override |
||||||
|
State<StatefulWidget> createState() { |
||||||
|
return _CourseBanner(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
class _CourseBanner extends State<CourseBanner> { |
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Container( |
||||||
|
child: AspectRatio( |
||||||
|
aspectRatio: 2.08, |
||||||
|
child: Swiper( |
||||||
|
viewportFraction: 0.88, |
||||||
|
scale: 0.93, |
||||||
|
pagination: SwiperPagination( |
||||||
|
alignment: Alignment.bottomCenter, |
||||||
|
builder: DotSwiperPaginationBuilder( |
||||||
|
size: 8, |
||||||
|
activeSize: 8, |
||||||
|
space: 5, |
||||||
|
activeColor: Colors.black, |
||||||
|
color: Colors.black.withAlpha(76), |
||||||
|
), |
||||||
|
), |
||||||
|
physics: BouncingScrollPhysics(), |
||||||
|
itemBuilder: (context, position) { |
||||||
|
return InkWell( |
||||||
|
onTap: () { |
||||||
|
bannerClick(widget.bannerData[position]); |
||||||
|
}, |
||||||
|
child: MImage( |
||||||
|
(widget.bannerData != null && position < widget.bannerData.length) |
||||||
|
? widget.bannerData[position].imgUrl |
||||||
|
: "", |
||||||
|
fit: BoxFit.cover, |
||||||
|
radius: BorderRadius.circular(8), |
||||||
|
errorSrc: "assets/image/default_2_1.png", |
||||||
|
fadeSrc: "assets/image/default_2_1.png", |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
itemCount: (widget.bannerData != null && widget.bannerData.length > 0) |
||||||
|
? widget.bannerData.length |
||||||
|
: 1), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/// contentType 跳转类型(0:不跳转,1:积分商品,2:活动,3:文章) |
||||||
|
bannerClick(BannerData bannerData) async { |
||||||
|
switch (bannerData.contentType) { |
||||||
|
case 1: |
||||||
|
Navigator.of(context).pushNamed('/router/integral_store_page', |
||||||
|
arguments: {"goodsId": bannerData.content}); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
Navigator.of(context) |
||||||
|
.pushNamed('/router/web_page', arguments: { |
||||||
|
"activityId": bannerData.content, |
||||||
|
}); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
Navigator.of(context) |
||||||
|
.pushNamed('/router/web_page', arguments: { |
||||||
|
"articleId": bannerData.content, |
||||||
|
}); |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
String router = bannerData.content; |
||||||
|
if (router.contains("?")) { |
||||||
|
String params = router.substring(router.indexOf("?")); |
||||||
|
params = params.replaceAll("?", ""); |
||||||
|
Map map = jsonDecode(params); |
||||||
|
Navigator.of(context).pushNamed(router, arguments: map); |
||||||
|
} else { |
||||||
|
Navigator.of(context).pushNamed(router); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,204 @@ |
|||||||
|
import 'package:flutter/cupertino.dart'; |
||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
||||||
|
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
||||||
|
import 'package:huixiang/retrofit/data/course_list.dart'; |
||||||
|
import 'package:huixiang/retrofit/retrofit_api.dart'; |
||||||
|
import 'package:huixiang/utils/font_weight.dart'; |
||||||
|
import 'package:huixiang/view_widget/custom_image.dart'; |
||||||
|
import 'package:huixiang/view_widget/item_title.dart'; |
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||||
|
|
||||||
|
class HomeClass extends StatefulWidget { |
||||||
|
final List<CourseList> classList; |
||||||
|
|
||||||
|
HomeClass(this.classList); |
||||||
|
@override |
||||||
|
State<StatefulWidget> createState() { |
||||||
|
return _HomeClass(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class _HomeClass extends State<HomeClass> { |
||||||
|
ApiService apiService; |
||||||
|
BMFCoordinate latLng; |
||||||
|
|
||||||
|
BMFMapController _mapController; |
||||||
|
final TextEditingController editingController = TextEditingController(); |
||||||
|
|
||||||
|
@override |
||||||
|
void initState() { |
||||||
|
super.initState(); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Column( |
||||||
|
children: [ |
||||||
|
ItemTitle( |
||||||
|
text: "回乡小课堂", |
||||||
|
imgPath: "assets/image/ketang.png", |
||||||
|
), |
||||||
|
Container( |
||||||
|
height: 189, |
||||||
|
margin: EdgeInsets.only(top:10), |
||||||
|
child: ListView.builder( |
||||||
|
scrollDirection: Axis.horizontal, |
||||||
|
physics: BouncingScrollPhysics(), |
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10), |
||||||
|
itemCount:widget.classList == null ? 0 : widget.classList.length, |
||||||
|
itemBuilder: (context, position) { |
||||||
|
return GestureDetector( |
||||||
|
onTap: () { |
||||||
|
Navigator.of(context).pushNamed('/router/class_details'); |
||||||
|
}, |
||||||
|
child: classItem(widget.classList[position]), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Widget classItem(CourseList classList) { |
||||||
|
return Container( |
||||||
|
width: 168, |
||||||
|
height: 189, |
||||||
|
margin: EdgeInsets.symmetric( |
||||||
|
horizontal: 6.w, |
||||||
|
vertical: 3, |
||||||
|
), |
||||||
|
color: Colors.white, |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
Stack( |
||||||
|
alignment: Alignment(0.9,0.9), |
||||||
|
children: [ |
||||||
|
Container( |
||||||
|
color: Color.fromARGB(80, 0, 0, 0), |
||||||
|
child: ClipRRect( |
||||||
|
child: MImage( |
||||||
|
classList.coverImg, |
||||||
|
width: double.infinity, |
||||||
|
height: 120, |
||||||
|
fit: BoxFit.cover, |
||||||
|
errorSrc: "assets/image/default_1.png", |
||||||
|
fadeSrc: "assets/image/default_1.png", |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.vertical( |
||||||
|
top: Radius.circular(4), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
Container( |
||||||
|
padding: EdgeInsets.only(left: 4), |
||||||
|
child:Row( |
||||||
|
children: [ |
||||||
|
Row( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Image.asset( |
||||||
|
"assets/image/ketang_like.png", |
||||||
|
width: 16.w, |
||||||
|
height: 16.h, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
SizedBox(width:5), |
||||||
|
Text( |
||||||
|
classList.likes.toString(), |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
SizedBox(width:8), |
||||||
|
Row( |
||||||
|
children: [ |
||||||
|
Image.asset( |
||||||
|
"assets/image/ketang_message.png", |
||||||
|
width: 16.w, |
||||||
|
height: 16.h, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
SizedBox(width:5), |
||||||
|
Text( |
||||||
|
classList.viewers.toString(), |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
Container( |
||||||
|
padding: EdgeInsets.only(left: 3,top: 2), |
||||||
|
child: Column( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
SizedBox(height:2), |
||||||
|
Row( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Container( |
||||||
|
height: 15.h, |
||||||
|
width: 30.w, |
||||||
|
alignment: Alignment.center, |
||||||
|
decoration: BoxDecoration( |
||||||
|
borderRadius: |
||||||
|
BorderRadius.circular(2), |
||||||
|
border: Border.all( |
||||||
|
width: 1, |
||||||
|
color: Color(0xFFFF7A1A), |
||||||
|
style: BorderStyle.solid, |
||||||
|
), |
||||||
|
), |
||||||
|
child: Text( |
||||||
|
( classList?.tags != null && classList.tags.length > 0 )?classList.tags[0] : "", |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.medium, |
||||||
|
color: Color(0xFFFF7A1A), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
SizedBox(width:5), |
||||||
|
Expanded(child: Text( |
||||||
|
classList.subject, |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 14.sp, |
||||||
|
fontWeight: MyFontWeight.medium, |
||||||
|
color: Colors.black, |
||||||
|
), |
||||||
|
),), |
||||||
|
], |
||||||
|
), |
||||||
|
SizedBox(height:3), |
||||||
|
Text( |
||||||
|
"讲师:${classList.author.name}", |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 12.sp, |
||||||
|
fontWeight: MyFontWeight.regular, |
||||||
|
color: Colors.black, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,114 @@ |
|||||||
|
/// id : "1452472226421932032" |
||||||
|
/// createTime : "2021-10-25 11:08:59" |
||||||
|
/// createUser : "1" |
||||||
|
/// updateTime : "2021-10-25 11:08:59" |
||||||
|
/// updateUser : "1" |
||||||
|
/// name : "4444" |
||||||
|
/// isTop : true |
||||||
|
/// sort : 0 |
||||||
|
/// isDelete : 0 |
||||||
|
|
||||||
|
class CategorySelectList { |
||||||
|
CategorySelectList({ |
||||||
|
String id, |
||||||
|
String createTime, |
||||||
|
String createUser, |
||||||
|
String updateTime, |
||||||
|
String updateUser, |
||||||
|
String name, |
||||||
|
bool isTop, |
||||||
|
int sort, |
||||||
|
int isDelete,}){ |
||||||
|
_id = id; |
||||||
|
_createTime = createTime; |
||||||
|
_createUser = createUser; |
||||||
|
_updateTime = updateTime; |
||||||
|
_updateUser = updateUser; |
||||||
|
_name = name; |
||||||
|
_isTop = isTop; |
||||||
|
_sort = sort; |
||||||
|
_isDelete = isDelete; |
||||||
|
} |
||||||
|
|
||||||
|
CategorySelectList.fromJson(dynamic json) { |
||||||
|
_id = json['id']; |
||||||
|
_createTime = json['createTime']; |
||||||
|
_createUser = json['createUser']; |
||||||
|
_updateTime = json['updateTime']; |
||||||
|
_updateUser = json['updateUser']; |
||||||
|
_name = json['name']; |
||||||
|
_isTop = json['isTop']; |
||||||
|
_sort = json['sort']; |
||||||
|
_isDelete = json['isDelete']; |
||||||
|
} |
||||||
|
String _id; |
||||||
|
String _createTime; |
||||||
|
String _createUser; |
||||||
|
String _updateTime; |
||||||
|
String _updateUser; |
||||||
|
String _name; |
||||||
|
bool _isTop; |
||||||
|
int _sort; |
||||||
|
int _isDelete; |
||||||
|
|
||||||
|
String get id => _id; |
||||||
|
String get createTime => _createTime; |
||||||
|
String get createUser => _createUser; |
||||||
|
String get updateTime => _updateTime; |
||||||
|
String get updateUser => _updateUser; |
||||||
|
String get name => _name; |
||||||
|
bool get isTop => _isTop; |
||||||
|
int get sort => _sort; |
||||||
|
int get isDelete => _isDelete; |
||||||
|
|
||||||
|
|
||||||
|
set id(String value) { |
||||||
|
_id = value; |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
final map = <String, dynamic>{}; |
||||||
|
map['id'] = _id; |
||||||
|
map['createTime'] = _createTime; |
||||||
|
map['createUser'] = _createUser; |
||||||
|
map['updateTime'] = _updateTime; |
||||||
|
map['updateUser'] = _updateUser; |
||||||
|
map['name'] = _name; |
||||||
|
map['isTop'] = _isTop; |
||||||
|
map['sort'] = _sort; |
||||||
|
map['isDelete'] = _isDelete; |
||||||
|
return map; |
||||||
|
} |
||||||
|
|
||||||
|
set createTime(String value) { |
||||||
|
_createTime = value; |
||||||
|
} |
||||||
|
|
||||||
|
set createUser(String value) { |
||||||
|
_createUser = value; |
||||||
|
} |
||||||
|
|
||||||
|
set updateTime(String value) { |
||||||
|
_updateTime = value; |
||||||
|
} |
||||||
|
|
||||||
|
set updateUser(String value) { |
||||||
|
_updateUser = value; |
||||||
|
} |
||||||
|
|
||||||
|
set name(String value) { |
||||||
|
_name = value; |
||||||
|
} |
||||||
|
|
||||||
|
set isTop(bool value) { |
||||||
|
_isTop = value; |
||||||
|
} |
||||||
|
|
||||||
|
set sort(int value) { |
||||||
|
_sort = value; |
||||||
|
} |
||||||
|
|
||||||
|
set isDelete(int value) { |
||||||
|
_isDelete = value; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,220 @@ |
|||||||
|
/// id : "1452470112895369216" |
||||||
|
/// createTime : "2021-10-25 11:00:35" |
||||||
|
/// createUser : "1" |
||||||
|
/// updateTime : "2021-10-25 11:00:35" |
||||||
|
/// updateUser : "1" |
||||||
|
/// categoryId : "1452453250065235968" |
||||||
|
/// subject : "11" |
||||||
|
/// tags : ["11"] |
||||||
|
/// coverImg : "https://pos.upload.gznl.top/0000/2021/10/61dda29b-19cf-4d47-b6c7-c07f895beeaa.jpg" |
||||||
|
/// author : {"name":"11","avatar":"11"} |
||||||
|
/// introduce : "11" |
||||||
|
/// viewers : 0 |
||||||
|
/// likes : 0 |
||||||
|
/// state : true |
||||||
|
/// isDelete : 0 |
||||||
|
|
||||||
|
class CourseList { |
||||||
|
CourseList({ |
||||||
|
String id, |
||||||
|
String createTime, |
||||||
|
String createUser, |
||||||
|
String updateTime, |
||||||
|
String updateUser, |
||||||
|
String categoryId, |
||||||
|
String subject, |
||||||
|
List<String> tags, |
||||||
|
String coverImg, |
||||||
|
Author author, |
||||||
|
String introduce, |
||||||
|
int viewers, |
||||||
|
int likes, |
||||||
|
bool state, |
||||||
|
int isDelete,}){ |
||||||
|
_id = id; |
||||||
|
_createTime = createTime; |
||||||
|
_createUser = createUser; |
||||||
|
_updateTime = updateTime; |
||||||
|
_updateUser = updateUser; |
||||||
|
_categoryId = categoryId; |
||||||
|
_subject = subject; |
||||||
|
_tags = tags; |
||||||
|
_coverImg = coverImg; |
||||||
|
_author = author; |
||||||
|
_introduce = introduce; |
||||||
|
_viewers = viewers; |
||||||
|
_likes = likes; |
||||||
|
_state = state; |
||||||
|
_isDelete = isDelete; |
||||||
|
} |
||||||
|
|
||||||
|
CourseList.fromJson(dynamic json) { |
||||||
|
_id = json['id']; |
||||||
|
_createTime = json['createTime']; |
||||||
|
_createUser = json['createUser']; |
||||||
|
_updateTime = json['updateTime']; |
||||||
|
_updateUser = json['updateUser']; |
||||||
|
_categoryId = json['categoryId']; |
||||||
|
_subject = json['subject']; |
||||||
|
_tags = json['tags'] != null ? json['tags'].cast<String>() : []; |
||||||
|
_coverImg = json['coverImg']; |
||||||
|
_author = json['author'] != null ? Author.fromJson(json['author']) : null; |
||||||
|
_introduce = json['introduce']; |
||||||
|
_viewers = json['viewers']; |
||||||
|
_likes = json['likes']; |
||||||
|
_state = json['state']; |
||||||
|
_isDelete = json['isDelete']; |
||||||
|
} |
||||||
|
String _id; |
||||||
|
String _createTime; |
||||||
|
String _createUser; |
||||||
|
String _updateTime; |
||||||
|
String _updateUser; |
||||||
|
String _categoryId; |
||||||
|
String _subject; |
||||||
|
List<String> _tags; |
||||||
|
String _coverImg; |
||||||
|
Author _author; |
||||||
|
String _introduce; |
||||||
|
int _viewers; |
||||||
|
int _likes; |
||||||
|
bool _state; |
||||||
|
int _isDelete; |
||||||
|
|
||||||
|
String get id => _id; |
||||||
|
String get createTime => _createTime; |
||||||
|
String get createUser => _createUser; |
||||||
|
String get updateTime => _updateTime; |
||||||
|
String get updateUser => _updateUser; |
||||||
|
String get categoryId => _categoryId; |
||||||
|
String get subject => _subject; |
||||||
|
List<String> get tags => _tags; |
||||||
|
String get coverImg => _coverImg; |
||||||
|
Author get author => _author; |
||||||
|
String get introduce => _introduce; |
||||||
|
int get viewers => _viewers; |
||||||
|
int get likes => _likes; |
||||||
|
bool get state => _state; |
||||||
|
int get isDelete => _isDelete; |
||||||
|
|
||||||
|
|
||||||
|
set id(String value) { |
||||||
|
_id = value; |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
final map = <String, dynamic>{}; |
||||||
|
map['id'] = _id; |
||||||
|
map['createTime'] = _createTime; |
||||||
|
map['createUser'] = _createUser; |
||||||
|
map['updateTime'] = _updateTime; |
||||||
|
map['updateUser'] = _updateUser; |
||||||
|
map['categoryId'] = _categoryId; |
||||||
|
map['subject'] = _subject; |
||||||
|
map['tags'] = _tags; |
||||||
|
map['coverImg'] = _coverImg; |
||||||
|
if (_author != null) { |
||||||
|
map['author'] = _author.toJson(); |
||||||
|
} |
||||||
|
map['introduce'] = _introduce; |
||||||
|
map['viewers'] = _viewers; |
||||||
|
map['likes'] = _likes; |
||||||
|
map['state'] = _state; |
||||||
|
map['isDelete'] = _isDelete; |
||||||
|
return map; |
||||||
|
} |
||||||
|
|
||||||
|
set createTime(String value) { |
||||||
|
_createTime = value; |
||||||
|
} |
||||||
|
|
||||||
|
set createUser(String value) { |
||||||
|
_createUser = value; |
||||||
|
} |
||||||
|
|
||||||
|
set updateTime(String value) { |
||||||
|
_updateTime = value; |
||||||
|
} |
||||||
|
|
||||||
|
set updateUser(String value) { |
||||||
|
_updateUser = value; |
||||||
|
} |
||||||
|
|
||||||
|
set categoryId(String value) { |
||||||
|
_categoryId = value; |
||||||
|
} |
||||||
|
|
||||||
|
set subject(String value) { |
||||||
|
_subject = value; |
||||||
|
} |
||||||
|
|
||||||
|
set tags(List<String> value) { |
||||||
|
_tags = value; |
||||||
|
} |
||||||
|
|
||||||
|
set coverImg(String value) { |
||||||
|
_coverImg = value; |
||||||
|
} |
||||||
|
|
||||||
|
set author(Author value) { |
||||||
|
_author = value; |
||||||
|
} |
||||||
|
|
||||||
|
set introduce(String value) { |
||||||
|
_introduce = value; |
||||||
|
} |
||||||
|
|
||||||
|
set viewers(int value) { |
||||||
|
_viewers = value; |
||||||
|
} |
||||||
|
|
||||||
|
set likes(int value) { |
||||||
|
_likes = value; |
||||||
|
} |
||||||
|
|
||||||
|
set state(bool value) { |
||||||
|
_state = value; |
||||||
|
} |
||||||
|
|
||||||
|
set isDelete(int value) { |
||||||
|
_isDelete = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// name : "11" |
||||||
|
/// avatar : "11" |
||||||
|
|
||||||
|
class Author { |
||||||
|
Author({ |
||||||
|
String name, |
||||||
|
String avatar,}){ |
||||||
|
_name = name; |
||||||
|
_avatar = avatar; |
||||||
|
} |
||||||
|
|
||||||
|
Author.fromJson(dynamic json) { |
||||||
|
_name = json['name']; |
||||||
|
_avatar = json['avatar']; |
||||||
|
} |
||||||
|
String _name; |
||||||
|
String _avatar; |
||||||
|
|
||||||
|
String get name => _name; |
||||||
|
String get avatar => _avatar; |
||||||
|
|
||||||
|
|
||||||
|
set name(String value) { |
||||||
|
_name = value; |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
final map = <String, dynamic>{}; |
||||||
|
map['name'] = _name; |
||||||
|
map['avatar'] = _avatar; |
||||||
|
return map; |
||||||
|
} |
||||||
|
|
||||||
|
set avatar(String value) { |
||||||
|
_avatar = value; |
||||||
|
} |
||||||
|
} |