fix: web书籍部分图片加载失败
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
"ComponentPublicInstance": true,
|
"ComponentPublicInstance": true,
|
||||||
"ComputedRef": true,
|
"ComputedRef": true,
|
||||||
"EffectScope": true,
|
"EffectScope": true,
|
||||||
|
"ElLoading": true,
|
||||||
"ElMessage": true,
|
"ElMessage": true,
|
||||||
"InjectionKey": true,
|
"InjectionKey": true,
|
||||||
"PropType": true,
|
"PropType": true,
|
||||||
|
|||||||
Vendored
+1
@@ -5,6 +5,7 @@
|
|||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
const EffectScope: typeof import('vue')['EffectScope']
|
const EffectScope: typeof import('vue')['EffectScope']
|
||||||
|
const ElLoading: typeof import('element-plus/es')['ElLoading']
|
||||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
||||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||||
const computed: typeof import('vue')['computed']
|
const computed: typeof import('vue')['computed']
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div
|
<div
|
||||||
class="book"
|
class="book"
|
||||||
v-for="book in props.books"
|
v-for="book in books"
|
||||||
:key="book.bookUrl"
|
:key="book.bookUrl"
|
||||||
@click="handleClick(book)"
|
@click="handleClick(book)"
|
||||||
>
|
>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<div class="author">
|
<div class="author">
|
||||||
{{ book.author }}
|
{{ book.author }}
|
||||||
</div>
|
</div>
|
||||||
<div class="tags" v-show="props.isSearch">
|
<div class="tags" v-show="isSearch">
|
||||||
<el-tag
|
<el-tag
|
||||||
v-for="tag in book.kind?.split(',').slice(0, 2)"
|
v-for="tag in book.kind?.split(',').slice(0, 2)"
|
||||||
:key="tag"
|
:key="tag"
|
||||||
@@ -30,16 +30,16 @@
|
|||||||
{{ tag }}
|
{{ tag }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="update-info" v-show="!props.isSearch">
|
<div class="update-info" v-show="!isSearch">
|
||||||
<div class="dot">•</div>
|
<div class="dot">•</div>
|
||||||
<div class="size">共{{ book.totalChapterNum }}章</div>
|
<div class="size">共{{ book.totalChapterNum }}章</div>
|
||||||
<div class="dot">•</div>
|
<div class="dot">•</div>
|
||||||
<div class="date">{{ dateFormat(book.lastCheckTime) }}</div>
|
<div class="date">{{ dateFormat(book.lastCheckTime) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="intro" v-show="props.isSearch">{{ book.intro }}</div>
|
<div class="intro" v-show="isSearch">{{ book.intro }}</div>
|
||||||
|
|
||||||
<div class="dur-chapter" v-show="!props.isSearch">
|
<div class="dur-chapter" v-show="!isSearch">
|
||||||
已读:{{ book.durChapterTitle }}
|
已读:{{ book.durChapterTitle }}
|
||||||
</div>
|
</div>
|
||||||
<div class="last-chapter">最新:{{ book.latestChapterTitle }}</div>
|
<div class="last-chapter">最新:{{ book.latestChapterTitle }}</div>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-for="(para, index) in props.carray" :key="index">
|
<div v-for="(para, index) in carray" :key="index">
|
||||||
<img
|
<img
|
||||||
class="full"
|
class="full"
|
||||||
v-if="/^\s*<img[^>]*src[^>]+>$/.test(para)"
|
v-if="/^\s*<img[^>]*src[^>]+>$/.test(para)"
|
||||||
:src="getImageSrc(para)"
|
:src="getImageSrc(para)"
|
||||||
|
@error.once="proxyImage"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<p v-else :style="style" v-html="para" />
|
<p v-else :style="style" v-html="para" />
|
||||||
@@ -12,8 +13,10 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import config from "../plugins/config";
|
import config from "../plugins/config";
|
||||||
|
import { getImageFromLegado, isLegadoUrl } from "../plugins/utils";
|
||||||
|
|
||||||
const store = useBookStore();
|
const store = useBookStore();
|
||||||
const props = defineProps(["carray"]);
|
defineProps(["carray"]);
|
||||||
|
|
||||||
const fontFamily = computed(() => {
|
const fontFamily = computed(() => {
|
||||||
if (store.config.font >= 0) {
|
if (store.config.font >= 0) {
|
||||||
@@ -30,10 +33,15 @@ const style = computed(() => {
|
|||||||
return style;
|
return style;
|
||||||
});
|
});
|
||||||
|
|
||||||
function getImageSrc(content) {
|
const getImageSrc = (content) => {
|
||||||
const imgPattern = /<img[^>]*src="([^"]*(?:"[^>]+\})?)"[^>]*>/;
|
const imgPattern = /<img[^>]*src="([^"]*(?:"[^>]+\})?)"[^>]*>/;
|
||||||
return content.match(imgPattern)[1];
|
const src = content.match(imgPattern)[1];
|
||||||
}
|
if (isLegadoUrl(src)) return getImageFromLegado(src);
|
||||||
|
return src;
|
||||||
|
};
|
||||||
|
const proxyImage = (event) => {
|
||||||
|
event.target.src = getImageFromLegado(event.target.src);
|
||||||
|
};
|
||||||
|
|
||||||
watch(fontSize, () => {
|
watch(fontSize, () => {
|
||||||
store.setShowContent(false);
|
store.setShowContent(false);
|
||||||
|
|||||||
@@ -11,12 +11,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
const { source } = defineProps(['source'])
|
defineProps(["source"]);
|
||||||
const store = useSourceStore()
|
const store = useSourceStore();
|
||||||
const { errorPushSources } = storeToRefs(store)
|
const { errorPushSources } = storeToRefs(store);
|
||||||
const handleSourceClick = source => {
|
const handleSourceClick = (source) => {
|
||||||
store.changeCurrentSource(source)
|
store.changeCurrentSource(source);
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.error {
|
.error {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-checkbox-group id="source-list" v-model="sourceSelect">
|
<el-checkbox-group id="source-list" v-model="sourceSelect">
|
||||||
<virtual-list
|
<virtual-list
|
||||||
style="height: 100%; overflow-y: auto; overflow-x: hidden;"
|
style="height: 100%; overflow-y: auto; overflow-x: hidden"
|
||||||
:data-key="(source) => source.bookSourceUrl || source.sourceUrl"
|
:data-key="(source) => source.bookSourceUrl || source.sourceUrl"
|
||||||
:data-sources="sourcesFiltered"
|
:data-sources="sourcesFiltered"
|
||||||
:data-component="SourceItem"
|
:data-component="SourceItem"
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Folder, Delete, Download, Search } from "@element-plus/icons-vue";
|
import { Folder, Delete, Download, Search } from "@element-plus/icons-vue";
|
||||||
import { isSourceContains } from "../utils/souce";
|
import { isSourceContains } from "../utils/souce";
|
||||||
import VirtualList from 'vue3-virtual-scroll-list';
|
import VirtualList from "vue3-virtual-scroll-list";
|
||||||
import SourceItem from "./SourceItem.vue";
|
import SourceItem from "./SourceItem.vue";
|
||||||
|
|
||||||
const store = useSourceStore();
|
const store = useSourceStore();
|
||||||
@@ -98,7 +98,10 @@ const importSourceFile = () => {
|
|||||||
};
|
};
|
||||||
const outExport = () => {
|
const outExport = () => {
|
||||||
const exportFile = document.createElement("a");
|
const exportFile = document.createElement("a");
|
||||||
let sources = sourceSelect.value.length === 0 ? sourcesFiltered.value : sourceSelect.value,
|
let sources =
|
||||||
|
sourceSelect.value.length === 0
|
||||||
|
? sourcesFiltered.value
|
||||||
|
: sourceSelect.value,
|
||||||
sourceType = isBookSource.value ? "BookSource" : "RssSource";
|
sourceType = isBookSource.value ? "BookSource" : "RssSource";
|
||||||
|
|
||||||
exportFile.download = `${sourceType}_${Date()
|
exportFile.download = `${sourceType}_${Date()
|
||||||
@@ -129,5 +132,4 @@ const outExport = () => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-tabs id="source-edit">
|
<el-tabs id="source-edit">
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-for="{ name, children } in tabsData"
|
v-for="{ name, children } in Object.values(config)"
|
||||||
:label="name"
|
:label="name"
|
||||||
:key="name"
|
:key="name"
|
||||||
>
|
>
|
||||||
@@ -59,11 +59,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
const store = useSourceStore();
|
const store = useSourceStore();
|
||||||
|
defineProps(["config"]);
|
||||||
const props = defineProps(["config"]);
|
|
||||||
|
|
||||||
const tabsData = Object.values(props.config);
|
|
||||||
|
|
||||||
const { currentSource } = storeToRefs(store);
|
const { currentSource } = storeToRefs(store);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -73,11 +73,12 @@ import { isInvaildSource } from "../utils/souce";
|
|||||||
const store = useSourceStore();
|
const store = useSourceStore();
|
||||||
const pull = () => {
|
const pull = () => {
|
||||||
const loadingMsg = ElMessage({
|
const loadingMsg = ElMessage({
|
||||||
message: '加载中……',
|
message: "加载中……",
|
||||||
showClose: true,
|
showClose: true,
|
||||||
duration: 0
|
duration: 0,
|
||||||
})
|
});
|
||||||
API.getSources().then(({ data }) => {
|
API.getSources()
|
||||||
|
.then(({ data }) => {
|
||||||
if (data.isSuccess) {
|
if (data.isSuccess) {
|
||||||
store.changeTabName("editList");
|
store.changeTabName("editList");
|
||||||
store.saveSources(data.data);
|
store.saveSources(data.data);
|
||||||
@@ -91,7 +92,8 @@ const pull = () => {
|
|||||||
type: "error",
|
type: "error",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).finally(() => loadingMsg.close());
|
})
|
||||||
|
.finally(() => loadingMsg.close());
|
||||||
};
|
};
|
||||||
|
|
||||||
const push = () => {
|
const push = () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { formatDate } from "@vueuse/shared";
|
import { formatDate } from "@vueuse/shared";
|
||||||
|
|
||||||
export const isLegadoUrl = (/** @type {string} */ url) =>
|
export const isLegadoUrl = (/** @type {string} */ url) =>
|
||||||
/,\s*\s*\{/.test(url) ||
|
/,\s*\{/.test(url) ||
|
||||||
!(
|
!(
|
||||||
url.startsWith("http") ||
|
url.startsWith("http") ||
|
||||||
url.startsWith("data:") ||
|
url.startsWith("data:") ||
|
||||||
@@ -11,10 +11,6 @@ export const isLegadoUrl = (/** @type {string} */ url) =>
|
|||||||
* @param {string} src
|
* @param {string} src
|
||||||
*/
|
*/
|
||||||
export function getImageFromLegado(src) {
|
export function getImageFromLegado(src) {
|
||||||
//返回阅读代理的图片链接 已经代理的或者dataurl返回传入值
|
|
||||||
if (!isLegadoUrl(src)) {
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
(import.meta.env.VITE_API || location.origin) +
|
(import.meta.env.VITE_API || location.origin) +
|
||||||
"/image?path=" +
|
"/image?path=" +
|
||||||
|
|||||||
@@ -85,7 +85,7 @@
|
|||||||
<div class="title" :index="data.index" v-if="showContent">
|
<div class="title" :index="data.index" v-if="showContent">
|
||||||
{{ data.title }}
|
{{ data.title }}
|
||||||
</div>
|
</div>
|
||||||
<chapter-content :carray="data.content" v-if="showContent"/>
|
<chapter-content :carray="data.content" v-if="showContent" />
|
||||||
</div>
|
</div>
|
||||||
<div class="loading" ref="loading"></div>
|
<div class="loading" ref="loading"></div>
|
||||||
<div class="bottom-bar" ref="bottom"></div>
|
<div class="bottom-bar" ref="bottom"></div>
|
||||||
@@ -139,15 +139,13 @@ const {
|
|||||||
showContent,
|
showContent,
|
||||||
} = storeToRefs(store);
|
} = storeToRefs(store);
|
||||||
|
|
||||||
const { chapterPos, index: chapterIndex} = toRefs(store.readingBook);
|
const { chapterPos, index: chapterIndex } = toRefs(store.readingBook);
|
||||||
|
|
||||||
const { theme, infiniteLoading } = toRefs(store.config);
|
const { theme, infiniteLoading } = toRefs(store.config);
|
||||||
|
|
||||||
// 主题部分
|
// 主题部分
|
||||||
const bodyColor = computed(() => settings.themes[theme.value].body);
|
const bodyColor = computed(() => settings.themes[theme.value].body);
|
||||||
const chapterColor = computed(
|
const chapterColor = computed(() => settings.themes[theme.value].content);
|
||||||
() => settings.themes[theme.value].content
|
|
||||||
);
|
|
||||||
const popupColor = computed(() => settings.themes[theme.value].popup);
|
const popupColor = computed(() => settings.themes[theme.value].popup);
|
||||||
|
|
||||||
const readWidth = computed(() => {
|
const readWidth = computed(() => {
|
||||||
@@ -215,7 +213,6 @@ watch(popupColor, (color) => {
|
|||||||
rightBarTheme.value.background = color;
|
rightBarTheme.value.background = color;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (chapterData.value.length > 0) {
|
if (chapterData.value.length > 0) {
|
||||||
store.setContentLoading(false);
|
store.setContentLoading(false);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ const searchBook = () => {
|
|||||||
() => {
|
() => {
|
||||||
showLoading.value = false;
|
showLoading.value = false;
|
||||||
if (books.value.length == 0) {
|
if (books.value.length == 0) {
|
||||||
ElMessage.info("搜索结果为空")
|
ElMessage.info("搜索结果为空");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -224,7 +224,7 @@ const fetchBookShelfData = () => {
|
|||||||
showLoading.value = false;
|
showLoading.value = false;
|
||||||
store.setConnectType("danger");
|
store.setConnectType("danger");
|
||||||
store.setConnectStatus("连接失败");
|
store.setConnectStatus("连接失败");
|
||||||
ElMessage.error("后端连接失败")
|
ElMessage.error("后端连接失败");
|
||||||
store.setNewConnect(false);
|
store.setNewConnect(false);
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,10 +34,5 @@ if (/bookSource/i.test(location.href)) {
|
|||||||
width: 360px;
|
width: 360px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
#loading {
|
|
||||||
position: fixed;
|
|
||||||
top: 100px;
|
|
||||||
left: 90vw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user