home_page.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. import 'package:cpt_main/modules/home/home_state.dart';
  2. import 'package:cs_resources/generated/assets.dart';
  3. import 'package:cs_resources/generated/l10n.dart';
  4. import 'package:cs_resources/theme/app_colors_theme.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter/src/widgets/framework.dart';
  7. import 'package:hooks_riverpod/hooks_riverpod.dart';
  8. import 'package:auto_route/auto_route.dart';
  9. import 'package:plugin_platform/engine/toast/toast_engine.dart';
  10. import 'package:router/componentRouter/community_service.dart';
  11. import 'package:router/componentRouter/component_service_manager.dart';
  12. import 'package:widgets/ext/ex_widget.dart';
  13. import 'package:widgets/my_appbar.dart';
  14. import 'package:widgets/my_load_image.dart';
  15. import 'package:widgets/my_text_view.dart';
  16. import 'item_home_category.dart';
  17. import 'home_view_model.dart';
  18. import 'item_home_last_news.dart';
  19. import 'item_home_last_trans.dart';
  20. import 'item_home_manage_guide.dart';
  21. import 'item_home_property_news.dart';
  22. @RoutePage()
  23. class HomePage extends HookConsumerWidget {
  24. const HomePage({super.key});
  25. @override
  26. Widget build(BuildContext context, WidgetRef ref) {
  27. final viewModel = ref.read(homeViewModelProvider.notifier);
  28. final state = ref.watch(homeViewModelProvider);
  29. return Scaffold(
  30. appBar: MyAppBar.appBar(context, "Good Afternoon,Mike",
  31. backIconPath: Assets.mainTabMeSelected,
  32. backIconWidth: 18.5,
  33. backIconHeight: 20,
  34. showBackButton: true,
  35. backgroundColor: context.appColors.whiteBG,
  36. backCallback: (){
  37. ToastEngine.show("测试去登录页面");
  38. ComponentServiceManager().authService.startLoginPage();
  39. },
  40. actions: [
  41. Center(
  42. child: Stack(
  43. clipBehavior: Clip.none, // 不裁剪超出边界的内容
  44. alignment: Alignment.topLeft,
  45. children: <Widget>[
  46. // 通知图标
  47. const MyAssetImage(Assets.mainHomeNotificationIcon, width: 19, height: 20),
  48. //未读消息
  49. Positioned(
  50. left: 0,
  51. top: 0,
  52. child: Transform.translate(
  53. offset: const Offset(-10, -5),
  54. child: MyTextView(
  55. "99",
  56. boxWidth: 20.0,
  57. textColor: Colors.white,
  58. fontSize: 10,
  59. isFontLight: true,
  60. backgroundColor: context.appColors.redDefault,
  61. cornerRadius: 8,
  62. paddingTop: 2,
  63. paddingBottom: 2,
  64. textAlign: TextAlign.center,
  65. ),
  66. ),
  67. ),
  68. ],
  69. ).onTap(viewModel.gotoNotificationPage))
  70. .marginOnly(right: 15),
  71. ],
  72. showBottomDivider: true),
  73. backgroundColor: context.appColors.backgroundDefault,
  74. body: CustomScrollView(
  75. scrollDirection: Axis.vertical,
  76. physics: const BouncingScrollPhysics(),
  77. slivers: [
  78. //支付与奖励
  79. _buildPaymentAndRewardsWidget(context, ref),
  80. //间距
  81. _buildSliverSpace(20),
  82. //九宫选项组 (固定)
  83. _buildCategoryWidget(context, ref),
  84. //轮播图片 (动态)
  85. _buildBannerImage(),
  86. //最新的新闻(动态)
  87. _buildLastNews(context, ref),
  88. //最新的交易
  89. SliverToBoxAdapter(
  90. child: MyTextView(
  91. marginTop: 14,
  92. marginLeft: 15,
  93. marginBottom: 14,
  94. S.current.latest_transactions,
  95. textColor: context.appColors.textPrimary,
  96. fontSize: 16,
  97. isFontMedium: true,
  98. ),
  99. ),
  100. //最新交易列表 (动态)
  101. _buildLastTransaction(context, state),
  102. //房产新闻
  103. SliverToBoxAdapter(
  104. child: MyTextView(
  105. marginTop: 14,
  106. marginLeft: 15,
  107. marginBottom: 14,
  108. onClick: viewModel.gotoPropertyNewsPage,
  109. S.current.property_news,
  110. textColor: context.appColors.textPrimary,
  111. fontSize: 16,
  112. isFontMedium: true,
  113. ),
  114. ),
  115. //房产新闻列表 (动态)
  116. _buildPropertyNews(context, state),
  117. //管理员介绍 (固定)
  118. _buildManagementGuides(context, ref),
  119. //间距
  120. _buildSliverSpace(15),
  121. ],
  122. ),
  123. );
  124. }
  125. //顶部的支付与奖励的布局
  126. Widget _buildPaymentAndRewardsWidget(BuildContext context, WidgetRef ref) {
  127. final viewModel = ref.read(homeViewModelProvider.notifier);
  128. return SliverToBoxAdapter(
  129. child: Container(
  130. color: context.appColors.whiteBG,
  131. width: double.infinity,
  132. height: 45,
  133. child: Column(
  134. children: [
  135. Row(
  136. children: [
  137. Row(
  138. mainAxisSize: MainAxisSize.max,
  139. mainAxisAlignment: MainAxisAlignment.center,
  140. children: [
  141. const MyAssetImage(Assets.mainHomePaymentIcon, width: 16.5, height: 18).marginOnly(left: 20),
  142. MyTextView(
  143. S.current.payment,
  144. textColor: context.appColors.textBlack,
  145. fontSize: 15,
  146. isFontMedium: true,
  147. ).paddingOnly(left: 13, right: 13).expanded(),
  148. const MyAssetImage(Assets.mainHomeMoreIcon, width: 6, height: 8.5).marginOnly(right: 15),
  149. ],
  150. ).onTap(viewModel.gotoPaymentPage).expanded(),
  151. Container(color: context.appColors.dividerDefault, width: 0.5, height: double.infinity),
  152. Row(
  153. mainAxisSize: MainAxisSize.max,
  154. mainAxisAlignment: MainAxisAlignment.center,
  155. children: [
  156. const MyAssetImage(Assets.mainHomeRewardsIcon, width: 16.5, height: 17).marginOnly(left: 20),
  157. MyTextView(
  158. S.current.rewards,
  159. textColor: context.appColors.textBlack,
  160. fontSize: 15,
  161. isFontMedium: true,
  162. ).paddingOnly(left: 13, right: 4).expanded(),
  163. MyTextView(
  164. "9568",
  165. textColor: context.appColors.textBlack,
  166. fontSize: 15,
  167. isFontBold: true,
  168. ).paddingOnly(left: 1, right: 4),
  169. const MyAssetImage(Assets.mainHomeMoreIcon, width: 6, height: 8.5).marginOnly(right: 15),
  170. ],
  171. ).onTap(viewModel.gotoRewardsPage).expanded(),
  172. ],
  173. ).expanded(),
  174. //底部分割线
  175. Container(color: context.appColors.dividerDefault, height: 0.5, width: double.infinity),
  176. ],
  177. ),
  178. ),
  179. );
  180. }
  181. Widget _buildSliverSpace(double size) {
  182. return SliverToBoxAdapter(
  183. child: SizedBox(height: size),
  184. );
  185. }
  186. //九宫格选项组
  187. Widget _buildCategoryWidget(BuildContext context, WidgetRef ref) {
  188. final viewModel = ref.read(homeViewModelProvider.notifier);
  189. final state = ref.watch(homeViewModelProvider);
  190. return SliverGrid(
  191. gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
  192. crossAxisCount: 3, // 三列
  193. mainAxisSpacing: 10.0, // 主轴(上下)的间距
  194. crossAxisSpacing: 0.0, // 交叉轴(左右)的间距
  195. childAspectRatio: 9 / 8, // 子组件的宽高比
  196. ),
  197. delegate: SliverChildBuilderDelegate(
  198. (BuildContext context, int index) {
  199. return HomeCategoryItem(
  200. category: state.homeCategory[index],
  201. ).onTap(() {
  202. viewModel.switchCategory(index);
  203. }); // 生成每个网格项
  204. },
  205. childCount: state.homeCategory.length, // 总共的网格项数
  206. ),
  207. );
  208. }
  209. //Banner的布局
  210. Widget _buildBannerImage() {
  211. return SliverToBoxAdapter(
  212. child: Center(
  213. child: MyLoadImage(
  214. "https://t11.baidu.com/it/u=1326770860,192430039&fm=30&app=106&f=JPEG?w=640&h=427&s=33B5BFAA6A165BCA182937620300D077",
  215. width: 345,
  216. height: 152.5,
  217. cornerRadius: 5,
  218. ),
  219. ).marginOnly(top: 21),
  220. );
  221. }
  222. //最新新闻
  223. Widget _buildLastNews(BuildContext context, WidgetRef ref) {
  224. final viewModel = ref.read(homeViewModelProvider.notifier);
  225. final state = ref.watch(homeViewModelProvider);
  226. return SliverToBoxAdapter(
  227. child: Column(
  228. crossAxisAlignment: CrossAxisAlignment.start,
  229. mainAxisAlignment: MainAxisAlignment.start,
  230. children: [
  231. MyTextView(
  232. S.current.latest_news,
  233. fontSize: 16,
  234. marginTop: 14,
  235. marginBottom: 14,
  236. isFontMedium: true,
  237. onClick: viewModel.gotoLastNewsPage,
  238. textColor: context.appColors.textPrimary,
  239. ),
  240. SingleChildScrollView(
  241. scrollDirection: Axis.horizontal,
  242. physics: const BouncingScrollPhysics(),
  243. clipBehavior: Clip.none,
  244. child: Row(
  245. children: List.generate(state.lastNews.length, (index) {
  246. return LastNewsItem(
  247. lastNews: state.lastNews[index],
  248. );
  249. }),
  250. ),
  251. )
  252. ],
  253. ).paddingOnly(left: 15, right: 15));
  254. }
  255. //最新的交易列表
  256. Widget _buildLastTransaction(BuildContext context, HomeState state) {
  257. return SliverPadding(
  258. padding: const EdgeInsets.symmetric(horizontal: 15),
  259. sliver: DecoratedSliver(
  260. decoration: BoxDecoration(
  261. color: context.appColors.whiteBG,
  262. borderRadius: BorderRadius.circular(5.0),
  263. boxShadow: [
  264. BoxShadow(
  265. color: const Color(0xFF656565).withOpacity(0.1),
  266. offset: const Offset(0, 1.5),
  267. blurRadius: 2.5,
  268. spreadRadius: 1.5,
  269. ),
  270. ],
  271. ),
  272. sliver: SliverPadding(
  273. padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
  274. sliver: SliverList(
  275. delegate: SliverChildBuilderDelegate(
  276. (BuildContext context, int index) {
  277. return Padding(
  278. padding: const EdgeInsets.symmetric(vertical: 10),
  279. child: LastTransItem(
  280. lastTrans: state.lastTrans[index],
  281. ),
  282. );
  283. },
  284. childCount: state.lastTrans.length,
  285. ),
  286. ),
  287. ),
  288. ),
  289. );
  290. }
  291. //房产新闻的双列表
  292. Widget _buildPropertyNews(BuildContext context, HomeState state) {
  293. return SliverList(
  294. delegate: SliverChildListDelegate(
  295. [
  296. // PropertyNews(),
  297. // 第一个水平滑动列表
  298. _buildPropertyNewsHorizontalList(),
  299. const SizedBox(height: 10),
  300. // // 第二个水平滑动列表
  301. _buildPropertyNewsHorizontalList(),
  302. ],
  303. ),
  304. );
  305. }
  306. Widget _buildPropertyNewsHorizontalList() {
  307. return SingleChildScrollView(
  308. scrollDirection: Axis.horizontal,
  309. physics: const BouncingScrollPhysics(),
  310. clipBehavior: Clip.none,
  311. child: Row(
  312. children: List.generate(5, (index) {
  313. return PropertyNews();
  314. }),
  315. ).marginOnly(left: 15, right: 15),
  316. );
  317. }
  318. //管理员介绍
  319. Widget _buildManagementGuides(BuildContext context, WidgetRef ref) {
  320. final viewModel = ref.read(homeViewModelProvider.notifier);
  321. final state = ref.watch(homeViewModelProvider);
  322. return SliverToBoxAdapter(
  323. child: Column(
  324. crossAxisAlignment: CrossAxisAlignment.start,
  325. mainAxisAlignment: MainAxisAlignment.start,
  326. children: [
  327. MyTextView(
  328. S.current.strata_management_guides,
  329. fontSize: 16,
  330. marginTop: 14,
  331. marginBottom: 14,
  332. onClick: viewModel.gotoManageGuidePage,
  333. isFontMedium: true,
  334. textColor: context.appColors.textPrimary,
  335. ),
  336. SingleChildScrollView(
  337. scrollDirection: Axis.horizontal,
  338. physics: const BouncingScrollPhysics(),
  339. clipBehavior: Clip.none,
  340. child: Row(
  341. children: List.generate(state.manage_guide.length, (index) {
  342. return ManageGuideItem(
  343. manageGuide: state.manage_guide[index],
  344. );
  345. }),
  346. ),
  347. )
  348. ],
  349. ).paddingOnly(left: 15, right: 15));
  350. }
  351. }