1
0

feat: 实现整书导出

This commit is contained in:
2025-09-29 14:09:24 +08:00
parent cf5f7470c6
commit 46b1aa8853
2 changed files with 51 additions and 0 deletions

View File

@@ -159,6 +159,14 @@ function Bookshelf() {
actionType: 'dialog',
dialog: detailDialog(),
},
{
type: 'action',
label: '导出',
level: 'link',
size: 'sm',
actionType: 'download',
api: `${commonInfo.baseUrl}/book/export/\${id}`,
},
{
className: 'text-danger btn-deleted',
type: 'action',

View File

@@ -1,15 +1,25 @@
package com.lanyuanxiaoyao.bookstore.controller;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.lanyuanxiaoyao.bookstore.entity.Book;
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.service.template.controller.SimpleControllerSupport;
import jakarta.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -29,6 +39,39 @@ public class BookController extends SimpleControllerSupport<Book, BookController
return bookService.tags();
}
@GetMapping("export/{book_id}")
public void export(@PathVariable("book_id") Long bookId, HttpServletResponse response) throws IOException {
var book = bookService.detailOrThrow(bookId);
var result = new StringBuilder();
result.append(StrUtil.format("""
书名:{}
作者:{}
简介:{}
来源:{}
""", book.getName(), book.getAuthor(), book.getDescription(), book.getSource()));
book.getChapters()
.stream()
.sorted(Comparator.comparing(Chapter::getSequence))
.forEach(chapter -> {
result.append(StrUtil.format("第{}章 {}", chapter.getSequence(), chapter.getName()));
result.append("\n\n");
chapter.getContent()
.stream()
.sorted(Comparator.comparing(Line::getSequence))
.forEach(line -> {
result.append(line.getText());
result.append("\n");
});
result.append("\n\n");
});
response.setHeader("Access-Control-Expose-Headers", "Content-Type");
response.setHeader("Content-Type", "text/plain");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", StrUtil.format("attachment; filename={}", URLUtil.encodeAll(StrUtil.format("{}.txt", book.getName()))));
IoUtil.copy(new ByteArrayInputStream(result.toString().getBytes()), response.getOutputStream());
}
@Override
protected Function<SaveItem, Book> saveItemMapper() {
return item -> {