DIgitalLife/lib/views/social.dart
2024-08-29 16:25:25 +08:00

292 lines
10 KiB
Dart

import 'package:environmental_protection/common/user_information.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
class SocialPage extends StatefulWidget {
const SocialPage({super.key});
@override
State<SocialPage> createState() => _SocialPageState();
}
class _SocialPageState extends State<SocialPage> {
List<Map<String, dynamic>> posts = [];
@override
void initState() {
super.initState();
_fetchPosts();
}
Future<void> _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<Map<String, dynamic>>.from(data['rows']);
});
} else {
throw Exception('Failed to load posts');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("友邻社交"),
),
body: GridView.builder(
padding: const EdgeInsets.all(10.0),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.75,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
),
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PostDetailPage(postId: post['id']),
),
);
},
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
resolve(post['cover']).toString(),
fit: BoxFit.cover,
height: 150,
width: double.infinity,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(post['nickName'] ?? "未知用户", style: const TextStyle(fontSize: 16)),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: [
const Icon(Icons.favorite, color: Colors.red, size: 16),
const SizedBox(width: 5),
Text(post['likeNum'].toString()),
],
),
),
],
),
),
);
},
),
floatingActionButton: FloatingActionButton(
heroTag: 'uniqueTag',
onPressed: () {
// 添加发布帖子的功能
},
child: const Icon(Icons.add),
),
);
}
}
class PostDetailPage extends StatefulWidget {
final int postId;
const PostDetailPage({super.key, required this.postId});
@override
State<PostDetailPage> createState() => _PostDetailPageState();
}
class _PostDetailPageState extends State<PostDetailPage> {
Map<String, dynamic>? post;
List<Map<String, dynamic>> 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<void> _fetchPostDetail() async {
final url = resolve('api/post/${widget.postId}');
final response = await GlobalInformation.getInstance().requester.get(url);
if (response.statusCode == 200) {
setState(() {
post = Map<String, dynamic>.from(jsonDecode(response.body)['data']);
});
} else {
throw Exception('Failed to load post detail');
}
}
Future<void> _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<Map<String, dynamic>>.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: 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<ScrollNotification>(
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("没有更多评论了")),
);
}
final comment = comments[index];
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)),
Row(
children: [
const Icon(Icons.favorite, color: Colors.red, size: 16),
const SizedBox(width: 4),
Text(comment['likeNum'].toString()),
],
),
],
),
],
),
);
},
),
)
),
),
const Divider(),
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("发布"),
),
],
),
),
],
)
);
}
}