基础组件库
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 

265 líneas
8.1 KiB

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