Browse Source

1、商品详情的完善后

tags/0.0.1
PH2 4 years ago
parent
commit
fb06daaf86
48 changed files with 1435 additions and 322 deletions
  1. +8
    -3
      lib/pages/goods_details_page/bloc/goods_details_page_bloc.dart
  2. +95
    -27
      lib/pages/goods_details_page/bloc/goods_details_page_repository.dart
  3. +10
    -5
      lib/pages/goods_details_page/goods_details_page.dart
  4. +11
    -0
      lib/pages/sreach_page/sreach_page.dart
  5. +11
    -0
      lib/pages/sreach_result_page/sreach_result_page.dart
  6. +15
    -3
      lib/register.dart
  7. +6
    -2
      lib/widgets/goods_details/coupon/bloc/counpon_bloc.dart
  8. +8
    -0
      lib/widgets/goods_details/coupon/bloc/counpon_repository.dart
  9. +3
    -0
      lib/widgets/goods_details/coupon/bloc/counpon_state.dart
  10. +1
    -1
      lib/widgets/goods_details/coupon/counpon_sk.dart
  11. +43
    -27
      lib/widgets/goods_details/coupon/counpon_widget.dart
  12. +53
    -1
      lib/widgets/goods_details/coupon/model/counpon_model.dart
  13. +54
    -0
      lib/widgets/goods_details/detail_img/bloc/goods_details_img_bloc.dart
  14. +18
    -0
      lib/widgets/goods_details/detail_img/bloc/goods_details_img_event.dart
  15. +35
    -0
      lib/widgets/goods_details/detail_img/bloc/goods_details_img_repository.dart
  16. +30
    -0
      lib/widgets/goods_details/detail_img/bloc/goods_details_img_state.dart
  17. +110
    -0
      lib/widgets/goods_details/detail_img/goods_details_img.dart
  18. +11
    -0
      lib/widgets/goods_details/detail_img/goods_details_img_sk.dart
  19. +41
    -0
      lib/widgets/goods_details/detail_img/model/goods_details_img_model.dart
  20. +34
    -5
      lib/widgets/goods_details/evaluate/goods_details_evaluate_widget.dart
  21. +39
    -0
      lib/widgets/goods_details/evaluate/model/goods_details_evaluate_model.dart
  22. +51
    -0
      lib/widgets/goods_details/footer/bloc/goods_details_footer_bloc.dart
  23. +23
    -0
      lib/widgets/goods_details/footer/bloc/goods_details_footer_event.dart
  24. +25
    -0
      lib/widgets/goods_details/footer/bloc/goods_details_footer_repository.dart
  25. +29
    -0
      lib/widgets/goods_details/footer/bloc/goods_details_footer_state.dart
  26. +2
    -1
      lib/widgets/goods_details/footer/goods_details_footer_sk.dart
  27. +74
    -38
      lib/widgets/goods_details/footer/goods_details_footer_widget.dart
  28. +69
    -0
      lib/widgets/goods_details/footer/model/goods_details_footer_model.dart
  29. +37
    -21
      lib/widgets/goods_details/price/goods_details_price_widget.dart
  30. +71
    -0
      lib/widgets/goods_details/price/model/goods_details_price_model.dart
  31. +7
    -6
      lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_bloc.dart
  32. +4
    -2
      lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_repository.dart
  33. +7
    -7
      lib/widgets/goods_details/slide_banner/goods_details_slide_banner_widget.dart
  34. +32
    -57
      lib/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart
  35. +14
    -9
      lib/widgets/goods_details/store/bloc/store_bloc.dart
  36. +6
    -1
      lib/widgets/goods_details/store/bloc/store_event.dart
  37. +10
    -1
      lib/widgets/goods_details/store/bloc/store_repository.dart
  38. +52
    -1
      lib/widgets/goods_details/store/model/store_model.dart
  39. +3
    -0
      lib/widgets/goods_details/store/store_sk.dart
  40. +22
    -22
      lib/widgets/goods_details/store/store_widget.dart
  41. +70
    -18
      lib/widgets/goods_details/title/goods_details_title_widget.dart
  42. +58
    -0
      lib/widgets/goods_details/title/model/goods_details_title_model.dart
  43. +34
    -1
      lib/widgets/goods_details/upgrade_tip/model/upgrade_tip_model.dart
  44. +40
    -21
      lib/widgets/goods_details/upgrade_tip/upgrade_tip_widget.dart
  45. +49
    -38
      lib/widgets/home/home_goods/home_goods_item.dart
  46. +4
    -0
      lib/widgets/home/home_goods/models/home_goods_model.dart
  47. +2
    -0
      lib/widgets/home/home_goods/models/home_goods_model.g.dart
  48. +4
    -4
      lib/widgets/home/home_slide_banner/home_slide_banner.dart

+ 8
- 3
lib/pages/goods_details_page/bloc/goods_details_page_bloc.dart View File

@@ -30,10 +30,15 @@ class GoodsDetailsPageBloc extends Bloc<GoodsDetailsPageEvent, GoodsDetailsPageS
}

Stream<GoodsDetailsPageState> _mapInitEventToState(GoodsDetailsPageInitEvent event) async* {
var result = await repository.fetchInitData(event.model);
if (!EmptyUtil.isEmpty(result))
var result = await repository.fetchInitModData(event.model);
if (!EmptyUtil.isEmpty(result)) {
yield GoodsDetailsPageLoadedState(model: result);
else
// var itemModelData = await repository.fetchModData(event.model);
// if(!EmptyUtil.isEmpty(itemModelData)){
// yield GoodsDetailsPageLoadedState(model: itemModelData);
// }
} else {
yield GoodsDetailsPageErrorState();
}
}
}

+ 95
- 27
lib/pages/goods_details_page/bloc/goods_details_page_repository.dart View File

@@ -1,40 +1,108 @@
import 'dart:convert';
import 'package:zhiying_comm/zhiying_comm.dart';

