From bf91a6f206ceb546bbee54f2e3acf31eeefc2cf8 Mon Sep 17 00:00:00 2001
From: Xwite <1797350009@qq.com>
Date: Sun, 29 Sep 2024 18:05:04 +0800
Subject: [PATCH] =?UTF-8?q?fix(modules/web):=20=E9=87=8D=E6=9E=84=E9=98=85?=
=?UTF-8?q?=E8=AF=BBAPI;=E5=B0=81=E9=9D=A2=E5=9B=BE=E7=89=87=E4=BC=98?=
=?UTF-8?q?=E5=85=88=E4=BD=BF=E7=94=A8=E6=BA=90=E7=AB=99=E8=B5=84=E6=BA=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 添加图片代理接口API;API地址测试(3s超时)
---
modules/web/.eslintrc-auto-import.json | 7 +-
modules/web/src/api/axios.js | 17 +-
modules/web/src/api/index.js | 100 +++++++--
modules/web/src/auto-imports.d.ts | 6 +-
modules/web/src/components/BookItems.vue | 15 +-
modules/web/src/components/ChapterContent.vue | 7 +-
modules/web/src/main.js | 2 -
modules/web/src/pages/bookshelf/config.js | 17 --
modules/web/src/pages/bookshelf/main.js | 2 -
modules/web/src/store/bookStore.js | 10 +-
modules/web/src/utils/utils.js | 16 +-
modules/web/src/views/BookShelf.vue | 199 ++++++++++--------
12 files changed, 222 insertions(+), 176 deletions(-)
delete mode 100644 modules/web/src/pages/bookshelf/config.js
diff --git a/modules/web/.eslintrc-auto-import.json b/modules/web/.eslintrc-auto-import.json
index 051d6ac72..cf5c92ea2 100644
--- a/modules/web/.eslintrc-auto-import.json
+++ b/modules/web/.eslintrc-auto-import.json
@@ -5,6 +5,7 @@
"ComputedRef": true,
"EffectScope": true,
"ElMessage": true,
+ "ElMessageBox": true,
"InjectionKey": true,
"PropType": true,
"Ref": true,
@@ -78,8 +79,6 @@
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
- "watchSyncEffect": true,
- "toValue": true,
- "WritableComputedRef": true
+ "watchSyncEffect": true
}
-}
+}
\ No newline at end of file
diff --git a/modules/web/src/api/axios.js b/modules/web/src/api/axios.js
index 16018213b..f3931c9ad 100644
--- a/modules/web/src/api/axios.js
+++ b/modules/web/src/api/axios.js
@@ -1,25 +1,10 @@
import axios from "axios";
const SECOND = 1000;
-const remoteIp = ref(localStorage.getItem("remoteIp"));
const ajax = axios.create({
- // baseURL: import.meta.env.VITE_API || location.origin,
+ baseURL: import.meta.env.VITE_API || localStorage.getItem("remoteIp") || location.origin,
timeout: 120 * SECOND,
});
-ajax.interceptors.request.use((config) => {
- config.baseURL = baseUrl();
- return config;
-});
-
export default ajax;
-
-export const setRemoteIp = (ip) => {
- remoteIp.value = ip;
- localStorage.setItem("remoteIp", ip);
-};
-
-export const baseUrl = () => {
- return remoteIp.value || location.origin;
-};
diff --git a/modules/web/src/api/index.js b/modules/web/src/api/index.js
index 86ff820ee..7e045998d 100644
--- a/modules/web/src/api/index.js
+++ b/modules/web/src/api/index.js
@@ -1,14 +1,48 @@
-import ajax, { baseUrl } from "./axios";
+import ajax from "./axios";
import { ElMessage } from "element-plus/es";
/** https://github.com/gedoor/legado/tree/master/app/src/main/java/io/legado/app/api */
/** https://github.com/gedoor/legado/tree/master/app/src/main/java/io/legado/app/web */
-const getUrl = () => {
- const { hostname, port } = new URL(baseUrl());
- return `${hostname}:${Number(port) + 1}`;
+let legado_http_origin
+let legado_webSocket_origin
+
+const setLeagdoHttpUrl = (http_url) => {
+ let legado_webSocket_port;
+ const { protocol, hostname, port } = new URL(http_url);
+ if (!protocol.startsWith("http"))
+ throw new Error("unexpect protocol:" + http_url);
+ ajax.defaults.baseURL = http_url;
+ legado_http_origin = http_url;
+ if (port !== "") {
+ legado_webSocket_port = Number(port) + 1;
+ } else {
+ legado_webSocket_port = protocol.startsWith("https:") ? "444" : "81";
+ }
+ legado_webSocket_origin =
+ `${protocol.startsWith("https:") ? "wss://" : "ws://"}${hostname}:${legado_webSocket_port}`;
+
+ console.info("legado_server_config:");
+ console.table({legado_http_origin, legado_webSocket_origin});
};
+// 手动初始化 阅读web服务地址
+setLeagdoHttpUrl(ajax.defaults.baseURL);
+
+const testLeagdoHttpUrlConnection = async (http_url) => {
+ const {data = {}} = await ajax.get("/getReadConfig", {
+ baseURL: http_url,
+ timeout: 3000
+ })
+ // 返回结果应该是JSON 并有键值isSuccess
+ try {
+ if ("isSuccess" in data) return
+ throw new Error("ReadConfig后端返回格式错误" )
+ } catch {
+ throw new Error("ReadConfig后端返回格式错误" )
+ }
+}
+
const isSourecEditor = /source/i.test(location.href);
const APIExceptionHandler = (error) => {
if (isSourecEditor) {
@@ -19,8 +53,10 @@ const APIExceptionHandler = (error) => {
}
throw error;
};
+
ajax.interceptors.response.use((response) => response, APIExceptionHandler);
+// 书架API
// Http
const getReadConfig = () => ajax.get("/getReadConfig");
const saveReadConfig = (config) => ajax.post("/saveReadConfig", config);
@@ -32,8 +68,8 @@ const saveBookProgressWithBeacon = (bookProgress) => {
if (!bookProgress) return;
// 常规请求可能会被取消 使用Fetch keep-alive 或者 navigator.sendBeacon
navigator.sendBeacon(
- `${baseUrl()}/saveBookProgress`,
- JSON.stringify(bookProgress),
+ `${legado_http_origin}/saveBookProgress`,
+ JSON.stringify(bookProgress)
);
};
@@ -44,22 +80,23 @@ const getChapterList = (/** @type {string} */ bookUrl) =>
const getBookContent = (
/** @type {string} */ bookUrl,
- /** @type {number} */ chapterIndex,
+ /** @type {number} */ chapterIndex
) =>
ajax.get(
"/getBookContent?url=" +
encodeURIComponent(bookUrl) +
"&index=" +
- chapterIndex,
+ chapterIndex
);
+// webSocket
const search = (
/** @type {string} */ searchKey,
/** @type {(data: string) => void} */ onReceive,
- /** @type {() => void} */ onFinish,
+ /** @type {() => void} */ onFinish
) => {
- // webSocket
- const url = `ws://${getUrl()}/searchBook`;
+
+ const url = `${legado_webSocket_origin}/searchBook`;
const socket = new WebSocket(url);
socket.onopen = () => {
@@ -77,6 +114,7 @@ const deleteBook = (book) => ajax.post("/deleteBook", book);
const isBookSource = /bookSource/i.test(location.href);
+// 源编辑API
// Http
const getSources = () =>
isBookSource ? ajax.get("/getBookSources") : ajax.get("/getRssSources");
@@ -96,14 +134,15 @@ const deleteSource = (data) =>
? ajax.post("/deleteBookSources", data)
: ajax.post("/deleteRssSources", data);
+// webSocket
const debug = (
/** @type {string} */ sourceUrl,
/** @type {string} */ searchKey,
/** @type {(data: string) => void} */ onReceive,
- /** @type {() => void} */ onFinish,
+ /** @type {() => void} */ onFinish
) => {
- // webSocket
- const url = `ws://${getUrl()}/${
+
+ const url = `${legado_webSocket_origin}/${
isBookSource ? "bookSource" : "rssSource"
}Debug`;
@@ -123,6 +162,32 @@ const debug = (
};
};
+/**
+ * 从阅读获取需要特定处理的书籍封面
+ * @param {string} coverUrl
+ */
+const getProxyCoverUrl = (coverUrl) => {
+ if(coverUrl.startsWith(legado_http_origin)) return coverUrl
+ return legado_http_origin + "/cover?path=" + encodeURIComponent(coverUrl);
+}
+/**
+ * 从阅读获取需要特定处理的图片
+ * @param {string} src
+ * @param {`{number}`} width
+ */
+const getProxyImageUrl = (src, width) => {
+ if (src.startsWith(legado_http_origin)) return src
+ return (
+ legado_http_origin +
+ "/image?path=" +
+ encodeURIComponent(src) +
+ "&url=" +
+ encodeURIComponent(sessionStorage.getItem("bookUrl")) +
+ "&width=" +
+ width
+ );
+}
+
export default {
getReadConfig,
saveReadConfig,
@@ -140,4 +205,11 @@ export default {
saveSource,
deleteSource,
debug,
+
+ getProxyCoverUrl,
+ getProxyImageUrl,
+
+ testLeagdoHttpUrlConnection,
+ setLeagdoHttpUrl,
+ legado_http_origin,
};
diff --git a/modules/web/src/auto-imports.d.ts b/modules/web/src/auto-imports.d.ts
index 567fdd4b1..a0f15d7d0 100644
--- a/modules/web/src/auto-imports.d.ts
+++ b/modules/web/src/auto-imports.d.ts
@@ -1,12 +1,12 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
-// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const ElMessage: typeof import('element-plus/es')['ElMessage']
+ const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
@@ -62,7 +62,6 @@ declare global {
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
- const toValue: typeof import('vue')['toValue']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
@@ -82,6 +81,5 @@ declare global {
// for type re-export
declare global {
// @ts-ignore
- export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
- import('vue')
+ export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
}
diff --git a/modules/web/src/components/BookItems.vue b/modules/web/src/components/BookItems.vue
index c8543882c..cb503dfa8 100644
--- a/modules/web/src/components/BookItems.vue
+++ b/modules/web/src/components/BookItems.vue
@@ -12,6 +12,7 @@
class="cover"
:src="getCover(book.coverUrl)"
:key="book.coverUrl"
+ @error.once="proxyImage"
alt=""
loading="lazy"
/>
@@ -49,16 +50,20 @@