feat(original-app): 원작 리스트

- 페이징 추가
This commit is contained in:
Klaus 2025-09-15 16:00:09 +09:00
parent 387f5388d9
commit edeecad2ce
3 changed files with 31 additions and 10 deletions

View File

@ -33,13 +33,13 @@ interface OriginalWorkRepository : JpaRepository<OriginalWork, Long> {
): List<OriginalWork> ): List<OriginalWork>
/** /**
* 앱용 원작 목록 조회 * 앱용 원작 목록 조회 (페이징)
* - 소프트 삭제 제외 * - 소프트 삭제 제외
* - includeAdult=false이면 19 제외 * - includeAdult=false이면 19 제외
* - 활성 캐릭터가 하나라도 연결된 원작만 조회 * - 활성 캐릭터가 하나라도 연결된 원작만 조회
*/ */
@Query( @Query(
""" value = """
SELECT ow FROM OriginalWork ow SELECT ow FROM OriginalWork ow
WHERE ow.isDeleted = false WHERE ow.isDeleted = false
AND (:includeAdult = true OR ow.isAdult = false) AND (:includeAdult = true OR ow.isAdult = false)
@ -48,7 +48,16 @@ interface OriginalWorkRepository : JpaRepository<OriginalWork, Long> {
WHERE c.originalWork = ow AND c.isActive = true WHERE c.originalWork = ow AND c.isActive = true
) )
ORDER BY ow.createdAt DESC ORDER BY ow.createdAt DESC
""",
countQuery = """
SELECT COUNT(ow) FROM OriginalWork ow
WHERE ow.isDeleted = false
AND (:includeAdult = true OR ow.isAdult = false)
AND EXISTS (
SELECT 1 FROM ChatCharacter c
WHERE c.originalWork = ow AND c.isActive = true
)
""" """
) )
fun findAllForApp(@Param("includeAdult") includeAdult: Boolean): List<OriginalWork> fun findAllForAppPage(@Param("includeAdult") includeAdult: Boolean, pageable: Pageable): Page<OriginalWork>
} }

View File

@ -31,20 +31,23 @@ class OriginalWorkController(
) { ) {
/** /**
* 원작 목록 * 원작 목록 (페이징)
* - 로그인 불필요 * - 로그인 불필요
* - 본인인증하지 않은 경우 19 제외 * - 본인인증하지 않은 경우 19 제외
* - 활성 캐릭터가 하나라도 연결된 원작만 노출 * - 활성 캐릭터가 하나라도 연결된 원작만 노출
* - 요청: page(기본 0), size(기본 20)
* - 반환: totalCount + [imageUrl, title, contentType] * - 반환: totalCount + [imageUrl, title, contentType]
*/ */
@GetMapping("/list") @GetMapping("/list")
fun list( fun list(
@RequestParam(defaultValue = "0") page: Int,
@RequestParam(defaultValue = "20") size: Int,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
val includeAdult = member?.auth != null val includeAdult = member?.auth != null
val list = queryService.listForApp(includeAdult) val pageRes = queryService.listForAppPage(includeAdult, page, size)
val content = list.map { OriginalWorkListItemResponse.from(it, imageHost) } val content = pageRes.content.map { OriginalWorkListItemResponse.from(it, imageHost) }
ApiResponse.ok(OriginalWorkListResponse(totalCount = content.size.toLong(), content = content)) ApiResponse.ok(OriginalWorkListResponse(totalCount = pageRes.totalElements, content = content))
} }
/** /**

View File

@ -21,12 +21,21 @@ class OriginalWorkQueryService(
private val chatCharacterRepository: ChatCharacterRepository private val chatCharacterRepository: ChatCharacterRepository
) { ) {
/** /**
* 앱용 원작 목록 조회 * 앱용 원작 목록 조회 (페이징)
* @param includeAdult true면 19 포함, false면 제외 * @param includeAdult true면 19 포함, false면 제외
* @param page 페이지 번호(0부터)
* @param size 페이지 크기(기본 20, 최대 50)
*/ */
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun listForApp(includeAdult: Boolean): List<OriginalWork> { fun listForAppPage(includeAdult: Boolean, page: Int = 0, size: Int = 20): Page<OriginalWork> {
return originalWorkRepository.findAllForApp(includeAdult) val safePage = if (page < 0) 0 else page
val safeSize = when {
size <= 0 -> 20
size > 50 -> 50
else -> size
}
val pageable = PageRequest.of(safePage, safeSize, Sort.by("createdAt").descending())
return originalWorkRepository.findAllForAppPage(includeAdult, pageable)
} }
/** /**