class GoodsDetailsPageRepository {
List<Map<String, dynamic>> _pageData = [];

/// 初始化
Future<List<Map<String, dynamic>>> fetchInitData(Map<String, dynamic> model) async {
int id = 13;
var result = await NetUtil.post('/api/v1/mod',
method: NetMethod.POST,
params: Map<String, dynamic>.from({
'ids': [id]
}));




/// 获取数据
Future<List<Map<String, dynamic>>> fetchInitModData(final Map<String, dynamic> model) async{

String provider = model['provider'];
String goodId = model['good_id'];
try {
if(NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
return _loadData(id, result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
if (!EmptyUtil.isEmpty(provider) && !EmptyUtil.isEmpty(goodId)) {
Logger.log('商品类型 = $provider, 商品ID = $goodId');
var result = await NetUtil.post('/api/v1/detail/$provider/$goodId', method: NetMethod.GET);
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {

List<Map<String, dynamic>> _pageData = [];
/// 合并数据
List<dynamic> modLists = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'];
for(int i = 0; i < modLists.length; i++){
Map<String, dynamic> item = modLists[i];
Map<String, dynamic> data = item['data'];
Map<String, dynamic> style = jsonDecode(item['style']);

Map<String, dynamic> baseData = {'provider': provider, 'good_id': goodId};
style.addAll(baseData);

if(!EmptyUtil.isEmpty(data)){
style.addAll(data);
item['data'] = jsonEncode(style);
_pageData.add(item);
}else{
item['data'] = jsonEncode(style);
_pageData.add(item);
}
}

return _pageData;
}
}
} catch (e) {
}catch(e){
Logger.log(e);
}
return null;
}

/// 处理数据
List<Map<String, dynamic>> _loadData(int id, dynamic data) {
String key = id.toString();
Map<String, dynamic> json = Map<String, dynamic>.from(data);
if (json.containsKey(key)) {
List<dynamic> list = json[key];
_pageData = list.map((item) {
return Map<String, dynamic>.from(item);
}).toList();
return _pageData;
}
return null;
}

/// 获取缓存数据?
///【弃用】获取mod数据 把子mod数据塞在data中
// Future<List<Map<String, dynamic>>> fetchModData(final Map<String, dynamic> model) async{
// String provider = model['provider'];
// String goodId = model['good_id'];
// try {
// if (!EmptyUtil.isEmpty(provider) && !EmptyUtil.isEmpty(goodId)) {
// Logger.log('商品类型 = $provider, 商品ID = $goodId');
// var result = await NetUtil.post('/api/v1/detail/$provider/$goodId', method: NetMethod.GET);
// if(NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
// for (int i = 0; i < _pageData.length; i++) {
// //result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][i];
// Map<String, dynamic> resultData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][i];
// Map<String, dynamic> data = jsonDecode(_pageData[i]['data']);
// if(!EmptyUtil.isEmpty(data)){
// data.addAll(resultData);
// _pageData[i]['data'] = jsonEncode(data);
// }else{
// _pageData[i]['data'] = (null != resultData && resultData.length > 0) ? jsonEncode(resultData) : '';
// }
// }
// return _pageData;
// }
// }
// }catch(e){
// Logger.log(e);
// }
// return null;
// }
//
// ///【弃用】初始化
// Future<List<Map<String, dynamic>>> fetchInitData(Map<String, dynamic> model) async {
// int id = 13;
// var result = await NetUtil.post('/api/v1/mod', method: NetMethod.POST, params: {'ids': [id]});
// try {
// if(NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
// return _loadData(id, result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
// }
// } catch (e) {
// Logger.log(e);
// }
// return null;
// }
//
// ///【弃用】处理数据
// List<Map<String, dynamic>> _loadData(int id, dynamic data) {
// String key = id.toString();
// Map<String, dynamic> json = Map<String, dynamic>.from(data);
// if (json.containsKey(key)) {
// List<dynamic> list = json[key];
// _pageData = list.map((item) {
// return Map<String, dynamic>.from(item);
// }).toList();
// return _pageData;
// }
// return null;
// }

}

+ 10
- 5
lib/pages/goods_details_page/goods_details_page.dart View File

@@ -19,6 +19,11 @@ class GoodsDetailsPage extends StatefulWidget {
}

class _GoodsDetailsPageState extends State<GoodsDetailsPage> {
@override
void initState() {
print("parent data = ${widget.data}");
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -136,18 +141,18 @@ class _GoodsDetailsContainerState extends State<GoodsDetailsContainer> {
),
),
/// appBar
Align(
alignment: Alignment.topCenter,
child: _getAppBarWidget()),
Align(alignment: Alignment.topCenter, child: _getAppBarWidget()),

/// 底部
Align(alignment: Alignment.bottomCenter, child: GoodsDetailsFooterWidget(null))
Align(alignment: Alignment.bottomCenter, child: GoodsDetailsFooterWidget(!EmptyUtil.isEmpty(datas) ? datas[ datas.length-1 ] : null))
],
);
}

List<Widget> _createContent(BuildContext context, List<Map<String, dynamic>> datas) {
List<Widget> list = List();
for (int i = 0; i < datas.length; i++) {
/// datas.length - 1 为最后一个在底部
for (int i = 0; i < datas.length - 1; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));

print('item.modName ${item.modName}');


+ 11
- 0
lib/pages/sreach_page/sreach_page.dart View File

@@ -0,0 +1,11 @@
import 'package:flutter/material.dart';

///
/// 搜索页
///
class SreachPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

+ 11
- 0
lib/pages/sreach_result_page/sreach_result_page.dart View File

@@ -0,0 +1,11 @@
import 'package:flutter/material.dart';

///
/// 搜索结果页面
///
class SreachResultPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

+ 15
- 3
lib/register.dart View File

@@ -5,6 +5,8 @@ import 'package:zhiying_base_widget/pages/main_page/main_page.dart';
import 'package:zhiying_base_widget/pages/mine_detail_page/mine_detail_page.dart';
import 'package:zhiying_base_widget/pages/orders_page/orders_page.dart';
import 'package:zhiying_base_widget/pages/setting_page/setting_page.dart';
import 'package:zhiying_base_widget/pages/sreach_page/sreach_page.dart';
import 'package:zhiying_base_widget/pages/sreach_result_page/sreach_result_page.dart';
import 'package:zhiying_base_widget/pages/wallet_page/wallet_page.dart';
import 'package:zhiying_base_widget/widgets/home/home_auth/home_auth_creater.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/goods_details_footer_widget.dart';
@@ -33,6 +35,7 @@ import 'package:zhiying_comm/util/defalut_widget_creater.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

import 'widgets/goods_details/coupon/counpon_widget.dart';
import 'widgets/goods_details/detail_img/goods_details_img.dart';
import 'widgets/goods_details/evaluate/goods_details_evaluate_widget.dart';
import 'widgets/goods_details/title/goods_details_title_widget.dart';
import 'widgets/home/home_quick_entry/home_quick_entry.dart';
@@ -51,6 +54,8 @@ class BaseWidgetRegister {
PageFactory.regist('profile', (model) => MainPage(model));
PageFactory.regist('category', (model) => WalletPage());
PageFactory.regist('goods_details', (model) => GoodsDetailsPage(model));
PageFactory.regist('sreach', (model) => SreachPage() );
PageFactory.regist('sreach_result', (model) => SreachResultPage() );
// PageFactory.regist('login', (model) => LoginPage(model));
// PageFactory.regist('login_quick', (model) => LoginQuickPage(model));
// PageFactory.regist('login_account', (model) => LoginAccountPage(model));
@@ -73,7 +78,7 @@ class BaseWidgetRegister {
// WidgetFactory.regist('index_title', NormalNavCreater());
/// 首页搜索栏
// WidgetFactory.regist('index_search', HomeSreachCreater());
// WidgetFactory.regist('index_search', DefaultWidgetCreater((model) => HomeSreachWidget(model)));
WidgetFactory.regist('index_search', DefaultWidgetCreater((model) => HomeSreachWidget(model)));
/// 可滚动banner
WidgetFactory.regist('index_carousel', HomeSlideBannerCreater());
WidgetFactory.regist('index_recommend_list', GoodsListCreater());
@@ -89,6 +94,12 @@ class BaseWidgetRegister {
WidgetFactory.regist('index_banner_two', HomeBannerCreater());
WidgetFactory.regist('index_taobao_auth_tip', HomeAuthCreater());

/// ==================== 搜索页 ==================== ///


/// ==================== 搜索结果页 ==================== ///


/// ==================== 商品详情 ==================== ///
// 商品详情轮播图
WidgetFactory.regist('product_detail_carousel', DefaultWidgetCreater((model) => GoodsDetailsSlideBannerWidget(model)));
@@ -105,9 +116,10 @@ class BaseWidgetRegister {
// 商品详情宝贝评价
WidgetFactory.regist('product_detail_comment', DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model)));
// 商品详情图片
// WidgetFactory.regist('product_detail_img_list', MineNavCreater());
WidgetFactory.regist('product_detail_img_list', DefaultWidgetCreater((model) => GoodsDetailsImgWidget(model)));
// 商品详情底部推荐列表
// WidgetFactory.regist('product_detail_bottom_rec', DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model)));
// WidgetFactory.regist('product_detail_bottom_rec', DefaultWidgetCreater((model) => GoodsListCreater(model)));
WidgetFactory.regist('product_detail_bottom_rec', GoodsListCreater());
// 商品详情底部
WidgetFactory.regist('product_detail_bottom', DefaultWidgetCreater((model) => GoodsDetailsFooterWidget(model)));



+ 6
- 2
lib/widgets/goods_details/coupon/bloc/counpon_bloc.dart View File

@@ -1,9 +1,9 @@
import 'dart:async';
import 'dart:math';

import 'package:bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/bloc/counpon_repository.dart';
import 'bloc.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class CounponBloc extends Bloc<CounponEvent, CounponState> {
@override
@@ -25,6 +25,10 @@ class CounponBloc extends Bloc<CounponEvent, CounponState> {
/// 获取数据
Stream<CounponState> _mapInitEnvetTostate(CounponInitEvent event) async* {
var result = await repository.fetchParentData(event);
yield CounponLoadedState(model: result);
if(!EmptyUtil.isEmpty(result)) {
yield CounponLoadedState(model: result);
}else {
yield CounponErrorState();
}
}
}

+ 8
- 0
lib/widgets/goods_details/coupon/bloc/counpon_repository.dart View File

@@ -1,10 +1,18 @@
import 'dart:convert';

import 'package:zhiying_base_widget/widgets/goods_details/coupon/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/model/counpon_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class CounponRepository {

/// 获取父页面传进来的数据
Future<CounponModel> fetchParentData(CounponInitEvent event) async{
try{
return CounponModel.fromJson(json.decode(event.model['data']));
}catch(e){
Logger.log('CounponRepository e = $e');
}
return null;
}



+ 3
- 0
lib/widgets/goods_details/coupon/bloc/counpon_state.dart View File

@@ -5,11 +5,13 @@ abstract class CounponState extends Equatable {
const CounponState();
}

/// 初始化
class CounponInitial extends CounponState {
@override
List<Object> get props => [];
}

/// 数据加载成功
class CounponLoadedState extends CounponState {
CounponModel model;

@@ -19,6 +21,7 @@ class CounponLoadedState extends CounponState {
List<Object> get props => [this.model];
}

/// 数据加载失败
class CounponErrorState extends CounponState {
@override
List<Object> get props => [];


+ 1
- 1
lib/widgets/goods_details/coupon/counpon_sk.dart View File

@@ -5,7 +5,7 @@ class CounponSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 12),
width: double.infinity,
height: 70,
child: _shimmerWidget(width: double.infinity, height: 65, radius: 7.5),


+ 43
- 27
lib/widgets/goods_details/coupon/counpon_widget.dart View File

@@ -5,6 +5,7 @@ import 'package:zhiying_base_widget/widgets/goods_details/coupon/counpon_sk.dart
import 'package:zhiying_base_widget/widgets/goods_details/coupon/model/counpon_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:cached_network_image/cached_network_image.dart';

///
/// 优惠券widget
@@ -16,26 +17,26 @@ class CounponWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Container();
// return BlocProvider<CounponBloc>(
// create: (_) => CounponBloc(repository: CounponRepository())..add(CounponInitEvent(model: model)),
// child: CounponContainer(),
// );
// return Container();
return BlocProvider<CounponBloc>(
create: (_) => CounponBloc(repository: CounponRepository())..add(CounponInitEvent(model: model)),
child: CounponWidgetContainer(),
);
}
}

class CounponContainer extends StatefulWidget {
class CounponWidgetContainer extends StatefulWidget {
@override
_CounponContainerState createState() => _CounponContainerState();
_CounponWidgetContainerState createState() => _CounponWidgetContainerState();
}

class _CounponContainerState extends State<CounponContainer> {
class _CounponWidgetContainerState extends State<CounponWidgetContainer> {
/// 点击领取
void _onJump(CounponModel model) {}

@override
Widget build(BuildContext context) {
BlocConsumer<CounponBloc, CounponState>(
return BlocConsumer<CounponBloc, CounponState>(
listener: (context, state) {},
buildWhen: (prev, current) {
if (current is CounponErrorState) {
@@ -45,10 +46,9 @@ class _CounponContainerState extends State<CounponContainer> {
},
builder: (context, state) {
if (state is CounponLoadedState) {
// return _getMainWdiget(state.model);
return _getMainWdiget(state.model);
}
// return CounponSkeleton();
return Container();
return CounponSkeleton();
},
);
}
@@ -60,17 +60,30 @@ class _CounponContainerState extends State<CounponContainer> {
behavior: HitTestBehavior.opaque,
child: Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
padding: const EdgeInsets.only(left: 18.5),
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
/// 价格
_getPriceWidget(model),
const SizedBox(width: 7.5),
/// 有效期
_getTimeWidget(model)
],
color: Colors.white,
padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 12),
child: Container(
// color: Colors.red,
width: double.infinity,
padding: const EdgeInsets.only(left: 18.5, top: 12, bottom: 14),
decoration: BoxDecoration(
image: DecorationImage(
image: CachedNetworkImageProvider(
model?.bg_img ??'',
),
fit: BoxFit.fill
)
),
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
/// 价格
_getPriceWidget(model),
const SizedBox(width: 7.5),
/// 有效期
_getTimeWidget(model)
],
),
),
),
);
@@ -79,12 +92,14 @@ class _CounponContainerState extends State<CounponContainer> {
/// 价格
Widget _getPriceWidget(CounponModel model) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
/// 价格类型
Text('¥', style: TextStyle(fontSize: 15, color: HexColor.fromHex('#FFFFFF'))),
Text(model?.price_type ?? '¥ ', style: TextStyle(fontSize: 15, color: HexColor.fromHex(model?.price_type_color ?? '#FFFFFF'))),

/// 价格
Text('100', style: TextStyle(fontSize: 30, color: HexColor.fromHex('#FFFFFF'))),
Text(model?.coupon_price ??'100', style: TextStyle(fontSize: 30, color: HexColor.fromHex(model?.coupon_price_color ?? '#FFFFFF'), fontFamily: 'Din', package: 'zhiying_base_widget')),
],
);
}
@@ -92,12 +107,13 @@ class _CounponContainerState extends State<CounponContainer> {
/// 名称与有效期
Widget _getTimeWidget(CounponModel model) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
/// 标题
Text('优惠券', style: TextStyle(fontSize: 17, color: HexColor.fromHex('#FFFFFF'))),
Text(model?.coupon_title ?? '优惠券', style: TextStyle(fontSize: 17, color: HexColor.fromHex( model?.coupon_title_color ?? '#FFFFFF'))),

/// 到期时间
Text('有效期至2020-10-01', style: TextStyle(fontSize: 10, color: HexColor.fromHex('#FFFFFF')))
Text(model?.coupon_endtime ?? '有效期至2020-10-01', style: TextStyle(fontSize: 10, color: HexColor.fromHex(model?.coupon_time_color ?? '#FFFFFF')))
],
);
}


