diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Controller.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Controller.kt deleted file mode 100644 index 1ab6587..0000000 --- a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Controller.kt +++ /dev/null @@ -1,271 +0,0 @@ -package com.lanyuanxiaoyao.bookstore - -import cn.hutool.core.util.IdUtil -import jakarta.annotation.Resource -import jakarta.transaction.Transactional -import org.slf4j.LoggerFactory -import org.springframework.data.domain.PageRequest -import org.springframework.data.domain.Sort -import org.springframework.web.bind.annotation.* - -data class PageResponse( - val items: List, - val total: Long, -) - -data class SingleResponse( - val data: Map, -) { - constructor(e: E): this(mapOf("item" to e)) -} - -@RestController -@RequestMapping("book") -class BookController { - private val log = LoggerFactory.getLogger(javaClass) - - @Resource - private lateinit var bookRepository: BookRepository - - @GetMapping("list") - fun list( - @RequestParam("page", defaultValue = "1") page: Int, - @RequestParam("size", defaultValue = "10") size: Int - ): PageResponse { - val pageable = bookRepository.findAll(PageRequest.of(0.coerceAtLeast(page - 1), size)) - return PageResponse( - pageable.content.map { ViewItem(it) }, - pageable.totalElements, - ) - } - - @Transactional - @PostMapping("save") - fun save(@RequestBody item: ViewItem) { - bookRepository.save( - Book( - bookId = item.bookId ?: IdUtil.fastSimpleUUID(), - name = item.name, - author = item.author, - description = item.description, - source = item.source, - tags = item.tags?.toMutableSet() ?: mutableSetOf() - ) - ) - } - - @GetMapping("detail/{bookId}") - fun detail(@PathVariable("bookId") bookId: String): ViewItem { - return bookRepository.findById(bookId).orElseThrow().let { ViewItem(it) } - } - - @Transactional - @GetMapping("remove/{bookId}") - fun remove(@PathVariable("bookId") bookId: String) { - bookRepository.deleteById(bookId) - } - - @GetMapping("tags") - fun tags(): List { - return bookRepository.findAllTag() - } - - data class ViewItem( - val bookId: String?, - val name: String, - val author: String?, - val description: String, - val source: String?, - val tags: Set?, - ) { - constructor(book: Book) : this( - book.bookId, - book.name, - book.author, - book.description, - book.source, - book.tags, - ) - } -} - -@RestController -@RequestMapping("chapter") -class ChapterController { - private val log = LoggerFactory.getLogger(javaClass) - - @Resource - private lateinit var bookRepository: BookRepository - - @Resource - private lateinit var chapterRepository: ChapterRepository - - @Resource - private lateinit var lineRepository: LineRepository - - @GetMapping("list/{bookId}") - fun list( - @PathVariable("bookId") bookId: String, - @RequestParam("page", defaultValue = "1") page: Int, - @RequestParam("size", defaultValue = "10") size: Int - ): PageResponse { - val pageable = chapterRepository.findAll({ root, _, builder -> - builder.equal(root.get("book").get("bookId"), bookId) - }, PageRequest.of(0.coerceAtLeast(page - 1), size)) - return PageResponse( - pageable.content.map { ViewItem(it) }, - pageable.totalElements, - ) - } - - @Transactional - @PostMapping("save/{bookId}") - fun save(@PathVariable("bookId") bookId: String, @RequestBody item: ViewItem) { - val book = bookRepository.findById(bookId).orElseThrow() - chapterRepository.save( - Chapter( - chapterId = item.chapterId ?: IdUtil.fastSimpleUUID(), - name = item.name, - sequence = item.sequence, - description = item.description, - book = book, - ) - ) - } - - @Transactional - @PostMapping("import/{chapterId}") - fun import(@PathVariable("chapterId") chapterId: String, @RequestBody item: ImportItem) { - val chapter = chapterRepository.findById(chapterId).orElseThrow() - var startIndex = chapter.content.size.toLong() - if (item.override) { - lineRepository.deleteAllInBatch(chapter.content) - startIndex = 0 - } - chapter.content = item.text - .split("\n") - .mapIndexed { index, line -> - Line( - lineId = IdUtil.fastSimpleUUID(), - sequence = startIndex + index, - text = line.trim(), - chapter = chapter, - ) - } - .toMutableSet() - chapterRepository.save(chapter) - } - - @GetMapping("detail/{chapterId}") - fun detail(@PathVariable("chapterId") chapterId: String): ViewItem { - return chapterRepository.findById(chapterId).orElseThrow().let { ViewItem(it) } - } - - @GetMapping("show/{chapterId}") - fun show(@PathVariable("chapterId") chapterId: String): SingleResponse { - return SingleResponse( - lineRepository - .findAll({ root, _, builder -> - builder.equal(root.get("chapter").get("chapterId"), chapterId) - }, Sort.by(Sort.Direction.DESC, "sequence")) - .joinToString("\n") { "

${it.text}

" } - ) - } - - @Transactional - @GetMapping("remove/{chapterId}") - fun remove(@PathVariable("chapterId") chapterId: String) { - chapterRepository.deleteById(chapterId) - } - - data class ViewItem( - val chapterId: String?, - val name: String?, - val sequence: Int, - val description: String?, - ) { - constructor(chapter: Chapter) : this( - chapter.chapterId, - chapter.name, - chapter.sequence, - chapter.description, - ) - } - - data class ImportItem( - val override: Boolean = false, - val text: String - ) -} - -@RestController -@RequestMapping("line") -class LineController { - private val log = LoggerFactory.getLogger(javaClass) - - @Resource - private lateinit var chapterRepository: ChapterRepository - - @Resource - private lateinit var lineRepository: LineRepository - - @GetMapping("list/{chapterId}") - fun list( - @PathVariable("chapterId") chapterId: String, - @RequestParam("page", defaultValue = "1") page: Int, - @RequestParam("size", defaultValue = "10") size: Int - ): PageResponse { - val pageable = lineRepository.findAll({ root, _, builder -> - builder.equal(root.get("chapter").get("chapterId"), chapterId) - }, PageRequest.of(0.coerceAtLeast(page - 1), size)) - return PageResponse( - pageable.content.map { ViewItem(it) }, - pageable.totalElements, - ) - } - - @Transactional - @PostMapping("save/{lineId}") - fun save(@PathVariable("lineId") lineId: String, @RequestBody item: ViewItem) { - val chapter = chapterRepository.findById(lineId).orElseThrow() - lineRepository.save( - Line( - lineId = item.lineId ?: IdUtil.fastSimpleUUID(), - sequence = item.sequence, - text = item.text, - chapter = chapter, - ) - ) - } - - @Transactional - @PostMapping("update/{lineId}") - fun update(@PathVariable("lineId") lineId: String, @RequestBody item: ViewItem) { - val line = lineRepository.findById(lineId).orElseThrow() - line.text = item.text - lineRepository.save(line) - } - - @GetMapping("detail/{lineId}") - fun detail(@PathVariable("lineId") lineId: String): ViewItem { - return lineRepository.findById(lineId).orElseThrow().let { ViewItem(it) } - } - - @Transactional - @GetMapping("remove/{lineId}") - fun remove(@PathVariable("lineId") lineId: String) { - lineRepository.deleteById(lineId) - } - - data class ViewItem( - val lineId: String?, - val sequence: Long, - val text: String, - ) { - constructor(line: Line) : this( - line.lineId, - line.sequence, - line.text, - ) - } -} diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Entity.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Entity.kt index d5321f5..a240286 100644 --- a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Entity.kt +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Entity.kt @@ -2,7 +2,20 @@ package com.lanyuanxiaoyao.bookstore -import jakarta.persistence.* +import jakarta.persistence.CascadeType +import jakarta.persistence.Column +import jakarta.persistence.ConstraintMode +import jakarta.persistence.ElementCollection +import jakarta.persistence.Entity +import jakarta.persistence.FetchType +import jakarta.persistence.ForeignKey +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.Lob +import jakarta.persistence.ManyToOne +import jakarta.persistence.NamedAttributeNode +import jakarta.persistence.NamedEntityGraph +import jakarta.persistence.OneToMany import org.hibernate.annotations.DynamicUpdate import org.springframework.data.jpa.repository.EntityGraph import org.springframework.data.jpa.repository.JpaRepository diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Helper.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Helper.kt new file mode 100644 index 0000000..c79b5b0 --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Helper.kt @@ -0,0 +1,12 @@ +package com.lanyuanxiaoyao.bookstore + +data class PageResponse( + val items: List, + val total: Long, +) + +data class SingleResponse( + val data: Map, +) { + constructor(e: E) : this(mapOf("item" to e)) +} \ No newline at end of file diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/BookController.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/BookController.kt new file mode 100644 index 0000000..5c56280 --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/BookController.kt @@ -0,0 +1,87 @@ +package com.lanyuanxiaoyao.bookstore.controller + +import cn.hutool.core.util.IdUtil +import com.lanyuanxiaoyao.bookstore.Book +import com.lanyuanxiaoyao.bookstore.BookRepository +import com.lanyuanxiaoyao.bookstore.PageResponse +import jakarta.annotation.Resource +import jakarta.transaction.Transactional +import org.slf4j.LoggerFactory +import org.springframework.data.domain.PageRequest +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("book") +class BookController { + private val log = LoggerFactory.getLogger(javaClass) + + @Resource + private lateinit var bookRepository: BookRepository + + @GetMapping("list") + fun list( + @RequestParam("page", defaultValue = "1") page: Int, + @RequestParam("size", defaultValue = "10") size: Int + ): PageResponse { + val pageable = bookRepository.findAll(PageRequest.of(0.coerceAtLeast(page - 1), size)) + return PageResponse( + pageable.content.map { ViewItem(it) }, + pageable.totalElements, + ) + } + + @Transactional + @PostMapping("save") + fun save(@RequestBody item: ViewItem) { + bookRepository.save( + Book( + bookId = item.bookId ?: IdUtil.fastSimpleUUID(), + name = item.name, + author = item.author, + description = item.description, + source = item.source, + tags = item.tags?.toMutableSet() ?: mutableSetOf() + ) + ) + } + + @GetMapping("detail/{bookId}") + fun detail(@PathVariable("bookId") bookId: String): ViewItem { + return bookRepository.findById(bookId).orElseThrow().let { ViewItem(it) } + } + + @Transactional + @GetMapping("remove/{bookId}") + fun remove(@PathVariable("bookId") bookId: String) { + bookRepository.deleteById(bookId) + } + + @GetMapping("tags") + fun tags(): List { + return bookRepository.findAllTag() + } + + data class ViewItem( + val bookId: String?, + val name: String, + val author: String?, + val description: String, + val source: String?, + val tags: Set?, + ) { + constructor(book: Book) : this( + book.bookId, + book.name, + book.author, + book.description, + book.source, + book.tags, + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/ChapterController.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/ChapterController.kt new file mode 100644 index 0000000..59d30ec --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/ChapterController.kt @@ -0,0 +1,132 @@ +package com.lanyuanxiaoyao.bookstore.controller + +import cn.hutool.core.util.IdUtil +import com.lanyuanxiaoyao.bookstore.Book +import com.lanyuanxiaoyao.bookstore.BookRepository +import com.lanyuanxiaoyao.bookstore.Chapter +import com.lanyuanxiaoyao.bookstore.ChapterRepository +import com.lanyuanxiaoyao.bookstore.Line +import com.lanyuanxiaoyao.bookstore.LineRepository +import com.lanyuanxiaoyao.bookstore.PageResponse +import com.lanyuanxiaoyao.bookstore.SingleResponse +import jakarta.annotation.Resource +import jakarta.transaction.Transactional +import org.slf4j.LoggerFactory +import org.springframework.data.domain.PageRequest +import org.springframework.data.domain.Sort +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("chapter") +class ChapterController { + private val log = LoggerFactory.getLogger(javaClass) + + @Resource + private lateinit var bookRepository: BookRepository + + @Resource + private lateinit var chapterRepository: ChapterRepository + + @Resource + private lateinit var lineRepository: LineRepository + + @GetMapping("list/{bookId}") + fun list( + @PathVariable("bookId") bookId: String, + @RequestParam("page", defaultValue = "1") page: Int, + @RequestParam("size", defaultValue = "10") size: Int + ): PageResponse { + val pageable = chapterRepository.findAll({ root, _, builder -> + builder.equal(root.get("book").get("bookId"), bookId) + }, PageRequest.of(0.coerceAtLeast(page - 1), size)) + return PageResponse( + pageable.content.map { ViewItem(it) }, + pageable.totalElements, + ) + } + + @Transactional + @PostMapping("save/{bookId}") + fun save(@PathVariable("bookId") bookId: String, @RequestBody item: ViewItem) { + val book = bookRepository.findById(bookId).orElseThrow() + chapterRepository.save( + Chapter( + chapterId = item.chapterId ?: IdUtil.fastSimpleUUID(), + name = item.name, + sequence = item.sequence, + description = item.description, + book = book, + ) + ) + } + + @Transactional + @PostMapping("import/{chapterId}") + fun import(@PathVariable("chapterId") chapterId: String, @RequestBody item: ImportItem) { + val chapter = chapterRepository.findById(chapterId).orElseThrow() + var startIndex = chapter.content.size.toLong() + if (item.override) { + lineRepository.deleteAllInBatch(chapter.content) + startIndex = 0 + } + chapter.content = item.text + .split("\n") + .mapIndexed { index, line -> + Line( + lineId = IdUtil.fastSimpleUUID(), + sequence = startIndex + index, + text = line.trim(), + chapter = chapter, + ) + } + .toMutableSet() + chapterRepository.save(chapter) + } + + @GetMapping("detail/{chapterId}") + fun detail(@PathVariable("chapterId") chapterId: String): ViewItem { + return chapterRepository.findById(chapterId).orElseThrow().let { ViewItem(it) } + } + + @GetMapping("show/{chapterId}") + fun show(@PathVariable("chapterId") chapterId: String): SingleResponse { + return SingleResponse( + lineRepository + .findAll({ root, _, builder -> + builder.equal(root.get("chapter").get("chapterId"), chapterId) + }, Sort.by(Sort.Direction.DESC, "sequence")) + .joinToString("\n") { "

${it.text}

" } + ) + } + + @Transactional + @GetMapping("remove/{chapterId}") + fun remove(@PathVariable("chapterId") chapterId: String) { + chapterRepository.deleteById(chapterId) + } + + data class ViewItem( + val chapterId: String?, + val name: String?, + val sequence: Int, + val description: String?, + ) { + constructor(chapter: Chapter) : this( + chapter.chapterId, + chapter.name, + chapter.sequence, + chapter.description, + ) + } + + data class ImportItem( + val override: Boolean = false, + val text: String + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/LineController.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/LineController.kt new file mode 100644 index 0000000..a2e8f8a --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/LineController.kt @@ -0,0 +1,91 @@ +package com.lanyuanxiaoyao.bookstore.controller + +import cn.hutool.core.util.IdUtil +import com.lanyuanxiaoyao.bookstore.Chapter +import com.lanyuanxiaoyao.bookstore.ChapterRepository +import com.lanyuanxiaoyao.bookstore.Line +import com.lanyuanxiaoyao.bookstore.LineRepository +import com.lanyuanxiaoyao.bookstore.PageResponse +import jakarta.annotation.Resource +import jakarta.transaction.Transactional +import org.slf4j.LoggerFactory +import org.springframework.data.domain.PageRequest +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("line") +class LineController { + private val log = LoggerFactory.getLogger(javaClass) + + @Resource + private lateinit var chapterRepository: ChapterRepository + + @Resource + private lateinit var lineRepository: LineRepository + + @GetMapping("list/{chapterId}") + fun list( + @PathVariable("chapterId") chapterId: String, + @RequestParam("page", defaultValue = "1") page: Int, + @RequestParam("size", defaultValue = "10") size: Int + ): PageResponse { + val pageable = lineRepository.findAll({ root, _, builder -> + builder.equal(root.get("chapter").get("chapterId"), chapterId) + }, PageRequest.of(0.coerceAtLeast(page - 1), size)) + return PageResponse( + pageable.content.map { ViewItem(it) }, + pageable.totalElements, + ) + } + + @Transactional + @PostMapping("save/{lineId}") + fun save(@PathVariable("lineId") lineId: String, @RequestBody item: ViewItem) { + val chapter = chapterRepository.findById(lineId).orElseThrow() + lineRepository.save( + Line( + lineId = item.lineId ?: IdUtil.fastSimpleUUID(), + sequence = item.sequence, + text = item.text, + chapter = chapter, + ) + ) + } + + @Transactional + @PostMapping("update/{lineId}") + fun update(@PathVariable("lineId") lineId: String, @RequestBody item: ViewItem) { + val line = lineRepository.findById(lineId).orElseThrow() + line.text = item.text + lineRepository.save(line) + } + + @GetMapping("detail/{lineId}") + fun detail(@PathVariable("lineId") lineId: String): ViewItem { + return lineRepository.findById(lineId).orElseThrow().let { ViewItem(it) } + } + + @Transactional + @GetMapping("remove/{lineId}") + fun remove(@PathVariable("lineId") lineId: String) { + lineRepository.deleteById(lineId) + } + + data class ViewItem( + val lineId: String?, + val sequence: Long, + val text: String, + ) { + constructor(line: Line) : this( + line.lineId, + line.sequence, + line.text, + ) + } +} \ No newline at end of file diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 5e780e4..ad00eeb 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -32,7 +32,7 @@