import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:news_app/constant/color_res.dart'; import 'package:news_app/constant/config.dart'; import 'package:news_app/util/time_util.dart'; import '../../constant/size_res.dart'; import '../../model/activity_model.dart'; import '../../provider/activity_detail_provider.dart'; import '../../util/device_util.dart'; import '../../util/share_util.dart'; import '../../widget/load_image.dart'; import '../../widget/my_txt.dart'; import '../../widget/right_action_widget.dart'; class ActivityDetailPage extends ConsumerStatefulWidget { final String activityId; const ActivityDetailPage(this.activityId, {super.key}); @override ConsumerState createState() => _ActivityDetailPageState(); } final activityDetailProvider = NotifierProvider( () => ActivityDetailProvider(), ); String getRegisterStatus(String registerStatus) { switch (registerStatus) { case "0": return "未报名"; case "1": return "已报名"; case "2": return "审核通过"; case "3": return "审核不通过"; default: return "未报名"; } } class _ActivityDetailPageState extends ConsumerState { bool _isWeChatInstalled = false; @override void initState() { super.initState(); ref .read(activityDetailProvider.notifier) .fetchActivityDetail(activityId: widget.activityId); _checkWeChatInstallation(); } Future _checkWeChatInstallation() async { if (Platform.isAndroid) { final installed = await isWeChatInstalledOnlyAndroid(); setState(() => _isWeChatInstalled = installed); } else if (Platform.isIOS) { final installed = await fluwx.isWeChatInstalled; setState(() => _isWeChatInstalled = installed); } } @override void dispose() { _nameController.dispose(); _phoneController.dispose(); super.dispose(); } final TextEditingController _nameController = TextEditingController(); final TextEditingController _phoneController = TextEditingController(); Future shareAction(ActivityModelRecord data) async { showModalBottomSheet( context: context, builder: (context) => SafeArea( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox(height: 10.h), Container( width: double.infinity, height: 80.h, decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(10.r), topRight: Radius.circular(10.r), ), color: Colors.white, ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (_isWeChatInstalled) GestureDetector( onTap: () { Navigator.pop(context); shareWeiXinUrl( title: data.shareDesc ?? "", url: data.shareUrl ?? "", ); }, child: Container( width: 100.w, height: 80.h, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ LoadAssetImage( 'share_wxhy', width: 40.w, height: 40.h, ), SizedBox(height: 10.h), myTxt( text: "微信好友", color: Colors.black, fontSize: 12.sp, fontWeight: FontWeight.bold, ), ], ), ), ), if (_isWeChatInstalled) GestureDetector( onTap: () { Navigator.pop(context); shareWeiXinPYUrl( title: data.shareDesc ?? "", url: data.shareUrl ?? "", ); }, child: Container( width: 100.w, height: 80.h, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ LoadAssetImage( 'share_pyq', width: 40.w, height: 40.h, ), SizedBox(height: 10.h), myTxt( text: "朋友圈", color: Colors.black, fontSize: 12.sp, fontWeight: FontWeight.bold, ), ], ), ), ), GestureDetector( onTap: () { Navigator.pop(context); shareUrl( title: data.shareDesc ?? "", url: data.shareUrl ?? "", ); }, child: Container( width: 100.w, height: 80.h, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ LoadAssetImage( 'share_xtfx', width: 40.w, height: 40.h, ), SizedBox(height: 10.h), myTxt( text: "系统分享", color: Colors.black, fontSize: 12.sp, fontWeight: FontWeight.bold, ), ], ), ), ), ], ), ), ], ), ), ); } void _showRegisterDialog(WidgetRef ref) { showModalBottomSheet( backgroundColor: Colors.transparent, isScrollControlled: true, // 🔥 关键:允许内容超出默认高度 context: context, builder: (BuildContext context) { return DraggableScrollableSheet( initialChildSize: 0.6, maxChildSize: 0.9, minChildSize: 0.4, expand: false, builder: (context, scrollController) { return ClipRRect( borderRadius: BorderRadius.vertical(top: Radius.circular(20.r)), child: Container( padding: EdgeInsets.only( left: horizontalPadding, right: horizontalPadding, bottom: bottomBarHeight, // 🔥 关键:适配键盘高度 ), color: Colors.white, child: SingleChildScrollView( controller: scrollController, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 30.h), Center( child: myTxt( text: "活动报名", fontWeight: FontWeight.bold, fontSize: 18.sp, color: color333333, ), ), SizedBox(height: 30.h), Text.rich( TextSpan( text: "*", style: TextStyle(color: Colors.red), children: [ TextSpan( text: "姓名", style: TextStyle( color: color333333, fontSize: 16.sp, ), ), ], ), ), SizedBox(height: 15.h), SizedBox( height: 50.h, child: TextField( controller: _nameController, textInputAction: TextInputAction.next, decoration: InputDecoration( contentPadding: EdgeInsets.only( bottom: 4.h, left: 10.w, ), hintText: "请输入姓名", hintStyle: TextStyle( color: color666666, fontSize: 16.sp, ), //无边框 border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide.none, ), fillColor: colorF5F7FD, filled: true, ), ), ), SizedBox(height: 30.h), Text.rich( TextSpan( text: "*", style: TextStyle(color: Colors.red), children: [ TextSpan( text: "手机号", style: TextStyle( color: color333333, fontSize: 16.sp, ), ), ], ), ), SizedBox(height: 15.h), SizedBox( height: 50.h, child: TextField( controller: _phoneController, keyboardType: TextInputType.phone, textInputAction: TextInputAction.done, decoration: InputDecoration( contentPadding: EdgeInsets.only( bottom: 4.h, left: 10.w, ), hintText: "请输入手机号", hintStyle: TextStyle( color: color666666, fontSize: 16.sp, ), //无边框 border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide.none, ), fillColor: colorF5F7FD, filled: true, ), ), ), SizedBox(height: 30.h), GestureDetector( onTap: () { ref .watch(activityDetailProvider.notifier) .fetchRegisterActivity( activityId: widget.activityId, name: _nameController.text, phone: _phoneController.text, ); }, child: Container( margin: EdgeInsets.symmetric(vertical: 20.h), decoration: BoxDecoration( color: color5F59F7, borderRadius: BorderRadius.all( Radius.circular(20.r), ), ), height: 45.h, alignment: Alignment.center, child: myTxt( text: "提交", color: Colors.white, fontSize: 16.sp, ), ), ), ], ), ), ), ); }, ); }, ); } @override Widget build(BuildContext context) { final detail = ref.watch(activityDetailProvider); return Scaffold( appBar: AppBar( // 移除阴影 scrolledUnderElevation: 0, centerTitle: true, // 禁用滚动时的阴影变化 title: myTxt(text: "活动详情", color: Colors.black, fontSize: 18.sp), leading: IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.black), onPressed: () { Navigator.pop(context); }, ), actions: [ Padding( padding: EdgeInsets.only(right: horizontalPadding), child: RightActionWidget( isLike: detail.isLiked ?? false, isFavorite: detail.isFavorite ?? false, tap: (value) { if (value == 0) { ref .read(activityDetailProvider.notifier) .fetchActivityLike( contentId: widget.activityId, current: detail.isLiked ?? false, ); } else if (value == 1) { ref .read(activityDetailProvider.notifier) .fetchActivityFavorite( contentId: widget.activityId, current: detail.isFavorite ?? false, ); } else if (value == 2) { // shareUrl( // title: detail.shareDesc ?? "", // url: detail.shareUrl ?? "", // ); shareAction(detail); if (uuid.isNotEmpty) { ref .read(activityDetailProvider.notifier) .fetchActivityShare(activityId: widget.activityId); } } }, ), ), ], ), body: Stack( children: [ LoadImage( detail.image ?? 'bignone', width: double.infinity, height: 190.h, fit: BoxFit.fill, holderImg: 'bignone', ), SingleChildScrollView( child: Column( children: [ SizedBox(height: 169.h), Container( padding: EdgeInsets.only( left: 14.w, right: 14.w, bottom: 26.h, ), decoration: BoxDecoration( color: Color(0xFFFFFFFF), borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), ), child: Column( children: [ SizedBox(height: 10.w), myTxt( text: detail.title ?? "金融赋能镇江高质量发展大会", color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold, ), SizedBox(height: 10.w), Text( detail.summary ?? "继今年全市“新春第一会”再次吹响“产业强市”号角后,在3月5日召开的全市金融系统工作会议上,“产业强市”再次成为高频词。", style: TextStyle( color: Color(0xFF333333), fontSize: 13, ), maxLines: 1000, ), SizedBox(height: 10.w), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: 10.w, height: 10.h, alignment: Alignment.center, decoration: BoxDecoration( color: Color(0xFF4578FF), borderRadius: BorderRadius.all( Radius.circular(5), ), ), child: Container( width: 6.w, height: 6.h, alignment: Alignment.center, decoration: BoxDecoration( color: Color(0xFFFFFFFF), borderRadius: BorderRadius.all( Radius.circular(3), ), ), ), ), SizedBox(width: 4), myTxt( text: "活动报名人数限额:${detail.registerLimit}", color: Color(0xFF333333), fontSize: 12, ), ], ), SizedBox(height: 10.w), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: 10.w, height: 10.h, alignment: Alignment.center, decoration: BoxDecoration( color: Color(0xFF4578FF), borderRadius: BorderRadius.all( Radius.circular(5), ), ), child: Container( width: 6.w, height: 6.h, alignment: Alignment.center, decoration: BoxDecoration( color: Color(0xFFFFFFFF), borderRadius: BorderRadius.all( Radius.circular(3), ), ), ), ), SizedBox(width: 4), myTxt( text: "活动报名时间:${TimeUtil.formatTime(detail.registerStartTime)} / ${TimeUtil.formatTime(detail.registerEndTime)}", color: Color(0xFF333333), fontSize: 12, ), ], ), SizedBox(height: 10.w), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( Icons.alarm_outlined, color: Color(0xFF333333), size: 13, ), SizedBox(width: 4), myTxt( text: "时间:${TimeUtil.formatTime(detail.activityStartTime)} / ${TimeUtil.formatTime(detail.activityEndTime)}", color: Color(0xFF333333), fontSize: 12, ), ], ), SizedBox(height: 10.w), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( Icons.location_on_outlined, color: Color(0xFF333333), size: 13, ), SizedBox(width: 4), myTxt( text: "地址:${detail.activityLocation}", color: Color(0xFF333333), fontSize: 12, ), ], ), SizedBox(height: 10.w), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( Icons.people_alt_outlined, color: Color(0xFF333333), size: 13, ), SizedBox(width: 4), myTxt( text: "举办方:${detail.activityOrg}", color: Color(0xFF333333), fontSize: 12, ), ], ), SizedBox(height: 12.w), Container( color: Color(0xFFDCDFE2), height: 1, width: double.infinity, ), SizedBox(height: 12.h), HtmlWidget(detail.content ?? ""), ], ), ), ], ), ), if (detail.canRegister == true) Positioned( bottom: bottomBarHeight, left: horizontalPadding, right: horizontalPadding, child: ColoredBox( color: Colors.white, child: GestureDetector( onTap: () { if (detail.registerStatus == "0") { _showRegisterDialog(ref); } }, child: Container( margin: EdgeInsets.symmetric(vertical: 20.h), decoration: BoxDecoration( color: color5F59F7, borderRadius: BorderRadius.all(Radius.circular(20.r)), ), height: 45.h, alignment: Alignment.center, child: myTxt( text: getRegisterStatus(detail.registerStatus ?? ""), color: Colors.white, fontSize: 16.sp, ), ), ), ), ), ], ), ); } }