@@ -0,0 +1,3 @@ | |||
export 'login_bloc.dart'; | |||
export 'login_event.dart'; | |||
export 'login_state.dart'; |
@@ -0,0 +1,15 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import './bloc.dart'; | |||
class LoginBloc extends Bloc<LoginEvent, LoginState> { | |||
@override | |||
LoginState get initialState => InitialLoginState(); | |||
@override | |||
Stream<LoginState> mapEventToState( | |||
LoginEvent event, | |||
) async* { | |||
// TODO: Add Logic | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class LoginEvent extends Equatable { | |||
const LoginEvent(); | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 初始化 | |||
class LoginInitEvent extends LoginEvent{} |
@@ -0,0 +1,19 @@ | |||
import 'package:zhiying_comm/util/net_util.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class LoginRepository{ | |||
/// 获取页面数据 | |||
Future<Map> fetchNetPageData() async{ | |||
} | |||
/// 获取缓存的页面数据 | |||
Future<Map> fetchCachePageData() async{ | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class LoginState extends Equatable { | |||
const LoginState(); | |||
} | |||
class InitialLoginState extends LoginState { | |||
@override | |||
List<Object> get props => []; | |||
} |
@@ -0,0 +1,37 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/login_page/bloc/bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/login_page/bloc/login_bloc.dart'; | |||
/// | |||
/// 登陆页面 | |||
/// | |||
class LoginPage extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
LoginPage(this.data, {Key key}) : super(key: key); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
body: BlocProvider<LoginBloc>( | |||
create: (_) => LoginBloc()..add(LoginInitEvent()), | |||
child: SafeArea( | |||
child: LoginPageContainer(), | |||
), | |||
), | |||
); | |||
} | |||
} | |||
class LoginPageContainer extends StatefulWidget { | |||
@override | |||
_LoginPageContainerState createState() => _LoginPageContainerState(); | |||
} | |||
class _LoginPageContainerState extends State<LoginPageContainer> { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container(); | |||
} | |||
} |
@@ -1,7 +1,9 @@ | |||
import 'package:zhiying_base_widget/pages/login_page/login_page.dart'; | |||
import 'package:zhiying_base_widget/pages/main_page/main_page.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_goods/home_goods_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/home_banner_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_goods/home_goods_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_quick_entry/home_quick_entry_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_slide_banner/home_slide_banner_creater.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | |||
@@ -16,13 +18,18 @@ class BaseWidgetRegister { | |||
static void registPage() { | |||
PageFactory.regist('homePage', (model) => HomePage()); | |||
PageFactory.regist('index', (model) => MainPage(model)); | |||
PageFactory.regist('login', (model) => LoginPage(model) ); | |||
} | |||
// 注册控件 | |||
static void registWidgets() { | |||
WidgetFactory.regist('index_carousel', HomeBannerCreater()); | |||
/// 可滚动banner | |||
WidgetFactory.regist('index_carousel', HomeSlideBannerCreater()); | |||
WidgetFactory.regist('index_recommend_list', GoodsListCreater()); | |||
// 首页快速入口 | |||
WidgetFactory.regist('home_quick_entry', HomeQuickEntryCreater()); | |||
/// 首页快速入口 | |||
WidgetFactory.regist('multi_nav', HomeQuickEntryCreater()); | |||
/// 不可以滚动banner | |||
WidgetFactory.regist('index_banner_one', HomeBannerCreater()); | |||
WidgetFactory.regist('index_banner_two', HomeBannerCreater()); | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
export 'home_banner_bloc.dart'; | |||
export 'home_banner_event.dart'; | |||
export 'home_banner_state.dart'; |
@@ -0,0 +1,36 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/bloc/home_banner_repository.dart'; | |||
import './bloc.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class HomeBannerBloc extends Bloc<HomeBannerEvent, HomeBannerState> { | |||
HomeBannerRepository repository; | |||
HomeBannerBloc({@required this.repository}); | |||
@override | |||
HomeBannerState get initialState => InitialHomeBannerState(); | |||
@override | |||
Stream<HomeBannerState> mapEventToState( | |||
HomeBannerEvent event, | |||
) async* { | |||
final currentState = state; | |||
if (event is HomeBannerInitEvent) { | |||
yield* _mapHomeBannerInitEventToState(event); | |||
} | |||
} | |||
/// 初始化 | |||
Stream<HomeBannerState> _mapHomeBannerInitEventToState(HomeBannerInitEvent event) async* { | |||
var cache = await repository.fetchCacheData(modId: event.model['mod_id']); | |||
if (!EmptyUtil.isEmpty(cache)) yield HomeBannerCacheState(); | |||
var result = await repository.fetchNetData(modId: event.model['mod_id']); | |||
if (!EmptyUtil.isEmpty(result)) | |||
yield HomeBannerLoadedState(); | |||
else | |||
yield HomeBannerErrorState(); | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class HomeBannerEvent extends Equatable { | |||
const HomeBannerEvent(); | |||
} | |||
/// | |||
/// 初始化事件 | |||
/// | |||
class HomeBannerInitEvent extends HomeBannerEvent { | |||
final Map<String, dynamic> model; | |||
const HomeBannerInitEvent(this.model); | |||
@override | |||
List<Object> get props => []; | |||
} |
@@ -0,0 +1,24 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/model/HomeBannerModel.dart'; | |||
import 'package:zhiying_comm/util/net_util.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class HomeBannerRepository { | |||
/// 读取缓存数据 | |||
Future<HomeBannerModel> fetchCacheData({@required int modId}) async { | |||
var reult = await NetUtil.getRequestCachedData('/api/v1/mod', params: {'ids': [modId]}); | |||
if (!EmptyUtil.isEmpty(reult)) { | |||
return HomeBannerModel(); | |||
} | |||
return null; | |||
} | |||
/// 获取网路数据 | |||
Future<HomeBannerModel> fetchNetData({@required int modId}) async { | |||
var result = await NetUtil.post('/api/v1/mod', params: {'ids': [modId]}); | |||
if (NetUtil.isSuccess(result)) { | |||
return HomeBannerModel(); | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class HomeBannerState extends Equatable { | |||
const HomeBannerState(); | |||
} | |||
/// 初始化状态 | |||
class InitialHomeBannerState extends HomeBannerState { | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 数据加载完毕状态 | |||
class HomeBannerLoadedState extends HomeBannerState { | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 缓存数据加载完毕 | |||
class HomeBannerCacheState extends HomeBannerState { | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 数据加载失败 | |||
class HomeBannerErrorState extends HomeBannerState { | |||
@override | |||
List<Object> get props => []; | |||
} |
@@ -1,32 +0,0 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:flutter_swiper/flutter_swiper.dart'; | |||
class HomeBanner extends StatelessWidget { | |||
final Map<String, dynamic> model; | |||
const HomeBanner(this.model, {Key key}) : super(key: key); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
width: double.infinity, | |||
height: 200, | |||
child: Swiper( | |||
itemBuilder: (BuildContext context, int index) { | |||
// return new Image.network( | |||
// "http://via.placeholder.com/350x150", | |||
// fit: BoxFit.fill, | |||
// ); | |||
return Container(); | |||
}, | |||
itemCount: 3, | |||
pagination: new SwiperPagination(), | |||
control: new SwiperControl(), | |||
onTap: (index) { | |||
print(model.toString()); | |||
}, | |||
), | |||
); | |||
} | |||
} |
@@ -1,16 +1,15 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/home_banner.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/home_banner_sk.dart'; | |||
import 'package:flutter/src/widgets/framework.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/home_banner_widget.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class HomeBannerCreater extends WidgetCreater { | |||
@override | |||
List<Widget> createSkeleton(Map<String, dynamic> model) { | |||
return [HomeBannerSkeleton()]; | |||
} | |||
/// | |||
/// 不可滚动Banner | |||
/// | |||
class HomeBannerCreater extends WidgetCreater{ | |||
@override | |||
List<Widget> createWidgets(Map<String, dynamic> model) { | |||
return [HomeBanner(model)]; | |||
return [HomeBannerWidget(model)]; | |||
} | |||
} | |||
} |
@@ -1,23 +1,83 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:shimmer/shimmer.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class HomeBannerSkeleton extends StatelessWidget { | |||
final Map<String, dynamic> model; | |||
const HomeBannerSkeleton(this.model); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
height: 60, | |||
width: double.infinity, | |||
height: 200, | |||
color: Colors.white, | |||
child: Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Container( | |||
margin: EdgeInsets.all(10), | |||
decoration: BoxDecoration( | |||
color: Colors.white, | |||
borderRadius: BorderRadius.all(Radius.circular(10))), | |||
), | |||
), | |||
child: _styleWidget(EmptyUtil.isEmpty(model) ? 1 : model.containsKey('mod_name') ? _getCount(model['mod_name']) : 1), | |||
); | |||
} | |||
int _getCount(String modName) { | |||
if (!EmptyUtil.isEmpty(modName)) { | |||
if (modName.endsWith('one')) { | |||
return 1; | |||
} | |||
if (modName.endsWith('two')) { | |||
return 2; | |||
} | |||
if (modName.endsWith('three')) { | |||
return 3; | |||
} | |||
if (modName.endsWith('four')) { | |||
return 4; | |||
} | |||
if (modName.endsWith('five')) { | |||
return 5; | |||
} | |||
} | |||
return 1; | |||
} | |||
Widget _styleWidget(int size) { | |||
List data = []; | |||
for(int i = 0 ; i < size; i++){ | |||
data.add(i); | |||
} | |||
return Row( | |||
children: data.map((index){ | |||
var margin; | |||
// if(index == 0 && size !=1){ | |||
// margin = const EdgeInsets.only(right: 10,); | |||
// }else if(index == size -1 && size != 2 && size != 1){ | |||
// margin = const EdgeInsets.only(left: 10); | |||
// }else{ | |||
// margin = const EdgeInsets.only(left: 10, right: 10); | |||
// } | |||
margin = const EdgeInsets.only(left: 10, right: 10); | |||
return Flexible( | |||
flex: 1, | |||
child: Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Container( | |||
height: double.infinity, | |||
width: double.infinity, | |||
margin: margin, | |||
decoration: BoxDecoration( | |||
color: Colors.white, | |||
borderRadius: BorderRadius.circular(7.5), | |||
), | |||
), | |||
), | |||
); | |||
}).toList(), | |||
); | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/bloc/bloc.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/bloc/home_banner_repository.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_banner/home_banner_sk.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
/// | |||
/// 不可以滚动Banner | |||
/// | |||
class HomeBannerWidget extends StatefulWidget { | |||
final Map<String, dynamic> model; | |||
const HomeBannerWidget(this.model); | |||
@override | |||
_HomeBannerWidgetState createState() => _HomeBannerWidgetState(); | |||
} | |||
class _HomeBannerWidgetState extends State<HomeBannerWidget> { | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocProvider<HomeBannerBloc>( | |||
create: (_) => HomeBannerBloc(repository: HomeBannerRepository())..add(HomeBannerInitEvent(widget.model)), | |||
child: HomeBannerContainer( | |||
model: widget.model, | |||
), | |||
); | |||
} | |||
} | |||
class HomeBannerContainer extends StatefulWidget { | |||
final Map<String, dynamic> model; | |||
const HomeBannerContainer({@required this.model}); | |||
@override | |||
_HomeBannerContainerState createState() => _HomeBannerContainerState(); | |||
} | |||
class _HomeBannerContainerState extends State<HomeBannerContainer> { | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocConsumer<HomeBannerBloc, HomeBannerState>( | |||
listener: (context, state) {}, | |||
buildWhen: (previous, current) { | |||
if (current is HomeBannerErrorState) { | |||
return false; | |||
} | |||
return true; | |||
}, | |||
builder: (context, state) { | |||
print(state); | |||
if (state is HomeBannerLoadedState) { | |||
return ItemWidget(data: [1,2,3],); | |||
} | |||
if (state is HomeBannerCacheState) { | |||
return ItemWidget(data: [1,2],); | |||
} | |||
return HomeBannerSkeleton(widget.model); | |||
}, | |||
); | |||
} | |||
} | |||
class ItemWidget extends StatelessWidget { | |||
final List data; | |||
ItemWidget({this.data}); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
height: 180.h, | |||
margin: EdgeInsets.only(top: 7.5, left: 2.5, right: 2.5), | |||
child: Row( | |||
children:data.map((index){ | |||
return Flexible( | |||
flex: 1, | |||
child: Container( | |||
margin: EdgeInsets.only( left: 5, right: 5), | |||
decoration: BoxDecoration( | |||
color: Colors.lightBlue, | |||
borderRadius: BorderRadius.circular(7.5) | |||
), | |||
), | |||
); | |||
}).toList(), | |||
), | |||
); | |||
} | |||
} | |||
@@ -0,0 +1,4 @@ | |||
class HomeBannerModel{ | |||
} |
@@ -0,0 +1,3 @@ | |||
export 'home_quick_entry_bloc.dart'; | |||
export 'home_quick_entry_event.dart'; | |||
export 'home_quick_entry_state.dart'; |
@@ -0,0 +1,38 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_quick_entry/bloc/home_quick_entry_repository.dart'; | |||
import './bloc.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class HomeQuickEntryBloc extends Bloc<HomeQuickEntryEvent, HomeQuickEntryState> { | |||
HomeQuickEntryRepository repository; | |||
HomeQuickEntryBloc({@required this.repository}); | |||
@override | |||
HomeQuickEntryState get initialState => InitialHomeQuickEntryState(); | |||
@override | |||
Stream<HomeQuickEntryState> mapEventToState(HomeQuickEntryEvent event) async* { | |||
final currentState = state; | |||
if (event is HomeQuickEntryInitEvent) { | |||
yield* _mapHomeQuickEntryInitToState(event); | |||
} | |||
} | |||
/// 初始化 | |||
Stream<HomeQuickEntryState> _mapHomeQuickEntryInitToState(HomeQuickEntryInitEvent event) async* { | |||
/// 获取缓存数据 | |||
var cached = await repository.fetchCachedData(); | |||
if (!EmptyUtil.isEmpty(cached)) { | |||
yield HomeQuickEntryCachedState(); | |||
} | |||
var result = await repository.fetchData(); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
yield HomeQuickEntryLoadedState(); | |||
} else { | |||
yield HomeQuickEntryErrorState(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class HomeQuickEntryEvent extends Equatable { | |||
const HomeQuickEntryEvent(); | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 初始事件 | |||
class HomeQuickEntryInitEvent extends HomeQuickEntryEvent {} |
@@ -0,0 +1,24 @@ | |||
import 'package:zhiying_comm/util/net_util.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class HomeQuickEntryRepository { | |||
/// 获取数据 | |||
Future<dynamic> fetchData() async { | |||
var result = await NetUtil.post('/api/v1/mod', params: {'ids':[7]}); | |||
if(NetUtil.isSuccess(result)){ | |||
} | |||
return null; | |||
} | |||
/// 获取缓存数据 | |||
Future<dynamic> fetchCachedData() async{ | |||
var result = await NetUtil.getRequestCachedData('/api/v1/mod', params: {'ids':[7]}); | |||
if(!EmptyUtil.isEmpty(result)){ | |||
return result; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class HomeQuickEntryState extends Equatable { | |||
const HomeQuickEntryState(); | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 初始化状态 | |||
class InitialHomeQuickEntryState extends HomeQuickEntryState { | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 加载数据完毕 | |||
class HomeQuickEntryLoadedState extends HomeQuickEntryState {} | |||
/// 加载缓存数据 | |||
class HomeQuickEntryCachedState extends HomeQuickEntryState {} | |||
/// 加载数据出错 | |||
class HomeQuickEntryErrorState extends HomeQuickEntryState {} |
@@ -1,10 +1,12 @@ | |||
import 'package:flutter/src/widgets/framework.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_quick_entry/home_quick_entry.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_quick_entry/home_quick_entry_sk.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'home_quick_entry_sk.dart'; | |||
import 'home_quick_entry_widget.dart'; | |||
class HomeQuickEntryCreater extends WidgetCreater{ | |||
/// | |||
/// 快速入口 | |||
/// | |||
class HomeQuickEntryCreater extends WidgetCreater { | |||
@override | |||
List<Widget> createSkeleton(Map<String, dynamic> model) { | |||
return [HomeQuickEntrySkeleton()]; | |||
@@ -14,6 +16,4 @@ class HomeQuickEntryCreater extends WidgetCreater{ | |||
List<Widget> createWidgets(Map<String, dynamic> model) { | |||
return [HomeQuickEntryWidget()]; | |||
} | |||
} | |||
} |
@@ -26,19 +26,19 @@ class HomeQuickEntryWidget extends StatelessWidget { | |||
: (data.length ~/ (rowSize * columSize)) + 1; | |||
double containerHeight = 145.h * ( data.length >= rowSize * columSize ? rowSize : (data.length / columSize).ceil()) + (rowSize == 1 ? 0 : 25.h); | |||
double headHeight = 50.h ; | |||
// double headHeight = 50.h ; | |||
return Container( | |||
margin: EdgeInsets.only(bottom: 25.h), | |||
height: containerHeight + headHeight, | |||
height: containerHeight ,//+ headHeight, | |||
width: double.infinity, | |||
child: Column( | |||
children: <Widget>[ | |||
Container( | |||
margin: EdgeInsets.symmetric(horizontal: 25.w), | |||
height: headHeight, | |||
color: Colors.green, | |||
), | |||
// Container( | |||
// margin: EdgeInsets.symmetric(horizontal: 25.w), | |||
// height: headHeight, | |||
// color: Colors.green, | |||
// ), | |||
Expanded( | |||
child: Swiper( | |||
itemHeight: 145.h, | |||
@@ -168,22 +168,29 @@ class HomeQuickEntryItem extends StatelessWidget { | |||
HomeQuickEntryItem({this.data}); | |||
_itemOnClick(){ | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Column( | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
// 图片 | |||
MyNetWorkImage(), | |||
SizedBox(height: 10.h), | |||
Text( | |||
'京东爆款$data', | |||
style: | |||
TextStyle(color: HexColor.fromHex('#666666'), fontSize: 20.sp), | |||
), | |||
return GestureDetector( | |||
onTap: () => _itemOnClick(), | |||
child: Column( | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
// 图片 | |||
MyNetWorkImage(), | |||
SizedBox(height: 10.h), | |||
Text( | |||
'京东爆款$data', | |||
style: | |||
TextStyle(color: HexColor.fromHex('#666666'), fontSize: 20.sp), | |||
), | |||
// SizedBox(height: 25.h,) | |||
], | |||
], | |||
), | |||
); | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
class HomeQuickEntryModel{ | |||
} |
@@ -0,0 +1,3 @@ | |||
export 'home_slide_banner_bloc.dart'; | |||
export 'home_slide_banner_event.dart'; | |||
export 'home_slide_banner_state.dart'; |
@@ -0,0 +1,39 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_slide_banner/bloc/home_slide_banner_event.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_slide_banner/bloc/home_slide_banner_repository.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_slide_banner/bloc/home_slide_banner_state.dart'; | |||
import './bloc.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
class HomeSlideBannerBloc extends Bloc<HomeSlideBannerEvent, HomeSlideBannerState> { | |||
HomeSlideBannerRepository repository; | |||
HomeSlideBannerBloc({@required this.repository}); | |||
@override | |||
HomeSlideBannerState get initialState => InitialHomeSlideBannerState(); | |||
@override | |||
Stream<HomeSlideBannerState> mapEventToState(HomeSlideBannerEvent event) async* { | |||
final currentState = state; | |||
/// 初始化 | |||
if (event is HomeBannerInitEvent) { | |||
print('---------HomeBannerInitEvent---------'); | |||
yield* _mapInitEventToState(event); | |||
} | |||
} | |||
/// 初始化 | |||
Stream<HomeSlideBannerState> _mapInitEventToState(HomeBannerInitEvent event) async* { | |||
var cached = await repository.fetchCachedDate(id: event.model['mod_id']); | |||
if (!EmptyUtil.isEmpty(cached)) yield HomeSlideBannerCachedState(datas: cached); | |||
var param = await repository.fetchData( id: event.model['mod_id']); | |||
if (!EmptyUtil.isEmpty(param)) | |||
yield HomeSlideBannerLoadedState(datas: param); | |||
else | |||
yield HomeSlideBannerLoadError(); | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
import 'package:equatable/equatable.dart'; | |||
abstract class HomeSlideBannerEvent extends Equatable { | |||
const HomeSlideBannerEvent(); | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 初始事件 | |||
class HomeBannerInitEvent extends HomeSlideBannerEvent{ | |||
final Map<String, dynamic> model; | |||
const HomeBannerInitEvent({this.model}); | |||
} |
@@ -0,0 +1,34 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_slide_banner/model/home_slide_banner_model.dart'; | |||
import 'package:zhiying_comm/util/net_util.dart'; | |||
import 'package:zhiying_comm/util/empty_util.dart'; | |||
import 'package:zhiying_comm/util/global_config.dart'; | |||
class HomeSlideBannerRepository{ | |||
/// 获取缓存数据 | |||
Future<List<HomeSlideBannerModelItems>> fetchCachedDate({@required int id}) async{ | |||
var cached = await NetUtil.getRequestCachedData('/api/v1/mod', params: {'ids': [id]}); | |||
if(!EmptyUtil.isEmpty(cached)){ | |||
HomeSlideBannerModel model = HomeSlideBannerModel.fromJson(cached); | |||
if(null != model && !EmptyUtil.isEmpty(model.items)){ | |||
return model.items; | |||
} | |||
} | |||
return null; | |||
} | |||
/// 获取数据 | |||
Future<List<HomeSlideBannerModelItems>> fetchData({@required int id}) async{ | |||
var params = await NetUtil.post('/api/v1/mod', params: {'ids': [id]}); | |||
if(!EmptyUtil.isEmpty(params) && NetUtil.isSuccess(params)){ | |||
HomeSlideBannerModel model = HomeSlideBannerModel.fromJson(params[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); | |||
if(null != model && !EmptyUtil.isEmpty(model.items)){ | |||
return model.items; | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
import 'package:equatable/equatable.dart'; | |||
import 'package:zhiying_base_widget/widgets/home_slide_banner/model/home_slide_banner_model.dart'; | |||
abstract class HomeSlideBannerState extends Equatable { | |||
const HomeSlideBannerState(); | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 初始化状态 | |||
class InitialHomeSlideBannerState extends HomeSlideBannerState { | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 缓存数据 | |||
class HomeSlideBannerCachedState extends HomeSlideBannerState { | |||
List<HomeSlideBannerModelItems> datas; | |||
HomeSlideBannerCachedState({this.datas}); | |||
@override | |||
List<Object> get props => [this.datas]; | |||
} | |||
/// 数据加载完毕状态 | |||
class HomeSlideBannerLoadedState extends HomeSlideBannerState { | |||
List<HomeSlideBannerModelItems> datas; | |||
HomeSlideBannerLoadedState({this.datas}); | |||
HomeSlideBannerLoadedState copyWith({List<HomeSlideBannerModelItems> newData}) { | |||
return HomeSlideBannerLoadedState( | |||
datas: newData ?? datas, | |||
); | |||
} | |||
@override | |||
List<Object> get props => [datas]; | |||
} | |||
/// 数据加载失败 | |||
class HomeSlideBannerLoadError extends HomeSlideBannerState {} |
@@ -0,0 +1,127 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
import 'package:flutter_swiper/flutter_swiper.dart'; | |||
import 'bloc/bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'bloc/home_slide_banner_repository.dart'; | |||
import 'home_slide_banner_sk.dart'; | |||
import 'model/home_slide_banner_model.dart'; | |||
/// | |||
/// banner轮播图 | |||
/// | |||
class HomeSlideBanner extends StatefulWidget { | |||
final Map<String, dynamic> model; | |||
const HomeSlideBanner(this.model, {Key key}) : super(key: key); | |||
@override | |||
_HomeSlideBannerState createState() => _HomeSlideBannerState(); | |||
} | |||
class _HomeSlideBannerState extends State<HomeSlideBanner> { | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocProvider<HomeSlideBannerBloc>( | |||
create: (_) => HomeSlideBannerBloc(repository: HomeSlideBannerRepository())..add(HomeBannerInitEvent(model: widget?.model)), | |||
child: HomeSlideBannerContainer(), | |||
); | |||
} | |||
} | |||
class HomeSlideBannerContainer extends StatefulWidget { | |||
@override | |||
_HomeSlideBannerContainerState createState() => _HomeSlideBannerContainerState(); | |||
} | |||
class _HomeSlideBannerContainerState extends State<HomeSlideBannerContainer> { | |||
/// 子元素点击事件 | |||
void _itemOnClick(HomeSlideBannerModelItems items) { | |||
print('点击了 $items'); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocConsumer<HomeSlideBannerBloc, HomeSlideBannerState>( | |||
listener: (BuildContext context, HomeSlideBannerState state) { | |||
if (state is HomeSlideBannerLoadError) { | |||
print('数据加载出错'); | |||
} | |||
}, | |||
buildWhen: (previous, current) { | |||
/// 数据加载出错不进行build | |||
if (current is HomeSlideBannerLoadError) { | |||
return false; | |||
} | |||
return true; | |||
}, | |||
builder: (context, state) { | |||
print('currente state = $state'); | |||
if (state is HomeSlideBannerLoadedState) { | |||
return _getMainWidget(state.datas); | |||
} | |||
if (state is HomeSlideBannerCachedState) { | |||
return _getMainWidget(state.datas); | |||
} | |||
// 骨架屏 | |||
return HomeSlideBannerSkeleton(); | |||
}, | |||
); | |||
} | |||
Widget _getMainWidget(List<HomeSlideBannerModelItems> datas) { | |||
return Container( | |||
width: double.infinity, | |||
height: 400.h, | |||
child: Swiper( | |||
itemBuilder: (BuildContext context, int index) { | |||
return Container( | |||
color: Colors.green, | |||
); | |||
}, | |||
itemCount: datas?.length ?? 0, | |||
onTap: (index) => _itemOnClick(datas[index]), | |||
pagination: _SwiperCustomPagination(datas?.length ?? 0), | |||
), | |||
); | |||
} | |||
// 自定义进度条 | |||
SwiperPlugin _SwiperCustomPagination(int pageCount) { | |||
List list = []; | |||
for (int i = 0; i < pageCount; i++) { | |||
list.add(i); | |||
} | |||
return SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) { | |||
return Align( | |||
alignment: Alignment(0.0, 0.9), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: list.map((index) { | |||
var borderRadius; | |||
if (index == 0) { | |||
borderRadius = BorderRadius.only(topLeft: Radius.circular(2), bottomLeft: Radius.circular(2)); | |||
} | |||
if (index == list.length - 1) { | |||
borderRadius = BorderRadius.only(topRight: Radius.circular(2), bottomRight: Radius.circular(2)); | |||
} | |||
if (index == config.activeIndex) { | |||
borderRadius = BorderRadius.all(Radius.circular(2)); | |||
} | |||
return Container( | |||
height: 4, | |||
width: 25, | |||
decoration: BoxDecoration( | |||
borderRadius: borderRadius, color: index == config.activeIndex ? HexColor.fromHex('#FF4242') : HexColor.fromHex('#FFFFFF')), | |||
); | |||
}).toList(), | |||
), | |||
); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'home_slide_banner.dart'; | |||
import 'home_slide_banner_sk.dart'; | |||
/// | |||
/// 可以滚动Banner | |||
/// | |||
class HomeSlideBannerCreater extends WidgetCreater { | |||
@override | |||
List<Widget> createSkeleton(Map<String, dynamic> model) { | |||
return [HomeSlideBannerSkeleton()]; | |||
} | |||
@override | |||
List<Widget> createWidgets(Map<String, dynamic> model) { | |||
return [HomeSlideBanner(model)]; | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:shimmer/shimmer.dart'; | |||
class HomeSlideBannerSkeleton extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
width: double.infinity, | |||
height: 200, | |||
color: Colors.white, | |||
child: Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Container( | |||
margin: EdgeInsets.all(10), | |||
decoration: BoxDecoration( | |||
color: Colors.white, | |||
borderRadius: BorderRadius.all(Radius.circular(10))), | |||
), | |||
), | |||
); | |||
} | |||
} |
@@ -0,0 +1,115 @@ | |||
class HomeSlideBannerModel { | |||
List<HomeSlideBannerModelItems> items; | |||
HomeSlideBannerModel({this.items}); | |||
HomeSlideBannerModel.fromJson(Map<String, dynamic> json) { | |||
if (json['6'] != null) { | |||
items = new List<HomeSlideBannerModelItems>(); | |||
json['6'].forEach((v) { | |||
items.add(new HomeSlideBannerModelItems.fromJson(v)); | |||
}); | |||
} | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
if (this.items != null) { | |||
data['6'] = this.items.map((v) => v.toJson()).toList(); | |||
} | |||
return data; | |||
} | |||
} | |||
class HomeSlideBannerModelItems { | |||
String modId; | |||
String modPid; | |||
String modName; | |||
String position; | |||
String title; | |||
String subtitle; | |||
String url; | |||
String margin; | |||
String aspectRatio; | |||
String icon; | |||
String img; | |||
String fontColor; | |||
String bgImg; | |||
String bgColor; | |||
String bgColorT; | |||
String badge; | |||
String path; | |||
String data; | |||
String sort; | |||
String isGlobal; | |||
HomeSlideBannerModelItems( | |||
{this.modId, | |||
this.modPid, | |||
this.modName, | |||
this.position, | |||
this.title, | |||
this.subtitle, | |||
this.url, | |||
this.margin, | |||
this.aspectRatio, | |||
this.icon, | |||
this.img, | |||
this.fontColor, | |||
this.bgImg, | |||
this.bgColor, | |||
this.bgColorT, | |||
this.badge, | |||
this.path, | |||
this.data, | |||
this.sort, | |||
this.isGlobal}); | |||
HomeSlideBannerModelItems.fromJson(Map<String, dynamic> json) { | |||
modId = json['mod_id']?.toString(); | |||
modPid = json['mod_pid']?.toString(); | |||
modName = json['mod_name']?.toString(); | |||
position = json['position']?.toString(); | |||
title = json['title']?.toString(); | |||
subtitle = json['subtitle']?.toString(); | |||
url = json['url']?.toString(); | |||
margin = json['margin']?.toString(); | |||
aspectRatio = json['aspect_ratio']?.toString(); | |||
icon = json['icon']?.toString(); | |||
img = json['img']?.toString(); | |||
fontColor = json['font_color']?.toString(); | |||
bgImg = json['bg_img']?.toString(); | |||
bgColor = json['bg_color']?.toString(); | |||
bgColorT = json['bg_color_t']?.toString(); | |||
badge = json['badge']?.toString(); | |||
path = json['path']?.toString(); | |||
data = json['data']?.toString(); | |||
sort = json['sort']?.toString(); | |||
isGlobal = json['is_global']?.toString(); | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['mod_id'] = this.modId; | |||
data['mod_pid'] = this.modPid; | |||
data['mod_name'] = this.modName; | |||
data['position'] = this.position; | |||
data['title'] = this.title; | |||
data['subtitle'] = this.subtitle; | |||
data['url'] = this.url; | |||
data['margin'] = this.margin; | |||
data['aspect_ratio'] = this.aspectRatio; | |||
data['icon'] = this.icon; | |||
data['img'] = this.img; | |||
data['font_color'] = this.fontColor; | |||
data['bg_img'] = this.bgImg; | |||
data['bg_color'] = this.bgColor; | |||
data['bg_color_t'] = this.bgColorT; | |||
data['badge'] = this.badge; | |||
data['path'] = this.path; | |||
data['data'] = this.data; | |||
data['sort'] = this.sort; | |||
data['is_global'] = this.isGlobal; | |||
return data; | |||
} | |||
} |