Skip to content

Commit 7c3a590

Browse files
authored
Merge pull request #7 from yyyCode/dev
feat(forum): 论坛话题/评论系统 + 管理后台
2 parents d6bb50e + 47a3f18 commit 7c3a590

23 files changed

Lines changed: 2091 additions & 2 deletions
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.yqz.openblog.forum.controller;
2+
3+
import com.yqz.openblog.common.ApiResponse;
4+
import com.yqz.openblog.common.PageResult;
5+
import com.yqz.openblog.forum.dto.ForumTopicResponse;
6+
import com.yqz.openblog.forum.service.ForumService;
7+
import org.springframework.security.access.prepost.PreAuthorize;
8+
import org.springframework.web.bind.annotation.*;
9+
10+
@RestController
11+
@RequestMapping("/api/v1/admin/forum")
12+
@CrossOrigin(origins = "*")
13+
public class ForumAdminController {
14+
15+
private final ForumService forumService;
16+
17+
public ForumAdminController(ForumService forumService) {
18+
this.forumService = forumService;
19+
}
20+
21+
@GetMapping("/topics")
22+
@PreAuthorize("hasAnyRole('ADMIN','AUTHOR')")
23+
public ApiResponse<PageResult<ForumTopicResponse>> list(
24+
@RequestParam(defaultValue = "0") int page,
25+
@RequestParam(defaultValue = "20") int size,
26+
@RequestParam(required = false) String status) {
27+
return ApiResponse.ok(forumService.listAllTopics(page, size, status));
28+
}
29+
30+
@PutMapping("/topics/{topicId}/hide")
31+
@PreAuthorize("hasAnyRole('ADMIN','AUTHOR')")
32+
public ApiResponse<Void> hide(@PathVariable Long topicId) {
33+
forumService.hideTopic(topicId);
34+
return ApiResponse.ok();
35+
}
36+
37+
@PutMapping("/topics/{topicId}/publish")
38+
@PreAuthorize("hasAnyRole('ADMIN','AUTHOR')")
39+
public ApiResponse<Void> publish(@PathVariable Long topicId) {
40+
forumService.publishTopic(topicId);
41+
return ApiResponse.ok();
42+
}
43+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.yqz.openblog.forum.controller;
2+
3+
import com.yqz.openblog.common.ApiResponse;
4+
import com.yqz.openblog.common.BizException;
5+
import com.yqz.openblog.common.PageResult;
6+
import com.yqz.openblog.forum.dto.ForumCommentRequest;
7+
import com.yqz.openblog.forum.dto.ForumCommentResponse;
8+
import com.yqz.openblog.forum.dto.ForumTopicCreateRequest;
9+
import com.yqz.openblog.forum.dto.ForumTopicResponse;
10+
import com.yqz.openblog.forum.service.ForumService;
11+
import com.yqz.openblog.security.CurrentUser;
12+
import jakarta.validation.Valid;
13+
import org.springframework.web.bind.annotation.*;
14+
15+
@RestController
16+
@RequestMapping("/api/v1/forum")
17+
@CrossOrigin(origins = "*")
18+
public class ForumController {
19+
20+
private final ForumService forumService;
21+
private final CurrentUser currentUser;
22+
23+
public ForumController(ForumService forumService, CurrentUser currentUser) {
24+
this.forumService = forumService;
25+
this.currentUser = currentUser;
26+
}
27+
28+
@GetMapping("/topics")
29+
public ApiResponse<PageResult<ForumTopicResponse>> listTopics(
30+
@RequestParam(defaultValue = "0") int page,
31+
@RequestParam(defaultValue = "20") int size) {
32+
return ApiResponse.ok(forumService.listTopics(page, size));
33+
}
34+
35+
@GetMapping("/topics/{topicId}")
36+
public ApiResponse<ForumTopicResponse> getTopic(@PathVariable Long topicId) {
37+
return ApiResponse.ok(forumService.getTopic(topicId));
38+
}
39+
40+
@PostMapping("/topics")
41+
public ApiResponse<ForumTopicResponse> createTopic(@Valid @RequestBody ForumTopicCreateRequest req) {
42+
Long uid = currentUser.userId();
43+
if (uid == null) {
44+
throw new BizException(4011, "请先登录");
45+
}
46+
return ApiResponse.ok(forumService.createTopic(uid, req));
47+
}
48+
49+
@GetMapping("/topics/{topicId}/comments")
50+
public ApiResponse<PageResult<ForumCommentResponse>> listComments(
51+
@PathVariable Long topicId,
52+
@RequestParam(defaultValue = "0") int page,
53+
@RequestParam(defaultValue = "50") int size) {
54+
return ApiResponse.ok(forumService.listComments(topicId, page, size));
55+
}
56+
57+
@PostMapping("/topics/{topicId}/comments")
58+
public ApiResponse<ForumCommentResponse> createComment(
59+
@PathVariable Long topicId,
60+
@Valid @RequestBody ForumCommentRequest req) {
61+
Long uid = currentUser.userId();
62+
if (uid == null) {
63+
throw new BizException(4011, "请先登录");
64+
}
65+
return ApiResponse.ok(forumService.createComment(topicId, uid, req));
66+
}
67+
68+
@DeleteMapping("/comments/{commentId}")
69+
public ApiResponse<Void> deleteComment(@PathVariable Long commentId) {
70+
Long uid = currentUser.userId();
71+
if (uid == null) {
72+
throw new BizException(4011, "请先登录");
73+
}
74+
forumService.deleteComment(commentId, uid, currentUser.isAdmin());
75+
return ApiResponse.ok();
76+
}
77+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.yqz.openblog.forum.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.Size;
5+
6+
public class ForumCommentRequest {
7+
8+
@NotBlank
9+
@Size(max = 2000)
10+
private String content;
11+
12+
public String getContent() {
13+
return content;
14+
}
15+
16+
public void setContent(String content) {
17+
this.content = content;
18+
}
19+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.yqz.openblog.forum.dto;
2+
3+
import java.time.Instant;
4+
5+
public class ForumCommentResponse {
6+
7+
private Long id;
8+
private Long topicId;
9+
private String content;
10+
private Long authorId;
11+
private String authorName;
12+
private String authorAvatar;
13+
private Instant createdAt;
14+
15+
public Long getId() {
16+
return id;
17+
}
18+
19+
public void setId(Long id) {
20+
this.id = id;
21+
}
22+
23+
public Long getTopicId() {
24+
return topicId;
25+
}
26+
27+
public void setTopicId(Long topicId) {
28+
this.topicId = topicId;
29+
}
30+
31+
public String getContent() {
32+
return content;
33+
}
34+
35+
public void setContent(String content) {
36+
this.content = content;
37+
}
38+
39+
public Long getAuthorId() {
40+
return authorId;
41+
}
42+
43+
public void setAuthorId(Long authorId) {
44+
this.authorId = authorId;
45+
}
46+
47+
public String getAuthorName() {
48+
return authorName;
49+
}
50+
51+
public void setAuthorName(String authorName) {
52+
this.authorName = authorName;
53+
}
54+
55+
public String getAuthorAvatar() {
56+
return authorAvatar;
57+
}
58+
59+
public void setAuthorAvatar(String authorAvatar) {
60+
this.authorAvatar = authorAvatar;
61+
}
62+
63+
public Instant getCreatedAt() {
64+
return createdAt;
65+
}
66+
67+
public void setCreatedAt(Instant createdAt) {
68+
this.createdAt = createdAt;
69+
}
70+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.yqz.openblog.forum.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.Size;
5+
6+
public class ForumTopicCreateRequest {
7+
8+
@NotBlank
9+
@Size(max = 200)
10+
private String title;
11+
12+
@NotBlank
13+
@Size(max = 20000)
14+
private String content;
15+
16+
public String getTitle() {
17+
return title;
18+
}
19+
20+
public void setTitle(String title) {
21+
this.title = title;
22+
}
23+
24+
public String getContent() {
25+
return content;
26+
}
27+
28+
public void setContent(String content) {
29+
this.content = content;
30+
}
31+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package com.yqz.openblog.forum.dto;
2+
3+
import java.time.Instant;
4+
5+
public class ForumTopicResponse {
6+
7+
private Long id;
8+
private String title;
9+
private String content;
10+
private String status;
11+
private Long authorId;
12+
private String authorName;
13+
private String authorAvatar;
14+
private Long viewCount;
15+
private Long commentCount;
16+
private Instant createdAt;
17+
private Instant updatedAt;
18+
19+
public Long getId() {
20+
return id;
21+
}
22+
23+
public void setId(Long id) {
24+
this.id = id;
25+
}
26+
27+
public String getTitle() {
28+
return title;
29+
}
30+
31+
public void setTitle(String title) {
32+
this.title = title;
33+
}
34+
35+
public String getContent() {
36+
return content;
37+
}
38+
39+
public void setContent(String content) {
40+
this.content = content;
41+
}
42+
43+
public String getStatus() {
44+
return status;
45+
}
46+
47+
public void setStatus(String status) {
48+
this.status = status;
49+
}
50+
51+
public Long getAuthorId() {
52+
return authorId;
53+
}
54+
55+
public void setAuthorId(Long authorId) {
56+
this.authorId = authorId;
57+
}
58+
59+
public String getAuthorName() {
60+
return authorName;
61+
}
62+
63+
public void setAuthorName(String authorName) {
64+
this.authorName = authorName;
65+
}
66+
67+
public String getAuthorAvatar() {
68+
return authorAvatar;
69+
}
70+
71+
public void setAuthorAvatar(String authorAvatar) {
72+
this.authorAvatar = authorAvatar;
73+
}
74+
75+
public Long getViewCount() {
76+
return viewCount;
77+
}
78+
79+
public void setViewCount(Long viewCount) {
80+
this.viewCount = viewCount;
81+
}
82+
83+
public Long getCommentCount() {
84+
return commentCount;
85+
}
86+
87+
public void setCommentCount(Long commentCount) {
88+
this.commentCount = commentCount;
89+
}
90+
91+
public Instant getCreatedAt() {
92+
return createdAt;
93+
}
94+
95+
public void setCreatedAt(Instant createdAt) {
96+
this.createdAt = createdAt;
97+
}
98+
99+
public Instant getUpdatedAt() {
100+
return updatedAt;
101+
}
102+
103+
public void setUpdatedAt(Instant updatedAt) {
104+
this.updatedAt = updatedAt;
105+
}
106+
}

0 commit comments

Comments
 (0)