+ 53
- 1
lib/widgets/goods_details/coupon/model/counpon_model.dart View File

@@ -1,2 +1,54 @@
class CounponModel {
String bg_img;
String coupon_endtime;
String coupon_price;
String coupon_price_color;
String coupon_time_color;
String coupon_title;
String coupon_title_color;
String coupon_url;
String price_type;
String price_type_color;

class CounponModel{}
CounponModel(
{this.bg_img,
this.coupon_endtime,
this.coupon_price,
this.coupon_price_color,
this.coupon_time_color,
this.coupon_title,
this.coupon_title_color,
this.coupon_url,
this.price_type,
this.price_type_color});

factory CounponModel.fromJson(Map<String, dynamic> json) {
return CounponModel(
bg_img: json['bg_img'],
coupon_endtime: json['coupon_endtime'],
coupon_price: json['coupon_price'],
coupon_price_color: json['coupon_price_color'],
coupon_time_color: json['coupon_time_color'],
coupon_title: json['coupon_title'],
coupon_title_color: json['coupon_title_color'],
coupon_url: json['coupon_url'],
price_type: json['price_type'],
price_type_color: json['price_type_color'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['bg_img'] = this.bg_img;
data['coupon_endtime'] = this.coupon_endtime;
data['coupon_price'] = this.coupon_price;
data['coupon_price_color'] = this.coupon_price_color;
data['coupon_time_color'] = this.coupon_time_color;
data['coupon_title'] = this.coupon_title;
data['coupon_title_color'] = this.coupon_title_color;
data['coupon_url'] = this.coupon_url;
data['price_type'] = this.price_type;
data['price_type_color'] = this.price_type_color;
return data;
}
}

+ 54
- 0
lib/widgets/goods_details/detail_img/bloc/goods_details_img_bloc.dart View File

@@ -0,0 +1,54 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/widgets/goods_details/detail_img/bloc/goods_details_img_repository.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_base_widget/widgets/goods_details/detail_img/model/goods_details_img_model.dart';
import 'package:zhiying_comm/util/global_config.dart';

part 'goods_details_img_event.dart';

part 'goods_details_img_state.dart';

class GoodsDetailsImgBloc extends Bloc<GoodsDetailsImgEvent, GoodsDetailsImgState> {
GoodsDetailsImgBloc({this.repository});

GoodsDetailsImgRepository repository;

@override
GoodsDetailsImgState get initialState => GoodsDetailsImgInitial();

@override
Stream<GoodsDetailsImgState> mapEventToState(
GoodsDetailsImgEvent event,
) async* {
/// 初始化事件
if (event is GoodsDetailsImgInitEvent) {
yield* _mapInitEventToState(event);
}
}

/// 初始化方法
Stream<GoodsDetailsImgState> _mapInitEventToState(GoodsDetailsImgInitEvent event) async* {
var parentData = await repository.fetchParentData(event.model);
if (!EmptyUtil.isEmpty(parentData)) {
yield GoodsDetailsImgLoadedState(model: parentData);
/// 如果等于淘宝类型,就前端去抓去商品详情图片
if (parentData.provider == GlobalConfig.PROVIDER_TB || parentData.provider == GlobalConfig.PROVIDER_TM) {
/// 进行网络访问
var netData = await repository.fetchNetData(event.model);
if (!EmptyUtil.isEmpty(netData)) {
// yield Good;
yield GoodsDetailsImgLoadedState(model: netData);
} else {
yield GoodsDetailsImgErrorState();
}
}

} else {
yield GoodsDetailsImgErrorState();
}
}
}

+ 18
- 0
lib/widgets/goods_details/detail_img/bloc/goods_details_img_event.dart View File

@@ -0,0 +1,18 @@
part of 'goods_details_img_bloc.dart';

abstract class GoodsDetailsImgEvent extends Equatable {
const GoodsDetailsImgEvent();

@override
List<Object> get props => [];
}

/// 初始化数据
class GoodsDetailsImgInitEvent extends GoodsDetailsImgEvent {
final Map<String, dynamic> model;

const GoodsDetailsImgInitEvent({@required this.model});

@override
List<Object> get props => [this.model];
}

+ 35
- 0
lib/widgets/goods_details/detail_img/bloc/goods_details_img_repository.dart View File

@@ -0,0 +1,35 @@
import 'dart:convert';

import 'package:zhiying_base_widget/widgets/goods_details/detail_img/model/goods_details_img_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:zhiying_comm/util/taobao/taobao_loader.dart';

class GoodsDetailsImgRepository {
GoodsDetailsImgModel _model;
/// 获取父数据
Future<GoodsDetailsImgModel> fetchParentData(final Map<String, dynamic> model) async {
try {
_model = GoodsDetailsImgModel.fromJson(jsonDecode(model['data']));
if(!EmptyUtil.isEmpty(_model)) {
return _model;
}
} catch (e) {
Logger.log('GoodsDetailsImgRepository e = $e');
}
return null;
}

/// 获取网络的数据
Future<GoodsDetailsImgModel> fetchNetData(final Map<String, dynamic> model) async {
try {
if(!EmptyUtil.isEmpty(_model)) {
List<String> imgs = await TaobaoLoader.loadImages(_model.good_id);
_model.image_detail_list = imgs;
return _model;
}
}catch(e){

}
return null;
}
}

+ 30
- 0
lib/widgets/goods_details/detail_img/bloc/goods_details_img_state.dart View File

@@ -0,0 +1,30 @@
part of 'goods_details_img_bloc.dart';

abstract class GoodsDetailsImgState extends Equatable {
const GoodsDetailsImgState();

@override
List<Object> get props => [];
}

class GoodsDetailsImgInitial extends GoodsDetailsImgState {
@override
List<Object> get props => [];
}

/// 数据加载成功
class GoodsDetailsImgLoadedState extends GoodsDetailsImgState {
GoodsDetailsImgModel model;

GoodsDetailsImgLoadedState({this.model});

GoodsDetailsImgLoadedState copyWith({@required GoodsDetailsImgModel newData}) {
return GoodsDetailsImgLoadedState(model: newData ?? model);
}

@override
List<Object> get props => [this.model];
}

/// 数据加载失败
class GoodsDetailsImgErrorState extends GoodsDetailsImgState {}

+ 110
- 0
lib/widgets/goods_details/detail_img/goods_details_img.dart View File

@@ -0,0 +1,110 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/detail_img/bloc/goods_details_img_bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/detail_img/goods_details_img_sk.dart';
import 'package:zhiying_base_widget/widgets/goods_details/detail_img/model/goods_details_img_model.dart';
import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:zhiying_base_widget/widgets/goods_details/detail_img/bloc/goods_details_img_repository.dart';

///
/// 商品详情图片
///
class GoodsDetailsImgWidget extends StatelessWidget {
final Map<String, dynamic> model;

const GoodsDetailsImgWidget(this.model);

@override
Widget build(BuildContext context) {
return BlocProvider<GoodsDetailsImgBloc>(
create: (_) => GoodsDetailsImgBloc(repository: GoodsDetailsImgRepository())..add(GoodsDetailsImgInitEvent(model: model)),
child: GoodsDetailsImgWidgetContainer(),
);
}
}

class GoodsDetailsImgWidgetContainer extends StatefulWidget {
@override
_GoodsDetailsImgWidgetContainerState createState() => _GoodsDetailsImgWidgetContainerState();
}

class _GoodsDetailsImgWidgetContainerState extends State<GoodsDetailsImgWidgetContainer> {
@override
Widget build(BuildContext context) {
return BlocConsumer<GoodsDetailsImgBloc, GoodsDetailsImgState>(
listener: (BuildContext context, GoodsDetailsImgState state) {
if (state is GoodsDetailsImgErrorState) {
print('数据加载出错');
}
},
buildWhen: (previous, current) {
/// 数据加载出错不进行build
if (current is GoodsDetailsImgErrorState) {
return false;
}
return true;
},
builder: (context, state) {
print('currente state = $state');
if (state is GoodsDetailsImgLoadedState) {
if (!EmptyUtil.isEmpty(state.model)) {
return _getMainWidget(state.model);
}
}
// 骨架屏
return GoodsDetailsImgSkeleton();
},
);
}

///
Widget _getMainWidget(GoodsDetailsImgModel model) {
return Column(
children: <Widget>[
/// 标题
_getTitleWidget(model),
/// 图片列表
_getImgListWidget(model),
],
);
}

/// 图片列表
Widget _getImgListWidget(GoodsDetailsImgModel model){
return Column(
children: model.image_detail_list.map((item){
return CachedNetworkImage(
imageUrl: item ?? '',
fit: BoxFit.fitWidth,
);
}).toList(),
);
}

/// 标题Widget
Widget _getTitleWidget(GoodsDetailsImgModel model) {
return Container(
color: Colors.white,
margin: const EdgeInsets.only(top: 6),
width: double.infinity,
padding: const EdgeInsets.only(top: 15, bottom: 15, left: 12.5, right: 12.5),
child: _getLeftWidget(model),
);
}

/// 左边图标加文字
Widget _getLeftWidget(GoodsDetailsImgModel model) {
return Row(
children: <Widget>[
CachedNetworkImage(
imageUrl: model?.icon ?? '',
width: 12,
),
const SizedBox(width: 2.5),
Text(model?.title ?? '商品详情', style: TextStyle(color: HexColor.fromHex(model?.title_color ?? '#333333'), fontSize: 12)),
],
);
}
}

+ 11
- 0
lib/widgets/goods_details/detail_img/goods_details_img_sk.dart View File

@@ -0,0 +1,11 @@
import 'package:flutter/material.dart';

///
/// 商品详情骨架图
///
class GoodsDetailsImgSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

+ 41
- 0
lib/widgets/goods_details/detail_img/model/goods_details_img_model.dart View File

@@ -0,0 +1,41 @@
class GoodsDetailsImgModel {
List<String> image_detail_list;
String title;
String title_color;
String provider;
String good_id;
String icon;

GoodsDetailsImgModel({
this.image_detail_list,
this.title,
this.title_color,
this.provider,
this.good_id,
this.icon
});

factory GoodsDetailsImgModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsImgModel(
image_detail_list: json['image_detail_list'] != null ? new List<String>.from(json['image_detail_list']) : null,
title: json['title'],
title_color: json['title_color'],
provider: json['provider'],
good_id: json['good_id'],
icon: json['icon']
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['title'] = this.title;
data['title_color'] = this.title_color;
if (this.image_detail_list != null) {
data['image_detail_list'] = this.image_detail_list;
}
data['provider'] = this.provider;
data['good_id'] = this.good_id;
data['icon'] = this.icon;
return data;
}
}

+ 34
- 5
lib/widgets/goods_details/evaluate/goods_details_evaluate_widget.dart View File

@@ -1,4 +1,8 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/evaluate/model/goods_details_evaluate_model.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
@@ -6,8 +10,15 @@ import 'package:zhiying_comm/zhiying_comm.dart';
///
class GoodsDetailsEvaluateWidget extends StatelessWidget {
final Map<String, dynamic> model;
GoodsDetailsEvaluateModel _modell;

const GoodsDetailsEvaluateWidget(this.model);
GoodsDetailsEvaluateWidget(this.model, {Key key}) : super(key: key) {
try {
_modell = GoodsDetailsEvaluateModel.fromJson(jsonDecode(model['data']));
} catch (e) {
Logger.log('GoodsDetailsEvaluateWidget e = $e}');
}
}

/// 点击查看更多
void _openLookMore() {}
@@ -18,21 +29,39 @@ class GoodsDetailsEvaluateWidget extends StatelessWidget {
onTap: () => _openLookMore(),
behavior: HitTestBehavior.opaque,
child: Container(
color: Colors.white,
margin: const EdgeInsets.only(top: 6),
width: double.infinity,
padding: const EdgeInsets.only(top: 15, bottom: 15, left: 12.5, right: 12.5),
child: getMainWidget(),
child: getMainWidget(_modell),
),
);
}

/// 评价以及查看更多
Widget getMainWidget() {
Widget getMainWidget(GoodsDetailsEvaluateModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('宝贝评价', style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 12)),
Text('查看更多 >', style: TextStyle(color: HexColor.fromHex('#999999'), fontSize: 11)),
getLeftWidget(model),
Text(model?.more ?? '查看更多 >', style: TextStyle(color: HexColor.fromHex(model?.more_color ?? '#999999'), fontSize: 11)),
],
);
}


