diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index 167384f..bd56582 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -9,8 +9,10 @@ import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.dto.req.AuthorRegisterReqDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.req.ChapterUpdateReqDto; import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; +import io.github.xxyopen.novel.dto.resp.ChapterContentRespDto; import io.github.xxyopen.novel.service.AuthorService; import io.github.xxyopen.novel.service.BookService; import io.swagger.v3.oas.annotations.Operation; @@ -98,6 +100,27 @@ public class AuthorController { return bookService.deleteBookChapter(chapterId); } + /** + * 小说章节查询接口 + */ + @Operation(summary = "小说章节查询接口") + @GetMapping("book/chapter/{chapterId}") + public RestResp getBookChapter( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { + return bookService.getBookChapter(chapterId); + } + + /** + * 小说章节更新接口 + */ + @Operation(summary = "小说章节更新接口") + @PutMapping("book/chapter/{chapterId}") + public RestResp updateBookChapter( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId, + @Valid @RequestBody ChapterUpdateReqDto dto) { + return bookService.updateBookChapter(chapterId, dto); + } + /** * 小说章节发布列表查询接口 */ diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java new file mode 100644 index 0000000..b131310 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java @@ -0,0 +1,40 @@ +package io.github.xxyopen.novel.dto.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 章节发布 请求DTO + * + * @author xiongxiaoyang + * @date 2022/5/23 + */ +@Data +public class ChapterUpdateReqDto { + + /** + * 章节名 + */ + @NotBlank + @Schema(description = "章节名", required = true) + private String chapterName; + + /** + * 章节内容 + */ + @Schema(description = "章节内容", required = true) + @NotBlank + @Length(min = 50) + private String chapterContent; + + /** + * 是否收费;1-收费 0-免费 + */ + @Schema(description = "是否收费;1-收费 0-免费", required = true) + @NotNull + private Integer isVip; + +} diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java new file mode 100644 index 0000000..6caebea --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java @@ -0,0 +1,35 @@ +package io.github.xxyopen.novel.dto.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +/** + * 小说内容 响应DTO + * + * @author xiongxiaoyang + * @date 2022/5/15 + */ +@Data +@Builder +public class ChapterContentRespDto { + + /** + * 章节标题 + */ + @Schema(description = "章节名") + private String chapterName; + + /** + * 章节内容 + */ + @Schema(description = "章节内容") + private String chapterContent; + + /** + * 是否收费;1-收费 0-免费 + */ + @Schema(description = "是否收费;1-收费 0-免费") + private Integer isVip; + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java index 9c21008..237137c 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java @@ -35,6 +35,7 @@ public class BookChapterCacheManager { .chapterName(bookChapter.getChapterName()) .chapterWordCount(bookChapter.getWordCount()) .chapterUpdateTime(bookChapter.getUpdateTime()) + .isVip(bookChapter.getIsVip()) .build(); } diff --git a/src/main/java/io/github/xxyopen/novel/service/BookService.java b/src/main/java/io/github/xxyopen/novel/service/BookService.java index 51f0c21..1a725a8 100644 --- a/src/main/java/io/github/xxyopen/novel/service/BookService.java +++ b/src/main/java/io/github/xxyopen/novel/service/BookService.java @@ -5,6 +5,7 @@ import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.req.ChapterUpdateReqDto; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; import io.github.xxyopen.novel.dto.resp.*; @@ -197,4 +198,20 @@ public interface BookService { */ RestResp deleteBookChapter(Long chapterId); + /** + * 小说章节查询 + * + * @param chapterId 章节ID + * @return 章节内容 + */ + RestResp getBookChapter(Long chapterId); + + /** + * 小说章节更新 + * + * @param chapterId 章节ID + * @param dto 更新内容 + * @return void + */ + RestResp updateBookChapter(Long chapterId, ChapterUpdateReqDto dto); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index ca60c00..2054972 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -19,6 +19,7 @@ import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.AuthorInfoDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.req.ChapterUpdateReqDto; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; import io.github.xxyopen.novel.dto.resp.*; import io.github.xxyopen.novel.manager.cache.*; @@ -486,6 +487,63 @@ public class BookServiceImpl implements BookService { return RestResp.ok(); } + @Override + public RestResp getBookChapter(Long chapterId) { + BookChapterRespDto chapter = bookChapterCacheManager.getChapter(chapterId); + String bookContent = bookContentCacheManager.getBookContent(chapterId); + return RestResp.ok( + ChapterContentRespDto.builder() + .chapterName(chapter.getChapterName()) + .chapterContent(bookContent) + .isVip(chapter.getIsVip()) + .build()); + } + + @Transactional + @Override + public RestResp updateBookChapter(Long chapterId, ChapterUpdateReqDto dto) { + // 1.查询章节信息 + BookChapterRespDto chapter = bookChapterCacheManager.getChapter(chapterId); + // 2.查询小说信息 + BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(chapter.getBookId()); + // 3.更新章节信息 + BookChapter newChapter = new BookChapter(); + newChapter.setId(chapterId); + newChapter.setChapterName(dto.getChapterName()); + newChapter.setWordCount(dto.getChapterContent().length()); + newChapter.setIsVip(dto.getIsVip()); + newChapter.setUpdateTime(LocalDateTime.now()); + bookChapterMapper.updateById(newChapter); + // 4.更新章节内容 + BookContent newContent = new BookContent(); + newContent.setContent(dto.getChapterContent()); + newContent.setUpdateTime(LocalDateTime.now()); + QueryWrapper bookContentQueryWrapper = new QueryWrapper<>(); + bookContentQueryWrapper.eq(DatabaseConsts.BookContentTable.COLUMN_CHAPTER_ID, chapterId); + bookContentMapper.update(newContent, bookContentQueryWrapper); + // 5.更新小说信息 + BookInfo newBookInfo = new BookInfo(); + newBookInfo.setId(chapter.getBookId()); + newBookInfo.setUpdateTime(LocalDateTime.now()); + newBookInfo.setWordCount( + bookInfo.getWordCount() - chapter.getChapterWordCount() + dto.getChapterContent().length()); + if (Objects.equals(bookInfo.getLastChapterId(), chapterId)) { + // 更新最新章节信息 + newBookInfo.setLastChapterName(dto.getChapterName()); + newBookInfo.setLastChapterUpdateTime(LocalDateTime.now()); + } + bookInfoMapper.updateById(newBookInfo); + // 6.清理章节信息缓存 + bookChapterCacheManager.evictBookChapterCache(chapterId); + // 7.清理章节内容缓存 + bookContentCacheManager.evictBookContentCache(chapterId); + // 8.清理小说信息缓存 + bookInfoCacheManager.evictBookInfoCache(chapter.getBookId()); + // 9.发送小说信息更新的 MQ 消息 + amqpMsgManager.sendBookChangeMsg(chapter.getBookId()); + return RestResp.ok(); + } + @Override public RestResp getBookContentAbout(Long chapterId) { log.debug("userId:{}", UserHolder.getUserId());