Ver código fonte

更新商品列表

tags/0.0.1
Weller 4 anos atrás
pai
commit
9f328e846d
25 arquivos alterados com 1022 adições e 226 exclusões
  1. BIN
     
  2. +1
    -0
      .dart_tool/build_resolvers/sdk.sum.deps
  3. +1
    -1
      .dart_tool/package_config.json
  4. +5
    -0
      .idea/codeStyles/codeStyleConfig.xml
  5. +13
    -0
      .idea/saveactions_settings.xml
  6. BIN
     
  7. BIN
     
  8. BIN
     
  9. +34
    -88
      lib/pages/main_page/main_page.dart
  10. +10
    -19
      lib/pages/main_page/main_page_bloc.dart
  11. +0
    -33
      lib/pages/main_page/main_page_sk.dart
  12. +64
    -0
      lib/widgets/home_goods/bloc/home_goods_bloc.dart
  13. +40
    -0
      lib/widgets/home_goods/bloc/home_goods_header_bloc.dart
  14. +69
    -15
      lib/widgets/home_goods/home_goods.dart
  15. +22
    -25
      lib/widgets/home_goods/home_goods_creater.dart
  16. +177
    -18
      lib/widgets/home_goods/home_goods_header.dart
  17. +240
    -1
      lib/widgets/home_goods/home_goods_item.dart
  18. +94
    -0
      lib/widgets/home_goods/models/home_goods_header_model.dart
  19. +57
    -0
      lib/widgets/home_goods/models/home_goods_header_model.g.dart
  20. +54
    -0
      lib/widgets/home_goods/models/home_goods_model.dart
  21. +36
    -0
      lib/widgets/home_goods/models/home_goods_model.g.dart
  22. +54
    -0
      lib/widgets/home_goods/models/home_goods_style_model.dart
  23. +37
    -0
      lib/widgets/home_goods/models/home_goods_style_model.g.dart
  24. +3
    -15
      lib/widgets/home_goods/skeleton/home_goods_header_sk.dart
  25. +11
    -11
      pubspec.yaml

+ 1
- 0
.dart_tool/build_resolvers/sdk.sum.deps Ver arquivo

@@ -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"}

+ 1
- 1
.dart_tool/package_config.json Ver arquivo

@@ -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"
}

+ 5
- 0
.idea/codeStyles/codeStyleConfig.xml Ver arquivo

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

+ 13
- 0
.idea/saveactions_settings.xml Ver arquivo

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SaveActionSettings">
<option name="actions">
<set>
<option value="activate" />
<option value="organizeImports" />
<option value="reformat" />
</set>
</option>
<option name="configurationPath" value="" />
</component>
</project>




+ 34
- 88
lib/pages/main_page/main_page.dart Ver arquivo