/// 左边图标加文字
Widget getLeftWidget(GoodsDetailsEvaluateModel model){
return Row(
children: <Widget>[
CachedNetworkImage(
imageUrl: model?.icon ?? '',
width: 12,
),
const SizedBox(width: 2.5),
Text(model?.title ?? '宝贝评价', style: TextStyle(color: HexColor.fromHex(model?.title_color ?? '#333333'), fontSize: 12)),
],
);
}

}

+ 39
- 0
lib/widgets/goods_details/evaluate/model/goods_details_evaluate_model.dart View File

@@ -0,0 +1,39 @@
class GoodsDetailsEvaluateModel {
String comment_url;
String more;
String more_color;
String title;
String title_color;
String icon;

GoodsDetailsEvaluateModel({
this.comment_url,
this.more,
this.more_color,
this.title,
this.title_color,
this.icon,
});

factory GoodsDetailsEvaluateModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsEvaluateModel(
comment_url: json['comment_url'],
more: json['more'],
more_color: json['more_color'],
title: json['title'],
title_color: json['title_color'],
icon: json['icon'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['comment_url'] = this.comment_url;
data['more'] = this.more;
data['more_color'] = this.more_color;
data['title'] = this.title;
data['title_color'] = this.title_color;
data['icon'] = this.icon;
return data;
}
}

+ 51
- 0
lib/widgets/goods_details/footer/bloc/goods_details_footer_bloc.dart View File

@@ -0,0 +1,51 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/bloc/goods_details_footer_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/model/goods_details_footer_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';

part 'goods_details_footer_event.dart';

part 'goods_details_footer_state.dart';

class GoodsDetailsFooterBloc extends Bloc<GoodsDetailsFooterEvent, GoodsDetailsFooterState> {
GoodsDetailsFooterBloc({this.repository});

GoodsDetailsFooterRepository repository;

@override
GoodsDetailsFooterState get initialState => GoodsDetailsFooterInitial();

@override
Stream<GoodsDetailsFooterState> mapEventToState(
GoodsDetailsFooterEvent event,
) async* {
/// 初始化
if (event is GoodsDetailsFooterInitEvent) {
yield* _mapInitEventToState(event);
}
}

/// 初始化
Stream<GoodsDetailsFooterState> _mapInitEventToState(GoodsDetailsFooterInitEvent event) async* {
var result = await repository.fetchParentData(event.model);
if (!EmptyUtil.isEmpty(result)) {
print('result = ${result.toString()}');
yield GoodsDetailsFooterLoadedState(model: result);
} else {
yield GoodsDetailsFooterErrorState();
}
}

/// 点击收藏
Stream<GoodsDetailsFooterState> _mapCollectEventToState(GoodsDetailsFooterCollectEvent event) async* {
var result = await repository.fetchCollect();
if (!EmptyUtil.isEmpty(result))
yield GoodsDetailsFooterLoadedState(model: result);
else
yield GoodsDetailsFooterErrorState();
}
}

+ 23
- 0
lib/widgets/goods_details/footer/bloc/goods_details_footer_event.dart View File

@@ -0,0 +1,23 @@
part of 'goods_details_footer_bloc.dart';

abstract class GoodsDetailsFooterEvent extends Equatable {
const GoodsDetailsFooterEvent();

@override
List<Object> get props => [];
}

/// 初始化事件
class GoodsDetailsFooterInitEvent extends GoodsDetailsFooterEvent {
final Map<String, dynamic> model;

const GoodsDetailsFooterInitEvent({@required this.model});

@override
List<Object> get props => [this.model];
}

/// 点击收藏
class GoodsDetailsFooterCollectEvent extends GoodsDetailsFooterEvent {

}

+ 25
- 0
lib/widgets/goods_details/footer/bloc/goods_details_footer_repository.dart View File

@@ -0,0 +1,25 @@
import 'dart:convert';

import 'package:zhiying_base_widget/widgets/goods_details/footer/model/goods_details_footer_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class GoodsDetailsFooterRepository {
/// 初始化数据
Future<GoodsDetailsFooterModel> fetchParentData(final Map<String, dynamic> model) async {
try {
return GoodsDetailsFooterModel.fromJson(jsonDecode(model['data']));
} catch (e) {
Logger.log('GoodsDetailsFooterRepository e = $e');
}
return null;
}

/// 点击收藏
Future<GoodsDetailsFooterModel> fetchCollect() async{
return null;
}

/// 跳转购买

/// 分享
}

+ 29
- 0
lib/widgets/goods_details/footer/bloc/goods_details_footer_state.dart View File

@@ -0,0 +1,29 @@
part of 'goods_details_footer_bloc.dart';

abstract class GoodsDetailsFooterState extends Equatable {
const GoodsDetailsFooterState();

@override
List<Object> get props => [];
}

class GoodsDetailsFooterInitial extends GoodsDetailsFooterState {
@override
List<Object> get props => [];
}

/// 数据加载完毕
class GoodsDetailsFooterLoadedState extends GoodsDetailsFooterState {
GoodsDetailsFooterModel model;

GoodsDetailsFooterLoadedState({@required this.model});

@override
List<Object> get props => [this.model];
}

/// 数据加载出错
class GoodsDetailsFooterErrorState extends GoodsDetailsFooterState {
@override
List<Object> get props => [];
}

+ 2
- 1
lib/widgets/goods_details/footer/goods_details_footer_sk.dart View File

@@ -6,6 +6,7 @@ class GoodsDetailsFooterSkeleton extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: Colors.white,
padding: const EdgeInsets.only(left: 21, right: 12.5, top: 12.5, bottom: 12.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -18,7 +19,7 @@ class GoodsDetailsFooterSkeleton extends StatelessWidget {
],
),

_shimmerWidget( height: 44, width: 230, radius: 22),
_shimmerWidget( height: 44, width: 180, radius: 22),
],
),
);


+ 74
- 38
lib/widgets/goods_details/footer/goods_details_footer_widget.dart View File

@@ -1,18 +1,30 @@
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/bloc/goods_details_footer_bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/bloc/goods_details_footer_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/goods_details_footer_sk.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/model/goods_details_footer_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:cached_network_image/cached_network_image.dart';

///
/// 商品详情底部Widget
///
class GoodsDetailsFooterWidget extends StatelessWidget {

final Map<String, dynamic> model;

const GoodsDetailsFooterWidget(this.model);

@override
Widget build(BuildContext context) {
return GooddsDetailsFooterContainer();
return Visibility(
visible: !EmptyUtil.isEmpty(model),
replacement: GoodsDetailsFooterSkeleton(),
child: BlocProvider<GoodsDetailsFooterBloc>(
create: (_) => GoodsDetailsFooterBloc(repository: GoodsDetailsFooterRepository())..add(GoodsDetailsFooterInitEvent(model: model)),
child: GooddsDetailsFooterContainer(),
),
);
}
}

@@ -36,38 +48,57 @@ class _GooddsDetailsFooterContainerState extends State<GooddsDetailsFooterContai

@override
Widget build(BuildContext context) {
return BlocConsumer<GoodsDetailsFooterBloc, GoodsDetailsFooterState>(
listener: (context, state) {},
buildWhen: (prev, current) {
if (current is GoodsDetailsFooterErrorState) {
return false;
}
return true;
},
builder: (context, state) {
print('GoodsDetailsFooterWidget state = $state');
if (state is GoodsDetailsFooterLoadedState) {
return _getMainWidget(state.model);
}
return GoodsDetailsFooterSkeleton();
},
);
}

