@@ -1,22 +0,0 @@ | |||||
import 'package:flutter/material.dart'; | |||||
class FavoritePage extends StatefulWidget { | |||||
@override | |||||
_FavoritePageState createState() => _FavoritePageState(); | |||||
} | |||||
class _FavoritePageState extends State<FavoritePage> { | |||||
GlobalKey _globalKey = GlobalKey(); | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return Scaffold( | |||||
appBar: AppBar( | |||||
title: Text('收藏夹'), | |||||
), | |||||
body: Column( | |||||
children: <Widget>[], | |||||
), | |||||
); | |||||
} | |||||
} |
@@ -1,17 +0,0 @@ | |||||
import 'package:flutter/material.dart'; | |||||
class PreviewPage extends StatelessWidget { | |||||
final Image image; | |||||
const PreviewPage({Key key, this.image}) : super(key: key); | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return Scaffold( | |||||
appBar: AppBar(), | |||||
body: Center( | |||||
child: image, | |||||
), | |||||
); | |||||
} | |||||
} |
@@ -0,0 +1,49 @@ | |||||
import 'dart:async'; | |||||
import 'package:bloc/bloc.dart'; | |||||
import 'package:equatable/equatable.dart'; | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:meta/meta.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/bloc/favorites_repository.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/model/favorites_style_model.dart'; | |||||
import 'package:zhiying_comm/util/empty_util.dart'; | |||||
part 'favorites_event.dart'; | |||||
part 'favorites_state.dart'; | |||||
class FavoritesBloc extends Bloc<FavoritesEvent, FavoritesState> { | |||||
// FavoritesBloc() : super(FavoritesInitial()); | |||||
FavoritesRepository repository; | |||||
FavoritesBloc(this.repository); | |||||
@override | |||||
// TODO: implement initialState | |||||
FavoritesState get initialState => FavoritesInitial(); | |||||
@override | |||||
Stream<FavoritesState> mapEventToState( | |||||
FavoritesEvent event, | |||||
) async* { | |||||
/// 初始化 | |||||
if (event is FavoritesInitEvent) { | |||||
yield* _mapInitEventToState(event); | |||||
} | |||||
} | |||||
/// 初始化 | |||||
Stream<FavoritesState> _mapInitEventToState(FavoritesInitEvent event) async* { | |||||
var cache = await repository.fetchCachedStyle(); | |||||
if (!EmptyUtil.isEmpty(cache)) { | |||||
yield FavoritesLoadedState(model: cache); | |||||
} | |||||
var result = await repository.fetchNetStyle(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesLoadedState(model: result); | |||||
} else { | |||||
yield FavoritesErrorState(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,7 @@ | |||||
part of 'favorites_bloc.dart'; | |||||
@immutable | |||||
abstract class FavoritesEvent {} | |||||
/// 初始化数据 | |||||
class FavoritesInitEvent extends FavoritesEvent {} |
@@ -0,0 +1,39 @@ | |||||
import 'dart:convert'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/model/favorites_style_model.dart'; | |||||
import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
class FavoritesRepository { | |||||
/// 请求网络样式 | |||||
Future<FavoritesStyleModel> fetchNetStyle() async { | |||||
try { | |||||
var result = await NetUtil.post('/api/v1/mod/pub.flutter.my_fav', cache: true, method: NetMethod.GET); | |||||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||||
var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | |||||
if(!EmptyUtil.isEmpty(modListData)){ | |||||
return FavoritesStyleModel.fromJson(jsonDecode(modListData)); | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.log(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 获取缓存样式 | |||||
Future<FavoritesStyleModel> fetchCachedStyle() async { | |||||
try { | |||||
var result = await NetUtil.getRequestCachedData(''); | |||||
if(!EmptyUtil.isEmpty(result)){ | |||||
var modListData = result['mod_list'][0]['data']; | |||||
if(!EmptyUtil.isEmpty(modListData)){ | |||||
return FavoritesStyleModel.fromJson(jsonDecode(modListData)); | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.log(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
part of 'favorites_bloc.dart'; | |||||
@immutable | |||||
abstract class FavoritesState extends Equatable { | |||||
@override | |||||
List<Object> get props => []; | |||||
} | |||||
/// 初始化状态(骨架图) | |||||
class FavoritesInitial extends FavoritesState {} | |||||
/// 数据加载成功 | |||||
class FavoritesLoadedState extends FavoritesState { | |||||
FavoritesStyleModel model; | |||||
FavoritesLoadedState({@required this.model}); | |||||
@override | |||||
List<Object> get props => [this.model]; | |||||
} | |||||
/// 未知错误 | |||||
class FavoritesErrorState extends FavoritesState {} |
@@ -0,0 +1,264 @@ | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:tab_indicator_styler/tab_indicator_styler.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/bloc/favorites_bloc.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/bloc/favorites_repository.dart'; | |||||
import 'package:zhiying_base_widget/widgets/favorites/goods_list/favorites_goods_list_widget.dart'; | |||||
import 'package:zhiying_comm/util/empty_util.dart'; | |||||
import 'package:zhiying_comm/util/extension/color.dart'; | |||||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
import 'package:provider/provider.dart'; | |||||
import 'package:zhiying_comm/util/log/let_log.dart'; | |||||
import 'package:fluttertoast/fluttertoast.dart'; | |||||
import 'package:zhiying_comm/util/router_util.dart'; | |||||
import 'model/favorites_style_model.dart'; | |||||
import 'notifier/favorites_page_notifier.dart'; | |||||
class FavoritesPage extends StatelessWidget { | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return MultiProvider( | |||||
providers: [ | |||||
ChangeNotifierProvider.value(value: FavoritesPageNotifier()), | |||||
], | |||||
child: BlocProvider<FavoritesBloc>( | |||||
create: (_) => FavoritesBloc(FavoritesRepository())..add(FavoritesInitEvent()), | |||||
child: _FavoritesPageContainer(), | |||||
), | |||||
); | |||||
} | |||||
} | |||||
class _FavoritesPageContainer extends StatefulWidget { | |||||
@override | |||||
_FavoritesPageContainerState createState() => _FavoritesPageContainerState(); | |||||
} | |||||
class _FavoritesPageContainerState extends State<_FavoritesPageContainer> with TickerProviderStateMixin { | |||||
TextEditingController _editingController; | |||||
FocusNode _focusNode; | |||||
TabController _tabController; | |||||
bool _isNotEditing = true; | |||||
/// 点击编辑 | |||||
void _onClickEditing() { | |||||
RouterUtil.hideKeyboard(context); | |||||
setState(() { | |||||
_isNotEditing = !_isNotEditing; | |||||
}); | |||||
Provider.of<FavoritesPageNotifier>(context, listen: false).editing(); | |||||
} | |||||
/// 点击搜索 | |||||
void _onClickSearch() {} | |||||
/// 执行搜索 | |||||
void _submitSearch() { | |||||
String keyword = _editingController?.text?.toString()?.trim(); | |||||
// if (!EmptyUtil.isEmpty(keyword)) { | |||||
_tabController.index = 0; | |||||
Provider.of<FavoritesPageNotifier>(context, listen: false).search(keyword); | |||||
// } else { | |||||
// Fluttertoast.showToast(msg: '请输入需要搜索的内容~'); | |||||
// } | |||||
} | |||||
/// tabBar的初始化 | |||||
void _tabControllerInit(FavoritesStyleModel model) { | |||||
if ((null == _tabController && !EmptyUtil.isEmpty(model?.tabList)) || | |||||
(!EmptyUtil.isEmpty(model?.tabList) && null != _tabController && _tabController.length != model.tabList.length)) { | |||||
_tabController = TabController(length: model.tabList.length, vsync: this) | |||||
..addListener(() { | |||||
if (!_tabController.indexIsChanging) { | |||||
RouterUtil.hideKeyboard(context); | |||||
Logger.log('tab index = ${_tabController.index}'); | |||||
Provider.of<FavoritesPageNotifier>(context, listen: false).changeSelectIndex(_tabController.index); | |||||
} | |||||
}); | |||||
} | |||||
} | |||||
@override | |||||
void initState() { | |||||
_editingController = TextEditingController(); | |||||
_focusNode = FocusNode(); | |||||
super.initState(); | |||||
} | |||||
@override | |||||
void dispose() { | |||||
_focusNode?.unfocus(); | |||||
_focusNode?.dispose(); | |||||
_editingController?.dispose(); | |||||
super.dispose(); | |||||
} | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return BlocConsumer<FavoritesBloc, FavoritesState>( | |||||
listener: (context, state) {}, | |||||
buildWhen: (prev, current) { | |||||
return true; | |||||
}, | |||||
builder: (context, state) { | |||||
if (state is FavoritesLoadedState) { | |||||
_tabControllerInit(state?.model); | |||||
return _buildMainWidget(state?.model); | |||||
} | |||||
return _buildSkeletonWidget(); | |||||
}, | |||||
); | |||||
} | |||||
/// mainWidget | |||||
Widget _buildMainWidget(FavoritesStyleModel model) { | |||||
return Scaffold( | |||||
resizeToAvoidBottomInset: false, | |||||
resizeToAvoidBottomPadding: false, | |||||
backgroundColor: HexColor.fromHex('#FFFFFF'), | |||||
appBar: _buildAppBarWidget(model), | |||||
body: Column( | |||||
children: <Widget>[ | |||||
/// 搜索框 | |||||
Padding(padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 4), child: _buildSearchWidget(model)), | |||||
/// tabBar | |||||
Padding(padding: const EdgeInsets.only(top: 4), child: _buildTabBarWidget(model)), | |||||
Expanded( | |||||
child: _buildTabBarViewWidget(model), | |||||
), | |||||
], | |||||
), | |||||
); | |||||
} | |||||
/// TabBar | |||||
Widget _buildTabBarWidget(FavoritesStyleModel model) { | |||||
return Container( | |||||
padding: const EdgeInsets.only(top: 12.5, bottom: 14.5), | |||||
width: double.infinity, | |||||
child: TabBar( | |||||
isScrollable: true, | |||||
labelStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), | |||||
unselectedLabelStyle: TextStyle(fontWeight: FontWeight.w400, fontSize: 14), | |||||
labelColor: HexColor.fromHex(model?.tabNameSelectedColor ?? '#FF0100'), | |||||
unselectedLabelColor: HexColor.fromHex(model?.tabNameColor ?? '#333333'), | |||||
indicatorSize: TabBarIndicatorSize.label, | |||||
controller: _tabController, | |||||
indicatorWeight: 5, | |||||
indicator: MaterialIndicator( | |||||
topLeftRadius: 1, | |||||
topRightRadius: 1, | |||||
bottomLeftRadius: 1, | |||||
bottomRightRadius: 1, | |||||
height: 2, | |||||
color: HexColor.fromHex(model?.tabLineColor ?? '#FF0100'), | |||||
horizontalPadding: 5, | |||||
), | |||||
tabs: model.tabList.map((e) => Text(e?.name ?? '')).toList(), | |||||
), | |||||
); | |||||
} | |||||
/// tabBarView | |||||
Widget _buildTabBarViewWidget(FavoritesStyleModel model) { | |||||
int length = model?.tabList?.length ?? 0; | |||||
if (length > 0) { | |||||
int index = -1; | |||||
return TabBarView( | |||||
controller: _tabController, | |||||
children: model.tabList.map((e) { | |||||
++index; | |||||
return FavoritesGoodsListWidget( | |||||
model: model, | |||||
type: e?.type, | |||||
currentIndex: index, | |||||
); | |||||
}).toList(), | |||||
); | |||||
} | |||||
return Container(color: HexColor.fromHex('#F9F9F9')); | |||||
} | |||||
/// 搜索框 | |||||
Widget _buildSearchWidget(FavoritesStyleModel model) { | |||||
return Container( | |||||
alignment: Alignment.center, | |||||
width: double.infinity, | |||||
height: 35, | |||||
decoration: BoxDecoration( | |||||
borderRadius: BorderRadius.circular(35 / 2), | |||||
color: HexColor.fromHex(model?.searchBarBgColor ?? '#F9F9F9'), | |||||
), | |||||
child: TextField( | |||||
controller: _editingController, | |||||
focusNode: _focusNode, | |||||
onSubmitted: (text) => _submitSearch(), | |||||
textInputAction: TextInputAction.search, | |||||
style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 14, textBaseline: TextBaseline.alphabetic), | |||||
textAlign: TextAlign.center, | |||||
decoration: InputDecoration( | |||||
fillColor: Colors.transparent, | |||||
filled: true, | |||||
isDense: true, | |||||
contentPadding: EdgeInsets.zero, | |||||
hintText: model?.searchBarText ?? '搜索商品', | |||||
hintStyle: TextStyle(color: HexColor.fromHex(model?.searchBarTextColor ?? '#999999'), fontSize: 14, textBaseline: TextBaseline.alphabetic), | |||||
border: InputBorder.none, | |||||
enabledBorder: InputBorder.none, | |||||
disabledBorder: InputBorder.none, | |||||
errorBorder: InputBorder.none, | |||||
focusedErrorBorder: InputBorder.none, | |||||
focusedBorder: InputBorder.none, | |||||
), | |||||
), | |||||
); | |||||
} | |||||
/// appbar | |||||
Widget _buildAppBarWidget(FavoritesStyleModel model) { | |||||
return AppBar( | |||||
backgroundColor: HexColor.fromHex(model?.appBarBgColor ?? '#FFFFFF'), | |||||
leading: IconButton( | |||||
icon: Icon( | |||||
Icons.arrow_back_ios, | |||||
size: 22, | |||||
color: HexColor.fromHex('#333333'), | |||||
), | |||||
onPressed: () => Navigator.maybePop(context), | |||||
), | |||||
title: Text( | |||||
model?.appBarName ?? '我的收藏', | |||||
style: TextStyle(color: HexColor.fromHex(model?.appBarNameColor ?? '#333333'), fontSize: 15, fontWeight: FontWeight.bold), | |||||
), | |||||
centerTitle: true, | |||||
elevation: 0, | |||||
actions: <Widget>[ | |||||
GestureDetector( | |||||
onTap: () => _onClickEditing(), | |||||
behavior: HitTestBehavior.opaque, | |||||
child: Center( | |||||
child: Padding( | |||||
padding: const EdgeInsets.only(right: 12.5), | |||||
child: Text( | |||||
_isNotEditing ? model?.appBarRightText ?? '编辑' : model?.appBarRightEditingText ?? '完成', | |||||
style: TextStyle( | |||||
color: HexColor.fromHex(_isNotEditing ? model?.appBarRightTextColor ?? '#333333' : model?.appBarRightEditingColor ?? '#FF4242'), | |||||
fontSize: 14, | |||||
fontWeight: FontWeight.bold), | |||||
), | |||||
), | |||||
), | |||||
) | |||||
], | |||||
); | |||||
} | |||||
/// 骨架图 | |||||
Widget _buildSkeletonWidget() { | |||||
return Scaffold( | |||||
body: Container(), | |||||
); | |||||
} | |||||
} |
@@ -0,0 +1,278 @@ | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_list_style_model.dart'; | |||||
class FavoritesStyleModel { | |||||
String appBarName; | |||||
String appBarNameColor; | |||||
String appBarBgImg; | |||||
String appBarBgColor; | |||||
String appBarRightText; | |||||
String appBarRightTextColor; | |||||
String appBarRightEditingText; | |||||
String appBarRightEditingColor; | |||||
String searchBarIcon; | |||||
String searchBarText; | |||||
String searchBarTextColor; | |||||
String searchBarBgColor; | |||||
String tabLineColor; | |||||
String tabItemNotFoundImg; | |||||
List<TabList> tabList; | |||||
HomeGoodsListStyleModel listStyle; | |||||
String editLeftConfirmColor; | |||||
String editLeftNoConfirmColor; | |||||
Bottom bottom; | |||||
ConfirmDialog confirmDialog; | |||||
String tabNameColor; | |||||
String tabNameSelectedColor; | |||||
String editLeftConfirmIcon; | |||||
String editLeftNoConfirmIcon; | |||||
FavoritesStyleModel({ | |||||
this.appBarName, | |||||
this.appBarNameColor, | |||||
this.appBarBgImg, | |||||
this.appBarBgColor, | |||||
this.appBarRightText, | |||||
this.appBarRightTextColor, | |||||
this.appBarRightEditingText, | |||||
this.appBarRightEditingColor, | |||||
this.searchBarIcon, | |||||
this.searchBarText, | |||||
this.searchBarTextColor, | |||||
this.searchBarBgColor, | |||||
this.tabLineColor, | |||||
this.tabItemNotFoundImg, | |||||
this.tabList, | |||||
this.listStyle, | |||||
this.editLeftConfirmColor, | |||||
this.editLeftNoConfirmColor, | |||||
this.bottom, | |||||
this.confirmDialog, | |||||
this.tabNameColor, | |||||
this.tabNameSelectedColor, | |||||
this.editLeftConfirmIcon, | |||||
this.editLeftNoConfirmIcon, | |||||
}); | |||||
FavoritesStyleModel.fromJson(Map<String, dynamic> json) { | |||||
appBarName = json['app_bar_name']; | |||||
appBarNameColor = json['app_bar_name_color']; | |||||
appBarBgImg = json['app_bar_bg_img']; | |||||
appBarBgColor = json['app_bar_bg_color']; | |||||
appBarRightText = json['app_bar_right_text']; | |||||
appBarRightTextColor = json['app_bar_right_text_color']; | |||||
appBarRightEditingText = json['app_bar_right_editing_text']; | |||||
appBarRightEditingColor = json['app_bar_right_editing_color']; | |||||
searchBarIcon = json['search_bar_icon']; | |||||
searchBarText = json['search_bar_text']; | |||||
searchBarTextColor = json['search_bar_text_color']; | |||||
searchBarBgColor = json['search_bar_bg_color']; | |||||
tabLineColor = json['tab_line_color']; | |||||
tabItemNotFoundImg = json['tab_item_not_found_img']; | |||||
if (json['tab_list'] != null) { | |||||
tabList = new List<TabList>(); | |||||
json['tab_list'].forEach((v) { | |||||
tabList.add(new TabList.fromJson(v)); | |||||
}); | |||||
} | |||||
listStyle = json['list_style'] != null ? new HomeGoodsListStyleModel.fromJson(json['list_style']) : null; | |||||
editLeftConfirmColor = json['edit_left_confirm_color']; | |||||
editLeftNoConfirmColor = json['edit_left_no_confirm_color']; | |||||
bottom = json['bottom'] != null ? new Bottom.fromJson(json['bottom']) : null; | |||||
confirmDialog = json['confirm_dialog'] != null ? new ConfirmDialog.fromJson(json['confirm_dialog']) : null; | |||||
tabNameColor = json['tab_name_color']; | |||||
tabNameSelectedColor = json['tab_name_selected_color']; | |||||
editLeftConfirmIcon = json['edit_left_confirm_icon']; | |||||
editLeftNoConfirmIcon = json['edit_left_no_confirm_icon']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['app_bar_name'] = this.appBarName; | |||||
data['app_bar_name_color'] = this.appBarNameColor; | |||||
data['app_bar_bg_img'] = this.appBarBgImg; | |||||
data['app_bar_bg_color'] = this.appBarBgColor; | |||||
data['app_bar_right_text'] = this.appBarRightText; | |||||
data['app_bar_right_text_color'] = this.appBarRightTextColor; | |||||
data['app_bar_right_editing_text'] = this.appBarRightEditingText; | |||||
data['app_bar_right_editing_color'] = this.appBarRightEditingColor; | |||||
data['search_bar_icon'] = this.searchBarIcon; | |||||
data['search_bar_text'] = this.searchBarText; | |||||
data['search_bar_text_color'] = this.searchBarTextColor; | |||||
data['search_bar_bg_color'] = this.searchBarBgColor; | |||||
data['tab_line_color'] = this.tabLineColor; | |||||
data['tab_item_not_found_img'] = this.tabItemNotFoundImg; | |||||
if (this.tabList != null) { | |||||
data['tab_list'] = this.tabList.map((v) => v.toJson()).toList(); | |||||
} | |||||
if (this.listStyle != null) { | |||||
data['list_style'] = this.listStyle.toJson(); | |||||
} | |||||
data['edit_left_confirm_color'] = this.editLeftConfirmColor; | |||||
data['edit_left_no_confirm_color'] = this.editLeftNoConfirmColor; | |||||
if (this.bottom != null) { | |||||
data['bottom'] = this.bottom.toJson(); | |||||
} | |||||
if (this.confirmDialog != null) { | |||||
data['confirm_dialog'] = this.confirmDialog.toJson(); | |||||
} | |||||
data['tab_name_color'] = this.tabNameColor; | |||||
data['tab_name_selected_color'] = this.tabNameSelectedColor; | |||||
data['edit_left_confirm_icon'] = this.editLeftConfirmIcon; | |||||
data['edit_left_no_confirm_icon'] = this.editLeftNoConfirmIcon; | |||||
return data; | |||||
} | |||||
} | |||||
class TabList { | |||||
String type; | |||||
String name; | |||||
String nameColor; | |||||
String nameSelectedColor; | |||||
TabList({this.type, this.name, this.nameColor, this.nameSelectedColor}); | |||||
TabList.fromJson(Map<String, dynamic> json) { | |||||
type = json['type']; | |||||
name = json['name']; | |||||
nameColor = json['name_color']; | |||||
nameSelectedColor = json['name_selected_color']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['type'] = this.type; | |||||
data['name'] = this.name; | |||||
data['name_color'] = this.nameColor; | |||||
data['name_selected_color'] = this.nameSelectedColor; | |||||
return data; | |||||
} | |||||
} | |||||
class Left { | |||||
String couonText; | |||||
String couponFontColor; | |||||
String couponBgColor; | |||||
String couponBgImg; | |||||
String isImg; | |||||
Left({this.couonText, this.couponFontColor, this.couponBgColor, this.couponBgImg, this.isImg}); | |||||
Left.fromJson(Map<String, dynamic> json) { | |||||
couonText = json['couon_text']; | |||||
couponFontColor = json['coupon_font_color']; | |||||
couponBgColor = json['coupon_bg_color']; | |||||
couponBgImg = json['coupon_bg_img']; | |||||
isImg = json['is_img']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['couon_text'] = this.couonText; | |||||
data['coupon_font_color'] = this.couponFontColor; | |||||
data['coupon_bg_color'] = this.couponBgColor; | |||||
data['coupon_bg_img'] = this.couponBgImg; | |||||
data['is_img'] = this.isImg; | |||||
return data; | |||||
} | |||||
} | |||||
class Right { | |||||
String commissionText; | |||||
String commissionFontColor; | |||||
String commissionBgColor; | |||||
String commissionBgImg; | |||||
String isImg; | |||||
Right({this.commissionText, this.commissionFontColor, this.commissionBgColor, this.commissionBgImg, this.isImg}); | |||||
Right.fromJson(Map<String, dynamic> json) { | |||||
commissionText = json['commission_text']; | |||||
commissionFontColor = json['commission_font_color']; | |||||
commissionBgColor = json['commission_bg_color']; | |||||
commissionBgImg = json['commission_bg_img']; | |||||
isImg = json['is_img']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['commission_text'] = this.commissionText; | |||||
data['commission_font_color'] = this.commissionFontColor; | |||||
data['commission_bg_color'] = this.commissionBgColor; | |||||
data['commission_bg_img'] = this.commissionBgImg; | |||||
data['is_img'] = this.isImg; | |||||
return data; | |||||
} | |||||
} | |||||
class Bottom { | |||||
String bgColor; | |||||
String leftText; | |||||
String leftColor; | |||||
String rightText; | |||||
String rightColor; | |||||
Bottom({this.bgColor, this.leftText, this.leftColor, this.rightText, this.rightColor}); | |||||
Bottom.fromJson(Map<String, dynamic> json) { | |||||
bgColor = json['bg_color']; | |||||
leftText = json['left_text']; | |||||
leftColor = json['left_color']; | |||||
rightText = json['right_text']; | |||||
rightColor = json['right_color']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['bg_color'] = this.bgColor; | |||||
data['left_text'] = this.leftText; | |||||
data['left_color'] = this.leftColor; | |||||
data['right_text'] = this.rightText; | |||||
data['right_color'] = this.rightColor; | |||||
return data; | |||||
} | |||||
} | |||||
class ConfirmDialog { | |||||
String bgText; | |||||
String bgTextColor; | |||||
String bgColor; | |||||
String leftText; | |||||
String leftTextColor; | |||||
String leftBtnBgColor; | |||||
String rightText; | |||||
String rightTextColor; | |||||
String rightBtnBgColor; | |||||
ConfirmDialog({this.bgText, this.bgTextColor, this.bgColor, this.leftText, this.leftTextColor, this.leftBtnBgColor, this.rightText, this.rightTextColor, this.rightBtnBgColor}); | |||||
ConfirmDialog.fromJson(Map<String, dynamic> json) { | |||||
bgText = json['bg_text']; | |||||
bgTextColor = json['bg_text_color']; | |||||
bgColor = json['bg_color']; | |||||
leftText = json['left_text']; | |||||
leftTextColor = json['left_text_color']; | |||||
leftBtnBgColor = json['left_btn_bg_color']; | |||||
rightText = json['right_text']; | |||||
rightTextColor = json['right_text_color']; | |||||
rightBtnBgColor = json['right_btn_bg_color']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['bg_text'] = this.bgText; | |||||
data['bg_text_color'] = this.bgTextColor; | |||||
data['bg_color'] = this.bgColor; | |||||
data['left_text'] = this.leftText; | |||||
data['left_text_color'] = this.leftTextColor; | |||||
data['left_btn_bg_color'] = this.leftBtnBgColor; | |||||
data['right_text'] = this.rightText; | |||||
data['right_text_color'] = this.rightTextColor; | |||||
data['right_btn_bg_color'] = this.rightBtnBgColor; | |||||
return data; | |||||
} | |||||
} |
@@ -0,0 +1,44 @@ | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:zhiying_comm/util/empty_util.dart'; | |||||
class FavoritesPageNotifier with ChangeNotifier { | |||||
/// 是否是编辑中 | |||||
bool isEditing = false; | |||||
/// 搜索关键字 | |||||
String keyword; | |||||
int selectIndex = 0; | |||||
/// 用于区分是编辑还是搜索 | |||||
bool editingTypeTag = true; | |||||
/// 用于区分是否修改 | |||||
// int changeVal = 0; | |||||
/// 选中的下标 | |||||
void changeSelectIndex(int index){ | |||||
this.selectIndex = index; | |||||
// ++changeVal; | |||||
notifyListeners(); | |||||
} | |||||
/// 编辑 | |||||
void editing() { | |||||
this.editingTypeTag = true; | |||||
this.isEditing = !isEditing; | |||||
// ++changeVal; | |||||
notifyListeners(); | |||||
} | |||||
/// 搜索 | |||||
void search(String keyword) { | |||||
// if (!EmptyUtil.isEmpty(keyword)) { | |||||
this.editingTypeTag = false; | |||||
this.keyword = keyword; | |||||
// ++changeVal; | |||||
notifyListeners(); | |||||
// } | |||||
} | |||||
} |
@@ -1,6 +1,6 @@ | |||||
import 'package:sharesdk_plugin/sharesdk_interface.dart'; | import 'package:sharesdk_plugin/sharesdk_interface.dart'; | ||||
import 'package:sharesdk_plugin/sharesdk_register.dart'; | import 'package:sharesdk_plugin/sharesdk_register.dart'; | ||||
import 'package:zhiying_base_widget/pages/favorite_page/favorite_page.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/feedback_page.dart'; | import 'package:zhiying_base_widget/pages/feedback_page/feedback_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | ||||
@@ -52,6 +52,7 @@ import 'package:zhiying_base_widget/widgets/wallet/wallet_income/wallet_income.d | |||||
import 'package:zhiying_comm/util/defalut_widget_creater.dart'; | import 'package:zhiying_comm/util/defalut_widget_creater.dart'; | ||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
import 'pages/favorites_page/favorites_page.dart'; | |||||
import 'pages/message_notice_page/message_notice_page.dart'; | import 'pages/message_notice_page/message_notice_page.dart'; | ||||
import 'pages/search_page/search_page.dart'; | import 'pages/search_page/search_page.dart'; | ||||
import 'pages/wallet_page/wallet_page.dart'; | import 'pages/wallet_page/wallet_page.dart'; | ||||
@@ -142,7 +143,7 @@ class BaseWidgetRegister { | |||||
// 邀请好友 | // 邀请好友 | ||||
PageFactory.regist( | PageFactory.regist( | ||||
'pub.flutter.invite_friends', (model) => InvitedFriendsPage(model)); | 'pub.flutter.invite_friends', (model) => InvitedFriendsPage(model)); | ||||
PageFactory.regist('pub.flutter.fav', (model) => FavoritePage()); | |||||
/// 我的团队 | /// 我的团队 | ||||
PageFactory.regist('pub.flutter.my_team', (model) => TeamPage(model)); | PageFactory.regist('pub.flutter.my_team', (model) => TeamPage(model)); | ||||
@@ -154,6 +155,9 @@ class BaseWidgetRegister { | |||||
/// 消息中心 | /// 消息中心 | ||||
PageFactory.regist( | PageFactory.regist( | ||||
'pub.flutter.message_center', (model) => MessageNoticePage(model)); | 'pub.flutter.message_center', (model) => MessageNoticePage(model)); | ||||
/// 我的收藏 | |||||
PageFactory.regist('pub.flutter.my_fav', (model) => FavoritesPage()); | |||||
} | } | ||||
// 注册控件 | // 注册控件 | ||||
@@ -0,0 +1,75 @@ | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/model/favorites_style_model.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
class FavoritesDialogWidget extends StatelessWidget { | |||||
ConfirmDialog styleModel; | |||||
FavoritesDialogWidget({@required this.styleModel}); | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return Scaffold( | |||||
backgroundColor: Colors.transparent, | |||||
body: Column( | |||||
mainAxisAlignment: MainAxisAlignment.center, | |||||
crossAxisAlignment: CrossAxisAlignment.center, | |||||
children: <Widget>[ | |||||
Container( | |||||
width: double.infinity, | |||||
padding: const EdgeInsets.only(top: 30, left: 17, right: 17, bottom: 12.5), | |||||
decoration: BoxDecoration(color: HexColor.fromHex(styleModel?.bgColor ?? '#FFFFFF'), borderRadius: BorderRadius.circular(8)), | |||||
margin: EdgeInsets.only(left: 46, right: 46), | |||||
child: Column( | |||||
children: <Widget>[ | |||||
/// 标题 | |||||
Text(styleModel?.bgText, style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold, color: HexColor.fromHex(styleModel?.bgTextColor ?? '#333333'))), | |||||
const SizedBox(height: 44), | |||||
Row( | |||||
children: <Widget>[ | |||||
Flexible(flex: 1, child: _buildCustomerButtonWidget( | |||||
text: styleModel?.leftText ?? '我在想想', | |||||
textColor:styleModel?.leftTextColor ?? '#FF4242', | |||||
bgColor: styleModel?.leftBtnBgColor ?? '#FFFFFF', | |||||
borderColor: styleModel?.leftTextColor ?? '#FF4242', | |||||
callback: ()=> Navigator.maybePop(context, 0), | |||||
)), | |||||
const SizedBox(width: 14), | |||||
Flexible(flex: 1, child: _buildCustomerButtonWidget( | |||||
text: styleModel?.rightText ?? '确认删除', | |||||
textColor: styleModel?.rightTextColor ?? '#FFFFFF', | |||||
borderColor: styleModel?.rightTextColor ?? '#FFFFFF', | |||||
bgColor: styleModel?.rightBtnBgColor ?? '#FF4242', | |||||
callback: ()=> Navigator.maybePop(context, 1), | |||||
)), | |||||
], | |||||
) | |||||
], | |||||
), | |||||
) | |||||
], | |||||
), | |||||
); | |||||
} | |||||
Widget _buildCustomerButtonWidget({String text, String textColor, String bgColor, String borderColor,GestureTapCallback callback, double height = 30}) { | |||||
return GestureDetector( | |||||
behavior: HitTestBehavior.opaque, | |||||
onTap: callback, | |||||
child: Container( | |||||
alignment: Alignment.center, | |||||
height: height, | |||||
width: double.infinity, | |||||
decoration: BoxDecoration( | |||||
color: HexColor.fromHex(bgColor), | |||||
borderRadius: BorderRadius.circular(height / 2), | |||||
border: Border.all(color: HexColor.fromHex(borderColor), width: 0.5), | |||||
), | |||||
child: Text( | |||||
text ?? '', | |||||
style: TextStyle(color: HexColor.fromHex(textColor), fontSize: 13), | |||||
), | |||||
), | |||||
); | |||||
} | |||||
} |
@@ -0,0 +1,173 @@ | |||||
import 'dart:async'; | |||||
import 'package:bloc/bloc.dart'; | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:meta/meta.dart'; | |||||
import 'package:zhiying_base_widget/widgets/favorites/goods_list/model/favorites_goods_list_model.dart'; | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_model.dart'; | |||||
import 'package:zhiying_comm/util/empty_util.dart'; | |||||
import 'favorites_goods_list_repository.dart'; | |||||
part 'favorites_goods_list_event.dart'; | |||||
part 'favorites_goods_list_state.dart'; | |||||
class FavoritesGoodsListBloc extends Bloc<FavoritesGoodsListEvent, FavoritesGoodsListState> { | |||||
@override | |||||
FavoritesGoodsListState get initialState => FavoritesGoodsListInitial(); | |||||
FavoritesGoodsListRepository repository; | |||||
FavoritesGoodsListBloc(this.repository); | |||||
@override | |||||
Stream<FavoritesGoodsListState> mapEventToState( | |||||
FavoritesGoodsListEvent event, | |||||
) async* { | |||||
/// 初始化数据 | |||||
if (event is FavoritesGoodsListInitEvent) { | |||||
yield* _mapInitEventToState(event); | |||||
} | |||||
/// 下拉刷新 | |||||
if (event is FavoritesGoodsListOnRefreshEvent) { | |||||
yield* _mapOnRefreshEventToState(event); | |||||
} | |||||
/// 上拉更多 | |||||
if (event is FavoritesGoodsListOnLoadEvent) { | |||||
yield* _mapOnLoadEventToState(event); | |||||
} | |||||
/// 删除 | |||||
if (event is FavoritesGoodsListDeleteEvent) { | |||||
yield* _mapDeleteEventToState(event); | |||||
} | |||||
/// 搜索 | |||||
if (event is FavoritesGoodsListSearchEvent) { | |||||
yield* _mapSearchEventToState(event); | |||||
} | |||||
/// 单个商品选中 | |||||
if(event is FavoritesGoodsListSignGoodsSelectEvent){ | |||||
yield* _mapSelectSignEventToState(event); | |||||
} | |||||
/// 所有商品选中 | |||||
if(event is FavoritesGoodsListGoodsSelectAllEvent){ | |||||
yield* _mapSelectAllEventToState(event); | |||||
} | |||||
if(event is FavoritesGoodsListGoodsCancelAllEvent){ | |||||
yield* _mapCancelAllEventToState(event); | |||||
} | |||||
// /// 切换样式 | |||||
// if (event is FavoritesGoodsListChangeStyleEvent) { | |||||
// yield* _mapChangeStyleEventToState(event); | |||||
// } | |||||
} | |||||
/// 初始化数据 | |||||
Stream<FavoritesGoodsListState> _mapInitEventToState(FavoritesGoodsListInitEvent event) async* { | |||||
var result = await repository.fetchInit(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListInitErrorState(); | |||||
} | |||||
} | |||||
/// 下拉刷新 | |||||
Stream<FavoritesGoodsListState> _mapOnRefreshEventToState(FavoritesGoodsListOnRefreshEvent event) async* { | |||||
var result = await repository.fetchRefresh(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListRefreshSuccessState(); | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListRefreshErrorState(); | |||||
yield FavoritesGoodsListErrorState(); | |||||
} | |||||
} | |||||
/// 上拉更多 | |||||
Stream<FavoritesGoodsListState> _mapOnLoadEventToState(FavoritesGoodsListOnLoadEvent event) async* { | |||||
var result = await repository.fetchLoad(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadSuccessState(); | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListLoadErrorState(); | |||||
yield FavoritesGoodsListErrorState(); | |||||
} | |||||
} | |||||
/// 删除 | |||||
Stream<FavoritesGoodsListState> _mapDeleteEventToState(FavoritesGoodsListDeleteEvent event) async* { | |||||
int length = repository.getSelectLength(); | |||||
if(length > 0) { | |||||
var result = await repository.delete(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListErrorState(); | |||||
} | |||||
}else{ | |||||
yield FavoritesGoodsListNotSelectState(); | |||||
} | |||||
} | |||||
/// 搜索 | |||||
Stream<FavoritesGoodsListState> _mapSearchEventToState(FavoritesGoodsListSearchEvent event) async* { | |||||
var result = await repository.search(event.keyword); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListInitErrorState(); | |||||
} | |||||
} | |||||
/// 所有商品选中 | |||||
Stream<FavoritesGoodsListState> _mapSelectAllEventToState(FavoritesGoodsListGoodsSelectAllEvent event) async*{ | |||||
var result = await repository.selectAllData(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListErrorState(); | |||||
} | |||||
} | |||||
/// 商品的全部取消 | |||||
Stream<FavoritesGoodsListState> _mapCancelAllEventToState(FavoritesGoodsListGoodsCancelAllEvent event) async*{ | |||||
var result = await repository.cancelSelectAllData(); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListErrorState(); | |||||
} | |||||
} | |||||
/// 单个商品选中 | |||||
Stream<FavoritesGoodsListState> _mapSelectSignEventToState(FavoritesGoodsListSignGoodsSelectEvent event) async*{ | |||||
var result = await repository.signSelectData(event.index); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
} else { | |||||
yield FavoritesGoodsListErrorState(); | |||||
} | |||||
} | |||||
// /// 切换样式 | |||||
// Stream<FavoritesGoodsListState> _mapChangeStyleEventToState(FavoritesGoodsListChangeStyleEvent event) async* { | |||||
// var result = await repository.fetchInit(); | |||||
// if (!EmptyUtil.isEmpty(result)) { | |||||
// yield FavoritesGoodsListLoadedState(dataModel: result); | |||||
// } else { | |||||
// yield FavoritesGoodsListInitErrorState(); | |||||
// } | |||||
// } | |||||
} |
@@ -0,0 +1,39 @@ | |||||
part of 'favorites_goods_list_bloc.dart'; | |||||
@immutable | |||||
abstract class FavoritesGoodsListEvent {} | |||||
/// 初始化数据 | |||||
class FavoritesGoodsListInitEvent extends FavoritesGoodsListEvent {} | |||||
/// 下拉刷新 | |||||
class FavoritesGoodsListOnRefreshEvent extends FavoritesGoodsListEvent {} | |||||
/// 上拉更多 | |||||
class FavoritesGoodsListOnLoadEvent extends FavoritesGoodsListEvent {} | |||||
/// 关键字搜索 | |||||
class FavoritesGoodsListSearchEvent extends FavoritesGoodsListEvent { | |||||
final String keyword; | |||||
FavoritesGoodsListSearchEvent(this.keyword); | |||||
} | |||||
/// 删除 | |||||
class FavoritesGoodsListDeleteEvent extends FavoritesGoodsListEvent {} | |||||
/// 切换样式 | |||||
class FavoritesGoodsListChangeStyleEvent extends FavoritesGoodsListEvent{} | |||||
/// 商品的当个选中 | |||||
class FavoritesGoodsListSignGoodsSelectEvent extends FavoritesGoodsListEvent{ | |||||
// final FavoritesGoodsListItemModel model; | |||||
final int index; | |||||
FavoritesGoodsListSignGoodsSelectEvent(this.index); | |||||
} | |||||
/// 商品的全选 | |||||
class FavoritesGoodsListGoodsSelectAllEvent extends FavoritesGoodsListEvent{} | |||||
/// 商品的全部取消 | |||||
class FavoritesGoodsListGoodsCancelAllEvent extends FavoritesGoodsListEvent{} |
@@ -0,0 +1,161 @@ | |||||
import 'package:flutter/cupertino.dart'; | |||||
import 'package:zhiying_base_widget/widgets/favorites/goods_list/model/favorites_goods_list_model.dart'; | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_model.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
class FavoritesGoodsListRepository { | |||||
String type; | |||||
final int _MAX = 5; | |||||
int _currentPage = 1; | |||||
bool _hasMoreData = true; | |||||
FavoritesGoodsListDataModel _oldData = new FavoritesGoodsListDataModel(); | |||||
Map<int, int> _selectIndex = {}; | |||||
FavoritesGoodsListRepository({this.type = 'all'}); | |||||
String keyword; | |||||
/// 返回选中的商品长度 | |||||
int getSelectLength() { | |||||
return _selectIndex.length; | |||||
} | |||||
/// 选中所有 | |||||
Future<FavoritesGoodsListDataModel> selectAllData() async { | |||||
_selectIndex.clear(); | |||||
int index = 0; | |||||
_oldData.lists.forEach((element) { | |||||
element.isSelect = true; | |||||
_selectIndex[index] = index; | |||||
++index; | |||||
}); | |||||
_oldData.isAllSelect = true; | |||||
return _oldData; | |||||
} | |||||
/// 单个选中状态 | |||||
Future<FavoritesGoodsListDataModel> signSelectData(final int selectIndex) async { | |||||
_oldData.lists[selectIndex].isSelect = !_oldData.lists[selectIndex].isSelect; | |||||
if (_oldData.lists[selectIndex].isSelect) { | |||||
// 新增 | |||||
_selectIndex[selectIndex] = selectIndex; | |||||
} else { | |||||
// 移除 | |||||
_selectIndex.remove(selectIndex); | |||||
} | |||||
_oldData.isAllSelect = false; | |||||
if (_selectIndex.length == _oldData.lists.length) { | |||||
_oldData.isAllSelect = true; | |||||
} | |||||
return _oldData; | |||||
} | |||||
/// 取消选中所有 or 重置选中状态 | |||||
Future<FavoritesGoodsListDataModel> cancelSelectAllData() async { | |||||
_selectIndex.clear(); | |||||
_oldData.lists.forEach((element) { | |||||
element.isSelect = false; | |||||
}); | |||||
_oldData.isAllSelect = false; | |||||
return _oldData; | |||||
} | |||||
/// 关键字搜索 | |||||
Future<FavoritesGoodsListDataModel> search(String keyword) async { | |||||
try { | |||||
_selectIndex.clear(); | |||||
_oldData.lists.clear(); | |||||
_currentPage = 1; | |||||
_hasMoreData = true; | |||||
this.keyword = keyword; | |||||
return _baseRequest(); | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 删除数据 | |||||
Future<FavoritesGoodsListDataModel> delete() async { | |||||
try { | |||||
// Logger.log('select Index length = ${_selectIndex.length}'); | |||||
if (_selectIndex.length > 0) { | |||||
List<String> gids = []; | |||||
_selectIndex.forEach((key, value) { | |||||
gids.add(_oldData.lists[value].goodId); | |||||
}); | |||||
var result = await NetUtil.post('/api/v1/user/myfav/delete', params: {'gids': gids}, method: NetMethod.POST); | |||||
if (NetUtil.isSuccess(result)) { | |||||
List<FavoritesGoodsListItemModel> tempList = []; | |||||
// TODO 这里有问题:移除删除 | |||||
for (int i = 0; i < _oldData.lists.length; i++) { | |||||
if (!_selectIndex.containsKey(i)) { | |||||
tempList.add(_oldData.lists[i]); | |||||
} | |||||
} | |||||
_oldData.lists.clear(); | |||||
_selectIndex.clear(); | |||||
_oldData.isAllSelect = false; | |||||
_oldData.lists = tempList; | |||||
return _oldData; | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 初始化请求 | |||||
Future<FavoritesGoodsListDataModel> fetchInit() async { | |||||
_currentPage = 1; | |||||
_hasMoreData = true; | |||||
_oldData?.lists?.clear(); | |||||
_selectIndex.clear(); | |||||
_oldData.isAllSelect = false; | |||||
return _baseRequest(); | |||||
} | |||||
/// 下拉刷新 | |||||
Future<FavoritesGoodsListDataModel> fetchRefresh() async { | |||||
return fetchInit(); | |||||
} | |||||
/// 上拉更多 | |||||
Future<FavoritesGoodsListDataModel> fetchLoad() async { | |||||
if (_hasMoreData) { | |||||
return _baseRequest(); | |||||
} | |||||
return null; | |||||
} | |||||
/// 基础请求 | |||||
Future<FavoritesGoodsListDataModel> _baseRequest() async { | |||||
try { | |||||
var result; | |||||
if(EmptyUtil.isEmpty(keyword)) { | |||||
result = await NetUtil.post('/api/v1/user/myfav/$type?page=${_currentPage.toString()}', params: {}, method: NetMethod.GET); | |||||
}else{ | |||||
result = await NetUtil.post('/api/v1/user/myfav/s', params: {'keyword': keyword}, method: NetMethod.POST); | |||||
} | |||||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||||
List data = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | |||||
data.forEach((element) { | |||||
_oldData.lists.add(FavoritesGoodsListItemModel.fromJson(element)); | |||||
}); | |||||
++_currentPage; | |||||
_hasMoreData = true; | |||||
// _hasMoreData = data.length >= _MAX ? true : false; | |||||
return _oldData; | |||||
} | |||||
_hasMoreData = false; | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
} |
@@ -0,0 +1,35 @@ | |||||
part of 'favorites_goods_list_bloc.dart'; | |||||
@immutable | |||||
abstract class FavoritesGoodsListState {} | |||||
/// 初始化状态(骨架图) | |||||
class FavoritesGoodsListInitial extends FavoritesGoodsListState {} | |||||
/// 初始化失败状态(空数据) | |||||
class FavoritesGoodsListInitErrorState extends FavoritesGoodsListState {} | |||||
/// 下拉刷新失败状态 | |||||
class FavoritesGoodsListRefreshErrorState extends FavoritesGoodsListState {} | |||||
/// 下拉刷新成功状态 | |||||
class FavoritesGoodsListRefreshSuccessState extends FavoritesGoodsListState {} | |||||
/// 上拉更多失败状态 | |||||
class FavoritesGoodsListLoadErrorState extends FavoritesGoodsListState {} | |||||
/// 上拉更多成功状态 | |||||
class FavoritesGoodsListLoadSuccessState extends FavoritesGoodsListState {} | |||||
/// 数据加载成功 | |||||
class FavoritesGoodsListLoadedState extends FavoritesGoodsListState { | |||||
// List<FavoritesGoodsListItemModel> dataModel; | |||||
FavoritesGoodsListDataModel dataModel; | |||||
FavoritesGoodsListLoadedState({@required this.dataModel}); | |||||
} | |||||
/// 没选中 | |||||
class FavoritesGoodsListNotSelectState extends FavoritesGoodsListState{} | |||||
/// 未知错误 | |||||
class FavoritesGoodsListErrorState extends FavoritesGoodsListState {} |
@@ -0,0 +1,325 @@ | |||||
import 'package:flutter/cupertino.dart'; | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:flutter/widgets.dart'; | |||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||||
import 'package:zhiying_base_widget/dialog/tip_dialog/tip_dialog.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/model/favorites_style_model.dart'; | |||||
import 'package:zhiying_base_widget/pages/favorites_page/notifier/favorites_page_notifier.dart'; | |||||
import 'package:zhiying_base_widget/widgets/favorites/dialog/favorites_dialog_widget.dart'; | |||||
import 'package:zhiying_base_widget/widgets/favorites/goods_list/bloc/favorites_goods_list_bloc.dart'; | |||||
import 'package:zhiying_base_widget/widgets/favorites/goods_list/bloc/favorites_goods_list_repository.dart'; | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/home_goods_item_single.dart'; | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_style_model.dart'; | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/skeleton/home_goods_sk.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
import 'package:provider/provider.dart'; | |||||
import 'package:fluttertoast/fluttertoast.dart'; | |||||
import 'model/favorites_goods_list_model.dart'; | |||||
class FavoritesGoodsListWidget extends StatelessWidget { | |||||
FavoritesStyleModel model; | |||||
String type; | |||||
int currentIndex; | |||||
FavoritesGoodsListWidget({@required this.model, @required this.type, this.currentIndex = 0}); | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return BlocProvider<FavoritesGoodsListBloc>( | |||||
create: (_) => FavoritesGoodsListBloc(FavoritesGoodsListRepository(type: type)), | |||||
child: _FavoritesGoodsListWidgetContainer(model, currentIndex), | |||||
); | |||||
} | |||||
} | |||||
class _FavoritesGoodsListWidgetContainer extends StatefulWidget { | |||||
FavoritesStyleModel styleModel; | |||||
int currentIndex; | |||||
_FavoritesGoodsListWidgetContainer(this.styleModel, this.currentIndex); | |||||
@override | |||||
__FavoritesGoodsListWidgetContainerState createState() => __FavoritesGoodsListWidgetContainerState(); | |||||
} | |||||
class __FavoritesGoodsListWidgetContainerState extends State<_FavoritesGoodsListWidgetContainer> with AutomaticKeepAliveClientMixin { | |||||
RefreshController _refreshController; | |||||
// 是否编辑中 | |||||
bool isEditing = false; | |||||
int lastChangeVal = -1; | |||||
/// 下拉刷新 | |||||
void _onRefresh() async { | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListOnRefreshEvent()); | |||||
} | |||||
/// 上拉更多 | |||||
void _onLoad() async { | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListOnLoadEvent()); | |||||
} | |||||
/// 商品点击选中 | |||||
void _onClickGoods(int index){ | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListSignGoodsSelectEvent(index)); | |||||
} | |||||
/// 全选 | |||||
void _onClickAllSelecct(FavoritesGoodsListDataModel dataModel) { | |||||
if(!dataModel.isAllSelect) { | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListGoodsSelectAllEvent()); | |||||
}else{ | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListGoodsCancelAllEvent()); | |||||
} | |||||
} | |||||
/// 点击删除 | |||||
void _onClickDelete(ConfirmDialog styleModel) async { | |||||
// | |||||
var result = await showDialog(context: context, child: FavoritesDialogWidget(styleModel: styleModel,)); | |||||
if(result == 1){ | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListDeleteEvent()); | |||||
} | |||||
} | |||||
@override | |||||
bool get wantKeepAlive => true; | |||||
@override | |||||
void initState() { | |||||
_refreshController = RefreshController(); | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListInitEvent()); | |||||
super.initState(); | |||||
} | |||||
@override | |||||
void didChangeDependencies() { | |||||
super.didChangeDependencies(); | |||||
FavoritesPageNotifier favoritesPageNotifier = Provider.of<FavoritesPageNotifier>(context); | |||||
if (null != favoritesPageNotifier) { | |||||
isEditing = favoritesPageNotifier.isEditing; | |||||
if(favoritesPageNotifier.editingTypeTag) { | |||||
// BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListGoodsCancelAllEvent()); | |||||
}else{ | |||||
// if(favoritesPageNotifier.selectIndex == widget.currentIndex) { | |||||
BlocProvider.of<FavoritesGoodsListBloc>(context).add(FavoritesGoodsListSearchEvent(favoritesPageNotifier?.keyword)); | |||||
// } | |||||
} | |||||
} | |||||
} | |||||
@override | |||||
void dispose() { | |||||
_refreshController?.dispose(); | |||||
super.dispose(); | |||||
} | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return Listener( | |||||
onPointerDown: (down)=> RouterUtil.hideKeyboard(context), | |||||
child: Container( | |||||
color: HexColor.fromHex('#F9F9F9'), | |||||
child: BlocConsumer<FavoritesGoodsListBloc, FavoritesGoodsListState>( | |||||
listener: (context, state) {}, | |||||
buildWhen: (prev, current) { | |||||
if (current is FavoritesGoodsListRefreshSuccessState) { | |||||
_refreshController?.refreshCompleted(resetFooterState: true); | |||||
return false; | |||||
} | |||||
if (current is FavoritesGoodsListRefreshErrorState) { | |||||
_refreshController?.refreshFailed(); | |||||
return false; | |||||
} | |||||
if (current is FavoritesGoodsListLoadSuccessState) { | |||||
_refreshController?.loadComplete(); | |||||
return false; | |||||
} | |||||
if (current is FavoritesGoodsListLoadErrorState) { | |||||
_refreshController?.loadNoData(); | |||||
return false; | |||||
} | |||||
if (current is FavoritesGoodsListErrorState) { | |||||
return false; | |||||
} | |||||
if(current is FavoritesGoodsListNotSelectState){ | |||||
Fluttertoast.showToast(msg: '请选择需要删除的商品~'); | |||||
return false; | |||||
} | |||||
return true; | |||||
}, | |||||
builder: (context, state) { | |||||
/// 初始化失败,空数据 | |||||
if (state is FavoritesGoodsListInitErrorState) { | |||||
return _buildEmptyWidget(widget?.styleModel); | |||||
} | |||||
/// 数据加载成功 | |||||
if (state is FavoritesGoodsListLoadedState) { | |||||
// Logger.log('__FavoritesGoodsListWidgetContainerState ==== 刷新 size = ${state?.dataModel?.lists?.length}'); | |||||
return _buildGoodsListWidget(widget?.styleModel, state?.dataModel); | |||||
} | |||||
/// 骨架图 | |||||
return _buildSkeletonWidget(widget?.styleModel); | |||||
}, | |||||
), | |||||
), | |||||
); | |||||
} | |||||
/// 有数据返回 | |||||
Widget _buildGoodsListWidget(FavoritesStyleModel styleModel, FavoritesGoodsListDataModel dataModel) { | |||||
/// 如果数据删除了,则返回空视图 | |||||
int length = dataModel?.lists?.length ?? 0; | |||||
if(length == 0) return _buildEmptyWidget(styleModel); | |||||
return Stack( | |||||
children: <Widget>[ | |||||
/// 数据 | |||||
SmartRefresher( | |||||
controller: _refreshController, | |||||
onRefresh: _onRefresh, | |||||
onLoading: _onLoad, | |||||
enablePullUp: true, | |||||
enablePullDown: true, | |||||
child: ListView.builder( | |||||
padding: EdgeInsets.only(top: 7.5, left: 12.5, right: isEditing ? 0 : 12.5), | |||||
itemCount: dataModel.lists.length, | |||||
itemBuilder: (context, index) { | |||||
FavoritesGoodsListItemModel item = dataModel.lists[index]; | |||||
return Row( | |||||
children: <Widget>[ | |||||
Visibility( | |||||
visible: isEditing , | |||||
child: GestureDetector( | |||||
onTap: ()=> _onClickGoods(index), | |||||
behavior: HitTestBehavior.opaque, | |||||
child: Container( | |||||
height: 20, | |||||
width: 20, | |||||
margin: const EdgeInsets.only(right: 8), | |||||
child: CachedNetworkImage( | |||||
imageUrl: item.isSelect ? styleModel?.editLeftConfirmIcon : styleModel?.editLeftNoConfirmIcon, | |||||
), | |||||
), | |||||
), | |||||
), | |||||
Expanded( | |||||
child: HomeGoodsItemSingle( | |||||
item, | |||||
HomeGoodsStyleModel()..listStyle = styleModel?.listStyle, | |||||
marginBottom: 0, | |||||
marginLeft: 0, | |||||
marginRight: 0, | |||||
marginTop: 0, | |||||
), | |||||
) | |||||
], | |||||
); | |||||
}), | |||||
), | |||||
/// 编辑 | |||||
_buildEditrWidget(widget?.styleModel, dataModel), | |||||
], | |||||
); | |||||
} | |||||
/// 编辑的底部Widget | |||||
Widget _buildEditrWidget(FavoritesStyleModel styleModel, FavoritesGoodsListDataModel dataModel) { | |||||
return Align( | |||||
alignment: Alignment.bottomCenter, | |||||
child: Visibility( | |||||
visible: isEditing , | |||||
child: Container( | |||||
padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 15.5, bottom: 15.5), | |||||
width: double.infinity, | |||||
decoration: BoxDecoration( | |||||
color: HexColor.fromHex(styleModel?.bottom?.bgColor ?? '#FFFFFF'), borderRadius: BorderRadius.only(topRight: Radius.circular(10), topLeft: Radius.circular(10))), | |||||
child: Row( | |||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||||
children: <Widget>[ | |||||
GestureDetector( | |||||
onTap: () => _onClickAllSelecct(dataModel), | |||||
behavior: HitTestBehavior.opaque, | |||||
child: Row( | |||||
children: <Widget>[ | |||||
Visibility( | |||||
visible: dataModel?.isAllSelect ?? false, | |||||
replacement: Container( | |||||
width: 20, | |||||
height: 20, | |||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), border: Border.all(color: HexColor.fromHex('#DCDCDC'), width: 0.5)), | |||||
), | |||||
child: Container( | |||||
height: 20, | |||||
width: 20, | |||||
child: CachedNetworkImage(imageUrl: styleModel?.editLeftConfirmIcon ?? '',), | |||||
), | |||||
), | |||||
const SizedBox(width: 8), | |||||
Text( | |||||
styleModel?.bottom?.leftText ?? '全选', | |||||
style: TextStyle( | |||||
fontSize: 15, | |||||
color: HexColor.fromHex(styleModel?.bottom?.leftColor ?? '#333333'), | |||||
fontWeight: FontWeight.bold, | |||||
), | |||||
), | |||||
], | |||||
), | |||||
), | |||||
GestureDetector( | |||||
onTap: () => _onClickDelete(styleModel?.confirmDialog), | |||||
behavior: HitTestBehavior.opaque, | |||||
child: Text( | |||||
styleModel?.bottom?.rightText ?? '删除', | |||||
style: TextStyle( | |||||
fontSize: 15, | |||||
color: HexColor.fromHex(styleModel?.bottom?.rightColor ?? '#FF4242'), | |||||
fontWeight: FontWeight.bold, | |||||
), | |||||
), | |||||
), | |||||
], | |||||
), | |||||
), | |||||
), | |||||
); | |||||
} | |||||
/// 空数据 | |||||
Widget _buildEmptyWidget(FavoritesStyleModel styleModel) { | |||||
return SmartRefresher( | |||||
controller: _refreshController, | |||||
onRefresh: _onRefresh, | |||||
enablePullDown: true, | |||||
enablePullUp: false, | |||||
child: Column( | |||||
children: <Widget>[ | |||||
const SizedBox(height: 80), | |||||
CachedNetworkImage(imageUrl: styleModel?.tabItemNotFoundImg ?? '', width: 188), | |||||
const SizedBox(height: 22), | |||||
Text( | |||||
'暂时没有商品噢\n快去浏览收藏吧', | |||||
style: TextStyle(fontSize: 15, color: HexColor.fromHex('#999999')), | |||||
) | |||||
], | |||||
), | |||||
); | |||||
} | |||||
/// 骨架图 | |||||
Widget _buildSkeletonWidget(FavoritesStyleModel styleModel) { | |||||
return HomeGoodsSkeleton(); | |||||
} | |||||
} |
@@ -0,0 +1,37 @@ | |||||
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_model.dart'; | |||||
// ignore: must_be_immutable | |||||
class FavoritesGoodsListDataModel { | |||||
// 是否全选 | |||||
bool isAllSelect = false; | |||||
List<FavoritesGoodsListItemModel> lists = []; | |||||
// FavoritesGoodsListDataModel({this.isEditing, this.isAllSelect, this.lists }); | |||||
FavoritesGoodsListDataModel(); | |||||
FavoritesGoodsListDataModel.fromJson(Map<String, dynamic> json) { | |||||
isAllSelect = json['isAllSelect'] ?? false; | |||||
if(json['data'] != null){ | |||||
json['data'].forEach((v){ | |||||
lists.add(new FavoritesGoodsListItemModel.fromJson(v)); | |||||
}); | |||||
} | |||||
} | |||||
} | |||||
class FavoritesGoodsListItemModel extends HomeGoodsModel { | |||||
bool isSelect; | |||||
FavoritesGoodsListItemModel.fromJson(Map<String, dynamic> json) { | |||||
super.fromJson(json); | |||||
isSelect = json['isSelect'] ?? false; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = super.toJson(); | |||||
data['isSelect'] = this.isSelect; | |||||
return data; | |||||
} | |||||
} |
@@ -27,11 +27,22 @@ class GoodsDetailsFooterBloc extends Bloc<GoodsDetailsFooterEvent, GoodsDetailsF | |||||
if (event is GoodsDetailsFooterInitEvent) { | if (event is GoodsDetailsFooterInitEvent) { | ||||
yield* _mapInitEventToState(event); | yield* _mapInitEventToState(event); | ||||
} | } | ||||
/// 收藏 | |||||
if(event is GoodsDetailsFooterCollectEvent){ | |||||
yield* _mapCollectEventToState(event); | |||||
} | |||||
/// 取消收藏 | |||||
if(event is GoodsDetailsFooterDeleteCollectEvent){ | |||||
yield* _mapDeleteCollectEventToState(event); | |||||
} | |||||
} | } | ||||
/// 初始化 | /// 初始化 | ||||
Stream<GoodsDetailsFooterState> _mapInitEventToState(GoodsDetailsFooterInitEvent event) async* { | Stream<GoodsDetailsFooterState> _mapInitEventToState(GoodsDetailsFooterInitEvent event) async* { | ||||
var result = await repository.fetchParentData(event.model); | var result = await repository.fetchParentData(event?.model); | ||||
if (!EmptyUtil.isEmpty(result)) { | if (!EmptyUtil.isEmpty(result)) { | ||||
print('result = ${result.toString()}'); | print('result = ${result.toString()}'); | ||||
yield GoodsDetailsFooterLoadedState(model: result); | yield GoodsDetailsFooterLoadedState(model: result); | ||||
@@ -42,10 +53,20 @@ class GoodsDetailsFooterBloc extends Bloc<GoodsDetailsFooterEvent, GoodsDetailsF | |||||
/// 点击收藏 | /// 点击收藏 | ||||
Stream<GoodsDetailsFooterState> _mapCollectEventToState(GoodsDetailsFooterCollectEvent event) async* { | Stream<GoodsDetailsFooterState> _mapCollectEventToState(GoodsDetailsFooterCollectEvent event) async* { | ||||
var result = await repository.fetchCollect(); | var result = await repository.fetchCollect(event?.model); | ||||
if (!EmptyUtil.isEmpty(result)) | if (!EmptyUtil.isEmpty(result)) | ||||
yield GoodsDetailsFooterLoadedState(model: result); | yield GoodsDetailsFooterLoadedState(model: result); | ||||
else | else | ||||
yield GoodsDetailsFooterErrorState(); | yield GoodsDetailsFooterErrorState(); | ||||
} | } | ||||
/// 取消收藏 | |||||
Stream<GoodsDetailsFooterState> _mapDeleteCollectEventToState(GoodsDetailsFooterDeleteCollectEvent event ) async*{ | |||||
var result = await repository.fetchDeleteCollect(event?.model); | |||||
if(!EmptyUtil.isEmpty(result)) | |||||
yield GoodsDetailsFooterLoadedState(model: result); | |||||
else | |||||
yield GoodsDetailsFooterErrorState(); | |||||
} | |||||
} | } |
@@ -19,5 +19,20 @@ class GoodsDetailsFooterInitEvent extends GoodsDetailsFooterEvent { | |||||
/// 点击收藏 | /// 点击收藏 | ||||
class GoodsDetailsFooterCollectEvent extends GoodsDetailsFooterEvent { | class GoodsDetailsFooterCollectEvent extends GoodsDetailsFooterEvent { | ||||
final Map<String, dynamic> model; | |||||
GoodsDetailsFooterCollectEvent({@required this.model}); | |||||
@override | |||||
List<Object> get props => [this.model]; | |||||
} | |||||
/// 取消收藏 | |||||
class GoodsDetailsFooterDeleteCollectEvent extends GoodsDetailsFooterEvent { | |||||
final Map<String, dynamic> model; | |||||
GoodsDetailsFooterDeleteCollectEvent({@required this.model}); | |||||
@override | |||||
List<Object> get props => [this.model]; | |||||
} | } |
@@ -4,18 +4,50 @@ import 'package:zhiying_base_widget/widgets/goods_details/footer/model/goods_det | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
class GoodsDetailsFooterRepository { | class GoodsDetailsFooterRepository { | ||||
GoodsDetailsFooterModel _oldmodel; | |||||
/// 初始化数据 | /// 初始化数据 | ||||
Future<GoodsDetailsFooterModel> fetchParentData(final Map<String, dynamic> model) async { | Future<GoodsDetailsFooterModel> fetchParentData(final Map<String, dynamic> model) async { | ||||
try { | try { | ||||
return GoodsDetailsFooterModel.fromJson(jsonDecode(model['data'])); | GoodsDetailsFooterModel data = GoodsDetailsFooterModel.fromJson(jsonDecode(model['data'])); | ||||
} catch (e) { | _oldmodel = data; | ||||
Logger.log('GoodsDetailsFooterRepository e = $e'); | return data; | ||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | } | ||||
return null; | return null; | ||||
} | } | ||||
/// 点击收藏 | /// 点击收藏 | ||||
Future<GoodsDetailsFooterModel> fetchCollect() async{ | Future<GoodsDetailsFooterModel> fetchCollect(final Map<String, dynamic> model) async { | ||||
try { | |||||
if (!EmptyUtil.isEmpty(model)) { | |||||
var result = await NetUtil.post('/api/v1/user/myfav', params: model, method: NetMethod.POST); | |||||
if(NetUtil.isSuccess(result)){ | |||||
_oldmodel.isFav = '1'; | |||||
return _oldmodel; | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 取消收藏 | |||||
Future<GoodsDetailsFooterModel> fetchDeleteCollect(final Map<String, dynamic> model) async{ | |||||
try{ | |||||
if(!EmptyUtil.isEmpty(model)){ | |||||
var result = await NetUtil.post('/api/v1/user/myfav/delete', params: {'gids':[model['good_id']]}, method: NetMethod.POST); | |||||
if(NetUtil.isSuccess(result)){ | |||||
_oldmodel.isFav = '0'; | |||||
return _oldmodel; | |||||
} | |||||
} | |||||
}catch(e, s){ | |||||
Logger.error(e,s); | |||||
} | |||||
return null; | return null; | ||||
} | } | ||||
@@ -1,15 +1,15 @@ | |||||
part of 'goods_details_footer_bloc.dart'; | part of 'goods_details_footer_bloc.dart'; | ||||
abstract class GoodsDetailsFooterState extends Equatable { | abstract class GoodsDetailsFooterState { | ||||
const GoodsDetailsFooterState(); | const GoodsDetailsFooterState(); | ||||
@override | // @override | ||||
List<Object> get props => []; | // List<Object> get props => []; | ||||
} | } | ||||
class GoodsDetailsFooterInitial extends GoodsDetailsFooterState { | class GoodsDetailsFooterInitial extends GoodsDetailsFooterState { | ||||
@override | // @override | ||||
List<Object> get props => []; | // List<Object> get props => []; | ||||
} | } | ||||
/// 数据加载完毕 | /// 数据加载完毕 | ||||
@@ -18,8 +18,8 @@ class GoodsDetailsFooterLoadedState extends GoodsDetailsFooterState { | |||||
GoodsDetailsFooterLoadedState({@required this.model}); | GoodsDetailsFooterLoadedState({@required this.model}); | ||||
@override | // @override | ||||
List<Object> get props => [this.model]; | // List<Object> get props => [this.model]; | ||||
} | } | ||||
/// 数据加载出错 | /// 数据加载出错 | ||||
@@ -75,7 +75,14 @@ class _GooddsDetailsFooterContainerState | |||||
} | } | ||||
/// 收藏 | /// 收藏 | ||||
void _collectOnClick() {} | void _collectOnClick(GoodsDetailsFooterModel model) { | ||||
bool isCollect = model.isFav == '0'; | |||||
if(isCollect){ // 收藏 | |||||
BlocProvider.of<GoodsDetailsFooterBloc>(context).add(GoodsDetailsFooterCollectEvent(model: model?.favArgs?.toJson())); | |||||
}else{ // 取消收藏 | |||||
BlocProvider.of<GoodsDetailsFooterBloc>(context).add(GoodsDetailsFooterDeleteCollectEvent(model: model?.favArgs?.toJson())); | |||||
} | |||||
} | |||||
/// 分享 | /// 分享 | ||||
void _shareOnClick(GoodsDetailsFooterModel model) async { | void _shareOnClick(GoodsDetailsFooterModel model) async { | ||||
@@ -221,13 +228,13 @@ class _GooddsDetailsFooterContainerState | |||||
)), | )), | ||||
GestureDetector( | GestureDetector( | ||||
behavior: HitTestBehavior.opaque, | behavior: HitTestBehavior.opaque, | ||||
onTap: () => _collectOnClick(), | onTap: () => _collectOnClick(model), | ||||
child: Padding( | child: Padding( | ||||
padding: const EdgeInsets.only(right: 0), | padding: const EdgeInsets.only(right: 0), | ||||
child: _getCustomWidget( | child: _getCustomWidget( | ||||
model?.collect ?? '收藏', | model?.collect ?? '收藏', | ||||
model?.collect_color ?? '999999', | model?.collect_color ?? '999999', | ||||
model?.collect_icon ?? ''))) | model?.isFav == '0' ? model?.collect_icon ?? '' : model?.collected_icon ?? ''))) | ||||
], | ], | ||||
); | ); | ||||
} | } | ||||
@@ -2,6 +2,7 @@ class GoodsDetailsFooterModel { | |||||
String collect; | String collect; | ||||
String collect_color; | String collect_color; | ||||
String collect_icon; | String collect_icon; | ||||
String collected_icon; | |||||
String home; | String home; | ||||
String home_color; | String home_color; | ||||
String home_icon; | String home_icon; | ||||
@@ -18,28 +19,46 @@ class GoodsDetailsFooterModel { | |||||
String share_value; | String share_value; | ||||
String self_buy_value; | String self_buy_value; | ||||
GoodsDetailsFooterModel( | String isFav; | ||||
{this.collect, | String buyUrl; | ||||
this.collect_color, | String shareUrl; | ||||
this.collect_icon, | FavArgs favArgs; | ||||
this.home, | ShareUrlArgs shareUrlArgs; | ||||
this.home_color, | GoodsDetailsFooterModel({ | ||||
this.home_icon, | this.buyUrl, | ||||
this.save_earn, | this.favArgs, | ||||
this.save_earn_bg1_color, | this.isFav, | ||||
this.save_earn_bg2_color, | this.shareUrl, | ||||
this.save_earn_color, | this.shareUrlArgs, | ||||
this.save_earn_val_color, | this.collect, | ||||
this.share_earn, | this.collect_color, | ||||
this.share_earn_bg1_color, | this.collect_icon, | ||||
this.share_earn_bg2_color, | this.home, | ||||
this.share_earn_color, | this.home_color, | ||||
this.share_earn_val_color, | this.home_icon, | ||||
this.share_value, | this.save_earn, | ||||
this.self_buy_value}); | this.save_earn_bg1_color, | ||||
this.save_earn_bg2_color, | |||||
this.save_earn_color, | |||||
this.save_earn_val_color, | |||||
this.share_earn, | |||||
this.share_earn_bg1_color, | |||||
this.share_earn_bg2_color, | |||||
this.share_earn_color, | |||||
this.share_earn_val_color, | |||||
this.share_value, | |||||
this.self_buy_value, | |||||
this.collected_icon, | |||||
}); | |||||
factory GoodsDetailsFooterModel.fromJson(Map<String, dynamic> json) { | factory GoodsDetailsFooterModel.fromJson(Map<String, dynamic> json) { | ||||
return GoodsDetailsFooterModel( | return GoodsDetailsFooterModel( | ||||
isFav: json['is_fav'], | |||||
buyUrl: json['buy_url'], | |||||
shareUrl: json['share_url'], | |||||
favArgs: json['fav_args'] != null ? new FavArgs.fromJson(json['fav_args']) : null, | |||||
shareUrlArgs: json['share_url_args'] != null ? new ShareUrlArgs.fromJson(json['share_url_args']) : null, | |||||
collect: json['collect'], | collect: json['collect'], | ||||
collect_color: json['collect_color'], | collect_color: json['collect_color'], | ||||
collect_icon: json['collect_icon'], | collect_icon: json['collect_icon'], | ||||
@@ -58,6 +77,7 @@ class GoodsDetailsFooterModel { | |||||
share_earn_val_color: json['share_earn_val_color'], | share_earn_val_color: json['share_earn_val_color'], | ||||
share_value: json['share_value'], | share_value: json['share_value'], | ||||
self_buy_value: json['self_buy_value'], | self_buy_value: json['self_buy_value'], | ||||
collected_icon: json['collected_icon'], | |||||
); | ); | ||||
} | } | ||||
@@ -81,6 +101,120 @@ class GoodsDetailsFooterModel { | |||||
data['share_earn_val_color'] = this.share_earn_val_color; | data['share_earn_val_color'] = this.share_earn_val_color; | ||||
data['share_value'] = this.share_value; | data['share_value'] = this.share_value; | ||||
data['self_buy_value'] = this.self_buy_value; | data['self_buy_value'] = this.self_buy_value; | ||||
data['collected_icon'] = this.collected_icon; | |||||
data['is_fav'] = this.isFav; | |||||
data['buy_url'] = this.buyUrl; | |||||
data['share_url'] = this.shareUrl; | |||||
if (this.favArgs != null) { | |||||
data['fav_args'] = this.favArgs.toJson(); | |||||
} | |||||
if (this.shareUrlArgs != null) { | |||||
data['share_url_args'] = this.shareUrlArgs.toJson(); | |||||
} | |||||
return data; | |||||
} | |||||
} | |||||
class FavArgs { | |||||
String provider; | |||||
String providerName; | |||||
String goodId; | |||||
String goodImage; | |||||
String goodTitle; | |||||
String shopName; | |||||
String coupon; | |||||
String couponUrl; | |||||
String commission; | |||||
String marketPrice; | |||||
String currentPrice; | |||||
String inorderCount; | |||||
Null detailData; | |||||
FavArgs( | |||||
{this.provider, | |||||
this.providerName, | |||||
this.goodId, | |||||
this.goodImage, | |||||
this.goodTitle, | |||||
this.shopName, | |||||
this.coupon, | |||||
this.couponUrl, | |||||
this.commission, | |||||
this.marketPrice, | |||||
this.currentPrice, | |||||
this.inorderCount, | |||||
this.detailData}); | |||||
FavArgs.fromJson(Map<String, dynamic> json) { | |||||
provider = json['provider']; | |||||
providerName = json['provider_name']; | |||||
goodId = json['good_id']; | |||||
goodImage = json['good_image']; | |||||
goodTitle = json['good_title']; | |||||
shopName = json['shop_name']; | |||||
coupon = json['coupon']; | |||||
couponUrl = json['coupon_url']; | |||||
commission = json['commission']; | |||||
marketPrice = json['market_price']; | |||||
currentPrice = json['current_price']; | |||||
inorderCount = json['inorder_count']; | |||||
detailData = json['detail_data']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['provider'] = this.provider; | |||||
data['provider_name'] = this.providerName; | |||||
data['good_id'] = this.goodId; | |||||
data['good_image'] = this.goodImage; | |||||
data['good_title'] = this.goodTitle; | |||||
data['shop_name'] = this.shopName; | |||||
data['coupon'] = this.coupon; | |||||
data['coupon_url'] = this.couponUrl; | |||||
data['commission'] = this.commission; | |||||
data['market_price'] = this.marketPrice; | |||||
data['current_price'] = this.currentPrice; | |||||
data['inorder_count'] = this.inorderCount; | |||||
data['detail_data'] = this.detailData; | |||||
return data; | |||||
} | |||||
} | |||||
class ShareUrlArgs { | |||||
String buyUrl; | |||||
String coupon; | |||||
String couponPrice; | |||||
String marketPrice; | |||||
String posterImage; | |||||
String selfbuyCommission; | |||||
String title; | |||||
String type; | |||||
ShareUrlArgs({this.buyUrl, this.coupon, this.couponPrice, this.marketPrice, this.posterImage, this.selfbuyCommission, this.title, this.type}); | |||||
ShareUrlArgs.fromJson(Map<String, dynamic> json) { | |||||
buyUrl = json['buy_url']; | |||||
coupon = json['coupon']; | |||||
couponPrice = json['coupon_price']; | |||||
marketPrice = json['market_price']; | |||||
posterImage = json['poster_image']; | |||||
selfbuyCommission = json['selfbuy_commission']; | |||||
title = json['title']; | |||||
type = json['type']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['buy_url'] = this.buyUrl; | |||||
data['coupon'] = this.coupon; | |||||
data['coupon_price'] = this.couponPrice; | |||||
data['market_price'] = this.marketPrice; | |||||
data['poster_image'] = this.posterImage; | |||||
data['selfbuy_commission'] = this.selfbuyCommission; | |||||
data['title'] = this.title; | |||||
data['type'] = this.type; | |||||
return data; | return data; | ||||
} | } | ||||
} | } |
@@ -14,8 +14,12 @@ class HomeGoodsItemSingle extends StatelessWidget { | |||||
final HomeGoodsModel goods; | final HomeGoodsModel goods; | ||||
final HomeGoodsStyleModel style; | final HomeGoodsStyleModel style; | ||||
Map<String, dynamic> data; | Map<String, dynamic> data; | ||||
final double marginLeft; | |||||
final double marginRight; | |||||
final double marginTop; | |||||
final double marginBottom; | |||||
HomeGoodsItemSingle(this.goods, this.style, {Key key, this.data}) | HomeGoodsItemSingle(this.goods, this.style, {Key key, this.data, this.marginBottom = 4, this.marginTop = 4, this.marginLeft= 12.5, this.marginRight = 12.5}) | ||||
: super(key: key) { | : super(key: key) { | ||||
if (this.data != null && this.data.containsKey('data')) { | if (this.data != null && this.data.containsKey('data')) { | ||||
String data = this.data['data']; | String data = this.data['data']; | ||||
@@ -36,7 +40,7 @@ class HomeGoodsItemSingle extends StatelessWidget { | |||||
return GestureDetector( | return GestureDetector( | ||||
onTap: () => _onJumpGoodsDetails(context, goods), | onTap: () => _onJumpGoodsDetails(context, goods), | ||||
child: Container( | child: Container( | ||||
margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 4, bottom: 4), | margin: EdgeInsets.only(left: marginLeft, right: marginRight, top: marginTop, bottom: marginBottom), | ||||
padding: EdgeInsets.all(7.5), | padding: EdgeInsets.all(7.5), | ||||
decoration: BoxDecoration( | decoration: BoxDecoration( | ||||
color: Colors.white, | color: Colors.white, | ||||
@@ -44,6 +44,21 @@ class HomeGoodsModel extends Equatable { | |||||
detailData = json['detail_data']; | detailData = json['detail_data']; | ||||
} | } | ||||
void fromJson(Map<String, dynamic> json) { | |||||
provider = json['provider']; | |||||
providerName = json['provider_name']; | |||||
goodId = json['good_id']; | |||||
goodImage = json['good_image']; | |||||
goodTitle = json['good_title']; | |||||
shopName = json['shop_name']; | |||||
coupon = json['coupon']; | |||||
commission = json['commission']; | |||||
marketPrice = json['market_price']; | |||||
currentPrice = json['current_price']; | |||||
inorderCount = json['inorder_count']; | |||||
detailData = json['detail_data']; | |||||
} | |||||
Map<String, dynamic> toJson() { | Map<String, dynamic> toJson() { | ||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
data['provider'] = this.provider; | data['provider'] = this.provider; | ||||