diff --git a/lib/models/app_config_model.dart b/lib/models/app_config_model.dart index 428831a..3856369 100644 --- a/lib/models/app_config_model.dart +++ b/lib/models/app_config_model.dart @@ -12,6 +12,9 @@ class AppConfigModel { // 引导页 AppConfigGuideModel guideImage; + ///新引导页参数 + GuideData guideData; + static AppConfigModel _config; AppConfigModel({this.keys, this.guideImage}); @@ -20,13 +23,12 @@ class AppConfigModel { static Future init({bool isGetCache = false}) async { try { - String cacheData = await SharedPreferencesUtil.getStringValue(GlobalConfig.GUIDE, defaultVal: '1'); if (isGetCache && cacheData != '1') { _config = AppConfigModel.fromJson(Map.from(json.decode(cacheData))); Logger.debug('基础设置初始化'); NetUtil.request('/api/v1/app/guide', onSuccess: (data) { - print(data); + Logger.log(json.encode(data)); var cacheString = json.encode(data); SharedPreferencesUtil.setNetCacheResult(GlobalConfig.GUIDE, cacheString); }); @@ -49,6 +51,7 @@ class AppConfigModel { AppConfigModel.fromJson(Map json) { keys = json['keys'] != null ? new AppConfigKeyModel.fromJson(json['keys']) : null; guideImage = json['guide_image'] != null ? new AppConfigGuideModel.fromJson(json['guide_image']) : null; + guideData = json['guide_data'] != null ? GuideData.fromJson(json['guide_data']) : null; } Map toJson() { @@ -101,6 +104,69 @@ class AppConfigKeyModel { } } +class GuideData { + String indicatorType; + String indicatorCssType; + String indicatorChooseColor; + String indicatorUnchooseColor; + String btnText; + String btnBgColor; + String btnTextColor; + List guideCss; + + GuideData({this.indicatorType, this.indicatorCssType, this.indicatorChooseColor, this.indicatorUnchooseColor, this.btnText, this.btnBgColor, this.btnTextColor, this.guideCss}); + + GuideData.fromJson(Map json) { + indicatorType = json['indicator_type']; + indicatorCssType = json['indicator_css_type']; + indicatorChooseColor = json['indicator_choose_color']; + indicatorUnchooseColor = json['indicator_unchoose_color']; + btnText = json['btn_text']; + btnBgColor = json['btn_bg_color']; + btnTextColor = json['btn_text_color']; + if (json['guide_css'] != null) { + guideCss = new List(); + json['guide_css'].forEach((v) { + guideCss.add(new GuideCss.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['indicator_type'] = this.indicatorType; + data['indicator_css_type'] = this.indicatorCssType; + data['indicator_choose_color'] = this.indicatorChooseColor; + data['indicator_unchoose_color'] = this.indicatorUnchooseColor; + data['btn_text'] = this.btnText; + data['btn_bg_color'] = this.btnBgColor; + data['btn_text_color'] = this.btnTextColor; + if (this.guideCss != null) { + data['guide_css'] = this.guideCss.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class GuideCss { + String bgImage; + String contentImage; + + GuideCss({this.bgImage, this.contentImage}); + + GuideCss.fromJson(Map json) { + bgImage = json['bg_image']; + contentImage = json['content_image']; + } + + Map toJson() { + final Map data = new Map(); + data['bg_image'] = this.bgImage; + data['content_image'] = this.contentImage; + return data; + } +} + class AppConfigKeyItemModel { String appId; String appkey; diff --git a/lib/pages/goods_details_page/goods_details_page.dart b/lib/pages/goods_details_page/goods_details_page.dart index 24d09c1..746fdf4 100644 --- a/lib/pages/goods_details_page/goods_details_page.dart +++ b/lib/pages/goods_details_page/goods_details_page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; +import 'dart:convert'; import 'dart:ui'; import 'package:event_bus/event_bus.dart'; @@ -13,6 +15,7 @@ import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier. import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifier.dart'; import 'package:zhiying_base_widget/widgets/goods_details/appbar/goods_details_appbar_widget.dart'; import 'package:zhiying_base_widget/widgets/goods_details/footer/goods_details_footer_widget.dart'; +import 'package:zhiying_base_widget/widgets/goods_details/footer/model/goods_details_footer_model.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; import 'notifier/goods_details_appbar_color_notifier.dart'; @@ -151,17 +154,27 @@ class _GoodsDetailsContainerState extends State { Widget _getMainWidget(List> datas) { return Scaffold( backgroundColor: Colors.white, - body: Container( - color: Color(0xfff1f1f1), - child: Stack( - children: [ - CustomScrollView( - controller: _controller, - slivers: _createContent(context, datas ?? []), - ), - Align(alignment: Alignment.topCenter, child: GoodsDetailsAppBarWidget(datas[0])), - ], - )), + body: Stack( + children: [ + Container( + color: Color(0xfff1f1f1), + child: Stack( + children: [ + CustomScrollView( + controller: _controller, + slivers: _createContent(context, datas ?? []), + ), + Align(alignment: Alignment.topCenter, child: GoodsDetailsAppBarWidget(datas[0])), + ], + )), + Align( + alignment: Alignment.bottomCenter, + child: _FloatView( + !EmptyUtil.isEmpty(datas) ? datas[datas.length - 1] : null, + ), + ) + ], + ), /// 底部 bottomNavigationBar: GoodsDetailsFooterWidget( @@ -261,4 +274,70 @@ class _GoodsDetailsContainerState extends State { // ), ); } + + ///构建浮动页 + _FloatView(Map model) { + if (model != null) { + return FloatView( + model: model, + ); + } + } +} + +class FloatView extends StatefulWidget { + final Map model; + + const FloatView({Key key, this.model}) : super(key: key); + + @override + _FloatViewState createState() => _FloatViewState(); +} + +class _FloatViewState extends State with TickerProviderStateMixin { + double floatMarginBottom = 0.0; + Timer floatTimer; + + AnimationController animationController; + + + Animation tween; + + GoodsDetailsFooterModel footerModel; + + @override + void initState() { + footerModel = GoodsDetailsFooterModel.fromJson(json.decode(widget?.model['data'])); + animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 3000)); + CurvedAnimation curvedAnimation = CurvedAnimation(parent: animationController, curve: Curves.easeInOutBack); + tween = Tween(begin: 5, end: 20).animate(curvedAnimation); + curvedAnimation.addListener(() { + setState(() {}); + }); + + // animationController.repeat(reverse: true); + + super.initState(); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container(); + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + margin: EdgeInsets.only(bottom: tween?.value ?? 0, right: 25), + color: Colors.red, + child: Text(""), + ), + ], + ); + } } diff --git a/lib/pages/guide_page/guide_page.dart b/lib/pages/guide_page/guide_page.dart index fced16d..ac10484 100644 --- a/lib/pages/guide_page/guide_page.dart +++ b/lib/pages/guide_page/guide_page.dart @@ -7,10 +7,11 @@ import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network import 'package:zhiying_comm/zhiying_comm.dart'; class GuidePage extends StatefulWidget { - final AppConfigGuideModel model; + final GuideData model; final List imageDatas; + final List bgImageDatas; - const GuidePage(this.model, this.imageDatas, {Key key}) : super(key: key); + const GuidePage(this.model, this.imageDatas, this.bgImageDatas, {Key key}) : super(key: key); @override State createState() => _GuidePageState(); @@ -19,54 +20,120 @@ class GuidePage extends StatefulWidget { class _GuidePageState extends State { @override Widget build(BuildContext context) { - bool isShowIndicator = (widget.model?.isShowIndicator ?? '0') == '1'; + bool isShowIndicator = (widget.model?.indicatorType ?? '0') == '1'; List list = List.generate(widget.imageDatas?.length, (index) => index); return WillPopScope( - onWillPop: () async => false,// 拦截Android返回键 + onWillPop: () async => false, // 拦截Android返回键 child: Material( child: Swiper( itemBuilder: (BuildContext context, int index) { // return CachedNetworkImage(imageUrl: widget.model.images[index],fit: BoxFit.cover,); - return Image.memory(widget.imageDatas[index], fit: BoxFit.cover,); - }, - - loop: false, - itemCount: widget.imageDatas?.length ?? 0, - pagination: isShowIndicator ? SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) { - return Align( - alignment: Alignment(0.0, 1), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: list.map((index) { - var borderRadius; - if (index == 0) { - borderRadius = BorderRadius.only(topLeft: Radius.circular(2), bottomLeft: Radius.circular(2)); - } - if (index == list.length - 1) { - borderRadius = BorderRadius.only(topRight: Radius.circular(2), bottomRight: Radius.circular(2)); - } - - if (index == config.activeIndex) { - borderRadius = BorderRadius.all(Radius.circular(2)); - } + Uint8List bgImage; + if (widget.bgImageDatas.length > index) { + bgImage = widget?.bgImageDatas[index]; + } - return SafeArea( - child: Container( - margin: EdgeInsets.only(bottom: 40), - height: 4, - width: 25, - decoration: BoxDecoration(borderRadius: borderRadius, color: index == config.activeIndex ? HexColor.fromHex('#FF4242') : HexColor.fromHex('#FFFFFF')), - ), - ); - }).toList() , - ), + return Stack( + alignment: Alignment.center, + children: [ + Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + image: DecorationImage( + image: Image.memory( + bgImage, + ).image, + fit: BoxFit.fill)), + child: Center( + child: Image.memory( + widget.imageDatas[index], + fit: BoxFit.fitWidth, + ))), + index == widget?.bgImageDatas?.length - 1 + ? Positioned( + left: 0, + right: 0, + bottom: 110, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + alignment: Alignment.center, + height: 46, + width: 180, + decoration: BoxDecoration( + color: HexColor.fromHex(widget?.model?.btnBgColor ?? ""), + borderRadius: BorderRadius.circular(45), + boxShadow: [BoxShadow(color: HexColor.fromHex(widget?.model?.btnBgColor), offset: Offset(1, 2), blurRadius: 6)]), + child: Text( + widget?.model?.btnText ?? "", + style: TextStyle(color: HexColor.fromHex(widget?.model?.btnTextColor ?? ""), fontSize: 16, height: 1.1), + ), + ), + ], + ), + ), + ) + : Container() + ], ); - }) : null, - onIndexChanged: (index) { }, + loop: false, + itemCount: widget.imageDatas?.length ?? 0, + pagination: widget?.model?.indicatorType != "1" + ? null + : widget?.model?.indicatorCssType == "2" + ? SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) { + return Align( + alignment: Alignment(0.0, 1), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: list.map((index) { + return SafeArea( + child: Container( + margin: EdgeInsets.only(bottom: 40, left: 5, right: 5), + height: 4, + width: 20, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: index == config.activeIndex + ? HexColor.fromHex(widget?.model?.indicatorChooseColor) + : HexColor.fromHex(widget?.model?.indicatorUnchooseColor)), + ), + ); + }).toList(), + ), + ); + }) + : SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) { + return Align( + alignment: Alignment(0.0, 1), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: list.map((index) { + return SafeArea( + child: Container( + margin: EdgeInsets.only(bottom: 40, left: 5, right: 5), + height: 10, + width: 10, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: index == config.activeIndex + ? HexColor.fromHex(widget?.model?.indicatorChooseColor) + : HexColor.fromHex(widget?.model?.indicatorUnchooseColor)), + ), + ); + }).toList(), + ), + ); + }), + onIndexChanged: (index) {}, onTap: (index) { - if (index == widget.model.images.length - 1) { + if (index == widget.model.guideCss.length - 1) { Navigator.pop(context, true); } }, diff --git a/lib/pages/launch_page/launch_page.dart b/lib/pages/launch_page/launch_page.dart index 7e10026..9796f4e 100644 --- a/lib/pages/launch_page/launch_page.dart +++ b/lib/pages/launch_page/launch_page.dart @@ -127,20 +127,28 @@ class _LaunchPageState extends State with TickerProviderStateMixin { Future _showGuideImage() async { try { // 引导页 - AppConfigGuideModel guide = AppConfigModel.getConfig()?.guideImage; - if (guide != null && guide.images.length > 0) { + AppConfigModel guide = AppConfigModel.getConfig(); + if (guide != null && guide.guideData.guideCss.length > 0) { Dio dio = Dio(); print("加载图片"); List guideImages = List(); - for (int i = 0; i < guide.images.length; i++) { - Response response = await dio.get(guide.images[i], options: Options(responseType: ResponseType.bytes)); + ListbgImages = List(); + for (int i = 0; i < guide.guideData.guideCss.length; i++) { + Response response = await dio.get(guide.guideData.guideCss[i].contentImage, options: Options(responseType: ResponseType.bytes)); if (response.statusCode == 200) { Uint8List data = Uint8List.fromList(response.data); guideImages.add(data); } + response = await dio.get(guide.guideData.guideCss[i].bgImage, options: Options(responseType: ResponseType.bytes)); + if (response.statusCode == 200) { + Uint8List data = Uint8List.fromList(response.data); + bgImages.add(data); + } } + + NativeUtil.notifyInitSuccess(); - await Navigator.of(context).push(CupertinoPageRoute(builder: (context) => GuidePage(guide, guideImages))); + await Navigator.of(context).push(CupertinoPageRoute(builder: (context) => GuidePage(guide.guideData, guideImages,bgImages))); } } catch (e) { throw "引导图加载失败"; diff --git a/lib/widgets/goods_details/footer/goods_details_footer_widget.dart b/lib/widgets/goods_details/footer/goods_details_footer_widget.dart index 2d587d4..7281d62 100644 --- a/lib/widgets/goods_details/footer/goods_details_footer_widget.dart +++ b/lib/widgets/goods_details/footer/goods_details_footer_widget.dart @@ -63,9 +63,7 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain @override void didChangeDependencies() { - _user = Provider - .of(context) - .userInfo; + _user = Provider.of(context).userInfo; super.didChangeDependencies(); } @@ -88,6 +86,12 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain /// 收藏 void _collectOnClick(GoodsDetailsFooterModel model) { + ///获取用户信息,未登录需要先登录 + var _user = Provider.of(context,listen: false).userInfo; + if (_user?.token == null || _user?.token?.length == 0) { + RouterUtil.goLogin(context); + return; + } bool isCollect = model.isFav == '0'; if (isCollect) { // 收藏 @@ -133,27 +137,23 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain } Widget _getMainWidget(GoodsDetailsFooterModel model) { - double height = MediaQuery - .of(context) - .padding - .bottom; + double height = MediaQuery.of(context).padding.bottom; return SafeArea( child: Container( width: double.infinity, padding: EdgeInsets.only(bottom: (height > 10 ? 0 : 8), top: 8, left: 12.5, 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)), - // ], + // 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: HexColor.fromHex(model?.bgColor), borderRadius: BorderRadius.only( topLeft: Radius.circular(ParseUtil.stringParseDouble(model?.topLeftRadius)), topRight: Radius.circular(ParseUtil.stringParseDouble(model?.topRightRadius)), bottomLeft: Radius.circular(ParseUtil.stringParseDouble(model?.bottomLeftRadius)), bottomRight: Radius.circular(ParseUtil.stringParseDouble(model?.bottomRightRadius)), - ) - ), + )), child: Container(height: 44, child: _getMainWidet(model)), ), ); @@ -165,7 +165,6 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - /// 首页与收藏 _getLeftWidget(model), @@ -187,7 +186,7 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain behavior: HitTestBehavior.opaque, onTap: () => _openHome(), child: Padding( - padding: const EdgeInsets.only(right: 35,left: 8), + padding: const EdgeInsets.only(right: 35, left: 8), child: _getCustomWidget(model?.listStyle?.leftIcon1?.text ?? '首页', model?.listStyle?.leftIcon1?.color ?? '999999', model?.listStyle?.leftIcon1?.beforeIcon ?? ''), )), ), @@ -213,8 +212,8 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.center, children: [ - (model?.listStyle?.rightIcon1?.isShow ?? "0") == "1" ? Expanded(child: _getFxzButton(model)):Container(), - (model?.listStyle?.rightIcon2?.isShow ?? "0") == "1" ? Expanded(child: _getZgsButton(model)):Container() + (model?.listStyle?.rightIcon1?.isShow ?? "0") == "1" ? Expanded(child: _getFxzButton(model)) : Container(), + (model?.listStyle?.rightIcon2?.isShow ?? "0") == "1" ? Expanded(child: _getZgsButton(model)) : Container() ], ), ); @@ -242,10 +241,10 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain width: double.infinity, // padding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5), decoration: BoxDecoration( - // 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), + // 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), image: DecorationImage(image: CachedNetworkImageProvider(model?.listStyle?.rightIcon1?.bgImage ?? ''), fit: BoxFit.fitWidth), borderRadius: BorderRadius.only(bottomLeft: Radius.circular(25), topLeft: Radius.circular(25))), child: Column( @@ -284,10 +283,10 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain // padding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5), height: 44, decoration: BoxDecoration( - // 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), + // 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), image: DecorationImage(image: CachedNetworkImageProvider(model?.listStyle?.rightIcon2?.bgImage ?? ''), fit: BoxFit.fitWidth), borderRadius: BorderRadius.only(bottomRight: Radius.circular(25), topRight: Radius.circular(25))), child: Column( @@ -319,7 +318,6 @@ class _GoodsDetailsFooterContainerState extends State<_GoodsDetailsFooterContain crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end, children: [ - /// 图标 CachedNetworkImage( imageUrl: icon,