Widget _getMainWidget(GoodsDetailsFooterModel model) {
return Container(
height: 70,
width: double.infinity,
padding: const EdgeInsets.only(bottom: 10, top: 12.5, left: 21, right: 12.5),
decoration: BoxDecoration(
boxShadow:[
BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0), blurRadius: 5.0, spreadRadius: 2.0),
BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0)),
],
color: Colors.white
// boxShadow: [
// BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0), blurRadius: 5.0, spreadRadius: 2.0),
// BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0)),
// ],
color: Colors.white,
),
child: _getMainWidet(),
child: _getMainWidet(model),
);
}

/// 主Widget
Widget _getMainWidet() {
Widget _getMainWidet(GoodsDetailsFooterModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
/// 首页与收藏
_getLeftWidget(),
_getLeftWidget(model),

/// 分享赚与自购省
_getRightWidget(),
_getRightWidget(model),
],
);
}

/// 首页 和 收藏
Widget _getLeftWidget() {
Widget _getLeftWidget(GoodsDetailsFooterModel model) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
@@ -77,47 +108,43 @@ class _GooddsDetailsFooterContainerState extends State<GooddsDetailsFooterContai
onTap: () => _openHome(),
child: Padding(
padding: const EdgeInsets.only(right: 35),
child: _getCustomWidget('首页', '999999', null),
child: _getCustomWidget(model?.home ?? '首页', model?.home_color ?? '999999', model?.home_icon ?? ''),
)),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _collectOnClick(),
child: Padding(padding: const EdgeInsets.only(right: 0), child: _getCustomWidget('收藏', '999999', null)))
child: Padding(padding: const EdgeInsets.only(right: 0), child: _getCustomWidget(model?.collect ?? '收藏', model?.collect_color ?? '999999', model?.collect_icon ?? '')))
],
);
}

/// 分享赚与自购省
Widget _getRightWidget() {
Widget _getRightWidget(GoodsDetailsFooterModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[_getFxzButton(), _getZgsButton()],
children: <Widget>[_getFxzButton(model), _getZgsButton(model)],
);
}

/// 分享赚,
Widget _getFxzButton() {
Widget _getFxzButton(GoodsDetailsFooterModel model) {
return GestureDetector(
onTap: () => _shareOnClick(),
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [HexColor.fromHex('#FFCA66'), HexColor.fromHex('#FFD961')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
topLeft: Radius.circular(25)
)
),
gradient: LinearGradient(colors: [HexColor.fromHex(model?.share_earn_bg1_color ?? '#FFCA66'), HexColor.fromHex(model?.share_earn_bg2_color ?? '#FFD961')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(25), topLeft: Radius.circular(25))),
child: Column(
children: <Widget>[
RichText(
text: TextSpan(text: '¥', style: TextStyle(fontSize: 12, color: HexColor.fromHex('FFFFFF')), children: [
TextSpan(text: '3.10', style: TextStyle(fontSize: 15, color: HexColor.fromHex('#FFFFFF'))),
text: TextSpan(text: '¥ ', style: TextStyle(fontSize: 12, color: HexColor.fromHex(model?.share_earn_val_color ?? 'FFFFFF')), children: [
TextSpan(text: model?.share_value ?? '0.0', style: TextStyle(fontSize: 15, color: HexColor.fromHex(model?.share_earn_color ?? '#FFFFFF'), fontFamily: 'Din', package: 'zhiying_base_widget')),
]),
),
Text('分享赚', style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 15))
Text(model?.share_earn ?? '分享赚', style: TextStyle(color: HexColor.fromHex(model?.share_earn_color ?? '#FFFFFF'), fontSize: 15))
],
),
),
@@ -125,7 +152,7 @@ class _GooddsDetailsFooterContainerState extends State<GooddsDetailsFooterContai
}

/// 自购省
Widget _getZgsButton() {
Widget _getZgsButton(GoodsDetailsFooterModel model) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _savemoneyOnClick(),
@@ -133,20 +160,23 @@ class _GooddsDetailsFooterContainerState extends State<GooddsDetailsFooterContai
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [HexColor.fromHex('#FF6969'), HexColor.fromHex('#FF4646')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(25),
topRight: Radius.circular(25)
)
),
gradient: LinearGradient(colors: [HexColor.fromHex(model?.save_earn_bg1_color ?? '#FF6969'), HexColor.fromHex(model?.save_earn_bg2_color ?? '#FF4646')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.only(bottomRight: Radius.circular(25), topRight: Radius.circular(25))),
child: Column(
children: <Widget>[
RichText(
text: TextSpan(text: '¥', style: TextStyle(fontSize: 12, color: HexColor.fromHex('FFFFFF')), children: [
TextSpan(text: '23.10', style: TextStyle(fontSize: 15, color: HexColor.fromHex('#FFFFFF'))),
text: TextSpan(text: '¥ ', style: TextStyle(fontSize: 12, color: HexColor.fromHex(model?.save_earn_val_color ?? 'FFFFFF')), children: [
TextSpan(
text: model?.slef_buy_value ??'0.0',
style: TextStyle(
fontSize: 15,
color: HexColor.fromHex(model?.save_earn_val_color ?? '#FFFFFF'),
fontFamily: 'Din',
package: 'zhiying_base_widget',
)),
]),
),
Text('自购省', style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 15))
Text(model?.save_earn ?? '自购省', style: TextStyle(color: HexColor.fromHex(model?.save_earn_color ?? '#FFFFFF'), fontSize: 15))
],
),
),
@@ -159,8 +189,14 @@ class _GooddsDetailsFooterContainerState extends State<GooddsDetailsFooterContai
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
/// 图标
Container(height: 25, width: 25, color: Colors.red, margin: const EdgeInsets.only(bottom: 3)),

CachedNetworkImage(
imageUrl: icon,
fit: BoxFit.fill,
width: 25,
height: 25,
),
// Container( width: 25, margin: const EdgeInsets.only(bottom: 3), child: CachedNetworkImage(imageUrl: icon, fit: BoxFit.fill, width: 25,),),
const SizedBox(height: 3),
/// 图片
Text(text, style: TextStyle(color: HexColor.fromHex(textColor), fontSize: 11))
],


+ 69
- 0
lib/widgets/goods_details/footer/model/goods_details_footer_model.dart View File

@@ -0,0 +1,69 @@

class GoodsDetailsFooterModel {
String collect;
String collect_color;
String collect_icon;
String home;
String home_color;
String home_icon;
String save_earn;
String save_earn_bg1_color;
String save_earn_bg2_color;
String save_earn_color;
String save_earn_val_color;
String share_earn;
String share_earn_bg1_color;
String share_earn_bg2_color;
String share_earn_color;
String share_earn_val_color;
String share_value;
String slef_buy_value;

GoodsDetailsFooterModel({this.collect, this.collect_color, this.collect_icon, this.home, this.home_color, this.home_icon, this.save_earn, 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.slef_buy_value});

factory GoodsDetailsFooterModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsFooterModel(
collect: json['collect'],
collect_color: json['collect_color'],
collect_icon: json['collect_icon'],
home: json['home'],
home_color: json['home_color'],
home_icon: json['home_icon'],
save_earn: json['save_earn'],
save_earn_bg1_color: json['save_earn_bg1_color'],
save_earn_bg2_color: json['save_earn_bg2_color'],
save_earn_color: json['save_earn_color'],
save_earn_val_color: json['save_earn_val_color'],
share_earn: json['share_earn'],
share_earn_bg1_color: json['share_earn_bg1_color'],
share_earn_bg2_color: json['share_earn_bg2_color'],
share_earn_color: json['share_earn_color'],
share_earn_val_color: json['share_earn_val_color'],
share_value: json['share_value'],
slef_buy_value: json['slef_buy_value'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['collect'] = this.collect;
data['collect_color'] = this.collect_color;
data['collect_icon'] = this.collect_icon;
data['home'] = this.home;
data['home_color'] = this.home_color;
data['home_icon'] = this.home_icon;
data['save_earn'] = this.save_earn;
data['save_earn_bg1_color'] = this.save_earn_bg1_color;
data['save_earn_bg2_color'] = this.save_earn_bg2_color;
data['save_earn_color'] = this.save_earn_color;
data['save_earn_val_color'] = this.save_earn_val_color;
data['share_earn'] = this.share_earn;
data['share_earn_bg1_color'] = this.share_earn_bg1_color;
data['share_earn_bg2_color'] = this.share_earn_bg2_color;
data['share_earn_color'] = this.share_earn_color;
data['share_earn_val_color'] = this.share_earn_val_color;
data['share_value'] = this.share_value;
data['slef_buy_value'] = this.slef_buy_value;
return data;
}
}

+ 37
- 21
lib/widgets/goods_details/price/goods_details_price_widget.dart View File

@@ -1,4 +1,7 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/price/model/goods_details_price_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
@@ -6,78 +9,91 @@ import 'package:zhiying_comm/zhiying_comm.dart';
///
class GoodsDetailsPriceWidget extends StatelessWidget {
final Map<String, dynamic> model;

const GoodsDetailsPriceWidget(this.model);
GoodsDetailsPriceModel _model;
GoodsDetailsPriceWidget(this.model, {Key key}) : super(key: key){
try{
_model = GoodsDetailsPriceModel.fromJson(jsonDecode(model['data']));
}catch(e){
Logger.log('GoodsDetailsPriceWidget e = $e');
}
}

@override
Widget build(BuildContext context) {
return Container(margin: const EdgeInsets.symmetric(horizontal: 12.5), child: _getMainWidget());
return Container(
width: double.infinity,
color: Colors.white,
padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 7.5),
child: _getMainWidget(_model),
);
}

/// 主体视图
Widget _getMainWidget() {
Widget _getMainWidget(GoodsDetailsPriceModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_getLeftWidget(),
_getLeftWidget(model),

/// 右边widget
_getBuyNumberWidget(),
_getBuyNumberWidget(model),
],
);
}

/// 左边的wiget 包括价格等
Widget _getLeftWidget() {
Widget _getLeftWidget(GoodsDetailsPriceModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
/// 价格
_getPriceWidget(),
_getPriceWidget(model),
const SizedBox(width: 5),

/// 券后
_getQhPriceWidget(),
_getQhPriceWidget(model),
const SizedBox(width: 5),

/// 积分
_getPointsWidget()
Visibility(
visible: !EmptyUtil.isEmpty(model?.point),
child: _getPointsWidget(model))
],
);
}

