parent
6c7f411869
commit
a05bc369b7
|
@ -54,12 +54,13 @@ class CharacterCommentController(
|
|||
fun listComments(
|
||||
@PathVariable characterId: Long,
|
||||
@RequestParam(required = false, defaultValue = "20") limit: Int,
|
||||
@RequestParam(required = false) cursor: Long?,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
if (member.auth == null) throw SodaException("본인인증을 하셔야 합니다.")
|
||||
|
||||
val data = service.listComments(imageHost, characterId, limit)
|
||||
val data = service.listComments(imageHost, characterId, cursor, limit)
|
||||
ApiResponse.ok(data)
|
||||
}
|
||||
|
||||
|
@ -68,13 +69,14 @@ class CharacterCommentController(
|
|||
@PathVariable characterId: Long,
|
||||
@PathVariable commentId: Long,
|
||||
@RequestParam(required = false, defaultValue = "20") limit: Int,
|
||||
@RequestParam(required = false) cursor: Long?,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
if (member.auth == null) throw SodaException("본인인증을 하셔야 합니다.")
|
||||
|
||||
// characterId는 서비스 내부 검증(원본 댓글과 캐릭터 일치)에서 검증됨
|
||||
val data = service.getReplies(imageHost, commentId, limit)
|
||||
val data = service.getReplies(imageHost, commentId, cursor, limit)
|
||||
ApiResponse.ok(data)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ data class CharacterReplyResponse(
|
|||
|
||||
data class CharacterCommentRepliesResponse(
|
||||
val original: CharacterCommentResponse,
|
||||
val replies: List<CharacterReplyResponse>
|
||||
val replies: List<CharacterReplyResponse>,
|
||||
val cursor: Long?
|
||||
)
|
||||
|
||||
// 댓글 리스트 조회 Response 컨테이너
|
||||
|
@ -50,5 +51,6 @@ data class CharacterCommentRepliesResponse(
|
|||
|
||||
data class CharacterCommentListResponse(
|
||||
val totalCount: Int,
|
||||
val comments: List<CharacterCommentResponse>
|
||||
val comments: List<CharacterCommentResponse>,
|
||||
val cursor: Long?
|
||||
)
|
||||
|
|
|
@ -9,8 +9,22 @@ interface CharacterCommentRepository : JpaRepository<CharacterComment, Long> {
|
|||
pageable: Pageable
|
||||
): List<CharacterComment>
|
||||
|
||||
fun findByChatCharacter_IdAndIsActiveTrueAndParentIsNullAndIdLessThanOrderByCreatedAtDesc(
|
||||
chatCharacterId: Long,
|
||||
id: Long,
|
||||
pageable: Pageable
|
||||
): List<CharacterComment>
|
||||
|
||||
fun countByParent_IdAndIsActiveTrue(parentId: Long): Int
|
||||
|
||||
fun findByParent_IdAndIsActiveTrueOrderByCreatedAtDesc(parentId: Long, pageable: Pageable): List<CharacterComment>
|
||||
|
||||
fun findByParent_IdAndIsActiveTrueAndIdLessThanOrderByCreatedAtDesc(
|
||||
parentId: Long,
|
||||
id: Long,
|
||||
pageable: Pageable
|
||||
): List<CharacterComment>
|
||||
|
||||
fun findFirstByChatCharacter_IdAndIsActiveTrueOrderByCreatedAtDesc(chatCharacterId: Long): CharacterComment?
|
||||
|
||||
// 전체(상위+답글) 활성 댓글 총 개수
|
||||
|
|
|
@ -83,31 +83,67 @@ class CharacterCommentService(
|
|||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun listComments(imageHost: String, characterId: Long, limit: Int = 20): CharacterCommentListResponse {
|
||||
fun listComments(
|
||||
imageHost: String,
|
||||
characterId: Long,
|
||||
cursor: Long?,
|
||||
limit: Int = 20
|
||||
): CharacterCommentListResponse {
|
||||
val pageable = PageRequest.of(0, limit)
|
||||
val comments = commentRepository.findByChatCharacter_IdAndIsActiveTrueAndParentIsNullOrderByCreatedAtDesc(
|
||||
val comments = if (cursor == null) {
|
||||
commentRepository.findByChatCharacter_IdAndIsActiveTrueAndParentIsNullOrderByCreatedAtDesc(
|
||||
characterId,
|
||||
pageable
|
||||
)
|
||||
} else {
|
||||
commentRepository.findByChatCharacter_IdAndIsActiveTrueAndParentIsNullAndIdLessThanOrderByCreatedAtDesc(
|
||||
characterId,
|
||||
cursor,
|
||||
pageable
|
||||
)
|
||||
}
|
||||
|
||||
val items = comments.map { toCommentResponse(imageHost, it) }
|
||||
val total = getTotalCommentCount(characterId)
|
||||
val nextCursor = if (items.size == limit) items.lastOrNull()?.commentId else null
|
||||
|
||||
return CharacterCommentListResponse(
|
||||
totalCount = total,
|
||||
comments = items
|
||||
comments = items,
|
||||
cursor = nextCursor
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getReplies(imageHost: String, commentId: Long, limit: Int = 20): CharacterCommentRepliesResponse {
|
||||
val original = commentRepository.findById(commentId).orElseThrow { SodaException("댓글을 찾을 수 없습니다.") }
|
||||
fun getReplies(
|
||||
imageHost: String,
|
||||
commentId: Long,
|
||||
cursor: Long?,
|
||||
limit: Int = 20
|
||||
): CharacterCommentRepliesResponse {
|
||||
val original = commentRepository.findById(commentId).orElseThrow {
|
||||
SodaException("댓글을 찾을 수 없습니다.")
|
||||
}
|
||||
if (!original.isActive) throw SodaException("비활성화된 댓글입니다.")
|
||||
|
||||
val pageable = PageRequest.of(0, limit)
|
||||
val replies = commentRepository.findByParent_IdAndIsActiveTrueOrderByCreatedAtDesc(commentId, pageable)
|
||||
val replies = if (cursor == null) {
|
||||
commentRepository.findByParent_IdAndIsActiveTrueOrderByCreatedAtDesc(commentId, pageable)
|
||||
} else {
|
||||
commentRepository.findByParent_IdAndIsActiveTrueAndIdLessThanOrderByCreatedAtDesc(
|
||||
commentId,
|
||||
cursor,
|
||||
pageable
|
||||
)
|
||||
}
|
||||
|
||||
val items = replies.map { toReplyResponse(imageHost, it) }
|
||||
val nextCursor = if (items.size == limit) items.lastOrNull()?.replyId else null
|
||||
|
||||
return CharacterCommentRepliesResponse(
|
||||
original = toCommentResponse(imageHost, original, 0),
|
||||
replies = replies.map { toReplyResponse(imageHost, it) }
|
||||
replies = items,
|
||||
cursor = nextCursor
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue