mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-02-16 12:01:00 +08:00
修复问题#927,#860
1.优化评论请求,将两个请求合并为一个 2.修改个人主页按钮的主次
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
package com.openisle.controller;
|
||||
|
||||
import com.openisle.dto.PostChangeLogDto;
|
||||
import com.openisle.dto.TimelineItemDto;
|
||||
import com.openisle.mapper.PostChangeLogMapper;
|
||||
import com.openisle.model.Comment;
|
||||
import com.openisle.dto.CommentDto;
|
||||
import com.openisle.dto.CommentRequest;
|
||||
import com.openisle.mapper.CommentMapper;
|
||||
import com.openisle.service.CaptchaService;
|
||||
import com.openisle.service.CommentService;
|
||||
import com.openisle.service.LevelService;
|
||||
import com.openisle.service.PointService;
|
||||
import com.openisle.model.CommentSort;
|
||||
import com.openisle.service.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -21,6 +22,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -34,6 +37,8 @@ public class CommentController {
|
||||
private final CaptchaService captchaService;
|
||||
private final CommentMapper commentMapper;
|
||||
private final PointService pointService;
|
||||
private final PostChangeLogService changeLogService;
|
||||
private final PostChangeLogMapper postChangeLogMapper;
|
||||
|
||||
@Value("${app.captcha.enabled:false}")
|
||||
private boolean captchaEnabled;
|
||||
@@ -85,15 +90,43 @@ public class CommentController {
|
||||
@GetMapping("/posts/{postId}/comments")
|
||||
@Operation(summary = "List comments", description = "List comments for a post")
|
||||
@ApiResponse(responseCode = "200", description = "Comments",
|
||||
content = @Content(array = @ArraySchema(schema = @Schema(implementation = CommentDto.class))))
|
||||
public List<CommentDto> listComments(@PathVariable Long postId,
|
||||
@RequestParam(value = "sort", required = false, defaultValue = "OLDEST") com.openisle.model.CommentSort sort) {
|
||||
content = @Content(array = @ArraySchema(schema = @Schema(implementation = TimelineItemDto.class))))
|
||||
public List<TimelineItemDto<?>> listComments(@PathVariable Long postId,
|
||||
@RequestParam(value = "sort", required = false, defaultValue = "OLDEST") CommentSort sort) {
|
||||
log.debug("listComments called for post {} with sort {}", postId, sort);
|
||||
List<CommentDto> list = commentService.getCommentsForPost(postId, sort).stream()
|
||||
List<CommentDto> commentDtoList = commentService.getCommentsForPost(postId, sort).stream()
|
||||
.map(commentMapper::toDtoWithReplies)
|
||||
.collect(Collectors.toList());
|
||||
log.debug("listComments returning {} comments", list.size());
|
||||
return list;
|
||||
List<PostChangeLogDto> postChangeLogDtoList = changeLogService.listLogs(postId).stream()
|
||||
.map(postChangeLogMapper::toDto)
|
||||
.collect(Collectors.toList());
|
||||
List<TimelineItemDto<?>> itemDtoList = new ArrayList<>();
|
||||
|
||||
itemDtoList.addAll(commentDtoList.stream()
|
||||
.map(c -> new TimelineItemDto<>(
|
||||
c.getId(),
|
||||
"comment",
|
||||
c.getCreatedAt(),
|
||||
c // payload 是 CommentDto
|
||||
))
|
||||
.toList());
|
||||
|
||||
itemDtoList.addAll(postChangeLogDtoList.stream()
|
||||
.map(l -> new TimelineItemDto<>(
|
||||
l.getId(),
|
||||
"log",
|
||||
l.getTime(), // 注意字段名不一样
|
||||
l // payload 是 PostChangeLogDto
|
||||
))
|
||||
.toList());
|
||||
// 排序
|
||||
Comparator<TimelineItemDto<?>> comparator = Comparator.comparing(TimelineItemDto::getCreatedAt);
|
||||
if (CommentSort.NEWEST.equals(sort)) {
|
||||
comparator = comparator.reversed();
|
||||
}
|
||||
itemDtoList.sort(comparator);
|
||||
log.debug("listComments returning {} comments", itemDtoList.size());
|
||||
return itemDtoList;
|
||||
}
|
||||
|
||||
@DeleteMapping("/comments/{id}")
|
||||
|
||||
20
backend/src/main/java/com/openisle/dto/TimelineItemDto.java
Normal file
20
backend/src/main/java/com/openisle/dto/TimelineItemDto.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.openisle.dto;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* comment and change_log Dto
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TimelineItemDto<T> {
|
||||
|
||||
private Long id;
|
||||
private String kind; // "comment" | "log"
|
||||
private LocalDateTime createdAt;
|
||||
private T payload; // 泛型,具体类型由外部决定
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
--primary-color-hover: rgb(9, 95, 105);
|
||||
--primary-color: rgb(10, 110, 120);
|
||||
--primary-color-disabled: rgba(93, 152, 156, 0.5);
|
||||
--secondary-color:rgb(255, 255, 255);
|
||||
--secondary-color-hover:rgba(165, 255, 255, 0.447);
|
||||
--new-post-icon-color: rgba(10, 111, 120, 0.598);
|
||||
--header-height: 60px;
|
||||
--header-background-color: white;
|
||||
|
||||
@@ -320,6 +320,7 @@ const mapComment = (
|
||||
level = 0,
|
||||
) => ({
|
||||
id: c.id,
|
||||
kind: 'comment',
|
||||
userName: c.author.username,
|
||||
medal: c.author.displayMedal,
|
||||
userId: c.author.id,
|
||||
@@ -374,6 +375,7 @@ const changeLogIcon = (l) => {
|
||||
|
||||
const mapChangeLog = (l) => ({
|
||||
id: l.id,
|
||||
kind: 'log',
|
||||
username: l.username,
|
||||
userAvatar: l.userAvatar,
|
||||
type: l.type,
|
||||
@@ -788,9 +790,9 @@ const fetchCommentSorts = () => {
|
||||
])
|
||||
}
|
||||
|
||||
const fetchComments = async () => {
|
||||
const fetchCommentsAndChangeLog = async () => {
|
||||
isFetchingComments.value = true
|
||||
console.debug('Fetching comments', { postId, sort: commentSort.value })
|
||||
console.info('Fetching comments and chang log', { postId, sort: commentSort.value })
|
||||
try {
|
||||
const token = getToken()
|
||||
const res = await fetch(
|
||||
@@ -799,11 +801,34 @@ const fetchComments = async () => {
|
||||
headers: { Authorization: token ? `Bearer ${token}` : '' },
|
||||
},
|
||||
)
|
||||
console.debug('Fetch comments response status', res.status)
|
||||
console.info('Fetch comments response status', res.status)
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
console.debug('Fetched comments count', data.length)
|
||||
comments.value = data.map(mapComment)
|
||||
console.info('Fetched comments data', data)
|
||||
|
||||
const commentList = []
|
||||
const changeLogList = []
|
||||
// 时间线列表,包含评论和日志
|
||||
const newTimelineItemList = []
|
||||
|
||||
for (const item of data) {
|
||||
const mappedPayload =
|
||||
item.kind === 'comment'
|
||||
? mapComment(item.payload)
|
||||
: mapChangeLog(item.payload)
|
||||
newTimelineItemList.push(mappedPayload)
|
||||
|
||||
if (item.kind === 'comment') {
|
||||
commentList.push(mappedPayload)
|
||||
} else {
|
||||
changeLogList.push(mappedPayload)
|
||||
}
|
||||
}
|
||||
|
||||
comments.value = commentList
|
||||
changeLogs.value = changeLogList
|
||||
timelineItems.value = newTimelineItemList
|
||||
|
||||
isFetchingComments.value = false
|
||||
await nextTick()
|
||||
gatherPostItems()
|
||||
@@ -815,37 +840,8 @@ const fetchComments = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const fetchChangeLogs = async () => {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE_URL}/api/posts/${postId}/change-logs`)
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
changeLogs.value = data.map(mapChangeLog)
|
||||
await nextTick()
|
||||
gatherPostItems()
|
||||
}
|
||||
} catch (e) {
|
||||
console.debug('Fetch change logs error', e)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// todo(tim): fetchComments, fetchChangeLogs 整合到一个请求,并且取消前端排序
|
||||
//
|
||||
const fetchTimeline = async () => {
|
||||
await Promise.all([fetchComments(), fetchChangeLogs()])
|
||||
const cs = comments.value.map((c) => ({ ...c, kind: 'comment' }))
|
||||
const ls = changeLogs.value.map((l) => ({ ...l, kind: 'log' }))
|
||||
|
||||
if (commentSort.value === 'NEWEST') {
|
||||
timelineItems.value = [...cs, ...ls].sort(
|
||||
(a, b) => new Date(b.createdAt) - new Date(a.createdAt),
|
||||
)
|
||||
} else {
|
||||
timelineItems.value = [...cs, ...ls].sort(
|
||||
(a, b) => new Date(a.createdAt) - new Date(b.createdAt),
|
||||
)
|
||||
}
|
||||
await fetchCommentsAndChangeLog()
|
||||
}
|
||||
|
||||
watch(commentSort, async () => {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<reduce-user />
|
||||
取消关注
|
||||
</div>
|
||||
<div v-if="!isMine" class="profile-page-header-subscribe-button" @click="sendMessage">
|
||||
<div v-if="!isMine" class="profile-page-header-send-mail-button" @click="sendMessage">
|
||||
<message-one />
|
||||
发私信
|
||||
</div>
|
||||
@@ -703,6 +703,26 @@ watch(selectedTab, async (val) => {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.profile-page-header-send-mail-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
border-radius: 8px;
|
||||
padding: 5px 10px;
|
||||
color: var(--primary-color);
|
||||
background-color: var(--secondary-color);
|
||||
border: 1px solid var(--primary-color);
|
||||
margin-top: 15px;
|
||||
width: fit-content;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.profile-page-header-send-mail-button:hover {
|
||||
background-color: var(--secondary-color-hover);
|
||||
}
|
||||
|
||||
.profile-level-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user