/// 价格
Widget _getPriceWidget() {
Widget _getPriceWidget(GoodsDetailsPriceModel model) {
return Row(
children: <Widget>[
Text('¥', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 15)),
Text('99', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 30)),
Text(model?.symbol ?? '¥ ', style: TextStyle(color: HexColor.fromHex( model?.price_color ??'#FF4242'), fontSize: 15)),
Text(model?.current_price ?? '0', style: TextStyle(color: HexColor.fromHex(model?.price_color ?? '#FF4242'), fontSize: 30, fontFamily: 'Din', package: 'zhiying_base_widget')),
],
);
}

/// 积分
Widget _getPointsWidget() {
Widget _getPointsWidget(GoodsDetailsPriceModel model) {
return Container(
decoration: BoxDecoration(color: HexColor.fromHex('#FFEFDA'), borderRadius: BorderRadius.circular(5)),
decoration: BoxDecoration(color: HexColor.fromHex(model?.points_bg_color ?? '#FFEFDA'), borderRadius: BorderRadius.circular(5)),
padding: const EdgeInsets.only(left: 4, right: 7.5, top: 4, bottom: 4),
child: Text('', style: TextStyle(color: HexColor.fromHex('#B78107'), fontSize: 9)),
child: Text(model?.point ?? '+ 0.00 积分', style: TextStyle(color: HexColor.fromHex( model?.points_color ?? '#B78107'), fontSize: 9, fontFamily: 'Din', package: 'zhiying_base_widget')),
);
}

/// 券后价格
Widget _getQhPriceWidget() {
Widget _getQhPriceWidget(GoodsDetailsPriceModel model) {
return Column(
children: <Widget>[
Text('券后', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 11)),
Text('¥ 199', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 10)),
Text(model?.ticket ?? '券后', style: TextStyle(color: HexColor.fromHex(model?.ticket_color ?? '#FF4242'), fontSize: 11)),
Text('${model?.symbol}${model?.market_price}' ?? '¥ 199', style: TextStyle(color: HexColor.fromHex(model?.ticket_price_color ?? '#FF4242'), fontSize: 10, fontFamily: 'Din', package: 'zhiying_base_widget', decoration: TextDecoration.lineThrough)),
],
);
}

/// 购买人数
Widget _getBuyNumberWidget() {
return Text('99999人已购买', style: TextStyle(color: HexColor.fromHex('#999999'), fontSize: 12.5));
Widget _getBuyNumberWidget(GoodsDetailsPriceModel model) {
return Text('${model?.sold_count}${model?.buy_text}' ?? '99999人已购买', style: TextStyle(color: HexColor.fromHex(model?.buy_color ?? '#999999'), fontSize: 12.5));
}
}

+ 71
- 0
lib/widgets/goods_details/price/model/goods_details_price_model.dart View File

@@ -0,0 +1,71 @@
class GoodsDetailsPriceModel {
String buy_color;
String buy_text;
String current_price;
String good_id;
String market_price;
String point;
String points_bg_color;
String points_color;
String sold_count;
String ticket;
String ticket_color;
String ticket_price_color;
String price_color;
String symbol;


GoodsDetailsPriceModel(
{this.buy_color,
this.buy_text,
this.current_price,
this.good_id,
this.market_price,
this.point,
this.points_bg_color,
this.points_color,
this.sold_count,
this.ticket,
this.ticket_color,
this.ticket_price_color,
this.price_color,
this.symbol});

factory GoodsDetailsPriceModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsPriceModel(
buy_color: json['buy_color'],
buy_text: json['buy_text'],
current_price: json['current_price'],
good_id: json['good_id'],
market_price: json['market_price'],
point: json['point'],
points_bg_color: json['points_bg_color'],
points_color: json['points_color'],
sold_count: json['sold_count'],
ticket: json['ticket'],
ticket_color: json['ticket_color'],
ticket_price_color: json['ticket_price_color'],
price_color: json['price_color'],
symbol: json['symbol'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['buy_color'] = this.buy_color;
data['buy_text'] = this.buy_text;
data['current_price'] = this.current_price;
data['good_id'] = this.good_id;
data['market_price'] = this.market_price;
data['point'] = this.point;
data['points_bg_color'] = this.points_bg_color;
data['points_color'] = this.points_color;
data['sold_count'] = this.sold_count;
data['ticket'] = this.ticket;
data['ticket_color'] = this.ticket_color;
data['ticket_price_color'] = this.ticket_price_color;
data['price_color'] = this.price_color;
data['symbol'] = this.symbol;
return data;
}
}

+ 7
- 6
lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_bloc.dart View File

@@ -35,12 +35,13 @@ class GoodsDetailsSlideBannerBloc extends Bloc<GoodsDetailsSlideBannerEvent, Goo
var parentData = await repository.fetchParentData(event.model);
if (!EmptyUtil.isEmpty(parentData)) {
yield GoodsDetailsSlideBannerLoadedState(model: parentData);
return;
}
var netData = await repository.fetchNetData(event.model);
if (!EmptyUtil.isEmpty(netData))
yield GoodsDetailsSlideBannerLoadedState(model: parentData);
else
}else{
yield GoodsDetailsSlideBannerErrorState();
}
// var netData = await repository.fetchNetData(event.model);
// if (!EmptyUtil.isEmpty(netData))
// yield GoodsDetailsSlideBannerLoadedState(model: parentData);
// else
// yield GoodsDetailsSlideBannerErrorState();
}
}

+ 4
- 2
lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_repository.dart View File

@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

