mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
style(modules/web): lint code with eslint
This commit is contained in:
@@ -3,8 +3,8 @@ import fs from "node:fs";
|
|||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
|
|
||||||
if (!process.env.GITHUB_ENV) {
|
if (!process.env.GITHUB_ENV) {
|
||||||
console.log("非Github WorkFlows环境,取消文件复制")
|
console.log("非Github WorkFlows环境,取消文件复制");
|
||||||
process.exit()
|
process.exit();
|
||||||
}
|
}
|
||||||
const LEGADO_ASSETS_WEB_VUE_DIR = new URL(
|
const LEGADO_ASSETS_WEB_VUE_DIR = new URL(
|
||||||
"../../../app/src/main/assets/web/vue",
|
"../../../app/src/main/assets/web/vue",
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import axios from "axios";
|
|||||||
const SECOND = 1000;
|
const SECOND = 1000;
|
||||||
|
|
||||||
const ajax = axios.create({
|
const ajax = axios.create({
|
||||||
baseURL: import.meta.env.VITE_API || localStorage.getItem("remoteIp") || location.origin,
|
baseURL:
|
||||||
|
import.meta.env.VITE_API ||
|
||||||
|
localStorage.getItem("remoteIp") ||
|
||||||
|
location.origin,
|
||||||
timeout: 120 * SECOND,
|
timeout: 120 * SECOND,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ 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/api */
|
||||||
/** https://github.com/gedoor/legado/tree/master/app/src/main/java/io/legado/app/web */
|
/** https://github.com/gedoor/legado/tree/master/app/src/main/java/io/legado/app/web */
|
||||||
|
|
||||||
let legado_http_origin
|
let legado_http_origin;
|
||||||
let legado_webSocket_origin
|
let legado_webSocket_origin;
|
||||||
|
|
||||||
const setLeagdoHttpUrl = (http_url) => {
|
const setLeagdoHttpUrl = (http_url) => {
|
||||||
let legado_webSocket_port;
|
let legado_webSocket_port;
|
||||||
@@ -19,29 +19,28 @@ const setLeagdoHttpUrl = (http_url) => {
|
|||||||
} else {
|
} else {
|
||||||
legado_webSocket_port = protocol.startsWith("https:") ? "444" : "81";
|
legado_webSocket_port = protocol.startsWith("https:") ? "444" : "81";
|
||||||
}
|
}
|
||||||
legado_webSocket_origin =
|
legado_webSocket_origin = `${protocol.startsWith("https:") ? "wss://" : "ws://"}${hostname}:${legado_webSocket_port}`;
|
||||||
`${protocol.startsWith("https:") ? "wss://" : "ws://"}${hostname}:${legado_webSocket_port}`;
|
|
||||||
|
|
||||||
console.info("legado_server_config:");
|
console.info("legado_server_config:");
|
||||||
console.table({legado_http_origin, legado_webSocket_origin});
|
console.table({ legado_http_origin, legado_webSocket_origin });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 手动初始化 阅读web服务地址
|
// 手动初始化 阅读web服务地址
|
||||||
setLeagdoHttpUrl(ajax.defaults.baseURL);
|
setLeagdoHttpUrl(ajax.defaults.baseURL);
|
||||||
|
|
||||||
const testLeagdoHttpUrlConnection = async (http_url) => {
|
const testLeagdoHttpUrlConnection = async (http_url) => {
|
||||||
const {data = {}} = await ajax.get("/getReadConfig", {
|
const { data = {} } = await ajax.get("/getReadConfig", {
|
||||||
baseURL: http_url,
|
baseURL: http_url,
|
||||||
timeout: 3000
|
timeout: 3000,
|
||||||
})
|
});
|
||||||
// 返回结果应该是JSON 并有键值isSuccess
|
// 返回结果应该是JSON 并有键值isSuccess
|
||||||
try {
|
try {
|
||||||
if ("isSuccess" in data) return data.data
|
if ("isSuccess" in data) return data.data;
|
||||||
throw new Error("ReadConfig后端返回格式错误" )
|
throw new Error("ReadConfig后端返回格式错误");
|
||||||
} catch {
|
} catch {
|
||||||
throw new Error("ReadConfig后端返回格式错误" )
|
throw new Error("ReadConfig后端返回格式错误");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const isSourecEditor = /source/i.test(location.href);
|
const isSourecEditor = /source/i.test(location.href);
|
||||||
const APIExceptionHandler = (error) => {
|
const APIExceptionHandler = (error) => {
|
||||||
@@ -59,7 +58,7 @@ ajax.interceptors.response.use((response) => response, APIExceptionHandler);
|
|||||||
// 书架API
|
// 书架API
|
||||||
// Http
|
// Http
|
||||||
/** @returns {Promise<import("axios").AxiosResponse<{isSuccess: boolean, data: string, errorMsg:string}>>} */
|
/** @returns {Promise<import("axios").AxiosResponse<{isSuccess: boolean, data: string, errorMsg:string}>>} */
|
||||||
const getReadConfig = () => ajax.get("/getReadConfig", {timeout: 3000});
|
const getReadConfig = () => ajax.get("/getReadConfig", { timeout: 3000 });
|
||||||
const saveReadConfig = (config) => ajax.post("/saveReadConfig", config);
|
const saveReadConfig = (config) => ajax.post("/saveReadConfig", config);
|
||||||
|
|
||||||
const saveBookProgress = (bookProgress) =>
|
const saveBookProgress = (bookProgress) =>
|
||||||
@@ -70,7 +69,7 @@ const saveBookProgressWithBeacon = (bookProgress) => {
|
|||||||
// 常规请求可能会被取消 使用Fetch keep-alive 或者 navigator.sendBeacon
|
// 常规请求可能会被取消 使用Fetch keep-alive 或者 navigator.sendBeacon
|
||||||
navigator.sendBeacon(
|
navigator.sendBeacon(
|
||||||
`${legado_http_origin}/saveBookProgress`,
|
`${legado_http_origin}/saveBookProgress`,
|
||||||
JSON.stringify(bookProgress)
|
JSON.stringify(bookProgress),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,22 +80,21 @@ const getChapterList = (/** @type {string} */ bookUrl) =>
|
|||||||
|
|
||||||
const getBookContent = (
|
const getBookContent = (
|
||||||
/** @type {string} */ bookUrl,
|
/** @type {string} */ bookUrl,
|
||||||
/** @type {number} */ chapterIndex
|
/** @type {number} */ chapterIndex,
|
||||||
) =>
|
) =>
|
||||||
ajax.get(
|
ajax.get(
|
||||||
"/getBookContent?url=" +
|
"/getBookContent?url=" +
|
||||||
encodeURIComponent(bookUrl) +
|
encodeURIComponent(bookUrl) +
|
||||||
"&index=" +
|
"&index=" +
|
||||||
chapterIndex
|
chapterIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
// webSocket
|
// webSocket
|
||||||
const search = (
|
const search = (
|
||||||
/** @type {string} */ searchKey,
|
/** @type {string} */ searchKey,
|
||||||
/** @type {(data: string) => void} */ onReceive,
|
/** @type {(data: string) => void} */ onReceive,
|
||||||
/** @type {() => void} */ onFinish
|
/** @type {() => void} */ onFinish,
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
const url = `${legado_webSocket_origin}/searchBook`;
|
const url = `${legado_webSocket_origin}/searchBook`;
|
||||||
const socket = new WebSocket(url);
|
const socket = new WebSocket(url);
|
||||||
|
|
||||||
@@ -140,9 +138,8 @@ const debug = (
|
|||||||
/** @type {string} */ sourceUrl,
|
/** @type {string} */ sourceUrl,
|
||||||
/** @type {string} */ searchKey,
|
/** @type {string} */ searchKey,
|
||||||
/** @type {(data: string) => void} */ onReceive,
|
/** @type {(data: string) => void} */ onReceive,
|
||||||
/** @type {() => void} */ onFinish
|
/** @type {() => void} */ onFinish,
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
const url = `${legado_webSocket_origin}/${
|
const url = `${legado_webSocket_origin}/${
|
||||||
isBookSource ? "bookSource" : "rssSource"
|
isBookSource ? "bookSource" : "rssSource"
|
||||||
}Debug`;
|
}Debug`;
|
||||||
@@ -168,16 +165,16 @@ const debug = (
|
|||||||
* @param {string} coverUrl
|
* @param {string} coverUrl
|
||||||
*/
|
*/
|
||||||
const getProxyCoverUrl = (coverUrl) => {
|
const getProxyCoverUrl = (coverUrl) => {
|
||||||
if(coverUrl.startsWith(legado_http_origin)) return coverUrl
|
if (coverUrl.startsWith(legado_http_origin)) return coverUrl;
|
||||||
return legado_http_origin + "/cover?path=" + encodeURIComponent(coverUrl);
|
return legado_http_origin + "/cover?path=" + encodeURIComponent(coverUrl);
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 从阅读获取需要特定处理的图片
|
* 从阅读获取需要特定处理的图片
|
||||||
* @param {string} src
|
* @param {string} src
|
||||||
* @param {number|`${number}`} width
|
* @param {number|`${number}`} width
|
||||||
*/
|
*/
|
||||||
const getProxyImageUrl = (src, width) => {
|
const getProxyImageUrl = (src, width) => {
|
||||||
if (src.startsWith(legado_http_origin)) return src
|
if (src.startsWith(legado_http_origin)) return src;
|
||||||
return (
|
return (
|
||||||
legado_http_origin +
|
legado_http_origin +
|
||||||
"/image?path=" +
|
"/image?path=" +
|
||||||
@@ -187,7 +184,7 @@ const getProxyImageUrl = (src, width) => {
|
|||||||
"&width=" +
|
"&width=" +
|
||||||
width
|
width
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getReadConfig,
|
getReadConfig,
|
||||||
|
|||||||
@@ -57,14 +57,12 @@ const props = defineProps(["books", "isSearch"]);
|
|||||||
const emit = defineEmits(["bookClick"]);
|
const emit = defineEmits(["bookClick"]);
|
||||||
const handleClick = (book) => emit("bookClick", book);
|
const handleClick = (book) => emit("bookClick", book);
|
||||||
const getCover = (coverUrl) => {
|
const getCover = (coverUrl) => {
|
||||||
return isLegadoUrl(coverUrl)
|
return isLegadoUrl(coverUrl) ? API.getProxyCoverUrl(coverUrl) : coverUrl;
|
||||||
? API.getProxyCoverUrl(coverUrl) : coverUrl
|
|
||||||
};
|
};
|
||||||
const proxyImage = (event) => {
|
const proxyImage = (event) => {
|
||||||
event.target.src = API.getProxyCoverUrl(event.target.src);
|
event.target.src = API.getProxyCoverUrl(event.target.src);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const subJustify = computed(() =>
|
const subJustify = computed(() =>
|
||||||
props.isSearch ? "space-between" : "flex-start",
|
props.isSearch ? "space-between" : "flex-start",
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,11 +34,15 @@ const props = defineProps({
|
|||||||
const getImageSrc = (content) => {
|
const getImageSrc = (content) => {
|
||||||
const imgPattern = /<img[^>]*src="([^"]*(?:"[^>]+\})?)"[^>]*>/;
|
const imgPattern = /<img[^>]*src="([^"]*(?:"[^>]+\})?)"[^>]*>/;
|
||||||
const src = content.match(imgPattern)[1];
|
const src = content.match(imgPattern)[1];
|
||||||
if (isLegadoUrl(src)) return API.getProxyImageUrl(src, useBookStore().config.readWidth)
|
if (isLegadoUrl(src))
|
||||||
|
return API.getProxyImageUrl(src, useBookStore().config.readWidth);
|
||||||
return src;
|
return src;
|
||||||
};
|
};
|
||||||
const proxyImage = (event) => {
|
const proxyImage = (event) => {
|
||||||
event.target.src = API.getProxyImageUrl(event.target.src, useBookStore().config.readWidth);
|
event.target.src = API.getProxyImageUrl(
|
||||||
|
event.target.src,
|
||||||
|
useBookStore().config.readWidth,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateWordCount = (paragraph) => {
|
const calculateWordCount = (paragraph) => {
|
||||||
|
|||||||
@@ -27,10 +27,7 @@ import CatalogItem from "./CatalogItem.vue";
|
|||||||
|
|
||||||
const store = useBookStore();
|
const store = useBookStore();
|
||||||
|
|
||||||
const {
|
const { catalog, popCataVisible, miniInterface } = storeToRefs(store);
|
||||||
catalog,
|
|
||||||
popCataVisible, miniInterface
|
|
||||||
} = storeToRefs(store);
|
|
||||||
|
|
||||||
//主题
|
//主题
|
||||||
const isNight = computed(() => store.theme);
|
const isNight = computed(() => store.theme);
|
||||||
@@ -89,7 +86,6 @@ const gotoChapter = (note) => {
|
|||||||
store.saveBookProgress();
|
store.saveBookProgress();
|
||||||
emit("getContent", chapterIndex);
|
emit("getContent", chapterIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -68,10 +68,7 @@
|
|||||||
"
|
"
|
||||||
>确定</el-button
|
>确定</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button type="primary" size="small" @click="loadFontFromURL"
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="loadFontFromURL"
|
|
||||||
>网络下载</el-button
|
>网络下载</el-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -196,14 +193,14 @@ watch(
|
|||||||
API.saveReadConfig(newValue);
|
API.saveReadConfig(newValue);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deep: 2 //深度为2
|
deep: 2, //深度为2
|
||||||
}
|
},
|
||||||
)
|
);
|
||||||
|
|
||||||
//主题颜色
|
//主题颜色
|
||||||
const theme = computed(() => store.theme);
|
const theme = computed(() => store.theme);
|
||||||
const isNight = computed(() => store.isNight);
|
const isNight = computed(() => store.isNight);
|
||||||
const moonIcon = computed(() => theme.value == 6 ? "" : "");
|
const moonIcon = computed(() => (theme.value == 6 ? "" : ""));
|
||||||
const themeColors = [
|
const themeColors = [
|
||||||
{
|
{
|
||||||
background: "rgba(250, 245, 235, 0.8)",
|
background: "rgba(250, 245, 235, 0.8)",
|
||||||
@@ -234,7 +231,7 @@ const popupTheme = computed(() => {
|
|||||||
});
|
});
|
||||||
const setTheme = (theme) => {
|
const setTheme = (theme) => {
|
||||||
store.config.theme = theme;
|
store.config.theme = theme;
|
||||||
}
|
};
|
||||||
|
|
||||||
//预置字体
|
//预置字体
|
||||||
const fonts = ref(["雅黑", "宋体", "楷书"]);
|
const fonts = ref(["雅黑", "宋体", "楷书"]);
|
||||||
@@ -253,51 +250,45 @@ const setCustomFont = () => {
|
|||||||
};
|
};
|
||||||
// 加载网络字体
|
// 加载网络字体
|
||||||
const loadFontFromURL = () => {
|
const loadFontFromURL = () => {
|
||||||
ElMessageBox.prompt(
|
ElMessageBox.prompt("请输入 字体网络链接", "提示", {
|
||||||
"请输入 字体网络链接",
|
confirmButtonText: "确定",
|
||||||
"提示",
|
cancelButtonText: "取消",
|
||||||
{
|
inputPattern: /^https?:.+$/,
|
||||||
confirmButtonText: "确定",
|
inputErrorMessage: "url 形式不正确",
|
||||||
cancelButtonText: "取消",
|
beforeClose: (action, instance, done) => {
|
||||||
inputPattern: /^https?:.+$/,
|
if (action === "confirm") {
|
||||||
inputErrorMessage: "url 形式不正确",
|
instance.confirmButtonLoading = true;
|
||||||
beforeClose: (action, instance, done) => {
|
instance.confirmButtonText = "下载中……";
|
||||||
if (action === "confirm") {
|
// instance.inputValue
|
||||||
instance.confirmButtonLoading = true;
|
const url = instance.inputValue;
|
||||||
instance.confirmButtonText = "下载中……";
|
if (typeof FontFace !== "function") {
|
||||||
// instance.inputValue
|
ElMessage.error("浏览器不支持FontFace");
|
||||||
const url = instance.inputValue
|
return done();
|
||||||
if (typeof FontFace !== "function") {
|
|
||||||
ElMessage.error("浏览器不支持FontFace");
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
const fontface = new FontFace(
|
|
||||||
customFontName.value,
|
|
||||||
`url("${url}")`
|
|
||||||
)
|
|
||||||
//@ts-ignore
|
|
||||||
document.fonts.add(fontface);
|
|
||||||
fontface.load()
|
|
||||||
//API.getBookShelf()
|
|
||||||
.then(function () {
|
|
||||||
instance.confirmButtonLoading = false;
|
|
||||||
ElMessage.info("字体加载成功!");
|
|
||||||
setCustomFont();
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
instance.confirmButtonLoading = false;
|
|
||||||
instance.confirmButtonText = "确定";
|
|
||||||
ElMessage.error("下载失败,请检查您输入的 url");
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
done();
|
|
||||||
}
|
}
|
||||||
},
|
const fontface = new FontFace(customFontName.value, `url("${url}")`);
|
||||||
}
|
//@ts-ignore
|
||||||
);
|
document.fonts.add(fontface);
|
||||||
}
|
fontface
|
||||||
|
.load()
|
||||||
|
//API.getBookShelf()
|
||||||
|
.then(function () {
|
||||||
|
instance.confirmButtonLoading = false;
|
||||||
|
ElMessage.info("字体加载成功!");
|
||||||
|
setCustomFont();
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
instance.confirmButtonLoading = false;
|
||||||
|
instance.confirmButtonText = "确定";
|
||||||
|
ElMessage.error("下载失败,请检查您输入的 url");
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//字体大小
|
//字体大小
|
||||||
const fontSize = computed(() => {
|
const fontSize = computed(() => {
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ const startDebug = async () => {
|
|||||||
try {
|
try {
|
||||||
await API.saveSource(store.currentSource);
|
await API.saveSource(store.currentSource);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
store.debugFinish()
|
store.debugFinish();
|
||||||
throw e
|
throw e;
|
||||||
}
|
}
|
||||||
API.debug(
|
API.debug(
|
||||||
store.currentSourceUrl,
|
store.currentSourceUrl,
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ import { Link } from "@element-plus/icons-vue";
|
|||||||
<el-link :icon="Link" href="/help/#httpTTSHelp" target="_blank"
|
<el-link :icon="Link" href="/help/#httpTTSHelp" target="_blank"
|
||||||
>在线朗读规则</el-link
|
>在线朗读规则</el-link
|
||||||
><br />
|
><br />
|
||||||
<el-link :icon="Link" href="/help/#webDavBookHelp" target="_blank"
|
<el-link :icon="Link" href="/help/#webDavBookHelp" target="_blank">
|
||||||
> WebDav书籍简明使用教程</el-link
|
WebDav书籍简明使用教程</el-link
|
||||||
><br />
|
><br />
|
||||||
<el-link :icon="Link" href="/help/#webDavHelp" target="_blank"
|
<el-link :icon="Link" href="/help/#webDavHelp" target="_blank">
|
||||||
> WebDav备份教程</el-link
|
WebDav备份教程</el-link
|
||||||
><br />
|
><br />
|
||||||
<el-link :icon="Link" href="https://regexr-cn.com/" target="_blank"
|
<el-link :icon="Link" href="https://regexr-cn.com/" target="_blank"
|
||||||
>正则表达式在线验证工具</el-link
|
>正则表达式在线验证工具</el-link
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ import SourceItem from "./SourceItem.vue";
|
|||||||
const store = useSourceStore();
|
const store = useSourceStore();
|
||||||
const sourceUrlSelect = ref([]);
|
const sourceUrlSelect = ref([]);
|
||||||
const searchKey = ref("");
|
const searchKey = ref("");
|
||||||
const sources = computed(() => store.sources);
|
const sources = computed(() => store.sources);
|
||||||
|
|
||||||
// 筛选源
|
// 筛选源
|
||||||
/** @type Ref<import('@/source').Source[]> */
|
/** @type Ref<import('@/source').Source[]> */
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createApp } from "vue";
|
|||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import "element-plus/theme-chalk/dark/css-vars.css"
|
import "element-plus/theme-chalk/dark/css-vars.css";
|
||||||
|
|
||||||
createApp(App).use(store).use(router).mount("#app");
|
createApp(App).use(store).use(router).mount("#app");
|
||||||
|
|
||||||
@@ -10,12 +10,12 @@ createApp(App).use(store).use(router).mount("#app");
|
|||||||
useBookStore().loadReadConfig();
|
useBookStore().loadReadConfig();
|
||||||
// 书架 同步Element PLUS 夜间模式
|
// 书架 同步Element PLUS 夜间模式
|
||||||
watch(
|
watch(
|
||||||
() => useBookStore().isNight,
|
() => useBookStore().isNight,
|
||||||
(isNight) => {
|
(isNight) => {
|
||||||
if (isNight) {
|
if (isNight) {
|
||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.remove("dark");
|
document.documentElement.classList.remove("dark");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
},
|
||||||
|
);
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ createApp(App).use(store).use(bookRouter).mount("#app");
|
|||||||
useBookStore().loadReadConfig();
|
useBookStore().loadReadConfig();
|
||||||
// 同步Element PLUS 夜间模式
|
// 同步Element PLUS 夜间模式
|
||||||
watch(
|
watch(
|
||||||
() => useBookStore().isNight,
|
() => useBookStore().isNight,
|
||||||
(isNight) => {
|
(isNight) => {
|
||||||
if (isNight) {
|
if (isNight) {
|
||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.remove("dark");
|
document.documentElement.classList.remove("dark");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
},
|
||||||
|
);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const useBookStore = defineStore("book", {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
theme: (state) => {
|
theme: (state) => {
|
||||||
return state.config.theme
|
return state.config.theme;
|
||||||
},
|
},
|
||||||
isNight: (state) => state.config.theme == 6,
|
isNight: (state) => state.config.theme == 6,
|
||||||
},
|
},
|
||||||
@@ -114,10 +114,12 @@ export const useBookStore = defineStore("book", {
|
|||||||
},
|
},
|
||||||
//读取阅读界面配置以初始化夜间模式 以免初次加载书架页面时闪屏
|
//读取阅读界面配置以初始化夜间模式 以免初次加载书架页面时闪屏
|
||||||
async loadReadConfig() {
|
async loadReadConfig() {
|
||||||
return API.getReadConfig().then(response => response.data)
|
return API.getReadConfig()
|
||||||
.then(({isSuccess, data}) =>
|
.then((response) => response.data)
|
||||||
isSuccess && this.setConfig(JSON.parse(data))
|
.then(
|
||||||
)
|
({ isSuccess, data }) =>
|
||||||
}
|
isSuccess && this.setConfig(JSON.parse(data)),
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -301,7 +301,10 @@ const toChapterPos = (pos) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 60秒保存一次进度
|
// 60秒保存一次进度
|
||||||
const saveBookProgressThrottle = useThrottleFn(() => store.saveBookProgress(), 60000)
|
const saveBookProgressThrottle = useThrottleFn(
|
||||||
|
() => store.saveBookProgress(),
|
||||||
|
60000,
|
||||||
|
);
|
||||||
|
|
||||||
const onReadedLengthChange = (index, pos) => {
|
const onReadedLengthChange = (index, pos) => {
|
||||||
saveReadingBookProgressToBrowser(index, pos);
|
saveReadingBookProgressToBrowser(index, pos);
|
||||||
@@ -491,7 +494,7 @@ onMounted(() => {
|
|||||||
bookAuthor: bookAuthor,
|
bookAuthor: bookAuthor,
|
||||||
bookUrl: bookUrl,
|
bookUrl: bookUrl,
|
||||||
index: chapterIndex,
|
index: chapterIndex,
|
||||||
chapterPos: chapterPos
|
chapterPos: chapterPos,
|
||||||
};
|
};
|
||||||
localStorage.setItem(bookUrl, JSON.stringify(book));
|
localStorage.setItem(bookUrl, JSON.stringify(book));
|
||||||
}
|
}
|
||||||
@@ -531,7 +534,6 @@ onMounted(() => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener("keyup", handleKeyPress);
|
window.removeEventListener("keyup", handleKeyPress);
|
||||||
window.removeEventListener("keydown", ignoreKeyPress);
|
window.removeEventListener("keydown", ignoreKeyPress);
|
||||||
@@ -544,7 +546,6 @@ onUnmounted(() => {
|
|||||||
scrollObserver = null;
|
scrollObserver = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const addToBookShelfConfirm = async () => {
|
const addToBookShelfConfirm = async () => {
|
||||||
const bookUrl = sessionStorage.getItem("bookUrl");
|
const bookUrl = sessionStorage.getItem("bookUrl");
|
||||||
const bookName = sessionStorage.getItem("bookName");
|
const bookName = sessionStorage.getItem("bookName");
|
||||||
@@ -553,10 +554,10 @@ const addToBookShelfConfirm = async () => {
|
|||||||
sessionStorage.removeItem("isSeachBook");
|
sessionStorage.removeItem("isSeachBook");
|
||||||
// 阅读的是搜索的书籍 并未在书架
|
// 阅读的是搜索的书籍 并未在书架
|
||||||
if (isSeachBook === "true") {
|
if (isSeachBook === "true") {
|
||||||
const addtoshelf = window.confirm(`是否将《${bookName}》放入书架?`)
|
const addtoshelf = window.confirm(`是否将《${bookName}》放入书架?`);
|
||||||
if (!addtoshelf) await API.deleteBook(book);
|
if (!addtoshelf) await API.deleteBook(book);
|
||||||
//按下返回键时不能触发 ElMessageBox.confirm
|
//按下返回键时不能触发 ElMessageBox.confirm
|
||||||
/* await ElMessageBox.confirm(
|
/* await ElMessageBox.confirm(
|
||||||
`是否将《${bookName}》放入书架?`,
|
`是否将《${bookName}》放入书架?`,
|
||||||
"放入书架",
|
"放入书架",
|
||||||
{
|
{
|
||||||
@@ -571,7 +572,7 @@ const addToBookShelfConfirm = async () => {
|
|||||||
await API.deleteBook(book);
|
await API.deleteBook(book);
|
||||||
}) */
|
}) */
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
onBeforeRouteLeave(async (to, from, next) => {
|
onBeforeRouteLeave(async (to, from, next) => {
|
||||||
await addToBookShelfConfirm();
|
await addToBookShelfConfirm();
|
||||||
next();
|
next();
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
<div class="recent-title">最近阅读</div>
|
<div class="recent-title">最近阅读</div>
|
||||||
<div class="reading-recent">
|
<div class="reading-recent">
|
||||||
<el-tag
|
<el-tag
|
||||||
:type="readingRecent.name == '尚无阅读记录' ? 'warning' : 'primary'"
|
:type="
|
||||||
|
readingRecent.name == '尚无阅读记录' ? 'warning' : 'primary'
|
||||||
|
"
|
||||||
class="recent-book"
|
class="recent-book"
|
||||||
size="large"
|
size="large"
|
||||||
@click="
|
@click="
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
readingRecent.name,
|
readingRecent.name,
|
||||||
readingRecent.author,
|
readingRecent.author,
|
||||||
readingRecent.chapterIndex,
|
readingRecent.chapterIndex,
|
||||||
readingRecent.chapterPos
|
readingRecent.chapterPos,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
:class="{ 'no-point': readingRecent.url == '' }"
|
:class="{ 'no-point': readingRecent.url == '' }"
|
||||||
@@ -40,37 +42,37 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="setting-wrapper">
|
<div class="setting-wrapper">
|
||||||
<div class="setting-title">基本设定</div>
|
<div class="setting-title">基本设定</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<el-tag
|
<el-tag
|
||||||
:type="connectType"
|
:type="connectType"
|
||||||
size="large"
|
size="large"
|
||||||
class="setting-connect"
|
class="setting-connect"
|
||||||
:class="{ 'no-point': newConnect }"
|
:class="{ 'no-point': newConnect }"
|
||||||
@click="setIP"
|
@click="setIP"
|
||||||
>
|
>
|
||||||
{{ connectStatus }}
|
{{ connectStatus }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom-icons">
|
|
||||||
<a
|
|
||||||
href="https://github.com/gedoor/legado_web_bookshelf"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div class="bottom-icon">
|
|
||||||
<img :src="githubUrl" alt="" />
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shelf-wrapper" ref="shelfWrapper">
|
<div class="bottom-icons">
|
||||||
<book-items
|
<a
|
||||||
:books="books"
|
href="https://github.com/gedoor/legado_web_bookshelf"
|
||||||
@bookClick="handleBookClick"
|
target="_blank"
|
||||||
:isSearch="isSearching"
|
>
|
||||||
></book-items>
|
<div class="bottom-icon">
|
||||||
|
<img :src="githubUrl" alt="" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shelf-wrapper" ref="shelfWrapper">
|
||||||
|
<book-items
|
||||||
|
:books="books"
|
||||||
|
@bookClick="handleBookClick"
|
||||||
|
:isSearch="isSearching"
|
||||||
|
></book-items>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ const readingRecent = ref({
|
|||||||
const shelfWrapper = ref(null);
|
const shelfWrapper = ref(null);
|
||||||
const { showLoading, closeLoading, loadingWrapper, isLoading } = useLoading(
|
const { showLoading, closeLoading, loadingWrapper, isLoading } = useLoading(
|
||||||
shelfWrapper,
|
shelfWrapper,
|
||||||
"正在获取书籍信息"
|
"正在获取书籍信息",
|
||||||
);
|
);
|
||||||
|
|
||||||
// 书架书籍和在线书籍搜索
|
// 书架书籍和在线书籍搜索
|
||||||
@@ -145,7 +147,7 @@ const searchBook = () => {
|
|||||||
if (books.value.length == 0) {
|
if (books.value.length == 0) {
|
||||||
ElMessage.info("搜索结果为空");
|
ElMessage.info("搜索结果为空");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -171,7 +173,7 @@ const setIP = () => {
|
|||||||
// instance.inputValue
|
// instance.inputValue
|
||||||
const ip = instance.inputValue;
|
const ip = instance.inputValue;
|
||||||
API.testLeagdoHttpUrlConnection("http://" + ip)
|
API.testLeagdoHttpUrlConnection("http://" + ip)
|
||||||
//API.getBookShelf()
|
//API.getBookShelf()
|
||||||
.then(function (configStr) {
|
.then(function (configStr) {
|
||||||
saveReadConfig(configStr);
|
saveReadConfig(configStr);
|
||||||
instance.confirmButtonLoading = false;
|
instance.confirmButtonLoading = false;
|
||||||
@@ -182,7 +184,7 @@ const setIP = () => {
|
|||||||
API.setLeagdoHttpUrl("http://" + ip);
|
API.setLeagdoHttpUrl("http://" + ip);
|
||||||
//持久化
|
//持久化
|
||||||
localStorage.setItem("remoteIp", ip);
|
localStorage.setItem("remoteIp", ip);
|
||||||
fetchBookShelfData()
|
fetchBookShelfData();
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
@@ -196,7 +198,7 @@ const setIP = () => {
|
|||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,13 +212,20 @@ const handleBookClick = async (book) => {
|
|||||||
durChapterPos = 0,
|
durChapterPos = 0,
|
||||||
} = book;
|
} = book;
|
||||||
// 判断是否为 searchBook
|
// 判断是否为 searchBook
|
||||||
const isSeachBook = "respondTime" in book
|
const isSeachBook = "respondTime" in book;
|
||||||
if (isSeachBook) {
|
if (isSeachBook) {
|
||||||
await API.saveBook(book);
|
await API.saveBook(book);
|
||||||
}
|
}
|
||||||
toDetail(bookUrl, name, author, durChapterIndex, durChapterPos, isSeachBook);
|
toDetail(bookUrl, name, author, durChapterIndex, durChapterPos, isSeachBook);
|
||||||
};
|
};
|
||||||
const toDetail = (bookUrl, bookName, bookAuthor, chapterIndex, chapterPos, isSeachBook) => {
|
const toDetail = (
|
||||||
|
bookUrl,
|
||||||
|
bookName,
|
||||||
|
bookAuthor,
|
||||||
|
chapterIndex,
|
||||||
|
chapterPos,
|
||||||
|
isSeachBook,
|
||||||
|
) => {
|
||||||
if (bookName === "尚无阅读记录") return;
|
if (bookName === "尚无阅读记录") return;
|
||||||
sessionStorage.setItem("bookUrl", bookUrl);
|
sessionStorage.setItem("bookUrl", bookUrl);
|
||||||
sessionStorage.setItem("bookName", bookName);
|
sessionStorage.setItem("bookName", bookName);
|
||||||
@@ -242,37 +251,36 @@ const loadShelf = () => {
|
|||||||
store
|
store
|
||||||
.saveBookProgress()
|
.saveBookProgress()
|
||||||
//确保各种网络情况下同步请求先完成
|
//确保各种网络情况下同步请求先完成
|
||||||
.finally(fetchBookShelfData)
|
.finally(fetchBookShelfData),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveReadConfig = configStr => {
|
const saveReadConfig = (configStr) => {
|
||||||
try {
|
try {
|
||||||
store.setConfig(JSON.parse(configStr));
|
store.setConfig(JSON.parse(configStr));
|
||||||
} catch {
|
} catch {
|
||||||
ElMessage.info("阅读界面解析错误");
|
ElMessage.info("阅读界面解析错误");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const fetchBookShelfData = () => {
|
const fetchBookShelfData = () => {
|
||||||
return API.getBookShelf()
|
return API.getBookShelf().then((response) => {
|
||||||
.then((response) => {
|
store.setConnectType("success");
|
||||||
store.setConnectType("success");
|
if (response.data.isSuccess) {
|
||||||
if (response.data.isSuccess) {
|
//store.increaseBookNum(response.data.data.length);
|
||||||
//store.increaseBookNum(response.data.data.length);
|
store.addBooks(
|
||||||
store.addBooks(
|
response.data.data.sort(function (a, b) {
|
||||||
response.data.data.sort(function (a, b) {
|
var x = a["durChapterTime"] || 0;
|
||||||
var x = a["durChapterTime"] || 0;
|
var y = b["durChapterTime"] || 0;
|
||||||
var y = b["durChapterTime"] || 0;
|
return y - x;
|
||||||
return y - x;
|
}),
|
||||||
})
|
);
|
||||||
);
|
} else {
|
||||||
} else {
|
ElMessage.error(response.data.errorMsg ?? "后端返回格式错误!");
|
||||||
ElMessage.error(response.data.errorMsg ?? "后端返回格式错误!");
|
}
|
||||||
}
|
store.setConnectStatus("已连接 " + API.legado_http_origin);
|
||||||
store.setConnectStatus("已连接 " + API.legado_http_origin);
|
store.setNewConnect(false);
|
||||||
store.setNewConnect(false);
|
});
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -285,17 +293,16 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
API.testLeagdoHttpUrlConnection()
|
API.testLeagdoHttpUrlConnection()
|
||||||
//.then(saveReadConfig) 应该在组件挂载前读取阅读配置
|
//.then(saveReadConfig) 应该在组件挂载前读取阅读配置
|
||||||
.then(loadShelf)
|
.then(loadShelf)
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
store.setConnectType("danger");
|
store.setConnectType("danger");
|
||||||
store.setConnectStatus("连接异常");
|
store.setConnectStatus("连接异常");
|
||||||
ElMessage.error("后端连接失败异常,请检查阅读WEB服务或者设置其它可用IP")
|
ElMessage.error("后端连接失败异常,请检查阅读WEB服务或者设置其它可用IP");
|
||||||
store.setNewConnect(false);
|
store.setNewConnect(false);
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import bookSourceConfig from "@/config/bookSourceEditConfig";
|
import bookSourceConfig from "@/config/bookSourceEditConfig";
|
||||||
import rssSourceConfig from "@/config/rssSourceEditConfig";
|
import rssSourceConfig from "@/config/rssSourceEditConfig";
|
||||||
import "@/assets/sourceeditor.css"
|
import "@/assets/sourceeditor.css";
|
||||||
import { useDark } from "@vueuse/core";
|
import { useDark } from "@vueuse/core";
|
||||||
|
|
||||||
useDark();
|
useDark();
|
||||||
|
|||||||
Reference in New Issue
Block a user