diff --git a/.dart_tool/build_resolvers/sdk.sum b/.dart_tool/build_resolvers/sdk.sum new file mode 100644 index 0000000..a788675 Binary files /dev/null and b/.dart_tool/build_resolvers/sdk.sum differ diff --git a/.dart_tool/build_resolvers/sdk.sum.deps b/.dart_tool/build_resolvers/sdk.sum.deps new file mode 100644 index 0000000..1c10e44 --- /dev/null +++ b/.dart_tool/build_resolvers/sdk.sum.deps @@ -0,0 +1 @@ +{"sdk":"2.7.2 (Mon Mar 23 22:11:27 2020 +0100) on \"macos_x64\"","analyzer":"/Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/analyzer-0.39.14","build_resolvers":"/Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/build_resolvers-1.3.11"} \ No newline at end of file diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index d336421..fe58bac 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json @@ -680,7 +680,7 @@ "languageVersion": "2.1" } ], - "generated": "2020-09-07T03:45:53.992384Z", + "generated": "2020-09-08T07:00:40.458603Z", "generator": "pub", "generatorVersion": "2.7.2" } diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/saveactions_settings.xml b/.idea/saveactions_settings.xml new file mode 100644 index 0000000..6025467 --- /dev/null +++ b/.idea/saveactions_settings.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/assets/fonts/DIN-Bold.otf b/assets/fonts/DIN-Bold.otf new file mode 100644 index 0000000..782e68e Binary files /dev/null and b/assets/fonts/DIN-Bold.otf differ diff --git a/assets/fonts/DIN-Medium.otf b/assets/fonts/DIN-Medium.otf new file mode 100644 index 0000000..ceed4be Binary files /dev/null and b/assets/fonts/DIN-Medium.otf differ diff --git a/assets/fonts/DIN-Regular.otf b/assets/fonts/DIN-Regular.otf new file mode 100644 index 0000000..2ea9379 Binary files /dev/null and b/assets/fonts/DIN-Regular.otf differ diff --git a/lib/pages/main_page/main_page.dart b/lib/pages/main_page/main_page.dart index 5b7b843..b3b0e8c 100644 --- a/lib/pages/main_page/main_page.dart +++ b/lib/pages/main_page/main_page.dart @@ -2,7 +2,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:zhiying_base_widget/pages/main_page/main_page_bloc.dart'; import 'package:zhiying_base_widget/pages/main_page/main_page_notifier.dart'; -import 'package:zhiying_base_widget/pages/main_page/main_page_sk.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; import 'package:provider/provider.dart'; import 'package:zhiying_comm/util/base_bloc.dart'; @@ -25,11 +24,13 @@ class _MainPageState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xfff9f9f9), - body: ChangeNotifierProvider( - create: (context) => MainPageNotifier(), - child: BlocProvider( - bloc: MainPageBloc(), - child: _MainPageContainer(widget.data), + body: SafeArea( + child: ChangeNotifierProvider( + create: (context) => MainPageNotifier(), + child: BlocProvider( + bloc: MainPageBloc(), + child: _MainPageContainer(widget.data), + ), ), ), ); @@ -46,29 +47,16 @@ class _MainPageContainer extends StatefulWidget { } class _MainPageContainerState extends State<_MainPageContainer> { - WidgetType _type = WidgetType.normal; bool _isEnded = false; ScrollController _controller = ScrollController(); MainPageBloc _bloc; - - List items = ["1", "2", "3", "4", "5", "6", "7", "8"]; RefreshController _refreshController = RefreshController(initialRefresh: false); - void _onRefresh() async { - // monitor network fetch - await Future.delayed(Duration(milliseconds: 1000)); - // if failed,use refreshFailed() - _refreshController.refreshCompleted(); - } - void _onLoading() async { - // monitor network fetch - await Future.delayed(Duration(milliseconds: 1000)); - // if failed,use loadFailed(),if no data return,use LoadNodata() - items.add((items.length + 1).toString()); - if (mounted) setState(() {}); - _refreshController.loadComplete(); + // await Future.delayed(Duration(milliseconds: 1000)); + // if (mounted) setState(() {}); + // _refreshController.loadComplete(); } @override @@ -80,7 +68,6 @@ class _MainPageContainerState extends State<_MainPageContainer> { @override void initState() { _bloc = BlocProvider.of(context); - _reload(); _controller.addListener(() { // print('${_controller.offset} ${_controller.position.maxScrollExtent}'); if (_controller.offset >= _controller.position.maxScrollExtent && @@ -97,79 +84,16 @@ class _MainPageContainerState extends State<_MainPageContainer> { super.initState(); } - void _reload() { - setState(() { - _type = WidgetType.skeleton; - }); - WidgetModel model = WidgetModel.fromJson(widget.data); - if ((model?.components?.length ?? 0) > 0) { - _bloc.loadData(model.components.map((item) => item.modId).toList()); - } - - // Future.delayed(Duration(seconds: 3), () { - // setState(() { - // _type = WidgetType.normal; - // }); - // }); - } - - List _createContent(BuildContext context) { - List list = List(); - list.add(SliverToBoxAdapter( - child: RaisedButton( - onPressed: () { - Provider.of(context, listen: false).loadMore(); - _reload(); - }, - child: Text('重置'), - ), - )); - list.addAll(WidgetFactory.create('index_carousel', - type: _type, - isSliver: true, - model: Map.from({'aaaaa': 'bbbb'}))); - list.addAll(WidgetFactory.create('home_quick_entry', type: _type, isSliver: true)); - list.addAll(WidgetFactory.create('index_recommend_list', - type: _type, isSliver: true)); - return list; - } - @override Widget build(BuildContext context) { - return StreamBuilder>>>( + return StreamBuilder>( stream: _bloc.outData, builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.data == null) { - return MainPageSkeleton(); - } - - _type = WidgetType.normal; return SmartRefresher( enablePullDown: true, - enablePullUp: true, + enablePullUp: false, header: WaterDropHeader(), - footer: CustomFooter( - builder: (BuildContext context, LoadStatus mode) { - Widget body; - if (mode == LoadStatus.idle) { - body = Text("上拉加载"); - } else if (mode == LoadStatus.loading) { - body = CupertinoActivityIndicator(); - } else if (mode == LoadStatus.failed) { - body = Text("加载失败!点击重试!"); - } else if (mode == LoadStatus.canLoading) { - body = Text("松手,加载更多!"); - } else { - body = Text("没有更多数据了!"); - } - return Container( - height: 55.0, - child: Center(child: body), - ); - }, - ), controller: _refreshController, - onRefresh: _onRefresh, onLoading: _onLoading, child: CustomScrollView( controller: _controller, @@ -179,4 +103,26 @@ class _MainPageContainerState extends State<_MainPageContainer> { }, ); } + + List _createContent(BuildContext context) { + WidgetModel model = WidgetModel.fromJson(widget.data); + + List list = List(); + for (int i = 0; i < model.components.length; i++) { + WidgetModel item = model.components[i]; + Map data = null; + if (widget.data.containsKey('components')) { + data = widget.data['components'][i]; + } + + list.addAll(WidgetFactory.create( + item.modName, + type: WidgetType.skeleton, + isSliver: true, + model: data, + )); + } + model.components.forEach((item) {}); + return list; + } } diff --git a/lib/pages/main_page/main_page_bloc.dart b/lib/pages/main_page/main_page_bloc.dart index 7e2fc0c..0cda2f5 100644 --- a/lib/pages/main_page/main_page_bloc.dart +++ b/lib/pages/main_page/main_page_bloc.dart @@ -4,12 +4,11 @@ import 'package:zhiying_comm/zhiying_comm.dart'; import 'package:zhiying_comm/util/base_bloc.dart'; class MainPageBloc extends BlocBase { - List>> _mains = List(); + Map _mains = Map(); - StreamController>>> _mainController = - StreamController>>>(); - Stream>>> get outData => - _mainController.stream; + StreamController> _mainController = + StreamController>(); + Stream> get outData => _mainController.stream; @override void dispose() { @@ -18,20 +17,12 @@ class MainPageBloc extends BlocBase { } void loadData(List ids) { - NetUtil.request('/api/v1/mod', - method: NetMethod.POST, - params: Map.from({'ids': ids}), onSuccess: (data) { - Map datas = data; - List>> result = List(); - for (int id in ids) { - if (datas.containsKey(id.toString())) { - result.add(List>.from(datas[id.toString()])); - } else { - result.add(List>()); - } - } - _mains = result; - _mainController.add(_mains); + NetUtil.request('/api/v1/config.json', onSuccess: (data) { + List list = data; + List> tabs = list.map((item) { + return Map.from(item); + }).toList(); + _mainController.add(tabs.first); }); } } diff --git a/lib/pages/main_page/main_page_sk.dart b/lib/pages/main_page/main_page_sk.dart deleted file mode 100644 index abf7823..0000000 --- a/lib/pages/main_page/main_page_sk.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zhiying_comm/zhiying_comm.dart'; - -// ignore: must_be_immutable -class MainPageSkeleton extends StatelessWidget { - ScrollController _controller; - - MainPageSkeleton({Key key}) : super(key: key) { - _controller = ScrollController(); - } - - @override - Widget build(BuildContext context) { - return SafeArea( - child: CustomScrollView( - controller: _controller, - slivers: _createContent(context), - ), - ); - } - - List _createContent(BuildContext context) { - List list = List(); - - list.addAll(WidgetFactory.create('index_carousel', - type: WidgetType.skeleton, - isSliver: true, - model: Map.from({'aaaaa': 'bbbb'}))); - list.addAll(WidgetFactory.create('index_recommend_list', - type: WidgetType.skeleton, isSliver: true)); - return list; - } -} diff --git a/lib/widgets/home_goods/bloc/home_goods_bloc.dart b/lib/widgets/home_goods/bloc/home_goods_bloc.dart new file mode 100644 index 0000000..9682e79 --- /dev/null +++ b/lib/widgets/home_goods/bloc/home_goods_bloc.dart @@ -0,0 +1,64 @@ +import 'dart:async'; + +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_model.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_style_model.dart'; +import 'package:zhiying_comm/util/base_bloc.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; + +class HomeGoodsBloc extends BlocBase { + List _goods = List(); + String storeName = ''; + HomeGoodsStyleModel style; + + String _provider = ''; + + int _page = 1; + + StreamController> _goodsController = + StreamController>(); + + Stream> get outData => _goodsController.stream; + + @override + void dispose() { + _goodsController.close(); + _goodsController = null; + } + + void loadMore(String provider) { + if (provider != _provider) { + _page = 1; + } + _provider = provider; + + if (_page == 1) { + _goods.clear(); + } + + NetUtil.request( + '/api/v1/rec/${provider.toString()}?page=${_page.toString()}', + method: NetMethod.GET, + onCache: (data) {}, onSuccess: (data) { + Map json = Map.from(data); + if (json.containsKey('good')) { + List list = json['good']; + List goods = list.map((item) { + return HomeGoodsModel.fromJson(Map.from(item)); + }).toList(); + if (goods.length > 0) { + _page++; + } + _goods.addAll(goods); + } + if (json.containsKey('style')) { + style = HomeGoodsStyleModel.fromJson( + Map.from(json['style'])); + } + if (json.containsKey('provider_name')) { + storeName = json['provider_name'].toString(); + } + + _goodsController.add(_goods); + }); + } +} diff --git a/lib/widgets/home_goods/bloc/home_goods_header_bloc.dart b/lib/widgets/home_goods/bloc/home_goods_header_bloc.dart new file mode 100644 index 0000000..accece6 --- /dev/null +++ b/lib/widgets/home_goods/bloc/home_goods_header_bloc.dart @@ -0,0 +1,40 @@ +import 'dart:async'; + +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_header_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import 'package:zhiying_comm/util/base_bloc.dart'; + +class HomeGoodsHeaderBloc extends BlocBase { + List _tabs = List(); + + StreamController> _tabController = + StreamController>(); + Stream> get outData => _tabController.stream; + + @override + void dispose() { + _tabController.close(); + _tabController = null; + } + + void loadData(int id) { + NetUtil.request('/api/v1/mod', + method: NetMethod.POST, + params: Map.from({ + 'ids': [id] + }), + onCache: (data) {}, onSuccess: (data) { + String key = id.toString(); + + Map json = Map.from(data); + if (json.containsKey(key)) { + List list = json[key]; + _tabs = list.map((item) { + return HomeGoodsHeaderModel.fromJson(Map.from(item)); + }).toList(); + } + + _tabController.add(_tabs); + }); + } +} diff --git a/lib/widgets/home_goods/home_goods.dart b/lib/widgets/home_goods/home_goods.dart index dd7916c..ac42ba2 100644 --- a/lib/widgets/home_goods/home_goods.dart +++ b/lib/widgets/home_goods/home_goods.dart @@ -1,10 +1,20 @@ +import 'package:event_bus/event_bus.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:zhiying_base_widget/pages/main_page/main_page_notifier.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/bloc/home_goods_bloc.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/home_goods_creater.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/home_goods_item.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_model.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_sk.dart'; +import 'package:zhiying_comm/util/base_bloc.dart'; class HomeGoods extends StatefulWidget { - HomeGoods({Key key}) : super(key: key); + final Map data; + final EventBus eventBus; + + HomeGoods(this.data, {Key key, this.eventBus}) : super(key: key); @override _HomeGoodsState createState() => _HomeGoodsState(); @@ -16,13 +26,48 @@ class _HomeGoodsState extends State { super.initState(); } + @override + Widget build(BuildContext context) { + return BlocProvider( + bloc: HomeGoodsBloc(), + child: _HomeGoodsContainer(widget.data, widget.eventBus), + ); + } +} + +class _HomeGoodsContainer extends StatefulWidget { + final Map data; + final EventBus eventBus; + + _HomeGoodsContainer(this.data, this.eventBus, {Key key}) : super(key: key); + + @override + _HomeGoodsContainerState createState() => _HomeGoodsContainerState(); +} + +class _HomeGoodsContainerState extends State<_HomeGoodsContainer> { + HomeGoodsBloc _bloc; + String _provider = ''; + + @override + void initState() { + _bloc = BlocProvider.of(context); + widget.eventBus.on().listen((data) { + _provider = data.provider; + _bloc.loadMore(_provider); + }); + + super.initState(); + } + @override void didChangeDependencies() { super.didChangeDependencies(); print('didChangeDependencies'); bool isNeedLoadMore = Provider.of(context).scrollEnd; - if (isNeedLoadMore) { + if (isNeedLoadMore && _provider != '') { print('HomeGoods loadmore...'); + _bloc.loadMore(_provider); } } @@ -30,19 +75,28 @@ class _HomeGoodsState extends State { Widget build(BuildContext context) { return Container( width: double.infinity, - child: ListView.builder( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: 20, - itemBuilder: (context, index) { - return Container( - width: double.infinity, - height: 70, - color: Colors.primaries[index % Colors.primaries.length], - child: Text( - Provider.of(context).scrollEnd.toString()), - ); - }), + child: StreamBuilder>( + stream: _bloc.outData, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data == null) { + return HomeGoodsSkeleton(); + } + + List goods = snapshot.data; + return ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: goods.length, + itemBuilder: (context, index) { + return HomeGoodsItem( + goods[index], + _bloc.style, + data: widget.data, + shop: _bloc.storeName, + ); + }); + }, + ), ); } } diff --git a/lib/widgets/home_goods/home_goods_creater.dart b/lib/widgets/home_goods/home_goods_creater.dart index b149e21..235c2a7 100644 --- a/lib/widgets/home_goods/home_goods_creater.dart +++ b/lib/widgets/home_goods/home_goods_creater.dart @@ -1,45 +1,42 @@ +import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/bloc/home_goods_header_bloc.dart'; import 'package:zhiying_base_widget/widgets/home_goods/home_goods.dart'; import 'package:zhiying_base_widget/widgets/home_goods/home_goods_header.dart'; -import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_header_sk.dart'; -import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_sk.dart'; +import 'package:zhiying_comm/util/base_bloc.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; -import 'package:event_bus/event_bus.dart'; class GoodsListCreater extends WidgetCreater { + final EventBus _eventBus = EventBus(); + @override List createWidgets(Map model) { - - EventBus eventBus = EventBus(); - return [ - SliverPersistentHeader( - pinned: true, - floating: false, - delegate: HomeGoodsDelegate(), - ), - SliverToBoxAdapter( - child: HomeGoods(), - ), - ]; - } + print('创建商品列表'); + Widget _widget = BlocProvider( + bloc: HomeGoodsHeaderBloc(), + child: HomeGoodsHeader(model, _eventBus), + ); - @override - List createSkeleton(Map model) { return [ SliverPersistentHeader( - pinned: true, - floating: false, - delegate: HomeGoodsHeaderSkeletonDelegate(), - ), + pinned: true, + floating: false, + delegate: HomeGoodsHeaderDelegate(_widget), + ), SliverToBoxAdapter( - child: HomeGoodsSkeleton(), - ), + child: HomeGoods(model, eventBus: _eventBus), + ), ]; } - @override bool isSliverChild() { return true; } } + +class HomeGoodsHeaderEvent { + String provider; + + HomeGoodsHeaderEvent(this.provider); +} diff --git a/lib/widgets/home_goods/home_goods_header.dart b/lib/widgets/home_goods/home_goods_header.dart index 6ce4ce9..6c8a35d 100644 --- a/lib/widgets/home_goods/home_goods_header.dart +++ b/lib/widgets/home_goods/home_goods_header.dart @@ -1,27 +1,22 @@ +import 'package:event_bus/event_bus.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/bloc/home_goods_header_bloc.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/home_goods_creater.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_header_model.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_header_sk.dart'; +import 'package:zhiying_comm/util/base_bloc.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; -class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { +class HomeGoodsHeaderDelegate extends SliverPersistentHeaderDelegate { + final Widget child; + + HomeGoodsHeaderDelegate(this.child) : super(); @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { - // print(shrinkOffset.toString()); - return Container( - color: Colors.red, - alignment: Alignment.center, - child: TabBar( - controller: TabController(initialIndex: 0, length: 6, vsync: ScrollableState()), - isScrollable: true, - tabs: [ - Tab(icon: Icon(Icons.local_florist)), - Tab(icon: Icon(Icons.change_history)), - Tab(icon: Icon(Icons.directions_bike)), - Tab(icon: Icon(Icons.local_florist)), - Tab(icon: Icon(Icons.change_history)), - Tab(icon: Icon(Icons.directions_bike)), - ], - ), - ); + return child; } @override @@ -34,3 +29,167 @@ class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => false; // 如果内容需要更新,设置为true } + +class HomeGoodsHeader extends StatelessWidget { + final Map model; + final EventBus eventBus; + + const HomeGoodsHeader( + this.model, + this.eventBus, { + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + bloc: HomeGoodsHeaderBloc(), + child: _HomeGoodsHeader(model, eventBus), + ); + } +} + +class _HomeGoodsHeader extends StatefulWidget { + final Map model; + final EventBus eventBus; + + _HomeGoodsHeader(this.model, this.eventBus, {Key key}) : super(key: key); + + @override + _HomeGoodsHeaderState createState() => _HomeGoodsHeaderState(); +} + +class _HomeGoodsHeaderState extends State<_HomeGoodsHeader> { + HomeGoodsHeaderBloc _bloc; + + @override + void dispose() { + _bloc.dispose(); + super.dispose(); + } + + @override + void initState() { + _bloc = BlocProvider.of(context); + _bloc.loadData(widget.model['mod_id']); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return StreamBuilder>( + stream: _bloc.outData, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data == null) { + return HomeGoodsHeaderSkeleton(); + } + return HomeGoodsHeaderContainer(snapshot.data, widget.eventBus); + }); + } +} + +class HomeGoodsHeaderContainer extends StatefulWidget { + final List headers; + final EventBus eventBus; + + HomeGoodsHeaderContainer(this.headers, this.eventBus, {Key key}) + : super(key: key); + + @override + _HomeGoodsHeaderContainerState createState() => + _HomeGoodsHeaderContainerState(); +} + +class _HomeGoodsHeaderContainerState extends State + with TickerProviderStateMixin { + List _widgets = List(); + + TabController _tabController; + int _currentIndex = 0; + + @override + void initState() { + _tabController = TabController(length: widget.headers.length, vsync: this); + if (widget.headers.first != null) { + widget.eventBus.fire(HomeGoodsHeaderEvent(widget.headers.first.modName)); + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + _widgets.clear(); + for (int index = 0; index < widget.headers.length; index++) { + _widgets.add(_HomeGoodsHeaderItem( + widget.headers[index], + isSelected: index == _currentIndex, + )); + } + + return Container( + width: double.infinity, + height: double.infinity, + color: Color(0xfff9f9f9), + child: TabBar( + indicatorColor: Colors.transparent, + controller: _tabController, + isScrollable: true, + tabs: _widgets, + onTap: (index) { + widget.eventBus + .fire(HomeGoodsHeaderEvent(widget.headers[index].modName)); + setState(() { + _currentIndex = index; + }); + }, + ), + ); + } +} + +class _HomeGoodsHeaderItem extends StatelessWidget { + final bool isSelected; + final HomeGoodsHeaderModel model; + + const _HomeGoodsHeaderItem(this.model, {Key key, this.isSelected = false}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + // width: 60, + // height: 54, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + model.title, + style: TextStyle( + color: HexColor.fromHex(model.fontColor), + fontSize: 17, + fontWeight: FontWeight.bold), + ), + Container( + margin: EdgeInsets.only(top: 4), + padding: EdgeInsets.only(left: 6, right: 6, top: 2, bottom: 2), + decoration: BoxDecoration( + color: isSelected + ? HexColor.fromHex(model.fontColor) + : Colors.transparent, + borderRadius: BorderRadius.circular(18)), + child: Text( + model.subtitle, + style: TextStyle( + fontSize: 10, + color: isSelected ? Colors.white : Color(0xff999999)), + textAlign: TextAlign.center, + ), + ), + ], + ), + )); + } +} diff --git a/lib/widgets/home_goods/home_goods_item.dart b/lib/widgets/home_goods/home_goods_item.dart index 1008235..2b603c3 100644 --- a/lib/widgets/home_goods/home_goods_item.dart +++ b/lib/widgets/home_goods/home_goods_item.dart @@ -1,15 +1,254 @@ +import 'dart:convert'; + +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_model.dart'; +import 'package:zhiying_base_widget/widgets/home_goods/models/home_goods_style_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +// ignore: must_be_immutable class HomeGoodsItem extends StatelessWidget { - const HomeGoodsItem({Key key}) : super(key: key); + final HomeGoodsModel goods; + final HomeGoodsStyleModel style; + final String shop; + Map data; + + HomeGoodsItem(this.goods, this.style, {Key key, this.data, this.shop}) + : super(key: key) { + if (this.data != null && this.data.containsKey('data')) { + String data = this.data['data']; + Map json = Map.from(jsonDecode(data)); + this.data = json; + } + } @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: [ + 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( + height: 126, + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + child: _createTitle(), + ), + _createShop(), + _createCupone(), + Expanded(child: Container()), + _createBottom(), + ], + ), + ), + ) + ], + ), + ); + } + + Widget _createTitle() { + return RichText( + maxLines: 2, + overflow: TextOverflow.ellipsis, + text: TextSpan(children: [ + WidgetSpan( + child: shop == null || shop == '' + ? Container() + : Container( + padding: + EdgeInsets.only(left: 2, right: 2, top: 3, bottom: 3), + margin: EdgeInsets.only(right: 4), + child: Text( + shop, + style: TextStyle( + fontSize: 9, + height: 1, + color: HexColor.fromHex('#ffffff'), + ), + ), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(2.5)), + ), + ), + TextSpan( + text: goods.goodTitle, + style: TextStyle( + fontSize: 15, + color: HexColor.fromHex('#333333'), + fontWeight: FontWeight.bold), + ) + ]), + ); + } + + Widget _createShop() { + return Container( + margin: EdgeInsets.only(top: 5), + width: double.infinity, + child: Row( + children: [ + Container( + width: 15, + height: 15, + margin: EdgeInsets.only(right: 2), + child: CachedNetworkImage( + imageUrl: style.shopIcon, + fit: BoxFit.fitHeight, + ), + ), + Expanded( + child: Text( + goods.shopName, + style: TextStyle( + color: HexColor.fromHex(style.shopNameColor), + fontSize: 11, + fontWeight: FontWeight.w400), + )) + ], + ), + ); + } + + Widget _createCupone() { + List widgets = List(); + if (goods.coupon != null && goods.coupon != '') { + widgets.add(Container( + margin: EdgeInsets.only(right: 5), + padding: EdgeInsets.only(left: 10, right: 10, top: 2, bottom: 2), + decoration: BoxDecoration( + color: HexColor.fromHex(style.couponBackgroundColor), + borderRadius: BorderRadius.circular(2.5), + ), + child: Text( + goods.coupon, + textAlign: TextAlign.center, + maxLines: 1, + style: TextStyle( + height: 1, + fontSize: 11, + color: HexColor.fromHex(style.couponFontColor), + ), + ), + )); + } + + if (goods.commission != null || goods.commission != '') { + widgets.add(Container( + margin: EdgeInsets.only(right: 5), + padding: EdgeInsets.only(left: 10, right: 10, top: 2, bottom: 2), + decoration: BoxDecoration( + color: HexColor.fromHex(style.commissionBackgroundColor), + borderRadius: BorderRadius.circular(2.5), + ), + child: Text( + goods.commission, + textAlign: TextAlign.center, + maxLines: 1, + style: TextStyle( + height: 1, + fontSize: 11, + color: HexColor.fromHex(style.commissionFontColor), + ), + ), + )); + } + + return Container( + margin: EdgeInsets.only(top: 6), + child: Row( + children: widgets, + ), + ); + } + + Widget _createBottom() { + return Container( + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _createPrice(), + _createOriginPrice(), + Expanded(child: Container()), + _createSale(), + ], + ), + ); + } + + Widget _createPrice() { + return RichText( + maxLines: 1, + overflow: TextOverflow.ellipsis, + text: TextSpan(children: [ + TextSpan( + text: '¥', + style: TextStyle( + fontSize: 10, + color: HexColor.fromHex(style.currentPriceColor), + fontWeight: FontWeight.bold, + fontFamily: 'Din', + package: 'zhiying_base_widget', + ), + ), + TextSpan( + text: goods.currentPrice, + style: TextStyle( + fontSize: 20, + color: HexColor.fromHex(style.currentPriceColor), + fontWeight: FontWeight.bold, + fontFamily: 'Din', + package: 'zhiying_base_widget', + ), + ) + ]), + ); + } + + Widget _createOriginPrice() { + return Padding( + padding: EdgeInsets.only(bottom: 2), + child: Text( + '¥${goods.marketPrice}', + style: TextStyle( + fontSize: 11, + height: 1, + color: HexColor.fromHex(style.marketPriceColor), + fontWeight: FontWeight.normal, + fontFamily: 'Din', + package: 'zhiying_base_widget', + decoration: TextDecoration.lineThrough, + ), + )); + } + + Widget _createSale() { + return Text( + '${goods.inorderCount}', + style: TextStyle(fontSize: 11, color: HexColor.fromHex('#999999')), ); } } diff --git a/lib/widgets/home_goods/models/home_goods_header_model.dart b/lib/widgets/home_goods/models/home_goods_header_model.dart new file mode 100644 index 0000000..d016409 --- /dev/null +++ b/lib/widgets/home_goods/models/home_goods_header_model.dart @@ -0,0 +1,94 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'home_goods_header_model.g.dart'; + +@JsonSerializable() +class HomeGoodsHeaderModel extends Object { + @JsonKey(name: 'mod_id') + int modId; + + @JsonKey(name: 'mod_pid') + int modPid; + + @JsonKey(name: 'mod_name') + String modName; + + @JsonKey(name: 'position') + String position; + + @JsonKey(name: 'title') + String title; + + @JsonKey(name: 'subtitle') + String subtitle; + + @JsonKey(name: 'url') + String url; + + @JsonKey(name: 'margin') + String margin; + + @JsonKey(name: 'aspect_ratio') + String aspectRatio; + + @JsonKey(name: 'icon') + String icon; + + @JsonKey(name: 'img') + String img; + + @JsonKey(name: 'font_color') + String fontColor; + + @JsonKey(name: 'bg_img') + String bgImg; + + @JsonKey(name: 'bg_color') + String bgColor; + + @JsonKey(name: 'bg_color_t') + String bgColorT; + + @JsonKey(name: 'badge') + String badge; + + @JsonKey(name: 'path') + String path; + + @JsonKey(name: 'data') + String data; + + @JsonKey(name: 'sort') + int sort; + + @JsonKey(name: 'is_global') + int isGlobal; + + HomeGoodsHeaderModel( + this.modId, + this.modPid, + this.modName, + this.position, + this.title, + this.subtitle, + this.url, + this.margin, + this.aspectRatio, + this.icon, + this.img, + this.fontColor, + this.bgImg, + this.bgColor, + this.bgColorT, + this.badge, + this.path, + this.data, + this.sort, + this.isGlobal, + ); + + factory HomeGoodsHeaderModel.fromJson(Map srcJson) => + _$HomeGoodsHeaderModelFromJson(srcJson); + + Map toJson() => _$HomeGoodsHeaderModelToJson(this); +} diff --git a/lib/widgets/home_goods/models/home_goods_header_model.g.dart b/lib/widgets/home_goods/models/home_goods_header_model.g.dart new file mode 100644 index 0000000..548f1f9 --- /dev/null +++ b/lib/widgets/home_goods/models/home_goods_header_model.g.dart @@ -0,0 +1,57 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'home_goods_header_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +HomeGoodsHeaderModel _$HomeGoodsHeaderModelFromJson(Map json) { + return HomeGoodsHeaderModel( + json['mod_id'] as int, + json['mod_pid'] as int, + json['mod_name'] as String, + json['position'] as String, + json['title'] as String, + json['subtitle'] as String, + json['url'] as String, + json['margin'] as String, + json['aspect_ratio'] as String, + json['icon'] as String, + json['img'] as String, + json['font_color'] as String, + json['bg_img'] as String, + json['bg_color'] as String, + json['bg_color_t'] as String, + json['badge'] as String, + json['path'] as String, + json['data'] as String, + json['sort'] as int, + json['is_global'] as int, + ); +} + +Map _$HomeGoodsHeaderModelToJson( + HomeGoodsHeaderModel instance) => + { + 'mod_id': instance.modId, + 'mod_pid': instance.modPid, + 'mod_name': instance.modName, + 'position': instance.position, + 'title': instance.title, + 'subtitle': instance.subtitle, + 'url': instance.url, + 'margin': instance.margin, + 'aspect_ratio': instance.aspectRatio, + 'icon': instance.icon, + 'img': instance.img, + 'font_color': instance.fontColor, + 'bg_img': instance.bgImg, + 'bg_color': instance.bgColor, + 'bg_color_t': instance.bgColorT, + 'badge': instance.badge, + 'path': instance.path, + 'data': instance.data, + 'sort': instance.sort, + 'is_global': instance.isGlobal, + }; diff --git a/lib/widgets/home_goods/models/home_goods_model.dart b/lib/widgets/home_goods/models/home_goods_model.dart new file mode 100644 index 0000000..9e5ba87 --- /dev/null +++ b/lib/widgets/home_goods/models/home_goods_model.dart @@ -0,0 +1,54 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'home_goods_model.g.dart'; + +@JsonSerializable() +class HomeGoodsModel extends Object { + @JsonKey(name: 'provider_name') + String providerName; + + @JsonKey(name: 'good_id') + String goodId; + + @JsonKey(name: 'good_image') + String goodImage; + + @JsonKey(name: 'good_title') + String goodTitle; + + @JsonKey(name: 'shop_name') + String shopName; + + @JsonKey(name: 'coupon') + String coupon; + + @JsonKey(name: 'commission') + String commission; + + @JsonKey(name: 'market_price') + String marketPrice; + + @JsonKey(name: 'current_price') + String currentPrice; + + @JsonKey(name: 'inorder_count') + String inorderCount; + + HomeGoodsModel( + this.providerName, + this.goodId, + this.goodImage, + this.goodTitle, + this.shopName, + this.coupon, + this.commission, + this.marketPrice, + this.currentPrice, + this.inorderCount, + ); + + factory HomeGoodsModel.fromJson(Map srcJson) => + _$HomeGoodsModelFromJson(srcJson); + + Map toJson() => _$HomeGoodsModelToJson(this); +} diff --git a/lib/widgets/home_goods/models/home_goods_model.g.dart b/lib/widgets/home_goods/models/home_goods_model.g.dart new file mode 100644 index 0000000..8e0acb1 --- /dev/null +++ b/lib/widgets/home_goods/models/home_goods_model.g.dart @@ -0,0 +1,36 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'home_goods_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +HomeGoodsModel _$HomeGoodsModelFromJson(Map json) { + return HomeGoodsModel( + json['provider_name'] as String, + json['good_id'] as String, + json['good_image'] as String, + json['good_title'] as String, + json['shop_name'] as String, + json['coupon'] as String, + json['commission'] as String, + json['market_price'] as String, + json['current_price'] as String, + json['inorder_count'] as String, + ); +} + +Map _$HomeGoodsModelToJson(HomeGoodsModel instance) => + { + 'provider_name': instance.providerName, + 'good_id': instance.goodId, + 'good_image': instance.goodImage, + 'good_title': instance.goodTitle, + 'shop_name': instance.shopName, + 'coupon': instance.coupon, + 'commission': instance.commission, + 'market_price': instance.marketPrice, + 'current_price': instance.currentPrice, + 'inorder_count': instance.inorderCount, + }; diff --git a/lib/widgets/home_goods/models/home_goods_style_model.dart b/lib/widgets/home_goods/models/home_goods_style_model.dart new file mode 100644 index 0000000..85e3570 --- /dev/null +++ b/lib/widgets/home_goods/models/home_goods_style_model.dart @@ -0,0 +1,54 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'home_goods_style_model.g.dart'; + +@JsonSerializable() +class HomeGoodsStyleModel extends Object { + @JsonKey(name: 'provider_name_color') + String providerNameColor; + + @JsonKey(name: 'provider_name_background_color') + String providerNameBackgroundColor; + + @JsonKey(name: 'shop_name_color') + String shopNameColor; + + @JsonKey(name: 'shop_icon') + String shopIcon; + + @JsonKey(name: 'coupon_background_color') + String couponBackgroundColor; + + @JsonKey(name: 'coupon_font_color') + String couponFontColor; + + @JsonKey(name: 'commission_background_color') + String commissionBackgroundColor; + + @JsonKey(name: 'commission_font_color') + String commissionFontColor; + + @JsonKey(name: 'market_price_color') + String marketPriceColor; + + @JsonKey(name: 'current_price_color') + String currentPriceColor; + + HomeGoodsStyleModel( + this.providerNameColor, + this.providerNameBackgroundColor, + this.shopNameColor, + this.shopIcon, + this.couponBackgroundColor, + this.couponFontColor, + this.commissionBackgroundColor, + this.commissionFontColor, + this.marketPriceColor, + this.currentPriceColor, + ); + + factory HomeGoodsStyleModel.fromJson(Map srcJson) => + _$HomeGoodsStyleModelFromJson(srcJson); + + Map toJson() => _$HomeGoodsStyleModelToJson(this); +} diff --git a/lib/widgets/home_goods/models/home_goods_style_model.g.dart b/lib/widgets/home_goods/models/home_goods_style_model.g.dart new file mode 100644 index 0000000..3cf2e24 --- /dev/null +++ b/lib/widgets/home_goods/models/home_goods_style_model.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'home_goods_style_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +HomeGoodsStyleModel _$HomeGoodsStyleModelFromJson(Map json) { + return HomeGoodsStyleModel( + json['provider_name_color'] as String, + json['provider_name_background_color'] as String, + json['shop_name_color'] as String, + json['shop_icon'] as String, + json['coupon_background_color'] as String, + json['coupon_font_color'] as String, + json['commission_background_color'] as String, + json['commission_font_color'] as String, + json['market_price_color'] as String, + json['current_price_color'] as String, + ); +} + +Map _$HomeGoodsStyleModelToJson( + HomeGoodsStyleModel instance) => + { + 'provider_name_color': instance.providerNameColor, + 'provider_name_background_color': instance.providerNameBackgroundColor, + 'shop_name_color': instance.shopNameColor, + 'shop_icon': instance.shopIcon, + 'coupon_background_color': instance.couponBackgroundColor, + 'coupon_font_color': instance.couponFontColor, + 'commission_background_color': instance.commissionBackgroundColor, + 'commission_font_color': instance.commissionFontColor, + 'MarketPriceColor': instance.marketPriceColor, + 'current_price_color': instance.currentPriceColor, + }; diff --git a/lib/widgets/home_goods/skeleton/home_goods_header_sk.dart b/lib/widgets/home_goods/skeleton/home_goods_header_sk.dart index a2c3e2d..0bc9069 100644 --- a/lib/widgets/home_goods/skeleton/home_goods_header_sk.dart +++ b/lib/widgets/home_goods/skeleton/home_goods_header_sk.dart @@ -1,13 +1,11 @@ import 'package:flutter/material.dart'; import 'package:shimmer/shimmer.dart'; -import 'package:zhiying_base_widget/widgets/home_banner/home_banner_sk.dart'; -class HomeGoodsHeaderSkeletonDelegate extends SliverPersistentHeaderDelegate { - HomeGoodsHeaderSkeletonDelegate(); +class HomeGoodsHeaderSkeleton extends StatelessWidget { + const HomeGoodsHeaderSkeleton({Key key}) : super(key: key); @override - Widget build( - BuildContext context, double shrinkOffset, bool overlapsContent) { + Widget build(BuildContext context) { return Container( width: double.infinity, height: double.infinity, @@ -48,14 +46,4 @@ class HomeGoodsHeaderSkeletonDelegate extends SliverPersistentHeaderDelegate { ), ); } - - @override - double get maxExtent => 64.0; - - @override - double get minExtent => 64.0; - - @override - bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => - false; // 如果内容需要更新,设置为true } diff --git a/pubspec.yaml b/pubspec.yaml index 1bf9f20..e342d9d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,10 @@ dev_dependencies: zhiying_comm: path: ../zhiying_comm + + + json_serializable: ^3.3.0 + build_runner: ^1.10.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -55,17 +59,13 @@ flutter: # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 + fonts: + - family: Din + fonts: + - asset: assets/fonts/DIN-Bold.otf + - asset: assets/fonts/DIN-Medium.otf + - asset: assets/fonts/DIN-Regular.otf + # # For details regarding fonts in packages, see # https://flutter.dev/custom-fonts/#from-packages