@@ -6,9 +8,9 @@ class GoodsDetailsSlideBannerRepository {
Future<GoodsDetailsSlideBannerModel> fetchParentData(final Map<String, dynamic> model) async {
if (!EmptyUtil.isEmpty(model)) {
try {
return GoodsDetailsSlideBannerModel.fromJson(model['data']);
return GoodsDetailsSlideBannerModel.fromJson(jsonDecode(model['data']));
} catch (e) {
Logger.log(e);
Logger.log('GoodsDetailsSlideBannerRepository = $e');
}
}
return null;


+ 7
- 7
lib/widgets/goods_details/slide_banner/goods_details_slide_banner_widget.dart View File

@@ -36,7 +36,7 @@ class GoodsDetailsSlideBannerContainer extends StatefulWidget {

class _GoodsDetailsSlideBannerContainerState extends State<GoodsDetailsSlideBannerContainer> {
/// 子元素点击事件
void _itemOnClick(IndexCarousel model) {
void _itemOnClick(String model) {
print('点击了 $model');
}

@@ -58,7 +58,7 @@ class _GoodsDetailsSlideBannerContainerState extends State<GoodsDetailsSlideBann
builder: (context, state) {
print('currente state = $state');
if (state is GoodsDetailsSlideBannerLoadedState) {
if (!EmptyUtil.isEmpty(state.model) && !EmptyUtil.isEmpty(state.model.index_carousel_list)) {
if (!EmptyUtil.isEmpty(state.model) && !EmptyUtil.isEmpty(state.model.image_list)) {
return _getMainWidget(state.model);
}
}
@@ -75,17 +75,17 @@ class _GoodsDetailsSlideBannerContainerState extends State<GoodsDetailsSlideBann
height: 375,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
IndexCarousel items = datas.index_carousel_list[index];
String items = datas.image_list[index];
return Container(
width: double.infinity,
child: CachedNetworkImage(imageUrl: items?.img ?? '', fit: BoxFit.cover),
child: CachedNetworkImage(imageUrl: items ?? '', fit: BoxFit.cover),
);
},
itemCount: datas?.index_carousel_list?.length ?? 0,
itemCount: datas?.image_list?.length ?? 0,
loop: true,
autoplay: true,
onTap: (index) => _itemOnClick(datas.index_carousel_list[index]),
pagination: _getSwiperStyleByType(datas, datas?.index_carousel_list?.length ?? 0),
onTap: (index) => _itemOnClick(datas.image_list[index]),
pagination: _getSwiperStyleByType(datas, datas?.image_list?.length ?? 0),
),
);
}


+ 32
- 57
lib/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart View File

@@ -1,61 +1,36 @@


class GoodsDetailsSlideBannerModel {
String pagination;
String pagination_open;
List<String> pagination_options;
List<IndexCarousel> index_carousel_list;
String pagination_select_color;
String pagination_unselect_color;

GoodsDetailsSlideBannerModel({this.pagination, this.pagination_open, this.pagination_options, this.pagination_select_color, this.pagination_unselect_color, this.index_carousel_list});

factory GoodsDetailsSlideBannerModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsSlideBannerModel(
pagination: json['pagination'],
pagination_open: json['pagination_open'],
pagination_options: json['pagination_options'] != null ? new List<String>.from(json['pagination_options']) : null,
index_carousel_list: json['index_carousel_list'] != null ? (json['index_carousel_list'] as List).map((i) => IndexCarousel.fromJson(i)).toList() : null,
pagination_select_color: json['pagination_select_color'],
pagination_unselect_color: json['pagination_unselect_color'],

);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['pagination'] = this.pagination;
data['pagination_open'] = this.pagination_open;
data['pagination_select_color'] = this.pagination_select_color;
data['pagination_unselect_color'] = this.pagination_unselect_color;
if (this.pagination_options != null) {
data['pagination_options'] = this.pagination_options;
List<String> image_list;
String pagination;
String pagination_open;
List<String> pagination_options;
String pagination_select_color;
String pagination_unselect_color;

GoodsDetailsSlideBannerModel({this.image_list, this.pagination, this.pagination_open, this.pagination_options, this.pagination_select_color, this.pagination_unselect_color});

factory GoodsDetailsSlideBannerModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsSlideBannerModel(
image_list: json['image_list'] != null ? new List<String>.from(json['image_list']) : null,
pagination: json['pagination'],
pagination_open: json['pagination_open'],
pagination_options: json['pagination_options'] != null ? new List<String>.from(json['pagination_options']) : null,
pagination_select_color: json['pagination_select_color'],
pagination_unselect_color: json['pagination_unselect_color'],
);
}
if (this.index_carousel_list != null) {
data['index_carousel_list'] = this.index_carousel_list.map((v) => v.toJson()).toList();
}
return data;
}
}


class IndexCarousel {
String img;
String skip_identifier;

IndexCarousel({this.img, this.skip_identifier});

factory IndexCarousel.fromJson(Map<String, dynamic> json) {
return IndexCarousel(
img: json['img'],
skip_identifier: json['skip_identifier'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['img'] = this.img;
data['skip_identifier'] = this.skip_identifier;
return data;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['pagination'] = this.pagination;
data['pagination_open'] = this.pagination_open;
data['pagination_select_color'] = this.pagination_select_color;
data['pagination_unselect_color'] = this.pagination_unselect_color;
if (this.image_list != null) {
data['image_list'] = this.image_list;
}
if (this.pagination_options != null) {
data['pagination_options'] = this.pagination_options;
}
return data;
}
}

+ 14
- 9
lib/widgets/goods_details/store/bloc/store_bloc.dart View File

@@ -1,8 +1,7 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/store_repository.dart';
import 'package:zhiying_comm/util/empty_util.dart'
'';
import 'package:zhiying_comm/util/empty_util.dart';

import 'bloc.dart';

@@ -29,15 +28,21 @@ class StoreBloc extends Bloc<StoreEvent, StoreState> {
/// 获取数据
Stream<StoreState> _mapInitEventToState(StoreInitEvent event) async*{
var result = await repository.fetchParentData(event);
if(!EmptyUtil.isEmpty(result)){
if(!EmptyUtil.isEmpty(result)) {
yield StoreLoadedState(model: result);
return;
}
var net = await repository.fetchNetData(event);
if(!EmptyUtil.isEmpty(net))
yield StoreLoadedState(model: result);
else
}else{
yield StoreErrorState();
}

// if(!EmptyUtil.isEmpty(result)){
// yield StoreLoadedState(model: result);
// return;
// }
// var net = await repository.fetchNetData(event);
// if(!EmptyUtil.isEmpty(net))
// yield StoreLoadedState(model: result);
// else
// yield StoreErrorState();
}

}

+ 6
- 1
lib/widgets/goods_details/store/bloc/store_event.dart View File

@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';

abstract class StoreEvent extends Equatable {
const StoreEvent();
@@ -6,6 +7,10 @@ abstract class StoreEvent extends Equatable {

/// 初始化事件
class StoreInitEvent extends StoreEvent {

final Map<String, dynamic> model;
const StoreInitEvent({@required this.model});

@override
List<Object> get props => [];
List<Object> get props => [this.model];
}

+ 10
- 1
lib/widgets/goods_details/store/bloc/store_repository.dart View File

@@ -1,9 +1,18 @@
import 'dart:convert';

import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/model/store_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class StoreRepository {
/// 获取上级数据
Future<StoreModel> fetchParentData(StoreInitEvent event) async {}
Future<StoreModel> fetchParentData(StoreInitEvent event) async {
try {
return StoreModel.fromJson(json.decode(event.model['data']));
} catch (e) {
Logger.log('StoreRepository e= $e');
}
}

/// 网络数据
Future<StoreModel> fetchNetData(StoreInitEvent event) async {}


+ 52
- 1
lib/widgets/goods_details/store/model/store_model.dart View File

@@ -1,3 +1,54 @@

class StoreModel {
String description;
String description_color;
String description_leve_icon;
String logistics;
String logistics_color;
String logistics_leve_icon;
String more;
String service;
String service_color;
String service_leve_icon;
String shop_id;
String shop_name;
String shop_name_color;

class StoreModel{}
StoreModel({this.description, this.description_color, this.description_leve_icon, this.logistics, this.logistics_color, this.logistics_leve_icon, this.more, this.service, this.service_color, this.service_leve_icon, this.shop_id, this.shop_name, this.shop_name_color});

factory StoreModel.fromJson(Map<String, dynamic> json) {
return StoreModel(
description: json['description'],
description_color: json['description_color'],
description_leve_icon: json['description_leve_icon'],
logistics: json['logistics'],
logistics_color: json['logistics_color'],
logistics_leve_icon: json['logistics_leve_icon'],
more: json['more'],
service: json['service'],
service_color: json['service_color'],
service_leve_icon: json['service_leve_icon'],
shop_id: json['shop_id'],
shop_name: json['shop_name'],
shop_name_color: json['shop_name_color'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['description'] = this.description;
data['description_color'] = this.description_color;
data['description_leve_icon'] = this.description_leve_icon;
data['logistics'] = this.logistics;
data['logistics_color'] = this.logistics_color;
data['logistics_leve_icon'] = this.logistics_leve_icon;
data['more'] = this.more;
data['service'] = this.service;
data['service_color'] = this.service_color;
data['service_leve_icon'] = this.service_leve_icon;
data['shop_id'] = this.shop_id;
data['shop_name'] = this.shop_name;
data['shop_name_color'] = this.shop_name_color;
return data;
}
}

+ 3
- 0
lib/widgets/goods_details/store/store_sk.dart View File

@@ -6,6 +6,7 @@ class StoreSkeleton extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
height: 50,
margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 20),
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
@@ -14,9 +15,11 @@ class StoreSkeleton extends StatelessWidget {
/// 图片
_shimmerWidget(width: 50, height: 50),

const SizedBox(width: 10),
///
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[

_shimmerWidget(width: 150, height: 20),


+ 22
- 22
lib/widgets/goods_details/store/store_widget.dart View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/store_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/model/store_model.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

@@ -18,7 +19,7 @@ class StoreWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<StoreBloc>(
create: (_) => StoreBloc(repository: StoreRepository())..add(StoreInitEvent()),
create: (_) => StoreBloc(repository: StoreRepository())..add(StoreInitEvent(model: model)),
child: StoreContainer(),
);
}
@@ -30,16 +31,11 @@ class StoreContainer extends StatefulWidget {
}

class _StoreContainerState extends State<StoreContainer> {

/// 点击更多
void _onMoreClick(){

}
void _onMoreClick() {}

/// 点击商家
void _onStoreClick(){

}
void _onStoreClick() {}

@override
Widget build(BuildContext context) {
@@ -63,14 +59,18 @@ class _StoreContainerState extends State<StoreContainer> {
/// 主视图
Widget _getMianWidget(StoreModel model) {
return Container(
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
color: Colors.white,
width: double.infinity,
height: 50 + 20.0 + 18,
padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 20, bottom: 18),
child: Row(
children: <Widget>[
/// 商家图片
_getStoreImgWidget(model),
const SizedBox(width: 7.5),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 商店名称与更多
@@ -98,19 +98,14 @@ class _StoreContainerState extends State<StoreContainer> {
/// 商店名称
Widget _getStoreNameWidget(StoreModel model) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 商店名称
Text(
'品胜京东自营旗舰店',
style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 13),
),
Text(model?.shop_name ?? '品胜京东自营旗舰店', style: TextStyle(color: HexColor.fromHex(model?.shop_name_color ?? '#333333'), fontSize: 13, fontWeight: FontWeight.bold)),

/// 更多
Text(
'更多店铺优惠 >',
style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 11),
),
Text(model?.more ?? '更多店铺优惠 >', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 11)),
],
);
}
@@ -121,13 +116,13 @@ class _StoreContainerState extends State<StoreContainer> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 宝贝描述 5.0
_getCoustomWidet('宝贝描述 5.0', '#999999', ''),
_getCoustomWidet(model?.description ?? '宝贝描述 5.0',model?.description_color ?? '#999999', model?.description_leve_icon ?? ''),

/// 物流服务 5.0
_getCoustomWidet('宝贝描述 5.0', '#999999', ''),
_getCoustomWidet(model?.logistics ?? '宝贝描述 5.0', model?.logistics_color ?? '#999999', model?.logistics_leve_icon ?? ''),

/// 服务态度 1.0
_getCoustomWidet('宝贝描述 5.0', '#999999', ''),
_getCoustomWidet(model?.service ?? '宝贝描述 5.0', model?.service_color ?? '#999999', model?.service_leve_icon ?? ''),
],
);
}
@@ -136,10 +131,15 @@ class _StoreContainerState extends State<StoreContainer> {
return Row(
children: <Widget>[
Text(text, style: TextStyle(fontSize: 11, color: HexColor.fromHex(textColor))),
const SizedBox(width: 3),
Container(
width: 12,
height: 12,
color: Colors.red,
// color: Colors.red,
child: CachedNetworkImage(
imageUrl: icon ?? '',

),
),
],
);


+ 70
- 18
lib/widgets/goods_details/title/goods_details_title_widget.dart View File

@@ -1,4 +1,7 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/title/model/goods_details_title_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
@@ -6,43 +9,92 @@ import 'package:zhiying_comm/zhiying_comm.dart';
///
class GoodsDetailsTitleWidget extends StatelessWidget {
final Map<String, dynamic> model;
GoodsDetailsTitleModel _model;

const GoodsDetailsTitleWidget(this.model);
GoodsDetailsTitleWidget(this.model, {Key key}) : super(key: key) {
try {
_model = GoodsDetailsTitleModel.fromJson(jsonDecode(model['data']));
} catch (e) {
Logger.log('GoodsDetailsTitleWidget e = $e');
}
}

@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
child: _getMaiWidget(),
color: Colors.white,
padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 6.5),
child: _getMaiWidget(_model),
);
}

/// 主widget
Widget _getMaiWidget() {
return RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
text: TextSpan(children: [
WidgetSpan(
child: _getGoodsTypeIcon(),
Widget _getMaiWidget(GoodsDetailsTitleModel model) {
return Column(
children: <Widget>[
RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
text: TextSpan(children: [
WidgetSpan(
child: _getGoodsTypeIcon(model),
),
_getGoodsTitle(model),
]),
),
_getGoodsTitle(),
]),
/// 优惠卷说明
Padding(padding: const EdgeInsets.only(top: 12.5), child: _getCounponDestrWidget(model)),
],
);
}

/// 商品类型图标
Widget _getGoodsTypeIcon() {
Widget _getGoodsTypeIcon(GoodsDetailsTitleModel model) {
return Container(
height: 15,
width: 32,
color: Colors.red,
// height: 15,
// width: 32,
padding: const EdgeInsets.only(left: 7.5, right: 7.5, bottom: 2, top: 3),
margin: const EdgeInsets.only(right: 4),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(2.5), color: HexColor.fromHex(model?.provider_bg_color)),
child: Text(model?.provider_name, style: TextStyle(color: HexColor.fromHex(model?.provider_name_color), fontSize: 9)),
);
}

/// 商品标题
InlineSpan _getGoodsTitle() {
return TextSpan(text: '品胜(PISEN)苹果数据线1.5米 适用于苹果手机所有机型 MFI认证安全稳定一年换新1.5米2米', style: TextStyle(fontSize: 14, color: HexColor.fromHex('#FF333333')));
InlineSpan _getGoodsTitle(GoodsDetailsTitleModel model) {
return TextSpan(
text: model?.title ?? '品胜(PISEN)苹果数据线1.5米 适用于苹果手机所有机型 MFI认证安全稳定一年换新1.5米2米',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: HexColor.fromHex(model?.good_title_color ?? '#FF333333'),
));
}

/// 优惠卷说明
Widget _getCounponDestrWidget(GoodsDetailsTitleModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
/// 领券立减100元 widget
_getCoumstonButtomWidget(model?.coupon_text, model?.coupon_text_color, model?.coupon_bg_color),
const SizedBox(width: 5),

/// 收货后返现5.5元
_getCoumstonButtomWidget(model?.commission_text, model?.commission_text_color, model?.commission_bg_color),
],
);
}

Widget _getCoumstonButtomWidget(String text, String textColor, String bg) {
return Container(
padding: const EdgeInsets.only(left: 13.5, right: 14.5, top: 2.5, bottom: 2.5),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: HexColor.fromHex(bg)),
child: Text(
text,
style: TextStyle(color: HexColor.fromHex(textColor), fontSize: 11),
),
);
}
}

+ 58
- 0
lib/widgets/goods_details/title/model/goods_details_title_model.dart View File

@@ -0,0 +1,58 @@
class GoodsDetailsTitleModel {
String commission_bg_color;
String commission_text;
String commission_text_color;
String coupon_bg_color;
String coupon_text;
String coupon_text_color;
String good_title_color;
String provider_bg_color;
String provider_name;
String provider_name_color;
String title;

GoodsDetailsTitleModel(
{this.commission_bg_color,
this.commission_text,
this.commission_text_color,
this.coupon_bg_color,
this.coupon_text,
this.coupon_text_color,
this.good_title_color,
this.provider_bg_color,
this.provider_name,
this.provider_name_color,
this.title});

factory GoodsDetailsTitleModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsTitleModel(
commission_bg_color: json['commission_bg_color'],
commission_text: json['commission_text'],
commission_text_color: json['commission_text_color'],
coupon_bg_color: json['coupon_bg_color'],
coupon_text: json['coupon_text'],
coupon_text_color: json['coupon_text_color'],
good_title_color: json['good_title_color'],
provider_bg_color: json['provider_bg_color'],
provider_name: json['provider_name'],
provider_name_color: json['provider_name_color'],
title: json['title'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['commission_bg_color'] = this.commission_bg_color;
data['commission_text'] = this.commission_text;
data['commission_text_color'] = this.commission_text_color;
data['coupon_bg_color'] = this.coupon_bg_color;
data['coupon_text'] = this.coupon_text;
data['coupon_text_color'] = this.coupon_text_color;
data['good_title_color'] = this.good_title_color;
data['provider_bg_color'] = this.provider_bg_color;
data['provider_name'] = this.provider_name;
data['provider_name_color'] = this.provider_name_color;
data['title'] = this.title;
return data;
}
}

+ 34
- 1
lib/widgets/goods_details/upgrade_tip/model/upgrade_tip_model.dart View File

@@ -1,3 +1,36 @@

class UpgradeTipModel{}
class UpgradeTipModel {
String bg_color;
String go_text;
String go_text_color;
String icon;
String text;
String text_color;
String url;

UpgradeTipModel({this.bg_color, this.go_text, this.go_text_color, this.icon, this.text, this.text_color, this.url});

factory UpgradeTipModel.fromJson(Map<String, dynamic> json) {
return UpgradeTipModel(
bg_color: json['bg_color'],
go_text: json['go_text'],
go_text_color: json['go_text_color'],
icon: json['icon'],
text: json['text'],
text_color: json['text_color'],
url: json['url'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['bg_color'] = this.bg_color;
data['go_text'] = this.go_text;
data['go_text_color'] = this.go_text_color;
data['icon'] = this.icon;
data['text'] = this.text;
data['text_color'] = this.text_color;
data['url'] = this.url;
return data;
}
}

+ 40
- 21
lib/widgets/goods_details/upgrade_tip/upgrade_tip_widget.dart View File

@@ -1,30 +1,47 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/upgrade_tip/model/upgrade_tip_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:cached_network_image/cached_network_image.dart';

///
/// 更新提示widget
///
class UpgradeTipWidget extends StatelessWidget {
final Map<String, dynamic> model;

const UpgradeTipWidget(this.model);
UpgradeTipModel _upgradeTipModel;
UpgradeTipWidget(this.model, {Key key}) : super(key: key){
try{
_upgradeTipModel = UpgradeTipModel.fromJson(jsonDecode(model['data']));
}catch(e){
Logger.log('UpgradeTipWidget e = $e');
}
}

@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.only(left: 12.5, right: 12.5, top: 12.5),
decoration: BoxDecoration(
color: HexColor.fromHex('#FFEFDA'),
borderRadius: BorderRadius.circular(30),
color: Colors.white,
borderRadius: BorderRadius.only(topLeft: Radius.circular(7.5), topRight: Radius.circular(7.5))
),
padding: const EdgeInsets.only(left: 10, right: 13, top: 10, bottom: 10),
margin: const EdgeInsets.symmetric(horizontal: 12.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_geLeftWidget(null),
_getRightWidget(null),
],
child: Container(
decoration: BoxDecoration(
/// 背景颜色
color: HexColor.fromHex(_upgradeTipModel?.bg_color ?? '#FFEFDA'),
borderRadius: BorderRadius.circular(30),
),
padding: const EdgeInsets.only(left: 10, right: 13, top: 10, bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_geLeftWidget(_upgradeTipModel),
_getRightWidget(_upgradeTipModel),
],
),
),
);
}
@@ -34,24 +51,26 @@ class UpgradeTipWidget extends StatelessWidget {
return Row(
children: <Widget>[
/// 图标
Container(width: 15, height: 15, color: Colors.red),
// Container(width: 15, height: 15, child: ,),
CachedNetworkImage(imageUrl: model?.icon ?? '', width: 15,),

const SizedBox(width: 7.5),

/// 文字
Text('下载APP升级运营商,享受更多收益', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11))
Text(model?.text ?? '下载APP升级运营商,享受更多收益', style: TextStyle(color: HexColor.fromHex( model?.text_color ?? '#C09023'), fontSize: 11))
],
);
}

/// 右边的视图
Widget _getRightWidget(UpgradeTipModel model) {
return Row(
children: <Widget>[
Text('前往下载', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11)),
const SizedBox(width: 4),
Text('》', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11))
],
);
return Text(model?.go_text ??'前往下载', style: TextStyle(color: HexColor.fromHex(model?.go_text_color ?? '#C09023'), fontSize: 11));
// return Row(
// children: <Widget>[
// Text(model?.go_text ??'前往下载', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11)),
// const SizedBox(width: 4),
// Text('》', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11))
// ],
// );
}
}

