feat: 章节增加修改功能
This commit is contained in:
8
.idea/GitCommitMessageStorage.xml
generated
Normal file
8
.idea/GitCommitMessageStorage.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GitCommitMessageStorage">
|
||||||
|
<option name="messageStorage">
|
||||||
|
<MessageStorage />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
16
.idea/csv-editor.xml
generated
Normal file
16
.idea/csv-editor.xml
generated
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CsvFileAttributes">
|
||||||
|
<option name="attributeMap">
|
||||||
|
<map>
|
||||||
|
<entry key="/dumpDataPreview">
|
||||||
|
<value>
|
||||||
|
<Attribute>
|
||||||
|
<option name="separator" value="," />
|
||||||
|
</Attribute>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -9,6 +9,48 @@ import {
|
|||||||
time,
|
time,
|
||||||
} from '../../util/amis.tsx'
|
} 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() {
|
function Book() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const {id} = useParams()
|
const {id} = useParams()
|
||||||
@@ -49,11 +91,11 @@ function Book() {
|
|||||||
sort: [
|
sort: [
|
||||||
{
|
{
|
||||||
column: 'sequence',
|
column: 'sequence',
|
||||||
direction: 'ASC',
|
direction: 'DESC',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
column: 'modifiedTime',
|
column: 'modifiedTime',
|
||||||
direction: 'DESC',
|
direction: 'ASC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -70,7 +112,9 @@ function Book() {
|
|||||||
actionType: 'ajax',
|
actionType: 'ajax',
|
||||||
tooltip: '序号重排',
|
tooltip: '序号重排',
|
||||||
tooltipPlacement: 'top',
|
tooltipPlacement: 'top',
|
||||||
api: `get:${commonInfo.baseUrl}/chapter/generate_sequence`
|
api: `get:${commonInfo.baseUrl}/chapter/generate_sequence`,
|
||||||
|
confirmText: '确认重排序号?',
|
||||||
|
confirmTitle: '序号重拍',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'action',
|
type: 'action',
|
||||||
@@ -142,7 +186,7 @@ function Book() {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: detailDialog(),
|
dialog: detailDialog(),
|
||||||
},*/
|
},*/
|
||||||
]
|
],
|
||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
@@ -193,14 +237,14 @@ function Book() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/*{
|
{
|
||||||
type: 'action',
|
type: 'action',
|
||||||
label: '修改',
|
label: '修改',
|
||||||
level: 'link',
|
level: 'link',
|
||||||
size: 'sm',
|
size: 'sm',
|
||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: detailDialog(),
|
dialog: detailDialog(id),
|
||||||
},*/
|
},
|
||||||
{
|
{
|
||||||
className: 'text-danger btn-deleted',
|
className: 'text-danger btn-deleted',
|
||||||
type: 'action',
|
type: 'action',
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ function Bookshelf() {
|
|||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: '书名',
|
label: '书名',
|
||||||
width: 150,
|
width: 120,
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -112,7 +112,7 @@ function Bookshelf() {
|
|||||||
{
|
{
|
||||||
name: 'source',
|
name: 'source',
|
||||||
label: '来源',
|
label: '来源',
|
||||||
width: 150,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {useParams} from 'react-router'
|
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() {
|
function Chapter() {
|
||||||
// const navigate = useNavigate()
|
// const navigate = useNavigate()
|
||||||
@@ -52,19 +59,46 @@ function Chapter() {
|
|||||||
},
|
},
|
||||||
...crudCommonOptions(),
|
...crudCommonOptions(),
|
||||||
...paginationTemplate(
|
...paginationTemplate(
|
||||||
undefined,
|
50,
|
||||||
undefined,
|
undefined,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: 'action',
|
type: 'action',
|
||||||
label: '',
|
label: '',
|
||||||
icon: 'fa fa-rotate-right',
|
icon: 'fa fa-book-open-reader',
|
||||||
actionType: 'ajax',
|
actionType: 'ajax',
|
||||||
tooltip: '序号重排',
|
tooltip: '序号重排',
|
||||||
tooltipPlacement: 'top',
|
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: [
|
columns: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +1,10 @@
|
|||||||
package com.lanyuanxiaoyao.bookstore;
|
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.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.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
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) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(BookStoreApplication.class, 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) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.lanyuanxiaoyao.bookstore.controller;
|
package com.lanyuanxiaoyao.bookstore.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
||||||
|
import com.lanyuanxiaoyao.bookstore.entity.Line;
|
||||||
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
||||||
import com.lanyuanxiaoyao.bookstore.service.BookService;
|
import com.lanyuanxiaoyao.bookstore.service.BookService;
|
||||||
import com.lanyuanxiaoyao.bookstore.service.ChapterService;
|
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.GlobalResponse;
|
||||||
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -43,7 +49,7 @@ public class ChapterController extends SimpleControllerSupport<Chapter, ChapterC
|
|||||||
public GlobalResponse<Object> saveWithContent(@RequestBody SaveWithContentItem item) {
|
public GlobalResponse<Object> saveWithContent(@RequestBody SaveWithContentItem item) {
|
||||||
if (SaveWithContentItem.Mode.CREATE.equals(item.mode())) {
|
if (SaveWithContentItem.Mode.CREATE.equals(item.mode())) {
|
||||||
var chapter = new Chapter();
|
var chapter = new Chapter();
|
||||||
chapter.setSequence(chapterService.latestSequence(item.bookId()));
|
chapter.setSequence(chapterService.latestSequence(item.bookId()) + 1);
|
||||||
chapter.setName(item.name());
|
chapter.setName(item.name());
|
||||||
chapter.setDescription(item.description());
|
chapter.setDescription(item.description());
|
||||||
chapter.setBook(bookService.detailOrThrow(item.bookId()));
|
chapter.setBook(bookService.detailOrThrow(item.bookId()));
|
||||||
@@ -62,6 +68,18 @@ public class ChapterController extends SimpleControllerSupport<Chapter, ChapterC
|
|||||||
return GlobalResponse.responseSuccess();
|
return GlobalResponse.responseSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("content/{chapter_id}")
|
||||||
|
public GlobalResponse<Map<String, Object>> 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")
|
@GetMapping("generate_sequence")
|
||||||
public GlobalResponse<Object> generateSequence() {
|
public GlobalResponse<Object> generateSequence() {
|
||||||
chapterService.generateSequence();
|
chapterService.generateSequence();
|
||||||
@@ -73,7 +91,7 @@ public class ChapterController extends SimpleControllerSupport<Chapter, ChapterC
|
|||||||
return item -> {
|
return item -> {
|
||||||
var chapter = new Chapter();
|
var chapter = new Chapter();
|
||||||
chapter.setId(item.id());
|
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.setName(item.name());
|
||||||
chapter.setDescription(item.description());
|
chapter.setDescription(item.description());
|
||||||
chapter.setBook(bookService.detailOrThrow(item.bookId()));
|
chapter.setBook(bookService.detailOrThrow(item.bookId()));
|
||||||
@@ -105,6 +123,7 @@ public class ChapterController extends SimpleControllerSupport<Chapter, ChapterC
|
|||||||
public record SaveItem(
|
public record SaveItem(
|
||||||
Long id,
|
Long id,
|
||||||
Long bookId,
|
Long bookId,
|
||||||
|
Double sequence,
|
||||||
String name,
|
String name,
|
||||||
String description
|
String description
|
||||||
) {
|
) {
|
||||||
@@ -118,10 +137,6 @@ public class ChapterController extends SimpleControllerSupport<Chapter, ChapterC
|
|||||||
Mode mode,
|
Mode mode,
|
||||||
String content
|
String content
|
||||||
) {
|
) {
|
||||||
public SaveItem toSaveItem() {
|
|
||||||
return new SaveItem(null, bookId, name, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
CREATE, OVERRIDE
|
CREATE, OVERRIDE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Line extends SimpleEntity {
|
|||||||
@Lob
|
@Lob
|
||||||
@Basic(fetch = FetchType.LAZY)
|
@Basic(fetch = FetchType.LAZY)
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
@Column(nullable = false)
|
@Column(nullable = false, columnDefinition = "longtext")
|
||||||
private String text;
|
private String text;
|
||||||
|
|
||||||
@ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
|
@ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package com.lanyuanxiaoyao.bookstore.service;
|
|||||||
|
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
||||||
|
import com.lanyuanxiaoyao.bookstore.entity.QChapter;
|
||||||
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
||||||
import com.lanyuanxiaoyao.bookstore.repository.ChapterRepository;
|
import com.lanyuanxiaoyao.bookstore.repository.ChapterRepository;
|
||||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.domain.Sort;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -32,7 +32,7 @@ public class ChapterService extends SimpleServiceSupport<Chapter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateSequence() {
|
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++) {
|
for (int index = 0; index < chapters.size(); index++) {
|
||||||
chapters.get(index).setSequence(NumberUtil.toDouble(index));
|
chapters.get(index).setSequence(NumberUtil.toDouble(index));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user