diff --git a/client/src/index.tsx b/client/src/index.tsx index 9aaf20a..590a8ad 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -2,7 +2,6 @@ import {createRoot} from 'react-dom/client' import {createHashRouter, Navigate, type RouteObject, RouterProvider} from 'react-router' import './index.scss' import './components/amis/Registry.ts' -import Overview from './pages/Overview.tsx' import Root from './pages/Root.tsx' import Test from './pages/Test.tsx' import Bookshelf from './pages/book/Bookshelf.tsx' @@ -16,11 +15,7 @@ const routes: RouteObject[] = [ children: [ { index: true, - element: , - }, - { - path: 'overview', - Component: Overview, + element: , }, { path: 'bookshelf', diff --git a/client/src/pages/Overview.tsx b/client/src/pages/Overview.tsx deleted file mode 100644 index 2d40eea..0000000 --- a/client/src/pages/Overview.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' - -function Overview() { - return ( -
- ) -} - -export default React.memo(Overview) \ No newline at end of file diff --git a/client/src/pages/Root.tsx b/client/src/pages/Root.tsx index 8cc3c39..8ccf863 100644 --- a/client/src/pages/Root.tsx +++ b/client/src/pages/Root.tsx @@ -25,11 +25,6 @@ const menus = { name: '概览', icon: , routes: [ - { - path: '/overview', - name: '概览', - icon: , - }, { path: '/bookshelf', name: '书架', diff --git a/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java b/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java index 9383c59..048d1ae 100644 --- a/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java +++ b/src/main/java/com/lanyuanxiaoyao/bookstore/BookStoreApplication.java @@ -1,9 +1,22 @@ package com.lanyuanxiaoyao.bookstore; +import cn.hutool.core.io.FileUtil; import com.blinkfox.fenix.EnableFenix; +import com.lanyuanxiaoyao.bookstore.entity.Chapter; +import com.lanyuanxiaoyao.bookstore.service.BookService; +import com.lanyuanxiaoyao.bookstore.service.ChapterService; +import com.lanyuanxiaoyao.bookstore.service.LineService; +import jakarta.annotation.Resource; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Comparator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.event.EventListener; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; /** @@ -17,7 +30,43 @@ import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @EnableFenix @EnableConfigurationProperties public class BookStoreApplication { + @Resource + private BookService bookService; + @Resource + private ChapterService chapterService; + @Resource + private LineService lineService; + public static void main(String[] args) { SpringApplication.run(BookStoreApplication.class, args); } + + @EventListener(ApplicationReadyEvent.class) + public void importIntoDatabase() throws IOException { + var items = new ArrayList(); + Files.list(Path.of("out")) + .sorted(Comparator.comparing(path -> FileUtil.lastModifiedTime(path.toFile()))) + .forEach(path -> { + try { + items.add(new Item( + path.getFileName().toString(), + Files.readString(path) + )); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + for (var item : items) { + var chapter = new Chapter(); + chapter.setSequence(chapterService.latestSequence(3608359126886400L) + 1); + chapter.setName(null); + chapter.setDescription(null); + chapter.setBook(bookService.detailOrThrow(3608359126886400L)); + var chapterId = chapterService.save(chapter); + lineService.load(chapterId, item.content()); + } + } + + private record Item(String title, String content) { + } } diff --git a/src/test/java/com/lanyuanxiaoyao/bookstore/BookCrawlerTest.java b/src/test/java/com/lanyuanxiaoyao/bookstore/BookCrawlerTest.java index 4c6399b..2bff83f 100644 --- a/src/test/java/com/lanyuanxiaoyao/bookstore/BookCrawlerTest.java +++ b/src/test/java/com/lanyuanxiaoyao/bookstore/BookCrawlerTest.java @@ -23,10 +23,10 @@ public class BookCrawlerTest { try { driver = new ChromeDriver( new ChromeDriverService.Builder() - .usingDriverExecutable(new File("/Users/lanyuanxiaoyao/Downloads/chromium/134/macOS-1345775/chromedriver")) + .usingDriverExecutable(new File("/Users/lanyuanxiaoyao/SynologyDrive/tools/chromium/134/macOS-1345775/chromedriver")) .build(), new ChromeOptions() - .setBinary(new File("/Users/lanyuanxiaoyao/Downloads/chromium/134/macOS-1345775/Chromium.app/Contents/MacOS/Chromium")) + .setBinary(new File("/Users/lanyuanxiaoyao/SynologyDrive/tools/chromium/134/macOS-1345775/Chromium.app/Contents/MacOS/Chromium")) .addArguments( // 允许不安全的域名 "--allow-insecure-localhost", @@ -58,7 +58,7 @@ public class BookCrawlerTest { "blink-settings=imagesEnabled=false" ) ); - var articleUrl = "https://www.alicesw.com/novel/33927.html"; + var articleUrl = "https://www.alicesw.com/novel/32007.html"; driver.get(articleUrl); var contextUrl = driver.findElement(By.xpath("//div[@class='book_newchap']//a[contains(text(),'查看所有章节')]")).getDomProperty("href"); if (StrUtil.isBlank(contextUrl)) { @@ -83,12 +83,12 @@ public class BookCrawlerTest { title = String.valueOf(index); } var filename = StrUtil.format("{}.txt", title.replaceAll("\\s", "_")); - var targetFile = Path.of("out", filename); + var targetFile = Path.of("out2", filename); Files.deleteIfExists(targetFile); Files.createFile(targetFile); Files.writeString(targetFile, text); - ThreadUtil.safeSleep(5000); + ThreadUtil.safeSleep(2000); } } finally { if (driver != null) { diff --git a/src/test/java/com/lanyuanxiaoyao/bookstore/UpdateIntoDatabase.java b/src/test/java/com/lanyuanxiaoyao/bookstore/UpdateIntoDatabase.java index 94dc38e..f8a29bc 100644 --- a/src/test/java/com/lanyuanxiaoyao/bookstore/UpdateIntoDatabase.java +++ b/src/test/java/com/lanyuanxiaoyao/bookstore/UpdateIntoDatabase.java @@ -1,9 +1,18 @@ package com.lanyuanxiaoyao.bookstore; -import cn.hutool.ai.AIUtil; -import cn.hutool.ai.ModelName; -import cn.hutool.ai.core.AIConfigBuilder; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.db.dialect.impl.MysqlDialect; +import com.lanyuanxiaoyao.service.template.helper.SnowflakeIdGenerator; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; import lombok.extern.slf4j.Slf4j; /** @@ -14,8 +23,8 @@ import lombok.extern.slf4j.Slf4j; */ @Slf4j public class UpdateIntoDatabase { - public static void main(String[] args) throws IOException { - /*var chapters = new ArrayList(); + public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException { + var chapters = new ArrayList(); Files.list(Path.of("out")) .sorted(Comparator.comparing(path -> FileUtil.lastModifiedTime(path.toFile()))) .forEach(path -> { @@ -28,10 +37,69 @@ public class UpdateIntoDatabase { throw new RuntimeException(e); } }); - for (var chapter : chapters) { - log.info("name: {}", chapter.title()); - }*/ - var response = AIUtil.chat( + Class.forName("com.mysql.cj.jdbc.Driver"); + try ( + var connection = DriverManager.getConnection( + "jdbc:mysql://mysql.lanyuanxiaoyao.com:43780/bookstore?useUnicode=true&characterEncoding=utf8&useSSL=false", + "bookstore", + "EzSn+RZ*x2&fHFh9kC+H" + ) + /*var ds = new SimpleDataSource( + "jdbc:mysql://mysql.lanyuanxiaoyao.com:43780/bookstore?useUnicode=true&characterEncoding=utf8&useSSL=false", + "bookstore", + "EzSn+RZ*x2&fHFh9kC+H", + "com.mysql.cj.jdbc.Driver" + )*/ + ) { + var dialect = new MysqlDialect(); + for (int index = 0; index < chapters.size(); index++) { + var chapter = chapters.get(index); + log.info("Chapter: {}", chapter.title()); + var now = LocalDateTime.now(); + var chapterId = SnowflakeIdGenerator.Snowflake.next(); + /*Db.use(ds, dialect).insert( + Entity.create("bookstore_chapter") + .set("id", chapterId) + .set("created_time", now) + .set("modified_time", now) + .set("sequence", index) + .set("book_id", 3608359126886400L) + );*/ + try (var statement = connection.prepareStatement("insert into bookstore_chapter(id,created_time,modified_time,sequence,book_id) values(?,current_timestamp(),current_timestamp(),?,?)")) { + statement.setLong(1, chapterId); + statement.setDouble(2, index); + statement.setLong(3, 3608359126886400L); + statement.execute(); + } + var lines = StrUtil.split(chapter.content, "\n") + .stream() + .map(StrUtil::trimToNull) + .filter(ObjectUtil::isNotNull) + .toList(); + // var entities = new ArrayList(); + for (int lineIndex = 0; lineIndex < lines.size(); lineIndex++) { + /*entities.add( + Entity.create("bookstore_line") + .set("id", SnowflakeIdGenerator.Snowflake.next()) + .set("created_time", now) + .set("modified_time", now) + .set("sequence", lineIndex) + .set("text", lines.get(lineIndex)) + .set("chapter_id", chapterId) + );*/ + try (var statement = connection.prepareStatement("insert into bookstore_line(id,created_time,modified_time,sequence,text,chapter_id) values(?,current_timestamp(),current_timestamp(),?,?,?)")) { + statement.setLong(1, SnowflakeIdGenerator.Snowflake.next()); + statement.setDouble(2, lineIndex); + statement.setString(3, lines.get(lineIndex)); + statement.setLong(4, chapterId); + statement.execute(); + } + } + // Db.use(ds, dialect).insert(entities); + } + } + + /*var response = AIUtil.chat( new AIConfigBuilder(ModelName.OPENAI.getValue()) .setApiUrl("http://127.0.0.1:30000") .setApiKey("*XMySqV%>hR&v>>g*NwCs3tpQ5FVMFEF2VHVTj