mirror of
https://github.com/gedoor/legado.git
synced 2024-07-06 23:47:49 +08:00
fix(web): 修复进度同步和返回书架同步
This commit is contained in:
parent
271aa770b1
commit
02a215202c
@ -12,6 +12,10 @@
|
||||
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
||||
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
||||
|
||||
**2023/05/09**
|
||||
|
||||
* web: 修复进度同步
|
||||
|
||||
**2023/05/08**
|
||||
|
||||
* 更新cronet: 113.0.5672.76
|
||||
|
@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div class="title">{{ title }}</div>
|
||||
<div v-for="(para, index) in carray" :key="index">
|
||||
<div class="title" wordCount="0">{{ title }}</div>
|
||||
<div
|
||||
v-for="(para, index) in contents"
|
||||
:key="index"
|
||||
:wordCount="calculateWordCount(para)"
|
||||
>
|
||||
<img
|
||||
class="full"
|
||||
v-if="/^\s*<img[^>]*src[^>]+>$/.test(para)"
|
||||
@ -8,34 +12,19 @@
|
||||
@error.once="proxyImage"
|
||||
loading="lazy"
|
||||
/>
|
||||
<p v-else :style="style" v-html="para" />
|
||||
<p v-else :style="{ fontFamily, fontSize }" v-html="para" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import config from "../plugins/config";
|
||||
import { getImageFromLegado, isLegadoUrl } from "../plugins/utils";
|
||||
import { getImageFromLegado, isLegadoUrl } from "@/plugins/utils";
|
||||
|
||||
const store = useBookStore();
|
||||
const props = defineProps({
|
||||
carray: { type: Array, required: true },
|
||||
contents: { type: Array, required: true },
|
||||
title: { type: String, required: true },
|
||||
spacing: { type: Object, required: true },
|
||||
});
|
||||
|
||||
const fontFamily = computed(() => {
|
||||
if (store.config.font >= 0) {
|
||||
return config.fonts[store.config.font];
|
||||
}
|
||||
return { fontFamily: store.config.customFontName };
|
||||
});
|
||||
const fontSize = computed(() => {
|
||||
return store.config.fontSize + "px";
|
||||
});
|
||||
const style = computed(() => {
|
||||
let style = fontFamily.value;
|
||||
style.fontSize = fontSize.value;
|
||||
return style;
|
||||
fontFamily: { type: String, required: true },
|
||||
fontSize: { type: String, required: true },
|
||||
});
|
||||
|
||||
const getImageSrc = (content) => {
|
||||
@ -48,16 +37,13 @@ const proxyImage = (event) => {
|
||||
event.target.src = getImageFromLegado(event.target.src);
|
||||
};
|
||||
|
||||
watch(fontSize, () => {
|
||||
store.setShowContent(false);
|
||||
nextTick(() => {
|
||||
store.setShowContent(true);
|
||||
});
|
||||
});
|
||||
const calculateWordCount = (paragraph) => {
|
||||
const imgPattern = /<img[^>]*src="[^"]*(?:"[^>]+\})?"[^>]*>/g;
|
||||
//内嵌图片文字为1
|
||||
const imagePlaceHolder = " ";
|
||||
return paragraph.trim().replaceAll(imgPattern, imagePlaceHolder).length;
|
||||
};
|
||||
|
||||
const letterSpacing = computed(() => props.spacing.letter); //字间距 倍数
|
||||
const lineSpacing = computed(() => 1 + props.spacing.line); //行距 基础行距1
|
||||
const paragraphSpacing = computed(() => props.spacing.paragraph); //段距
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -72,9 +58,9 @@ p {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
|
||||
letter-spacing: calc(v-bind("letterSpacing") * 1em);
|
||||
line-height: v-bind("lineSpacing");
|
||||
margin: calc(v-bind("paragraphSpacing") * 1em) 0;
|
||||
letter-spacing: calc(v-bind("props.spacing.letter") * 1em);
|
||||
line-height: calc(1 + v-bind("props.spacing.line"));
|
||||
margin: calc(v-bind("props.spacing.paragraph") * 1em) 0;
|
||||
|
||||
:deep(img) {
|
||||
height: 1em;
|
||||
|
@ -55,16 +55,11 @@ var settings = {
|
||||
},
|
||||
],
|
||||
fonts: [
|
||||
{
|
||||
fontFamily:
|
||||
"Microsoft YaHei, PingFangSC-Regular, HelveticaNeue-Light, Helvetica Neue Light, sans-serif",
|
||||
},
|
||||
{
|
||||
fontFamily: "PingFangSC-Regular, -apple-system, Simsun",
|
||||
},
|
||||
{
|
||||
fontFamily: "Kaiti",
|
||||
},
|
||||
"Microsoft YaHei, PingFangSC-Regular, HelveticaNeue-Light, Helvetica Neue Light, sans-serif",
|
||||
|
||||
"PingFangSC-Regular, -apple-system, Simsun",
|
||||
|
||||
"Kaiti",
|
||||
],
|
||||
};
|
||||
export default settings;
|
||||
|
@ -81,11 +81,18 @@
|
||||
<div class="chapter" ref="content" :style="chapterTheme">
|
||||
<div class="content">
|
||||
<div class="top-bar" ref="top"></div>
|
||||
<div v-for="data in chapterData" :key="data.index" ref="chapter">
|
||||
<div
|
||||
v-for="data in chapterData"
|
||||
:key="data.index"
|
||||
:chapterIndex="data.index"
|
||||
ref="chapter"
|
||||
>
|
||||
<chapter-content
|
||||
:carray="data.content"
|
||||
:contents="data.content"
|
||||
:title="data.title"
|
||||
:spacing="store.config.spacing"
|
||||
:fontSize="fontSize"
|
||||
:fontFamily="fontFamily"
|
||||
v-if="showContent"
|
||||
/>
|
||||
</div>
|
||||
@ -124,10 +131,9 @@ try {
|
||||
} catch {
|
||||
localStorage.removeItem("config");
|
||||
}
|
||||
|
||||
const loading = ref();
|
||||
|
||||
const noPoint = ref(true);
|
||||
|
||||
const showToolBar = ref(false);
|
||||
const chapterData = ref([]);
|
||||
const scrollObserve = ref(null);
|
||||
@ -139,11 +145,32 @@ const {
|
||||
readSettingsVisible,
|
||||
miniInterface,
|
||||
showContent,
|
||||
config,
|
||||
readingBook,
|
||||
} = storeToRefs(store);
|
||||
|
||||
const { chapterPos, index: chapterIndex } = toRefs(store.readingBook);
|
||||
const chapterPos = computed({
|
||||
get: () => readingBook.value.chapterPos,
|
||||
set: (value) => (readingBook.value.chapterPos = value),
|
||||
});
|
||||
const chapterIndex = computed({
|
||||
get: () => readingBook.value.index,
|
||||
set: (value) => (readingBook.value.index = value),
|
||||
});
|
||||
|
||||
const { theme, infiniteLoading } = toRefs(store.config);
|
||||
const theme = computed(() => config.value.theme);
|
||||
const infiniteLoading = computed(() => config.value.infiniteLoading);
|
||||
|
||||
// 字体
|
||||
const fontFamily = computed(() => {
|
||||
if (store.config.font >= 0) {
|
||||
return settings.fonts[store.config.font];
|
||||
}
|
||||
return store.config.customFontName;
|
||||
});
|
||||
const fontSize = computed(() => {
|
||||
return store.config.fontSize + "px";
|
||||
});
|
||||
|
||||
// 主题部分
|
||||
const bodyColor = computed(() => settings.themes[theme.value].body);
|
||||
@ -193,10 +220,7 @@ const rightBarTheme = computed(() => {
|
||||
display: miniInterface.value && !showToolBar.value ? "none" : "block",
|
||||
};
|
||||
});
|
||||
const isNight = ref(false);
|
||||
watchEffect(() => {
|
||||
isNight.value = theme.value == 6;
|
||||
});
|
||||
const isNight = computed(() => theme.value == 6);
|
||||
|
||||
watchEffect(() => {
|
||||
if (chapterData.value.length > 0) {
|
||||
@ -239,6 +263,7 @@ const getContent = (index, reloadChapter = true, chapterPos = 0) => {
|
||||
let data = res.data.data;
|
||||
let content = data.split(/\n+/);
|
||||
updateChapterData({ index, content, title }, reloadChapter);
|
||||
toChapterPos(chapterPos);
|
||||
} else {
|
||||
ElMessage({ message: res.data.errorMsg, type: "error" });
|
||||
let content = [res.data.errorMsg];
|
||||
@ -263,39 +288,32 @@ const getContent = (index, reloadChapter = true, chapterPos = 0) => {
|
||||
);
|
||||
};
|
||||
const chapter = ref();
|
||||
const toChapterPos = (chapterPos) => {
|
||||
if (!chapterPos) return;
|
||||
const toChapterPos = (pos) => {
|
||||
nextTick(() => {
|
||||
//计算chapterPos对应的段落行数
|
||||
let wordCount = 0;
|
||||
let index = chapterData.value[0].content.findIndex((paragraph) => {
|
||||
wordCount += paragraph.length;
|
||||
return wordCount >= chapterPos.value;
|
||||
});
|
||||
if (index == -1) index = chapterData.value[0].content.length - 1;
|
||||
if (index == 0) return; //第一行不跳转
|
||||
//跳转
|
||||
jump(chapter.value[0].children[1].children[index], {
|
||||
duration: 0,
|
||||
callback: () => (chapterPos.value = 0),
|
||||
});
|
||||
for (let element of chapter.value[0].children) {
|
||||
wordCount += parseInt(element.getAttribute("wordCount"));
|
||||
if (wordCount >= pos) {
|
||||
jump(element, {
|
||||
duration: 0,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
//计算当前章节阅读的字数
|
||||
const computeChapterPos = () => {
|
||||
//dom没渲染时 返回0
|
||||
if (!chapter.value[0]) return;
|
||||
if (chapter.value.length == 0) return;
|
||||
//计算当前阅读进度对应的element
|
||||
let index = chapterData.value.findIndex(
|
||||
(chapter) => chapter.index == chapterIndex.value
|
||||
let chapterElement = chapter.value.find(
|
||||
(element) => element.getAttribute("chapterIndex") == chapterIndex.value
|
||||
);
|
||||
if (index == -1) return;
|
||||
let element = chapter.value[index].children[1].children;
|
||||
if (!chapterElement) return;
|
||||
//计算已读字数
|
||||
let mChapterPos = 0;
|
||||
for (let paragraph of element) {
|
||||
let text = paragraph.innerText;
|
||||
mChapterPos += text.length;
|
||||
for (let paragraph of chapterElement.children) {
|
||||
mChapterPos += parseInt(paragraph.getAttribute("wordCount"));
|
||||
if (paragraph.getBoundingClientRect().top >= 0) {
|
||||
chapterPos.value = mChapterPos;
|
||||
break;
|
||||
@ -431,9 +449,7 @@ const handleIScrollObserve = (entries) => {
|
||||
const handleIReadingObserve = (entries) => {
|
||||
nextTick(() => {
|
||||
for (let { isIntersecting, target, boundingClientRect } of entries) {
|
||||
let titleElement = target.querySelector(".title");
|
||||
if (!titleElement) return;
|
||||
let chapterTitleIndex = parseInt(titleElement.getAttribute("index"));
|
||||
let chapterTitleIndex = parseInt(target.getAttribute("chapterIndex"));
|
||||
if (isIntersecting) {
|
||||
chapterIndex.value = chapterTitleIndex;
|
||||
} else {
|
||||
@ -454,17 +470,13 @@ const addReadingObserve = () => {
|
||||
chapterElements.forEach((el) => readingObserve.value.observe(el));
|
||||
});
|
||||
};
|
||||
/*
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
if (
|
||||
store.searchBooks.every((book) => book.bookUrl != store.readingBook.bookUrl)
|
||||
) {
|
||||
next();
|
||||
} else {
|
||||
alert(111);
|
||||
next(false);
|
||||
}
|
||||
computeChapterPos();
|
||||
saveReadingBookProgressToBrowser(chapterIndex.value);
|
||||
next();
|
||||
});
|
||||
/*
|
||||
window.addEventListener("beforeunload", (e) => {
|
||||
e.preventDefault();
|
||||
e.returnValue = "";
|
||||
@ -508,7 +520,6 @@ onMounted(() => {
|
||||
store.setReadingBook(book);
|
||||
|
||||
getContent(chapterIndex, true, chapterPos);
|
||||
|
||||
window.addEventListener("keyup", handleKeyPress);
|
||||
//监听底部加载
|
||||
scrollObserve.value = new IntersectionObserver(handleIScrollObserve, {
|
||||
|
@ -197,7 +197,7 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
showLoading.value = true;
|
||||
//await store.saveBookProcess();
|
||||
await store.saveBookProcess();
|
||||
fetchBookShelfData();
|
||||
});
|
||||
const fetchBookShelfData = () => {
|
||||
|
Loading…
Reference in New Issue
Block a user