+ 49
- 38
lib/widgets/home/home_goods/home_goods_item.dart View File

@@ -2,6 +2,7 @@ import 'dart:convert';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart';
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_model.dart';
import 'package:zhiying_base_widget/widgets/home/home_goods/models/home_goods_style_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
@@ -21,49 +22,59 @@ class HomeGoodsItem extends StatelessWidget {
}
}

/// 跳到商品详情
void _onJumpGoodsDetails(BuildContext context,HomeGoodsModel goods){
Navigator.push(context, MaterialPageRoute(
builder: (_)=> GoodsDetailsPage(goods.toJson())
));
}

@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 4, bottom: 4),
padding: EdgeInsets.all(7.5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(7.5))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 126,
height: 126,
margin: EdgeInsets.only(right: 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(7.5),
child: CachedNetworkImage(
imageUrl: goods.goodImage,
fit: BoxFit.fitHeight,
),
),
),
Expanded(
child: Container(
return GestureDetector(
onTap: ()=> _onJumpGoodsDetails(context, goods),
child: Container(
margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 4, bottom: 4),
padding: EdgeInsets.all(7.5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(7.5))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 126,
height: 126,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: double.infinity,
child: _createTitle(),
),
_createShop(),
_createCupone(),
Expanded(child: Container()),
_createBottom(),
],
margin: EdgeInsets.only(right: 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(7.5),
child: CachedNetworkImage(
imageUrl: goods.goodImage,
fit: BoxFit.fitHeight,
),
),
),
)
],
Expanded(
child: Container(
height: 126,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: double.infinity,
child: _createTitle(),
),
_createShop(),
_createCupone(),
Expanded(child: Container()),
_createBottom(),
],
),
),
)
],
),
),
);
}


+ 4
- 0
lib/widgets/home/home_goods/models/home_goods_model.dart View File

@@ -4,6 +4,9 @@ part 'home_goods_model.g.dart';

@JsonSerializable()
class HomeGoodsModel extends Object {
@JsonKey(name: 'provider')
String provider;

@JsonKey(name: 'provider_name')
String providerName;

@@ -35,6 +38,7 @@ class HomeGoodsModel extends Object {
String inorderCount;

HomeGoodsModel(
this.provider,
this.providerName,
this.goodId,
this.goodImage,


+ 2
- 0
lib/widgets/home/home_goods/models/home_goods_model.g.dart View File

@@ -8,6 +8,7 @@ part of 'home_goods_model.dart';

HomeGoodsModel _$HomeGoodsModelFromJson(Map<String, dynamic> json) {
return HomeGoodsModel(
json['provider'] as String,
json['provider_name'] as String,
json['good_id'] as String,
json['good_image'] as String,
@@ -23,6 +24,7 @@ HomeGoodsModel _$HomeGoodsModelFromJson(Map<String, dynamic> json) {

Map<String, dynamic> _$HomeGoodsModelToJson(HomeGoodsModel instance) =>
<String, dynamic>{
'provider': instance.provider,
'provider_name': instance.providerName,
'good_id': instance.goodId,
'good_image': instance.goodImage,


+ 4
- 4
lib/widgets/home/home_slide_banner/home_slide_banner.dart View File

@@ -44,10 +44,10 @@ class _HomeSlideBannerContainerState extends State<HomeSlideBannerContainer> {
/// 子元素点击事件
void _itemOnClick(IndexCarousel model) {
print('点击了 $model');
// RouterUtil.route(model.toJson(), context);
Navigator.push(context, MaterialPageRoute(
builder: (_) => PageFactory.create('goods_details', null)
));
RouterUtil.route(model.toJson(), context);
// Navigator.push(context, MaterialPageRoute(
// builder: (_) => PageFactory.create('goods_details', null)
// ));
}

@override


||||||
x
 
000:0
Loading…
Cancel
Save