diff --git a/src/import-epub-books/im-epubbooks-ui.ts b/src/import-epub-books/im-epubbooks-ui.ts
new file mode 100644
index 0000000..d04852c
--- /dev/null
+++ b/src/import-epub-books/im-epubbooks-ui.ts
@@ -0,0 +1,67 @@
+import { IChangedTiddlers } from 'tiddlywiki';
+import { widget as Widget } from '$:/core/modules/widgets/widget.js';
+
+class ImportEpubBooksMainWidget extends Widget {
+ refresh(_changedTiddlers: IChangedTiddlers) {
+ return false;
+ }
+
+ async render(parent: Node, _nextSibling: Node) {
+ this.parentDomNode = parent;
+ this.execute();
+
+ // 逻辑处理代码
+
+ const containerElement = document.createElement('div');
+ containerElement.innerHTML = `
+
+
+
+
+
+ `;
+ this.domNodes.push(parent.appendChild(containerElement));
+
+ const addButton = document.getElementById("importepubbooks-button-add");
+ const inputBox = document.getElementById("importepubbooks-path");
+
+
+ addButton.onclick = function () {
+ if (inputBox.value.length == 0) {
+ console.log("输入为空!");
+ tm_notify("Import epub books", "输入为空!");
+ } else {
+ await addBooks(inputBox.value);
+ }
+ }
+ }
+
+ tm_notify(generalNotification: string, message: string) {
+ $tw.wiki.addTiddler({ title: `$:/state/notification/${generalNotification}`, text: `${generalNotification}: ${message}` });
+ $tw.notifier.display(`$:/state/notification/${generalNotification}`);
+ }
+
+ async addBooks(data) {
+ // 将获取到的书籍以json条目的形式写入到tiddlers目录中。
+ }
+
+ /**
+ * 从路由中获取epub数据流。
+ * @param path epub文件路径或epubs文件夹路径
+ * @returns 数据流
+ */
+ async fetchData(path: string) {
+ // 内置插件 $:/temp/info-plugin。相对请求路径 obstore/ 也可以使用。
+ let fullUrl = $tw.wiki.getTiddlerText("$:/info/url/full");
+ var route = fullUrl + "importepubbooks" + "/" + path;
+ console.log("获取数据:" + route);
+ this.tm_notify("获取数据 (fetchData) ", `"${route}"`);
+ const response = await fetch(route);
+ const data = await response.json();
+ console.log("获取完成, 正在写入到wiki中。");
+ this.tm_notify("获取数据 (fetchData) ", "获取完成, 正在写入到wiki中");
+ return data;
+ }
+}
+
+exports.importepubbooks = ImportEpubBooksMainWidget;
\ No newline at end of file
diff --git a/src/import-epub-books/im-epubbooks-ui.ts.meta b/src/import-epub-books/im-epubbooks-ui.ts.meta
new file mode 100644
index 0000000..6815ac7
--- /dev/null
+++ b/src/import-epub-books/im-epubbooks-ui.ts.meta
@@ -0,0 +1,3 @@
+title: $:/plugins/whitefall/import-epub-books/im-epubbooks-ui.ts
+type: application/javascript
+module-type: widget
\ No newline at end of file
diff --git a/src/import-epub-books/router/get-epubbooks.js b/src/import-epub-books/router/get-epubbooks.js
new file mode 100644
index 0000000..e9cf9c1
--- /dev/null
+++ b/src/import-epub-books/router/get-epubbooks.js
@@ -0,0 +1,68 @@
+/*\
+title: $:/plugins/whitefall/import-epub-books/router/get-epub-books.js
+type: application/javascript
+module-type: route
+
+GET importepubbooks/:filepath
+
+request:importepubbooks/D:/Dropbox/21-Sandox/10-Picture/wine.epub
+response:返回importepubbooks找到的所有文件数据。
+
+\*/
+(function () {
+
+ /*jslint node: true, browser: true */
+ /*global $tw: false */
+ "use strict";
+
+ exports.method = "GET";
+
+ exports.path = /^\/importepubbooks\/(.+)$/;
+ exports.handler = function (request, response, state) {
+
+ var path = require("path"),
+ fs = require("fs"),
+ epubsFolder = $tw.utils.decodeURIComponentSafe(state.params[0]);
+
+ /**
+ * 获取epub文件或文件夹下的所有epub文件。
+ * @param epubsPath epub文件路径或epubs文件夹路径
+ * @return 字典包装的二进制数据流。
+ * @author WhiteFall 2023/06/24
+ */
+ var getEpubFiles = function (epubsPath) {
+ var basename,
+ result = { epubs: {} },
+ stat = fs.lstatSync(epubsPath),
+ extension,
+ epubData;
+ if (stat.isDirectory()) {
+ // 是一个epubs目录。
+ const files = fs.readdirSync(epubsPath);
+ for (const item of files) {
+ const filePath = path.join(epubsPath, item);
+ basename = path.basename(filePath);
+ extension = path.extname(basename);
+ if (extension === '.epub') {
+ // 二进制数据流。
+ epubData = fs.readFileSync(filePath);
+ result.epubs[basename] = epubData;
+ }
+ }
+ } else {
+ // 是一个epub文件。
+ basename = path.basename(epubsPath);
+ extension = path.extname(basename);
+ if (extension === '.epub') {
+ epubData = fs.readFileSync(epubsPath);
+ result.epubs[basename] = epubData;
+ }
+ }
+ const content = JSON.stringify(result);
+ // Send the file
+ state.sendResponse(200, { "Content-Type": "application/json" }, content);
+ }
+
+ getEpubFiles(epubsFolder);
+ };
+}());
\ No newline at end of file
diff --git a/src/import-epub-books/router/get-epubbooks.js.meta b/src/import-epub-books/router/get-epubbooks.js.meta
new file mode 100644
index 0000000..6e9e26a
--- /dev/null
+++ b/src/import-epub-books/router/get-epubbooks.js.meta
@@ -0,0 +1,3 @@
+title: $:/plugins/whitefall/import-epub-books/router/get-epubbooks.js
+type: application/javascript
+module-type: route
\ No newline at end of file