blob: af032a50c1db83a60ceca009b24579502f33c57f [file] [log] [blame]
223011385e9c35a2025-06-04 15:52:45 +08001package com.example.myproject.service;
2
22301138c1017df2025-06-05 16:11:39 +08003import com.example.myproject.entity.Collections;
223011385e9c35a2025-06-04 15:52:45 +08004import com.example.myproject.entity.Likes;
5import com.example.myproject.entity.Post;
6import com.example.myproject.entity.Users;
7import com.example.myproject.repository.CollectionsRepository;
8import com.example.myproject.repository.LikesRepository;
9import com.example.myproject.repository.PostRepository;
10import com.example.myproject.repository.UserRepository;
11import org.springframework.beans.factory.annotation.Autowired;
12import org.springframework.stereotype.Service;
22301138c1017df2025-06-05 16:11:39 +080013import org.springframework.transaction.annotation.Transactional;
223011385e9c35a2025-06-04 15:52:45 +080014import org.springframework.web.multipart.MultipartFile;
223011385e9c35a2025-06-04 15:52:45 +080015import java.io.IOException;
16import java.nio.file.Files;
17import java.nio.file.Path;
18import java.nio.file.Paths;
19import java.util.*;
20
21@Service
22public class PostService {
23
24 @Autowired
25 private PostRepository postRepository;
26
27 @Autowired
28 private UserRepository userRepository;
22301138c1017df2025-06-05 16:11:39 +080029
223011385e9c35a2025-06-04 15:52:45 +080030 @Autowired
31 private LikesRepository likesRepository;
32
33 @Autowired
34 private CollectionsRepository collectionsRepository;
35
36 private static final String IMAGE_DIR = "uploads/post/";
37
22301138c1017df2025-06-05 16:11:39 +080038 // 创建帖子 - 添加 @Transactional
39 @Transactional
223011385e9c35a2025-06-04 15:52:45 +080040 public Map<String, Object> createPost(Long userId, String postContent, String title, MultipartFile[] imageFiles) {
22301138c1017df2025-06-05 16:11:39 +080041 Users user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
223011385e9c35a2025-06-04 15:52:45 +080042 Post post = new Post();
43 post.setUser_id(user.getUserId());
44 post.setPostTime(new Date());
45 post.setPostLikeNum(0);
46 post.setPostCollectNum(0);
47 post.setPostContent(postContent);
48 post.setTitle(title);
49
223011385e9c35a2025-06-04 15:52:45 +080050 StringBuilder imageUrlsBuilder = new StringBuilder();
51 if (imageFiles != null && imageFiles.length > 0) {
52 for (int i = 0; i < imageFiles.length; i++) {
53 if (i > 0) {
54 imageUrlsBuilder.append(",");
55 }
56 try {
57 String imageUrl = saveImage(imageFiles[i]);
58 imageUrlsBuilder.append(imageUrl);
59 } catch (IOException e) {
60 throw new RuntimeException("Image upload failed: " + e.getMessage());
61 }
62 }
63 }
64 post.setImageUrl(imageUrlsBuilder.toString());
65 Post savedPost = postRepository.save(post);
22301138c1017df2025-06-05 16:11:39 +080066
223011385e9c35a2025-06-04 15:52:45 +080067 Map<String, Object> response = new HashMap<>();
68 response.put("postNo", savedPost.getPostNo());
69 response.put("message", "帖子创建成功");
70 return response;
71 }
72
73 // 保存图片并返回图片的 URL
74 public String saveImage(MultipartFile imageFile) throws IOException {
75 String fileName = imageFile.getOriginalFilename();
76 Path path = Paths.get(IMAGE_DIR + fileName);
77 Files.createDirectories(path.getParent());
78 Files.write(path, imageFile.getBytes());
79 return "/images/" + fileName;
80 }
81
22301138c1017df2025-06-05 16:11:39 +080082 // 编辑帖子 - 添加 @Transactional
83 @Transactional
223011385e9c35a2025-06-04 15:52:45 +080084 public void updatePost(Long postId, Post post) {
85 Post existingPost = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not found"));
86 if (post.getTitle() != null) {
87 existingPost.setTitle(post.getTitle());
88 }
89 if (post.getPostContent() != null) {
90 existingPost.setPostContent(post.getPostContent());
91 }
92 if (post.getImageUrl() != null) {
93 existingPost.setImageUrl(post.getImageUrl());
94 }
95 existingPost.setPostTime(post.getPostTime());
223011385e9c35a2025-06-04 15:52:45 +080096 postRepository.save(existingPost);
97 }
98
22301138c1017df2025-06-05 16:11:39 +080099 // 删除帖子 - 添加 @Transactional
100 @Transactional
223011385e9c35a2025-06-04 15:52:45 +0800101 public void deletePost(Long postId) {
102 // 查找指定 ID 的帖子,如果不存在则抛出异常
103 if (!postRepository.existsById(postId)) {
104 throw new RuntimeException("Post not found");
105 }
106 // 删除该帖子
107 postRepository.deleteById(postId);
108 }
109
22301138c1017df2025-06-05 16:11:39 +0800110 // 点赞帖子 - 添加 @Transactional
111 @Transactional
223011385e9c35a2025-06-04 15:52:45 +0800112 public void likePost(Long postId, Long userId) {
113 // 查找指定 ID 的帖子
114 Post post = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not found"));
115 post.setPostLikeNum(post.getPostLikeNum() + 1);
116
117 // 保存帖子
118 postRepository.save(post);
119 Likes like = new Likes();
120 like.setUserId(userId);
121 like.setPostNo(postId);
122 // 保存点赞记录
123 likesRepository.save(like);
124 }
125
22301138c1017df2025-06-05 16:11:39 +0800126 // 取消点赞帖子 - 已有 @Transactional
127 @Transactional
223011385e9c35a2025-06-04 15:52:45 +0800128 public void unlikePost(Long postId, Long userId) {
129 // 查找指定 ID 的帖子
130 Post post = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not found"));
131
132 // 如果点赞数大于 0,则减少点赞数
133 if (post.getPostLikeNum() > 0) {
134 post.setPostLikeNum(post.getPostLikeNum() - 1);
135 }
136
137 // 删除点赞表中对应的记录
138 likesRepository.deleteLikeByUserIdAndPostNo(userId, postId);
139
140 // 保存更新后的帖子
141 postRepository.save(post);
142 }
143
22301138c1017df2025-06-05 16:11:39 +0800144// // 获取帖子列表 - 不需要 @Transactional(只读操作)
145// public Map<String, Object> getAllPosts() {
146// List<Post> posts = postRepository.findAll();
147// List<Map<String, Object>> postList = new ArrayList<>();
148//
149// for (Post post : posts) {
150// Map<String, Object> postMap = new LinkedHashMap<>();
151// postMap.put("postNo", post.getPostNo());
152// postMap.put("user_id", post.getUser_id());
153// postMap.put("postContent", post.getPostContent());
154// postMap.put("imgUrl", post.getImageUrl());
155// postMap.put("title", post.getTitle());
156// postMap.put("createdAt",
157// post.getPostTime() != null ? post.getPostTime().toString() : "未设置");
158//
159// postMap.put("likeCount", post.getPostLikeNum());
160// postMap.put("collectCount", post.getPostCollectNum());
161//
162// postList.add(postMap);
163// }
164//
165// Map<String, Object> response = new HashMap<>();
166// // 统计帖子数量
167// response.put("total", postList.size());
168// response.put("posts", postList);
169//
170// return response;
171// }
172public Map<String, Object> getAllPosts() {
173 List<Post> posts = postRepository.findAll();
174 List<Map<String, Object>> postList = new ArrayList<>();
223011385e9c35a2025-06-04 15:52:45 +0800175
22301138c1017df2025-06-05 16:11:39 +0800176 for (Post post : posts) {
177 Map<String, Object> postMap = new LinkedHashMap<>();
178 postMap.put("postNo", post.getPostNo());
179 postMap.put("user_id", post.getUser_id());
180 postMap.put("postContent", post.getPostContent());
181 postMap.put("imgUrl", post.getImageUrl());
182 postMap.put("title", post.getTitle());
183 postMap.put("createdAt",
184 post.getPostTime() != null ? post.getPostTime().toString() : "未设置");
223011385e9c35a2025-06-04 15:52:45 +0800185
22301138c1017df2025-06-05 16:11:39 +0800186 postMap.put("likeCount", post.getPostLikeNum());
187 postMap.put("collectCount", post.getPostCollectNum());
223011385e9c35a2025-06-04 15:52:45 +0800188
22301138c1017df2025-06-05 16:11:39 +0800189 // 查询用户信息
190 Optional<Users> userOptional = userRepository.findById(post.getUser_id());
191 if (userOptional.isPresent()) {
192 Users user = userOptional.get();
193 postMap.put("username", user.getUsername());
194 postMap.put("avatarUrl", user.getAvatarUrl());
195 } else {
196 postMap.put("username", "未知用户");
197 postMap.put("avatarUrl", null);
223011385e9c35a2025-06-04 15:52:45 +0800198 }
199
22301138c1017df2025-06-05 16:11:39 +0800200 postList.add(postMap);
223011385e9c35a2025-06-04 15:52:45 +0800201 }
202
22301138c1017df2025-06-05 16:11:39 +0800203 Map<String, Object> response = new HashMap<>();
204 // 统计帖子数量
205 response.put("total", postList.size());
206 response.put("posts", postList);
207
208 return response;
209}
210
211
212 // 获取单个帖子 - 不需要 @Transactional(只读操作)
223011385e9c35a2025-06-04 15:52:45 +0800213 public Map<String, Object> getPostById(Long postId) {
223011385e9c35a2025-06-04 15:52:45 +0800214 Optional<Post> postOptional = postRepository.findById(postId);
215
223011385e9c35a2025-06-04 15:52:45 +0800216 if (postOptional.isPresent()) {
217 Post post = postOptional.get();
218 Map<String, Object> postData = new LinkedHashMap<>();
219 postData.put("postNo", post.getPostNo());
220 postData.put("user_id", post.getUser_id());
221 Long userId = post.getUser_id();
222 Users user = userRepository.findById(userId).orElse(null);
223
224 if (user != null) {
225 postData.put("username", user.getUsername());
22301138c1017df2025-06-05 16:11:39 +0800226 postData.put("avatarUrl", user.getAvatarUrl()); // 改成 avatarUrl,保持驼峰
223011385e9c35a2025-06-04 15:52:45 +0800227 } else {
22301138c1017df2025-06-05 16:11:39 +0800228 postData.put("username", "未知用户");
229 postData.put("avatarUrl", null);
223011385e9c35a2025-06-04 15:52:45 +0800230 }
231
232 postData.put("postContent", post.getPostContent());
22301138c1017df2025-06-05 16:11:39 +0800233 postData.put("imgUrl", post.getImageUrl()); // 改成 imgUrl,和列表接口保持一致
223011385e9c35a2025-06-04 15:52:45 +0800234 postData.put("postTime", post.getPostTime());
235 postData.put("postLikeNum", post.getPostLikeNum());
236 postData.put("postCollectNum", post.getPostCollectNum());
237 postData.put("title", post.getTitle());
238
239 return postData;
240 } else {
241 throw new RuntimeException("Post not found with id: " + postId);
242 }
243 }
244
245
22301138c1017df2025-06-05 16:11:39 +0800246 // 收藏帖子 - 添加 @Transactional
247 @Transactional
223011385e9c35a2025-06-04 15:52:45 +0800248 public void collectPost(Long postId, Long userId) {
249 Post post = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not found"));
250 post.setPostCollectNum(post.getPostCollectNum() + 1);
251 postRepository.save(post);
252
253 // 添加到收藏表
254 Collections collection = new Collections();
255 collection.setUserId(userId);
256 collection.setPostNo(postId);
257 collectionsRepository.save(collection);
258 }
259
22301138c1017df2025-06-05 16:11:39 +0800260 // 取消收藏 - 添加 @Transactional
261 @Transactional
223011385e9c35a2025-06-04 15:52:45 +0800262 public void uncollectPost(Long postId, Long userId) {
263 Post post = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not found"));
264 // 减少帖子收藏数
265 if (post.getPostCollectNum() > 0) {
266 post.setPostCollectNum(post.getPostCollectNum() - 1);
267 postRepository.save(post);
268 }
269
270 // 从收藏表中删除对应记录
271 collectionsRepository.deleteLikeByUserIdAndPostNo(userId, postId);
272 }
22301138b295a5f2025-06-04 19:20:30 +0800273 // 获取用户收藏的所有帖子
274 public List<Map<String, Object>> getAllCollections(Long userId) {
275 // 获取用户收藏的帖子ID
276 List<Collections> collections = collectionsRepository.findByUserId(userId);
277
278 // 如果没有收藏的帖子,返回空列表
279 if (collections.isEmpty()) {
280 return new ArrayList<>();
281 }
282
283 List<Map<String, Object>> response = new ArrayList<>();
284 for (Collections collection : collections) {
285 // 根据 postNo 查询帖子
286 Optional<Post> postOptional = postRepository.findById(collection.getPostNo());
287 if (postOptional.isPresent()) {
288 Post post = postOptional.get();
289
290 // 获取帖子作者的信息
291 Optional<Users> userOptional = userRepository.findById(post.getUser_id());
292 if (userOptional.isPresent()) {
293 Users user = userOptional.get();
294
295 // 将帖子数据和用户信息封装到 Map 中
296 Map<String, Object> postInfo = new LinkedHashMap<>();
297 postInfo.put("postNo", post.getPostNo());
298 postInfo.put("title", post.getTitle());
299 postInfo.put("postContent", post.getPostContent());
300 postInfo.put("imageUrl", post.getImageUrl());
301 postInfo.put("userId", post.getUser_id());
302 postInfo.put("username", user.getUsername()); // 帖子作者用户名
303 postInfo.put("avatarUrl", user.getAvatarUrl()); // 帖子作者头像
304
305 response.add(postInfo);
306 }
307 }
308 }
309 return response;
310 }
22301138c1017df2025-06-05 16:11:39 +0800311}