@@ -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<MainPage> {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xfff9f9f9),
body: ChangeNotifierProvider(
create: (context) => MainPageNotifier(),
child: BlocProvider<MainPageBloc>(
bloc: MainPageBloc(),
child: _MainPageContainer(widget.data),
body: SafeArea(
child: ChangeNotifierProvider(
create: (context) => MainPageNotifier(),
child: BlocProvider<MainPageBloc>(
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<String> 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<MainPageBloc>(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<Widget> _createContent(BuildContext context) {
List<Widget> list = List();
list.add(SliverToBoxAdapter(
child: RaisedButton(
onPressed: () {
Provider.of<MainPageNotifier>(context, listen: false).loadMore();
_reload();
},
child: Text('重置'),
),
));
list.addAll(WidgetFactory.create('index_carousel',
type: _type,
isSliver: true,
model: Map<String, dynamic>.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<List<List<Map<String, dynamic>>>>(
return StreamBuilder<Map<String, dynamic>>(
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<Widget> _createContent(BuildContext context) {
WidgetModel model = WidgetModel.fromJson(widget.data);

List<Widget> list = List();
for (int i = 0; i < model.components.length; i++) {
WidgetModel item = model.components[i];
Map<String, dynamic> 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;
}
}

+ 10
- 19
lib/pages/main_page/main_page_bloc.dart Ver arquivo

@@ -4,12 +4,11 @@ import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:zhiying_comm/util/base_bloc.dart';

class MainPageBloc extends BlocBase {
List<List<Map<String, dynamic>>> _mains = List();
Map<String, dynamic> _mains = Map();

StreamController<List<List<Map<String, dynamic>>>> _mainController =
StreamController<List<List<Map<String, dynamic>>>>();
Stream<List<List<Map<String, dynamic>>>> get outData =>
_mainController.stream;
StreamController<Map<String, dynamic>> _mainController =
StreamController<Map<String, dynamic>>();
Stream<Map<String, dynamic>> get outData => _mainController.stream;

@override
void dispose() {
@@ -18,20 +17,12 @@ class MainPageBloc extends BlocBase {
}

void loadData(List<int> ids) {
NetUtil.request('/api/v1/mod',
method: NetMethod.POST,
params: Map<String, dynamic>.from({'ids': ids}), onSuccess: (data) {
Map<String, dynamic> datas = data;
List<List<Map<String, dynamic>>> result = List();
for (int id in ids) {
if (datas.containsKey(id.toString())) {
result.add(List<Map<String, dynamic>>.from(datas[id.toString()]));
} else {
result.add(List<Map<String, dynamic>>());
}
}
_mains = result;
_mainController.add(_mains);
NetUtil.request('/api/v1/config.json', onSuccess: (data) {
List list = data;
List<Map<String, dynamic>> tabs = list.map((item) {
return Map<String, dynamic>.from(item);
}).toList();
_mainController.add(tabs.first);
});
}
}

+ 0
- 33
lib/pages/main_page/main_page_sk.dart Ver arquivo

@@ -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<Widget> _createContent(BuildContext context) {
List<Widget> list = List();

list.addAll(WidgetFactory.create('index_carousel',
type: WidgetType.skeleton,
isSliver: true,
model: Map<String, dynamic>.from({'aaaaa': 'bbbb'})));
list.addAll(WidgetFactory.create('index_recommend_list',
type: WidgetType.skeleton, isSliver: true));
return list;
}
}

+ 64
- 0
lib/widgets/home_goods/bloc/home_goods_bloc.dart Ver arquivo

@@ -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<HomeGoodsModel> _goods = List();
String storeName = '';
HomeGoodsStyleModel style;

String _provider = '';

int _page = 1;

StreamController<List<HomeGoodsModel>> _goodsController =
StreamController<List<HomeGoodsModel>>();

Stream<List<HomeGoodsModel>> 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<String, dynamic> json = Map<String, dynamic>.from(data);
if (json.containsKey('good')) {
List<dynamic> list = json['good'];
List<HomeGoodsModel> goods = list.map((item) {
return HomeGoodsModel.fromJson(Map<String, dynamic>.from(item));
}).toList();
if (goods.length > 0) {
_page++;
}
_goods.addAll(goods);
}
if (json.containsKey('style')) {
style = HomeGoodsStyleModel.fromJson(
Map<String, dynamic>.from(json['style']));
}
if (json.containsKey('provider_name')) {
storeName = json['provider_name'].toString();
}

_goodsController.add(_goods);
});
}
}

+ 40
- 0
lib/widgets/home_goods/bloc/home_goods_header_bloc.dart Ver arquivo

@@ -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<HomeGoodsHeaderModel> _tabs = List();

StreamController<List<HomeGoodsHeaderModel>> _tabController =
StreamController<List<HomeGoodsHeaderModel>>();
Stream<List<HomeGoodsHeaderModel>> 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<String, dynamic>.from({
'ids': [id]
}),
onCache: (data) {}, onSuccess: (data) {
String key = id.toString();

Map<String, dynamic> json = Map<String, dynamic>.from(data);
if (json.containsKey(key)) {
List<dynamic> list = json[key];
_tabs = list.map((item) {
return HomeGoodsHeaderModel.fromJson(Map<String, dynamic>.from(item));
}).toList();
}

_tabController.add(_tabs);
});
}
}

+ 69
- 15
lib/widgets/home_goods/home_goods.dart Ver arquivo

@@ -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<String, dynamic> 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<HomeGoods> {
super.initState();
}

@override
Widget build(BuildContext context) {
return BlocProvider<HomeGoodsBloc>(
bloc: HomeGoodsBloc(),
child: _HomeGoodsContainer(widget.data, widget.eventBus),
);
}
}

class _HomeGoodsContainer extends StatefulWidget {
final Map<String, dynamic> 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<HomeGoodsBloc>(context);
widget.eventBus.on<HomeGoodsHeaderEvent>().listen((data) {
_provider = data.provider;
_bloc.loadMore(_provider);
});

super.initState();
}

@override
void didChangeDependencies() {
super.didChangeDependencies();
print('didChangeDependencies');
bool isNeedLoadMore = Provider.of<MainPageNotifier>(context).scrollEnd;
if (isNeedLoadMore) {
if (isNeedLoadMore && _provider != '') {
print('HomeGoods loadmore...');
_bloc.loadMore(_provider);
}
}

@@ -30,19 +75,28 @@ class _HomeGoodsState extends State<HomeGoods> {
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<MainPageNotifier>(context).scrollEnd.toString()),
);
}),
child: StreamBuilder<List<HomeGoodsModel>>(
stream: _bloc.outData,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return HomeGoodsSkeleton();
}

List<HomeGoodsModel> 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,
);
});
},
),
);
}
}

