import 'package:environmental_protection/common/user_information.dart'; import 'package:flutter/material.dart'; import 'dart:convert'; class PostCard extends StatefulWidget { final Map post; const PostCard({super.key, required this.post}); @override State createState() => _PostCardState(); } class _PostCardState extends State { bool _isLike = false; @override Widget build(BuildContext context) { return GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => PostDetailPage(postId: widget.post['id']), ), ); }, child: Flex( direction: Axis.vertical, crossAxisAlignment: CrossAxisAlignment.start, children: [ Image.network( resolve(widget.post['cover']).toString(), fit: BoxFit.cover, height: 150, width: double.infinity, ), Padding( padding: const EdgeInsetsDirectional.only(top: 10), child: Flex( direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(widget.post['nickName'] ?? "未知用户", style: const TextStyle(fontSize: 16)), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: TextButton( onPressed: (){ setState(() { _isLike = !_isLike; }); }, child: Row( children: [ Icon(Icons.favorite, color: _isLike ? Colors.red : Colors.grey, size: 16), const SizedBox(width: 5), Text((_isLike ? widget.post['likeNum'] + 1 : widget.post['likeNum']).toString()), ], ) ) ), ], ), ) ], ), ); } } class SocialPage extends StatefulWidget { const SocialPage({super.key}); @override State createState() => _SocialPageState(); } class _SocialPageState extends State { List> posts = []; bool _isLoading = true; @override void initState() { super.initState(); _fetchPosts(); } Future _fetchPosts() async { var global = GlobalInformation.getInstance(); final response = await global.requester.get(resolve('api/post/list')); if (response.statusCode == 200) { final data = json.decode(response.body); setState(() { posts = List>.from(data['rows']); _isLoading = false; }); } else { throw Exception('Failed to load posts'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("友邻社交"), ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : GridView.builder( padding: const EdgeInsets.all(10.0), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.75, crossAxisSpacing: 10.0, ), itemCount: posts.length, itemBuilder: (context, index) { return PostCard(post: posts[index]); }, ), /* floatingActionButton: FloatingActionButton( heroTag: 'uniqueTag', onPressed: () { // 添加发布帖子的功能 }, child: const Icon(Icons.add), ),*/ ); } } class Comment extends StatefulWidget { final Map comment; const Comment({super.key, required this.comment}); @override State createState() => _CommentState(); } class _CommentState extends State { bool _isLike = false; @override Widget build(BuildContext context) { final comment = widget.comment; return ListTile( leading: comment['avatar'] != null && comment['avatar'] != '' ? CircleAvatar( backgroundImage: NetworkImage(resolve(comment['avatar']).toString()), ) : const SizedBox(width: 40, height: 40, child: Placeholder()), title: Text(comment['nickName'] ?? "未知用户"), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(comment['content'] ?? ""), const SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(comment['createTime'] ?? "未知", style: const TextStyle(fontSize: 12, color: Colors.grey)), TextButton( onPressed: (){ setState(() { _isLike = !_isLike; }); }, child: Row( children: [ Icon(Icons.favorite, color: _isLike ? Colors.red : Colors.grey, size: 16), const SizedBox(width: 5), Text((_isLike ? comment['likeNum'] + 1 : comment['likeNum']).toString()), ], ), ) ], ), ], ), ); } } class PostDetailPage extends StatefulWidget { final int postId; const PostDetailPage({super.key, required this.postId}); @override State createState() => _PostDetailPageState(); } class _PostDetailPageState extends State { Map? post; List> comments = []; int pageNum = 1; final int pageSize = 10; bool isLoading = false; bool hasMore = true; final TextEditingController _commentController = TextEditingController(); @override void initState() { super.initState(); _fetchPostDetail(); _fetchComments(); } Future _fetchPostDetail() async { final url = resolve('api/post/${widget.postId}'); final response = await GlobalInformation.getInstance().requester.get(url); if (response.statusCode == 200) { setState(() { post = Map.from(jsonDecode(response.body)['data']); }); } else { throw Exception('Failed to load post detail'); } } Future _fetchComments() async { if (isLoading || !hasMore) return; setState(() { isLoading = true; }); var url = resolve('api/post/comment/list'); url = url.replace(queryParameters: { 'postId': widget.postId.toString(), 'pageNum': pageNum.toString(), 'pageSize': pageSize.toString(), }); final response = await GlobalInformation.getInstance().requester.get( url, ); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { comments.addAll(List>.from(data['rows'])); hasMore = data['rows'].length == pageSize; if (hasMore) { pageNum++; } }); } else { throw Exception('Failed to load comments'); } setState(() { isLoading = false; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: const Icon(Icons.keyboard_arrow_left), ), title: const Text("帖子详情"), centerTitle: true, ), body: Stack( children: [ Positioned.fill(child: post == null ? const Center(child: CircularProgressIndicator()) : ListView( children: [ Container( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(post!['nickName'] ?? "未知用户", style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 10), Text("发布时间: ${post!['createTime']}"), const SizedBox(height: 20), Text(post!['content'] ?? "无内容", style: const TextStyle(fontSize: 16)), const SizedBox(height: 10), Image.network(resolve(post!['cover']).toString()), ], ), ), const Divider(), Expanded( child: NotificationListener( onNotification: (ScrollNotification scrollInfo) { if (!isLoading && scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) { _fetchComments(); } return false; }, child: SizedBox( height: 600, child: ListView.builder( itemCount: comments.length + 1, itemBuilder: (context, index) { if (index == comments.length) { return hasMore ? const Center(child: CircularProgressIndicator()) : const Padding( padding: EdgeInsets.all(8.0), child: Center(child: Text("没有更多评论了")), ); } return Comment(comment: comments[index]); }, ), ) ), ), ], )), Positioned.fill( bottom: 0, child: Flex( direction: Axis.vertical, mainAxisAlignment: MainAxisAlignment.end, children: [ Container( decoration: const BoxDecoration( color: Colors.white ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( child: TextField( decoration: const InputDecoration( hintText: '发表评论...', border: OutlineInputBorder(), ), controller: _commentController, ), ), const SizedBox(width: 10), ElevatedButton( onPressed: () { var global = GlobalInformation.getInstance(); global.requester.post(resolve('api/post/comment'), body: jsonEncode({"postId": widget.postId.toString(), "content": _commentController.text, "likeNum": "0", "parentId": 0})); _commentController.clear(); }, child: const Text("发布"), ), ], ), ), ) ], ) ) ], ) ); } }