import 'package:cached_network_image/cached_network_image.dart'; import 'package:dating_touchme_app/components/page_appbar.dart'; import 'package:dating_touchme_app/controller/home/timeline_info_controller.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:dating_touchme_app/model/home/post_comment_data.dart'; import 'package:dating_touchme_app/pages/home/report_page.dart'; import 'package:dating_touchme_app/pages/home/user_information_page.dart'; import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; class TimelineInfo extends StatelessWidget { final String id; const TimelineInfo({super.key, required this.id}); @override Widget build(BuildContext context) { return GetX( init: TimelineInfoController(id: id), builder: (controller) { return PopScope( canPop: false, onPopInvoked: (didPop) { if (didPop) return; Get.back(result: controller.item.value); }, child: Scaffold( appBar: AppBar( leading: BackButton( onPressed: () { Get.back(result: controller.item.value); }, ), backgroundColor: const Color.fromRGBO(255, 255, 255, 1), surfaceTintColor: const Color.fromRGBO(255, 255, 255, 1), centerTitle: true, title: Text( "详情", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: const Color.fromRGBO(51, 51, 51, 1) ), ), actions: [ Container( margin: EdgeInsets.only(right: 14.w), child: PopupMenuButton( tooltip: "", padding: EdgeInsets.zero, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), color: Colors.white, elevation: 8, offset: Offset(0, 32.w), // 相对按钮下移一点 itemBuilder: (context) => [ const PopupMenuItem(value: 'report', child: Text('举报')), ], onSelected: (v) { if (v == 'report') { print("举报"); Get.to(() => ReportPage(id: id,)); } }, child: Icon( Icons.keyboard_control, size: 24.w, color: const Color.fromRGBO(51, 51, 51, 1), ), // 你的小圆按钮 ), ) ], ), body: Stack( children: [ if(controller.item.value.id != null && controller.item.value.id != "") EasyRefresh( controller: controller.listRefreshController, header: const ClassicHeader( dragText: '下拉刷新', armedText: '释放刷新', readyText: '刷新中...', processingText: '刷新中...', processedText: '刷新完成', failedText: '刷新失败', noMoreText: '没有更多数据', showMessage: false ), footer: ClassicFooter( dragText: '上拉加载', armedText: '释放加载', readyText: '加载中...', processingText: '加载中...', processedText: '加载完成', failedText: '加载失败', noMoreText: '没有更多数据', showMessage: false ), // 下拉刷新 onRefresh: () async { print('推荐列表下拉刷新被触发'); controller.page.value = 1; controller.commentList.clear(); await controller.getPostData(); await controller.getCommentData(); controller.listRefreshController.finishRefresh(IndicatorResult.success); controller.listRefreshController.finishLoad(IndicatorResult.none); }, // 上拉加载更多 onLoad: () async { print('推荐列表上拉加载被触发, hasMore: '); controller.page.value += 1; controller.getCommentData(); }, child: SingleChildScrollView( child: Container( padding: EdgeInsets.symmetric( horizontal: 16.w, vertical: 10.w ), constraints: BoxConstraints( minHeight: MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ ClipRRect( borderRadius: BorderRadius.all(Radius.circular(40.w)), child: CachedNetworkImage( imageUrl: controller.item.value.profilePhoto ?? "", width: 40.w, height: 40.w, fit: BoxFit.cover, ), ).onTap((){ Get.to(() => UserInformationPage(miId: controller.item.value.miId ?? "")); }), SizedBox(width: 8.w,), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( controller.item.value.nickName ?? "", style: TextStyle( fontSize: 13.w, fontWeight: FontWeight.w500 ), ), Text( controller.item.value.createTime ?? "", style: TextStyle( fontSize: 11.w, color: const Color.fromRGBO(51, 51, 51, .6), fontWeight: FontWeight.w500 ), ) ], ) ], ), ], ), Container( margin: EdgeInsets.symmetric(vertical: 11.w), child: !controller.item.value.content!.contains('[emoji:') ? Text( controller.item.value.content ?? "", ) : Wrap( crossAxisAlignment: WrapCrossAlignment.center, children: controller.buildInputContentWidgets(), ), ), if(controller.imgList.length == 1) CachedNetworkImage( imageUrl: controller.imgList[0], width: 341.w, height: 341.w, fit: BoxFit.cover, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), image: DecorationImage( image: imageProvider, fit: BoxFit.cover, ), ), ), errorWidget: (context, url, error) => Image.asset( Assets.imagesUserAvatar, width: 341.w, height: 341.w, fit: BoxFit.cover, ), ).onTap((){ TDImageViewer.showImageViewer(context: context, images: controller.imgList); }), if(controller.imgList.length == 2) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ...controller.imgList.map((e){ return CachedNetworkImage( imageUrl: e, width: 165.w, height: 165.w, fit: BoxFit.cover, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), image: DecorationImage( image: imageProvider, fit: BoxFit.cover, ), ), ), errorWidget: (context, url, error) => Image.asset( Assets.imagesUserAvatar, width: 165.w, height: 165.w, fit: BoxFit.cover, ), ).onTap((){ TDImageViewer.showImageViewer(context: context, images: controller.imgList); }); }), ], ), if(controller.imgList.length > 2) Wrap( spacing: 13.w, runSpacing: 13.w, children: [ ...controller.imgList.map((e){ return CachedNetworkImage( imageUrl: e, width: 105.w, height: 105.w, fit: BoxFit.cover, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), image: DecorationImage( image: imageProvider, fit: BoxFit.cover, ), ), ), errorWidget: (context, url, error) => Image.asset( Assets.imagesUserAvatar, width: 105.w, height: 105.w, fit: BoxFit.cover, ), ).onTap((){ TDImageViewer.showImageViewer(context: context, images: controller.imgList); }); }), ], ), SizedBox(height: 15.w,), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Row( children: [ Image.asset( (controller.item.value.isLiked ?? false) ? Assets.imagesLikeActive : Assets.imagesLikeIcon, width: 14.w, height: 12.w, ), SizedBox(width: 6.w,), Text( "${controller.item.value.likeCount ?? 0}", style: TextStyle( fontSize: 11.w, color: const Color.fromRGBO(144, 144, 144, .6) ), ) ], ).onTap((){ controller.likePost(); }), SizedBox(width: 33.w,), Row( children: [ Image.asset( Assets.imagesCommentIcon, width: 15.w, height: 15.w, ), SizedBox(width: 6.w,), Text( "${controller.item.value.commentCount ?? 0}", style: TextStyle( fontSize: 11.w, color: const Color.fromRGBO(144, 144, 144, .6) ), ) ], ).onTap((){ controller.focusNode.value.requestFocus(); // controller.update(); }), ], ), SizedBox(height: 18.w,), Text( "全部评论(${controller.item.value.commentCount ?? 0})", style: TextStyle( fontSize: 13.w, color: const Color.fromRGBO(144, 144, 144, 1), fontWeight: FontWeight.w500 ), ), SizedBox(height: 20.w,), ...controller.commentList.map((e){ return CommentItem(item: e, controller: controller,); }), ], ), ), ), ), // if(controller.showInput.value) Positioned.fill( // child: Container( // color: const Color.fromRGBO(0, 0, 0, .4), // ).onTap((){ // controller.showInput.value = false; // FocusScope.of(context).unfocus(); // // }), // ), ListenableBuilder( listenable: controller.focusNode.value, // 直接监听焦点节点 builder: (context, child) { // 只有当焦点状态改变时,这段 builder 才会运行 return Visibility( visible: controller.focusNode.value.hasFocus, child: GestureDetector( onTap: () { FocusScope.of(context).unfocus(); controller.parentId.value = "0"; }, child: Container( color: const Color.fromRGBO(0, 0, 0, .4), // 这里放遮罩层的内容 ), ), ); }, ), Positioned( left: 0, bottom: 0, child: Container( width: 375.w, height: 60.w, color: Colors.white, padding: EdgeInsets.all(10.w), child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( color: const Color.fromRGBO(247, 247, 247, 1), borderRadius: BorderRadius.all(Radius.circular(40.w)) ), child: TextField( focusNode: controller.focusNode.value, controller: controller.messageController.value, style: TextStyle( fontSize: ScreenUtil().setWidth(14), height: 1 ), decoration: InputDecoration( contentPadding: EdgeInsets.symmetric( vertical: 0, horizontal: 17.w ), hintText: "请输入评论", border: const OutlineInputBorder( borderSide: BorderSide.none, // 这将移除边框 // 可选:设置圆角 ), // 如果你希望聚焦时和未聚焦时都没有边框,也可以设置 focusedBorder 和 enabledBorder focusedBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(4.0)), ), enabledBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(4.0)), ), ), onChanged: (value){ controller.message.value = value; }, ), ), ), Container( width: 60.w, height: 30.w, margin: EdgeInsets.only(left: 15.w), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(30.w)), gradient: LinearGradient( begin: Alignment.centerLeft, // 0%:左边开始 end: Alignment.centerRight, // 100%:右边结束 colors: [ Color.fromRGBO(131, 89, 255, 1), // 紫色 Color.fromRGBO(77, 127, 231, 1), // 中间淡蓝 Color.fromRGBO(61, 138, 224, 1), // 右侧深蓝 ], stops: [0.0, 0.7753, 1.0], // 对应 CSS 百分比:0%、77.53%、100% ), ), child: Center( child: Text( "发送", style: TextStyle( fontSize: 12.w, color: Colors.white ), ), ), ).onTap((){ controller.sendComment(); }) ], ), ), ) ], ), ), ); }, ); } } class CommentItem extends StatefulWidget { final Records item; final TimelineInfoController controller; const CommentItem({super.key, required this.item, required this.controller}); @override State createState() => _CommentItemState(); } class _CommentItemState extends State { @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: 20.w), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.all(Radius.circular(40.w)), child: CachedNetworkImage( imageUrl: widget.item.profilePhoto ?? "", width: 40.w, height: 40.w, fit: BoxFit.cover, ), ).onTap((){ Get.to(() => UserInformationPage(miId: widget.item.miId ?? "")); }), SizedBox(width: 8.w,), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.item.nickName ?? "", style: TextStyle( fontSize: 13.w, color: const Color.fromRGBO(144, 144, 144, 1), ), ), SizedBox(height: 5.w,), SizedBox( child: Text( widget.item.content ?? "", style: TextStyle( fontSize: 13.w, fontWeight: FontWeight.w500 ), ), ), SizedBox(height: 5.w,), Text( "${widget.item.createTime}·回复", style: TextStyle( fontSize: 11.w, color: const Color.fromRGBO(51, 51, 51, .6), ), ).onTap((){ widget.controller.parentId.value = widget.item.id ?? "0"; widget.controller.focusNode.value.requestFocus(); }), ], ), ) ], ), ), // Image.asset( // Assets.imagesLikeIcon, // width: 14.w, // ) ], ), Container( padding: EdgeInsets.only(left: 48.w), margin: EdgeInsets.only(top: 10.w), child: Column( children: [ ...widget.item.childPostCommentList?.map((e){ return SecondCommentItem(item: e,); }) ?? [], ], ), ) ], ), ); } } class SecondCommentItem extends StatefulWidget { final ChildPostCommentList item; const SecondCommentItem({super.key, required this.item}); @override State createState() => _SecondCommentItemState(); } class _SecondCommentItemState extends State { @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: 20.w), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.all(Radius.circular(40.w)), child: CachedNetworkImage( imageUrl: widget.item.profilePhoto ?? "", width: 40.w, height: 40.w, fit: BoxFit.cover, ), ).onTap((){ Get.to(() => UserInformationPage(miId: widget.item.miId ?? "")); }), SizedBox(width: 8.w,), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.item.nickName ?? "", style: TextStyle( fontSize: 13.w, color: const Color.fromRGBO(144, 144, 144, 1), ), ), SizedBox(height: 5.w,), SizedBox( child: Text( widget.item.content ?? "", style: TextStyle( fontSize: 13.w, fontWeight: FontWeight.w500 ), ), ), SizedBox(height: 5.w,), Text( "${widget.item.createTime}", style: TextStyle( fontSize: 11.w, color: const Color.fromRGBO(51, 51, 51, .6), ), ), ], ), ) ], ), ), // Image.asset( // Assets.imagesLikeIcon, // width: 14.w, // ) ], ), ); } }