+ 22
- 25
lib/widgets/home_goods/home_goods_creater.dart Ver arquivo

@@ -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<Widget> createWidgets(Map<String, dynamic> model) {
EventBus eventBus = EventBus();
return [
SliverPersistentHeader(
pinned: true,
floating: false,
delegate: HomeGoodsDelegate(),
),
SliverToBoxAdapter(
child: HomeGoods(),
),
];
}
print('创建商品列表');
Widget _widget = BlocProvider<HomeGoodsHeaderBloc>(
bloc: HomeGoodsHeaderBloc(),
child: HomeGoodsHeader(model, _eventBus),
);

@override
List<Widget> createSkeleton(Map<String, dynamic> 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);
}

+ 177
- 18
lib/widgets/home_goods/home_goods_header.dart Ver arquivo

@@ -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: <Widget>[
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<String, dynamic> model;
final EventBus eventBus;

const HomeGoodsHeader(
this.model,
this.eventBus, {
Key key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return BlocProvider<HomeGoodsHeaderBloc>(
bloc: HomeGoodsHeaderBloc(),
child: _HomeGoodsHeader(model, eventBus),
);
}
}

class _HomeGoodsHeader extends StatefulWidget {
final Map<String, dynamic> 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<HomeGoodsHeaderBloc>(context);
_bloc.loadData(widget.model['mod_id']);

super.initState();
}

@override
Widget build(BuildContext context) {
return StreamBuilder<List<HomeGoodsHeaderModel>>(
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<HomeGoodsHeaderModel> headers;
final EventBus eventBus;

HomeGoodsHeaderContainer(this.headers, this.eventBus, {Key key})
: super(key: key);

@override
_HomeGoodsHeaderContainerState createState() =>
_HomeGoodsHeaderContainerState();
}

class _HomeGoodsHeaderContainerState extends State<HomeGoodsHeaderContainer>
with TickerProviderStateMixin {
List<Widget> _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: <Widget>[
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,
),
),
],
),
));
}
}

+ 240
- 1
lib/widgets/home_goods/home_goods_item.dart Ver arquivo

@@ -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<String, dynamic> 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<String, dynamic> json = Map<String, dynamic>.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: <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(
height: 126,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
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: <Widget>[
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<Widget> 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: <Widget>[
_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')),
);
}
}

+ 94
- 0
lib/widgets/home_goods/models/home_goods_header_model.dart Ver arquivo

@@ -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<String, dynamic> srcJson) =>
_$HomeGoodsHeaderModelFromJson(srcJson);

Map<String, dynamic> toJson() => _$HomeGoodsHeaderModelToJson(this);
}

+ 57
- 0
lib/widgets/home_goods/models/home_goods_header_model.g.dart Ver arquivo

@@ -0,0 +1,57 @@
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'home_goods_header_model.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

HomeGoodsHeaderModel _$HomeGoodsHeaderModelFromJson(Map<String, dynamic> 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<String, dynamic> _$HomeGoodsHeaderModelToJson(
HomeGoodsHeaderModel instance) =>
<String, dynamic>{
'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,
};

+ 54
- 0
lib/widgets/home_goods/models/home_goods_model.dart Ver arquivo

@@ -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<String, dynamic> srcJson) =>
_$HomeGoodsModelFromJson(srcJson);

Map<String, dynamic> toJson() => _$HomeGoodsModelToJson(this);
}

+ 36
- 0
lib/widgets/home_goods/models/home_goods_model.g.dart Ver arquivo

@@ -0,0 +1,36 @@
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'home_goods_model.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

HomeGoodsModel _$HomeGoodsModelFromJson(Map<String, dynamic> 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<String, dynamic> _$HomeGoodsModelToJson(HomeGoodsModel instance) =>
<String, dynamic>{
'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,
};

+ 54
- 0
lib/widgets/home_goods/models/home_goods_style_model.dart Ver arquivo

@@ -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<String, dynamic> srcJson) =>
_$HomeGoodsStyleModelFromJson(srcJson);

Map<String, dynamic> toJson() => _$HomeGoodsStyleModelToJson(this);
}

+ 37
- 0
lib/widgets/home_goods/models/home_goods_style_model.g.dart Ver arquivo

@@ -0,0 +1,37 @@
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'home_goods_style_model.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

HomeGoodsStyleModel _$HomeGoodsStyleModelFromJson(Map<String, dynamic> 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<String, dynamic> _$HomeGoodsStyleModelToJson(
HomeGoodsStyleModel instance) =>
<String, dynamic>{
'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,
};

+ 3
- 15
lib/widgets/home_goods/skeleton/home_goods_header_sk.dart Ver arquivo

@@ -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
}

+ 11
- 11
pubspec.yaml Ver arquivo

@@ -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

Carregando…
Cancelar
Salvar