| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- import 'package:easy_refresh/easy_refresh.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- import 'package:flutter_swiper_view/flutter_swiper_view.dart';
- import 'package:go_router/go_router.dart';
- import 'package:news_app/constant/size_res.dart';
- import 'package:news_app/extension/base.dart';
- import 'package:news_app/ui/news/special_list_page.dart';
- import 'package:news_app/widget/my_txt.dart';
- import 'package:shimmer/shimmer.dart';
- import '../../constant/color_res.dart';
- import '../../gen/assets.gen.dart';
- import '../../model/activity_banner_model.dart';
- import '../../model/news_data_model.dart';
- import '../../provider/news_provider.dart';
- import '../../util/time_util.dart';
- import '../../widget/list_animation_layout.dart';
- import '../../widget/load_image.dart';
- /// @author: bo.zeng
- /// @email: cnhbwds@gmail.com
- /// @date: 2025 2025/4/9 16:00
- /// @description:
- class NewsChildMainPage extends ConsumerStatefulWidget {
- final int tabIndex;
- const NewsChildMainPage({super.key, required this.tabIndex});
- @override
- ConsumerState<NewsChildMainPage> createState() => _NewsChildMainPageState();
- }
- final newsProvider = NotifierProvider.family<NewsNotifier, NewsState, int>(() {
- return NewsNotifier();
- });
- class _NewsChildMainPageState extends ConsumerState<NewsChildMainPage>
- {
- final Map<int, String> _iconMap = {
- 0: Assets.images.zxzxIcon.path,
- 1: Assets.images.zxzxIcon1.path,
- 2: Assets.images.zxzxIcon2.path,
- 3: Assets.images.zxzxIcon2.path,
- };
- int pageNum = 1;
- int total = 0;
- @override
- void initState() {
- super.initState();
- ref.read(newsProvider(widget.tabIndex).notifier).fetchNewsItemList(pageNum);
- ref.read(newsProvider(widget.tabIndex).notifier).fetchBannerList();
- }
- @override
- Widget build(BuildContext context) {
- // super.build(context);
- // consoleLog(widget.tabIndex);
- final data = ref.watch(
- newsProvider(widget.tabIndex).select((p) => p.newsDataModel),
- );
- final bannerList = ref.watch(
- newsProvider(widget.tabIndex).select((p) => p.bannerList),
- );
- ref.listen(newsProvider(widget.tabIndex).select((p) => p.newsDataModel), (
- p,
- next,
- ) {
- total = next.records?.length ?? 0;
- });
- return EasyRefresh.builder(
- onRefresh: () async {
- // if (bannerList.isEmpty) {
- await ref
- .read(newsProvider(widget.tabIndex).notifier)
- .fetchBannerList();
- // }
- pageNum = 1;
- await ref
- .read(newsProvider(widget.tabIndex).notifier)
- .fetchNewsItemList(pageNum);
- return IndicatorResult.success;
- },
- onLoad: () async {
- if (total >= data.total.safeValue) {
- return IndicatorResult.noMore;
- } else {
- pageNum += 1;
- await ref
- .read(newsProvider(widget.tabIndex).notifier)
- .fetchNewsItemList(pageNum);
- }
- },
- childBuilder: (context, physics) {
- return Padding(
- padding: EdgeInsets.symmetric(
- horizontal: horizontalPadding,
- ),
- child: CustomScrollView(
- physics: physics,
- slivers: [
- //注意独家的部顶没有Banner
- if (widget.tabIndex != 5)
- SliverToBoxAdapter(
- child: Container(
- margin: EdgeInsets.only(top: 10.h),
- height: 300.h,
- child: Builder(
- builder: (context) {
- //其他都是banner
- return buildBanner(
- widget.tabIndex,
- bannerList,
- context,
- );
- },
- ),
- ),
- ),
- SliverToBoxAdapter(child: _buildTitle(widget.tabIndex)),
- if (widget.tabIndex <= 3)
- SliverToBoxAdapter(
- child: Container(
- margin: EdgeInsets.only(
- left: 10.w,
- top: 16.h,
- bottom: 10.h,
- ),
- alignment: Alignment.centerLeft,
- child: Image.asset(_iconMap[widget.tabIndex]!, scale: 2.5),
- ),
- ),
- // if (widget.tabIndex == 3)
- // SliverToBoxAdapter(child: _buildRowItem()),
- //新闻列表
- (data.records ?? []).isEmpty ? SliverList.separated(
- separatorBuilder: (context, index) {
- return Container(height: 10.h);
- },
- itemBuilder: (context, index) {
- return Shimmer.fromColors(
- baseColor: Color(0xffe5e5e5),
- highlightColor: Color(0xfff5f5f5),
- child: AnimationItem(),
- );
- },
- itemCount: 20,
- ) : SliverList.separated(
- separatorBuilder: (context, index) {
- return Container(height: 10.h);
- },
- itemBuilder: (context, index) {
- // if (widget.tabIndex == 4) {
- // return _buildLiquorItem(data.records?[index], context);
- // } else
- if (widget.tabIndex == 5) {
- return Container(
- child: _buildExclusiveWidget(
- data.records?[index],
- index,
- context,
- ),
- );
- } else {
- return Container(
- child: buildNewsNewItem(data.records?[index], context),
- ); //buildNewsNewItem(data.records?[index], context);
- }
- },
- itemCount: data.records?.length,
- )
- ],
- ),
- );
- },
- );
- }
- // @override
- // bool get wantKeepAlive => true;
- }
- Widget buildBanner(
- int tabIndex,
- List<ActivityBannerModel> bannerList,
- BuildContext context,
- ) {
- return Swiper(
- autoplay: true,
- // 关键配置:关闭viewportFraction和pageSnapping
- viewportFraction: 1.0,
- onTap: (index) {
- final item = bannerList[index];
- if ((item.sourceId ?? '').isNotEmpty) {
- if (item.type == 'column') {
- context.push(SpecialListPage.routeName, extra: item.sourceId);
- } else {
- context.push("/news/detail", extra: item.sourceId);
- }
- }
- },
- itemBuilder: (context, index) {
- if (bannerList.isEmpty) {
- return Container();
- }
- // int start = tabIndex * banners.length;
- // int end = start + banners.length;
- return ClipRRect(
- borderRadius: BorderRadius.circular(8),
- child: Stack(
- children: [
- LoadImage(
- bannerList[index].image ?? '',
- width: screenWidth,
- height:300.h,
- fit: BoxFit.cover,
- holderImg: 'bignone',
- ),
- if (tabIndex <= 3 || tabIndex == 5)
- Positioned(
- bottom: 20.h,
- left: 15.h,
- right: 20.h,
- child: Builder(
- builder: (context) {
- if (tabIndex == 3) {
- return Padding(
- padding: EdgeInsets.only(bottom: 5.h),
- child: myTxt(
- text: bannerList[index].title ?? '',
- color: Colors.white,
- fontSize: 15.sp,
- ),
- );
- } else {
- return Column(
- spacing: 1.h,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- SizedBox(height: 3.h),
- myTxt(
- text: bannerList[index].title ?? '',
- color: Colors.white,
- fontSize: 15.sp,
- ),
- ],
- );
- }
- },
- ),
- ),
- ],
- ),
- );
- },
- itemCount: bannerList.length,
- pagination: const SwiperPagination(),
- );
- }
- Widget buildNewsNewItem(NewsRecord? item, BuildContext context) {
- if (item == null) {
- return const SizedBox.shrink();
- }
- int imageLength = item.imagesSrc?.length ?? 0;
- return GestureDetector(
- onTap: () => context.push("/news/detail", extra: item.contentId),
- child: Container(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8.r),
- color: Colors.white,
- ),
- padding: EdgeInsets.all(10.w),
- child: Builder(
- builder: (context) {
- if (imageLength == 0 || imageLength == 3) {
- return _buildNewsVertical(item);
- } else {
- //别的一律当1张图处理
- return Row(
- children: [
- Expanded(
- child: SizedBox(
- height: 70.h,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- myTxt(
- text: item.title ?? "",
- fontWeight: FontWeight.bold,
- color: color333333,
- fontSize: 15.sp,
- maxLines: 2,
- ),
- Row(
- spacing: 20.w,
- children: [
- myTxt(
- text: item.author ?? "新华日报",
- fontSize: 12.sp,
- color: colorA7A6A6,
- ),
- myTxt(
- text: item.publishDateStr ?? "4天前",
- fontSize: 12.sp,
- color: colorA7A6A6,
- ),
- ],
- ),
- ],
- ),
- ),
- ),
- SizedBox(width: 5.w),
- LoadImage(
- width: 93.w,
- height: 70.h,
- item.imagesSrc?[0] ?? "",
- fit: BoxFit.cover,
- ),
- ],
- );
- }
- },
- ),
- ),
- );
- }
- Widget _buildNewsVertical(NewsRecord item) {
- return Column(
- spacing: 5.h,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- myTxt(
- text: item.title ?? "",
- fontWeight: FontWeight.bold,
- color: color333333,
- fontSize: 15.sp,
- maxLines: 1,
- ),
- myTxt(
- text: item.summary ?? "",
- color: color666666,
- fontSize: 12.sp,
- maxLines: 1,
- ),
- if (item.imagesSrc?.isNotEmpty == true)
- Row(
- children:
- item.imagesSrc
- ?.map((e) => Expanded(child: LoadImage(e, fit: BoxFit.cover)))
- .toList() ??
- [],
- ),
- Row(
- spacing: 20.w,
- children: [
- myTxt(text: item.author ?? "", fontSize: 12.sp, color: colorA7A6A6),
- myTxt(
- text: item.publishDateStr ?? "",
- fontSize: 12.sp,
- color: colorA7A6A6,
- ),
- ],
- ),
- ],
- );
- }
- Widget _buildTitle(int index) {
- switch (index) {
- case 0:
- return Container();
- case 1:
- return Container();
- case 2:
- return Container();
- case 3:
- return Container();
- case 4:
- return Padding(
- padding: EdgeInsets.only(
- top: 10.h,
- bottom: 10.h,
- left: horizontalPadding,
- ),
- child: myTxt(
- text: "深一度(行业观察)",
- color: Colors.black,
- fontWeight: FontWeight.bold,
- fontSize: 15.sp,
- ),
- );
- default:
- return SizedBox.shrink();
- }
- }
- //独家widget
- Widget _buildExclusiveWidget(
- NewsRecord? item,
- int index,
- BuildContext context,
- ) {
- return GestureDetector(
- onTap: () {
- context.push("/news/detail", extra: item?.contentId ?? '');
- },
- child: Container(
- margin: EdgeInsets.only(bottom: 15.h),
- child: Column(
- spacing: 8.h,
- children: [
- Row(
- spacing: 10.w,
- children: [
- Image.asset(Assets.images.hotDicsussion.path, width: 50.w),
- Flexible(
- child: myTxt(
- text: item?.title ?? "百年后,小西湖终于又有了湖",
- color: index == 0 ? Colors.white : color333333,
- fontSize: 16.sp,
- fontWeight: FontWeight.bold,
- maxLines: 1,
- ),
- ),
- ],
- ),
- ClipRRect(
- borderRadius: BorderRadius.circular(8.r),
- child: LoadImage(
- item?.imagesSrc?.first ?? '',
- height: 300.h,
- width: screenWidth,
- fit: BoxFit.cover,
- holderImg: 'bignone',
- ),
- ),
- Row(
- spacing: 10.w,
- children: [
- myTxt(
- text: item?.author ?? "新华日报",
- color: colorA7A6A6,
- fontSize: 12.sp,
- fontWeight: FontWeight.bold,
- ),
- SizedBox(width: 5.w),
- myTxt(
- text:item?.publishDateStr ?? '',
- color: colorA7A6A6,
- fontSize: 12.sp,
- fontWeight: FontWeight.bold,
- ),
- ],
- ),
- ],
- ),
- ),
- );
- }
|