diff --git a/.idea/GitCommitMessageStorage.xml b/.idea/GitCommitMessageStorage.xml new file mode 100644 index 0000000..e4fd56a --- /dev/null +++ b/.idea/GitCommitMessageStorage.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/.idea/csv-editor.xml b/.idea/csv-editor.xml new file mode 100644 index 0000000..af8e228 --- /dev/null +++ b/.idea/csv-editor.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/client/src/pages/book/Book.tsx b/client/src/pages/book/Book.tsx index 94451e5..55d88a3 100644 --- a/client/src/pages/book/Book.tsx +++ b/client/src/pages/book/Book.tsx @@ -9,6 +9,48 @@ import { time, } from '../../util/amis.tsx' +const detailDialog = (bookId: string | undefined) => { + return { + title: '添加书架', + size: 'md', + body: { + debug: commonInfo.debug, + type: 'form', + api: `${commonInfo.baseUrl}/chapter/save`, + initApi: `${commonInfo.baseUrl}/chapter/detail/\${id}`, + initFetchOn: '${id}', + ...horizontalFormOptions(), + canAccessSuperData: false, + body: [ + { + type: 'hidden', + name: 'bookId', + value: bookId, + }, + { + type: 'input-number', + name: 'sequence', + label: '序号', + required: true, + }, + { + type: 'input-text', + name: 'name', + label: '名称', + required: true, + clearable: true, + }, + { + type: 'textarea', + name: 'description', + label: '描述', + clearable: true, + }, + ], + }, + } +} + function Book() { const navigate = useNavigate() const {id} = useParams() @@ -49,11 +91,11 @@ function Book() { sort: [ { column: 'sequence', - direction: 'ASC', + direction: 'DESC', }, { column: 'modifiedTime', - direction: 'DESC', + direction: 'ASC', }, ], }, @@ -70,7 +112,9 @@ function Book() { actionType: 'ajax', tooltip: '序号重排', tooltipPlacement: 'top', - api: `get:${commonInfo.baseUrl}/chapter/generate_sequence` + api: `get:${commonInfo.baseUrl}/chapter/generate_sequence`, + confirmText: '确认重排序号?', + confirmTitle: '序号重拍', }, { type: 'action', @@ -142,7 +186,7 @@ function Book() { actionType: 'dialog', dialog: detailDialog(), },*/ - ] + ], ), columns: [ { @@ -193,14 +237,14 @@ function Book() { }, }, }, - /*{ + { type: 'action', label: '修改', level: 'link', size: 'sm', actionType: 'dialog', - dialog: detailDialog(), - },*/ + dialog: detailDialog(id), + }, { className: 'text-danger btn-deleted', type: 'action', diff --git a/client/src/pages/book/Bookshelf.tsx b/client/src/pages/book/Bookshelf.tsx index 41b6714..a39947b 100644 --- a/client/src/pages/book/Bookshelf.tsx +++ b/client/src/pages/book/Bookshelf.tsx @@ -96,7 +96,7 @@ function Bookshelf() { { name: 'name', label: '书名', - width: 150, + width: 120, fixed: 'left', }, { @@ -112,7 +112,7 @@ function Bookshelf() { { name: 'source', label: '来源', - width: 150, + width: 200, }, { name: 'tags', diff --git a/client/src/pages/book/Chapter.tsx b/client/src/pages/book/Chapter.tsx index 60be467..881259b 100644 --- a/client/src/pages/book/Chapter.tsx +++ b/client/src/pages/book/Chapter.tsx @@ -1,6 +1,13 @@ import React from 'react' import {useParams} from 'react-router' -import {amisRender, commonInfo, crudCommonOptions, horizontalFormOptions, paginationTemplate} from '../../util/amis.tsx' +import { + amisRender, + commonInfo, + crudCommonOptions, + horizontalFormOptions, + paginationTemplate, + readOnlyDialogOptions, +} from '../../util/amis.tsx' function Chapter() { // const navigate = useNavigate() @@ -52,19 +59,46 @@ function Chapter() { }, ...crudCommonOptions(), ...paginationTemplate( - undefined, + 50, undefined, [ { type: 'action', label: '', - icon: 'fa fa-rotate-right', + icon: 'fa fa-book-open-reader', actionType: 'ajax', tooltip: '序号重排', tooltipPlacement: 'top', - api: `get:${commonInfo.baseUrl}/line/generate_sequence/${id}` - } - ] + api: `get:${commonInfo.baseUrl}/line/generate_sequence/${id}`, + confirmText: '确认重排序号?', + confirmTitle: '序号重拍', + }, + { + type: 'action', + label: '', + icon: 'fa fa-glasses', + actionType: 'dialog', + tooltip: '全文阅读', + tooltipPlacement: 'top', + dialog: { + title: '全文查看', + size: 'md', + ...readOnlyDialogOptions(), + body: { + type: 'service', + size: 'none', + api: `${commonInfo.baseUrl}/chapter/content/${id}`, + body: { + type: 'markdown', + value: '${detail}', + options: { + breaks: true, + }, + }, + }, + }, + }, + ], ), columns: [ { diff --git a/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java b/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java index df504be..9383c59 100644 --- a/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java +++ b/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java @@ -1,23 +1,10 @@ package com.lanyuanxiaoyao.bookstore; -import cn.hutool.core.lang.Tuple; -import cn.hutool.core.text.csv.CsvUtil; -import cn.hutool.core.util.NumberUtil; -import cn.hutool.core.util.ObjectUtil; import com.blinkfox.fenix.EnableFenix; -import com.lanyuanxiaoyao.bookstore.entity.Chapter; -import com.lanyuanxiaoyao.bookstore.entity.Line; -import com.lanyuanxiaoyao.bookstore.service.BookService; -import com.lanyuanxiaoyao.bookstore.service.ChapterService; -import jakarta.annotation.Resource; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.util.stream.Collectors; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.transaction.annotation.Transactional; /** * 启动类 @@ -33,44 +20,4 @@ public class BookStoreApplication { public static void main(String[] args) { SpringApplication.run(BookStoreApplication.class, args); } - - @Resource - private BookService bookService; - @Resource - private ChapterService chapterService; - - @Transactional(rollbackFor = Throwable.class) - // @EventListener(ApplicationReadyEvent.class) - public void loadOldData() throws FileNotFoundException { - var reader = CsvUtil.getReader(new FileReader("C:\\Users\\lanyuanxiaoyao\\Result_6.csv")); - var rows = reader.stream() - .map(row -> new Row(Long.parseLong(row.get(0)), row.get(1), Long.parseLong(row.get(2)), row.get(3))) - .toList(); - var book = bookService.detailOrThrow(3602572744994816L); - rows.stream() - .map(row -> new Tuple(row.chapterSequence(), row.chapterTitle())) - .distinct() - .forEach(tuple -> { - var chapter = new Chapter(); - chapter.setSequence(NumberUtil.toDouble(tuple.get(0))); - chapter.setName(tuple.get(1)); - chapter.setBook(book); - - var lines = rows.stream() - .filter(row -> ObjectUtil.equals(row.chapterSequence(), tuple.get(0)) && ObjectUtil.equals(row.chapterTitle(), tuple.get(1))) - .map(row -> { - var line = new Line(); - line.setSequence(NumberUtil.toDouble(row.lineSequence())); - line.setText(row.lineText()); - line.setChapter(chapter); - return line; - }) - .collect(Collectors.toSet()); - chapter.setContent(lines); - chapterService.save(chapter); - }); - } - - public record Row(long chapterSequence, String chapterTitle, long lineSequence, String lineText) { - } } diff --git a/src/main/java/com/lanyuanxiaoyao/bookstore/controller/ChapterController.java b/src/main/java/com/lanyuanxiaoyao/bookstore/controller/ChapterController.java index 25ae242..d33b91c 100644 --- a/src/main/java/com/lanyuanxiaoyao/bookstore/controller/ChapterController.java +++ b/src/main/java/com/lanyuanxiaoyao/bookstore/controller/ChapterController.java @@ -1,6 +1,8 @@ package com.lanyuanxiaoyao.bookstore.controller; +import cn.hutool.core.util.ObjectUtil; import com.lanyuanxiaoyao.bookstore.entity.Chapter; +import com.lanyuanxiaoyao.bookstore.entity.Line; import com.lanyuanxiaoyao.bookstore.entity.vo.Option; import com.lanyuanxiaoyao.bookstore.service.BookService; import com.lanyuanxiaoyao.bookstore.service.ChapterService; @@ -8,11 +10,15 @@ import com.lanyuanxiaoyao.bookstore.service.LineService; import com.lanyuanxiaoyao.service.template.controller.GlobalResponse; import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport; import java.time.LocalDateTime; +import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.function.Function; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; 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; @@ -43,7 +49,7 @@ public class ChapterController extends SimpleControllerSupport saveWithContent(@RequestBody SaveWithContentItem item) { if (SaveWithContentItem.Mode.CREATE.equals(item.mode())) { var chapter = new Chapter(); - chapter.setSequence(chapterService.latestSequence(item.bookId())); + chapter.setSequence(chapterService.latestSequence(item.bookId()) + 1); chapter.setName(item.name()); chapter.setDescription(item.description()); chapter.setBook(bookService.detailOrThrow(item.bookId())); @@ -62,6 +68,18 @@ public class ChapterController extends SimpleControllerSupport> content(@PathVariable("chapter_id") Long chapterId) { + var chapter = chapterService.detailOrThrow(chapterId); + return GlobalResponse.responseDetailData( + chapter.getContent() + .stream() + .sorted(Comparator.comparing(Line::getSequence)) + .map(Line::getText) + .collect(Collectors.joining("\n")) + ); + } + @GetMapping("generate_sequence") public GlobalResponse generateSequence() { chapterService.generateSequence(); @@ -73,7 +91,7 @@ public class ChapterController extends SimpleControllerSupport { var chapter = new Chapter(); chapter.setId(item.id()); - chapter.setSequence(chapterService.latestSequence(item.bookId())); + chapter.setSequence(ObjectUtil.defaultIfNull(item.sequence(), chapterService.latestSequence(item.bookId()) + 1)); chapter.setName(item.name()); chapter.setDescription(item.description()); chapter.setBook(bookService.detailOrThrow(item.bookId())); @@ -105,6 +123,7 @@ public class ChapterController extends SimpleControllerSupport { } public void generateSequence() { - var chapters = chapterRepository.findAll(Sort.by(Sort.Direction.ASC, Chapter.Fields.sequence)); + var chapters = chapterRepository.findAll(QChapter.chapter.sequence.asc()); for (int index = 0; index < chapters.size(); index++) { chapters.get(index).setSequence(NumberUtil.toDouble(index)); }