基础组件库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

246 lines
7.2 KiB

  1. import 'package:event_bus/event_bus.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:pull_to_refresh/pull_to_refresh.dart';
  4. import 'package:provider/provider.dart';
  5. import 'package:flutter_bloc/flutter_bloc.dart';
  6. import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart';
  7. import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart';
  8. import 'package:zhiying_base_widget/widgets/home/home_auth/home_auth.dart';
  9. import 'package:zhiying_base_widget/widgets/refresh/refresh_header/refresh_gif_header.dart';
  10. import 'package:zhiying_comm/zhiying_comm.dart';
  11. import 'bloc/custom_item_page_bloc.dart';
  12. import 'bloc/custom_item_page_state.dart';
  13. import 'bloc/custom_item_page_event.dart';
  14. import 'bloc/custom_item_page_repository.dart';
  15. ///
  16. /// 通用模块的分类导航下的子模块
  17. ///
  18. ///
  19. class CustomItemPage extends StatelessWidget {
  20. final Map<String, dynamic> data;
  21. final int tabIndex;
  22. final String modPid;
  23. final String modId;
  24. final bool needBuildStatus;
  25. CustomItemPage(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus);
  26. @override
  27. Widget build(BuildContext context) {
  28. return MultiProvider(
  29. providers: [
  30. ChangeNotifierProvider.value(value: MainPageNotifier()),
  31. ],
  32. child: BlocProvider<CustomItemPageBloc>(
  33. create: (_) => CustomItemPageBloc(CustomItemPageRepository(this.data, this.tabIndex, this.modId, this.modPid)),
  34. child: _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus),
  35. ),
  36. );
  37. }
  38. }
  39. class _CustomItemPageContainer extends StatefulWidget {
  40. final Map<String, dynamic> data;
  41. final int tabIndex;
  42. final String modPid;
  43. final String modId;
  44. final bool needBuildStatus;
  45. const _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {Key key}) : super(key: key);
  46. @override
  47. __CustomItemPageContainerState createState() => __CustomItemPageContainerState();
  48. }
  49. class __CustomItemPageContainerState extends State<_CustomItemPageContainer> with AutomaticKeepAliveClientMixin {
  50. @override
  51. bool get wantKeepAlive => true;
  52. ScrollController _controller;
  53. RefreshController _refreshController;
  54. final EventBus _eventBus = EventBus();
  55. /// 回到顶点
  56. void _scrollTop() {
  57. // _controller.jumpTo(0);
  58. _controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.linear);
  59. }
  60. /// 初始化
  61. void _initEvent() {
  62. BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageInitEvent());
  63. }
  64. /// 刷新
  65. void _refreshEvent() {
  66. BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageRefreshEvent());
  67. }
  68. /// 下拉更多
  69. void _loadEvent() {
  70. // BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageLoadEvent());
  71. Provider.of<MainPageNotifier>(context, listen: false).loadMore();
  72. Future.delayed(Duration(milliseconds: 500), () => _refreshController?.loadComplete());
  73. }
  74. @override
  75. void initState() {
  76. _controller = ScrollController();
  77. _refreshController = RefreshController(initialRefresh: false);
  78. _initEvent();
  79. super.initState();
  80. }
  81. @override
  82. void dispose() {
  83. _controller?.dispose();
  84. _refreshController?.dispose();
  85. super.dispose();
  86. }
  87. @override
  88. Widget build(BuildContext context) {
  89. return BlocConsumer<CustomItemPageBloc, CustomItemPageState>(
  90. listener: (context, state) {},
  91. buildWhen: (prev, current) {
  92. if (current is CustomItemPageRefreshSuccessState) {
  93. _refreshController?.refreshCompleted(resetFooterState: true);
  94. return false;
  95. }
  96. if (current is CustomItemPageRefreshErrorState) {
  97. _refreshController?.refreshFailed();
  98. return false;
  99. }
  100. if (current is CustomItemPageLoadSuccessState) {
  101. _refreshController?.loadComplete();
  102. return false;
  103. }
  104. if (current is CustomItemPageLoadErrorState) {
  105. _refreshController?.loadNoData();
  106. return false;
  107. }
  108. if (current is CustomItemPageErrorState) {
  109. return false;
  110. }
  111. return true;
  112. },
  113. builder: (context, state) {
  114. if (state is CustomItemPageLoadedState) {
  115. if (EmptyUtil.isEmpty(state.model))
  116. return _buildEmptyWidget();
  117. else
  118. return _buildMainWidget(state.model);
  119. }
  120. if (state is CustomItemPageInitErrorState) {
  121. return _buildEmptyWidget();
  122. }
  123. return _buildSkeletonWidget();
  124. },
  125. );
  126. }
  127. /// 有数据
  128. Widget _buildMainWidget(final List<Map<String, dynamic>> model) {
  129. return MediaQuery.removePadding(
  130. context: context,
  131. removeTop: false,
  132. child: Stack(
  133. children: <Widget>[
  134. SmartRefresher(
  135. controller: _refreshController,
  136. enablePullDown: true,
  137. enablePullUp: true,
  138. onRefresh: _refreshEvent,
  139. onLoading: _loadEvent,
  140. header: RefreshGifHeader(),
  141. // footer: RefreshFooter(),
  142. child: CustomScrollView(
  143. controller: _controller,
  144. slivers: _buildContentWidgets(model),
  145. ),
  146. ),
  147. Align(
  148. alignment: Alignment.bottomCenter,
  149. child: Container( margin: const EdgeInsets.only(bottom: 8), child: _buildAuthWidget(model),), //_buildAuthWidget(model),
  150. )
  151. ],
  152. ),
  153. );
  154. }
  155. /// 根据widget的modName生成视图
  156. List<Widget> _buildContentWidgets(final List<Map<String, dynamic>> datas) {
  157. List<Widget> result = [];
  158. for (int i = 0; i < datas.length; i++) {
  159. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  160. if(item.modName == 'audit_tip'){
  161. Logger.debug('授权组件,跳过');
  162. continue;
  163. }
  164. if(item.modName == 'product'){
  165. datas[i]['eventBus'] = _eventBus;
  166. }
  167. result.addAll(WidgetFactory.create(
  168. item.modName,
  169. isSliver: true,
  170. model: datas[i],
  171. ));
  172. }
  173. // if (widget.needBuildStatus) {
  174. // double top = MediaQueryData.fromWindow(window).padding.top;
  175. // result.insert(
  176. // 0,
  177. // SliverPersistentHeader(
  178. // pinned: false,
  179. // floating: false,
  180. // delegate: CustomSliverPersistentHeaderDelegate(max: top, min: top, child: Container(
  181. // // color: Colors.yellow,
  182. // color: HexColor.fromHex('#FFFF4242'),
  183. // )),
  184. // ));
  185. //
  186. // }
  187. return result;
  188. }
  189. /// 空数据
  190. Widget _buildEmptyWidget() {
  191. return SmartRefresher(
  192. controller: _refreshController,
  193. onRefresh: _refreshEvent,
  194. enablePullDown: true,
  195. child: Container(
  196. child: EmptyWidget(),
  197. ),
  198. );
  199. }
  200. /// 骨架图
  201. Widget _buildSkeletonWidget() {
  202. return Container();
  203. }
  204. /// 特殊的授权组件
  205. Widget _buildAuthWidget(final List<Map<String, dynamic>> datas){
  206. int length = datas?.length ?? 0;
  207. if(length == 0) return Container();
  208. Widget rlt;
  209. for (int i = 0; i < datas.length; i++) {
  210. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  211. if(item.modName == 'audit_tip'){
  212. rlt = HomeAuth(datas[i]);
  213. break;
  214. }
  215. }
  216. return rlt ?? Container();
  217. }
  218. }