mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 23:56:42 +08:00
优化浏览器警告
This commit is contained in:
Generated
-16626
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@ export const checkPWAStatus = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检测是否为移动设备
|
// 检测是否为移动设备
|
||||||
const isMobileDevice = (): boolean => {
|
export const isMobileDevice = (): boolean => {
|
||||||
// 检查用户代理字符串
|
// 检查用户代理字符串
|
||||||
const userAgent = navigator.userAgent || ''
|
const userAgent = navigator.userAgent || ''
|
||||||
const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i
|
const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i
|
||||||
|
|||||||
@@ -48,16 +48,18 @@ const getImgUrl = computed(() => {
|
|||||||
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<VCardText
|
<template #default>
|
||||||
class="w-full flex flex-col flex-wrap justify-end align-left text-white absolute bottom-0 cursor-pointer pa-2"
|
<VCardText
|
||||||
>
|
class="w-full flex flex-col flex-wrap justify-end align-left text-white absolute bottom-0 cursor-pointer pa-2"
|
||||||
<h1
|
|
||||||
class="mb-1 text-white text-shadow font-extrabold text-xl line-clamp-2 overflow-hidden text-ellipsis ..."
|
|
||||||
>
|
>
|
||||||
{{ props.media?.title }}
|
<h1
|
||||||
</h1>
|
class="mb-1 text-white text-shadow font-extrabold text-xl line-clamp-2 overflow-hidden text-ellipsis ..."
|
||||||
<span class="text-shadow">{{ props.media?.subtitle }}</span>
|
>
|
||||||
</VCardText>
|
{{ props.media?.title }}
|
||||||
|
</h1>
|
||||||
|
<span class="text-shadow">{{ props.media?.subtitle }}</span>
|
||||||
|
</VCardText>
|
||||||
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
</template>
|
</template>
|
||||||
<div class="w-full absolute bottom-0">
|
<div class="w-full absolute bottom-0">
|
||||||
|
|||||||
@@ -170,13 +170,15 @@ onMounted(async () => {
|
|||||||
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<VCardText
|
<template #default>
|
||||||
class="w-full flex flex-col flex-wrap justify-end align-center text-white absolute bottom-0 cursor-pointer pa-2"
|
<VCardText
|
||||||
>
|
class="w-full flex flex-col flex-wrap justify-end align-center text-white absolute bottom-0 cursor-pointer pa-2"
|
||||||
<h1 class="mb-1 text-white text-shadow font-bold line-clamp-2 overflow-hidden text-ellipsis ...">
|
>
|
||||||
{{ props.media?.name }}
|
<h1 class="mb-1 text-white text-shadow font-bold line-clamp-2 overflow-hidden text-ellipsis ...">
|
||||||
</h1>
|
{{ props.media?.name }}
|
||||||
</VCardText>
|
</h1>
|
||||||
|
</VCardText>
|
||||||
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
</template>
|
</template>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|||||||
@@ -170,7 +170,9 @@ const iconPath: Ref<string> = computed(() => {
|
|||||||
if (imageLoadError.value) return noImage
|
if (imageLoadError.value) return noImage
|
||||||
// 如果是网络图片则使用代理后返回
|
// 如果是网络图片则使用代理后返回
|
||||||
if (props.plugin?.plugin_icon?.startsWith('http'))
|
if (props.plugin?.plugin_icon?.startsWith('http'))
|
||||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(props.plugin?.plugin_icon)}&cache=true`
|
return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(
|
||||||
|
props.plugin?.plugin_icon,
|
||||||
|
)}&cache=true`
|
||||||
|
|
||||||
return `./plugin_icon/${props.plugin?.plugin_icon}`
|
return `./plugin_icon/${props.plugin?.plugin_icon}`
|
||||||
})
|
})
|
||||||
@@ -475,7 +477,9 @@ watch(
|
|||||||
<div class="flex flex-nowrap items-center w-full pe-10">
|
<div class="flex flex-nowrap items-center w-full pe-10">
|
||||||
<div class="flex flex-nowrap max-w-40 items-center align-middle">
|
<div class="flex flex-nowrap max-w-40 items-center align-middle">
|
||||||
<VImg :src="authorPath" class="author-avatar" @load="isAvatarLoaded = true">
|
<VImg :src="authorPath" class="author-avatar" @load="isAvatarLoaded = true">
|
||||||
<VIcon v-if="!isAvatarLoaded" size="small" icon="mdi-github" class="me-1" />
|
<template #default>
|
||||||
|
<VIcon v-if="!isAvatarLoaded" size="small" icon="mdi-github" class="me-1" />
|
||||||
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
<a
|
<a
|
||||||
:href="props.plugin?.author_url"
|
:href="props.plugin?.author_url"
|
||||||
|
|||||||
@@ -346,7 +346,9 @@ function onSubscribeEditRemove() {
|
|||||||
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="absolute inset-0 outline-none subscribe-card-background"></div>
|
<template #default>
|
||||||
|
<div class="absolute inset-0 outline-none subscribe-card-background"></div>
|
||||||
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
<div
|
<div
|
||||||
v-if="subscribeState === 'P'"
|
v-if="subscribeState === 'P'"
|
||||||
|
|||||||
@@ -121,7 +121,9 @@ function doDelete() {
|
|||||||
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="absolute inset-0 subscribe-card-background"></div>
|
<template #default>
|
||||||
|
<div class="absolute inset-0 subscribe-card-background"></div>
|
||||||
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
</template>
|
</template>
|
||||||
<div class="h-full flex flex-col">
|
<div class="h-full flex flex-col">
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ async function doDelete() {
|
|||||||
<template>
|
<template>
|
||||||
<VDialog max-width="40rem" scrollable>
|
<VDialog max-width="40rem" scrollable>
|
||||||
<VCard>
|
<VCard>
|
||||||
<VDialogCloseBtn @click="emit('close')" />
|
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<VCol>
|
<VCol>
|
||||||
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
|
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
|
||||||
@@ -242,6 +241,7 @@ async function doDelete() {
|
|||||||
</div>
|
</div>
|
||||||
</VCol>
|
</VCol>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
|
<VDialogCloseBtn @click="emit('close')" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useTabStateRestore } from '@/composables/useStateRestore'
|
import { useTabStateRestore } from '@/composables/useStateRestore'
|
||||||
|
import { isMobileDevice } from '@/@core/utils/navigator'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@@ -77,6 +78,11 @@ const scrollTabs = (direction: 'left' | 'right') => {
|
|||||||
left: scrollPosition,
|
left: scrollPosition,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 滚动完成后更新指示器状态
|
||||||
|
setTimeout(() => {
|
||||||
|
updateTabsIndicator()
|
||||||
|
}, 300) // 等待滚动动画完成
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to check and update the indicator state
|
// Function to check and update the indicator state
|
||||||
@@ -84,14 +90,17 @@ const updateTabsIndicator = () => {
|
|||||||
const el = tabsContainerRef.value
|
const el = tabsContainerRef.value
|
||||||
if (!el) return
|
if (!el) return
|
||||||
|
|
||||||
|
// 在移动端不显示滚动指示器
|
||||||
|
const isMobile = isMobileDevice()
|
||||||
|
|
||||||
const tolerance = 1 // Allow 1px tolerance
|
const tolerance = 1 // Allow 1px tolerance
|
||||||
const hasOverflow = el.scrollWidth > el.clientWidth + tolerance
|
const hasOverflow = el.scrollWidth > el.clientWidth + tolerance
|
||||||
const isScrolledToEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - tolerance
|
const isScrolledToEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - tolerance
|
||||||
const isScrolledToStart = el.scrollLeft <= tolerance
|
const isScrolledToStart = el.scrollLeft <= tolerance
|
||||||
|
|
||||||
showTabsScrollIndicator.value = hasOverflow && !isScrolledToEnd
|
showTabsScrollIndicator.value = hasOverflow && !isScrolledToEnd && !isMobile
|
||||||
showLeftButton.value = hasOverflow && !isScrolledToStart
|
showLeftButton.value = hasOverflow && !isScrolledToStart && !isMobile
|
||||||
showRightButton.value = hasOverflow && !isScrolledToEnd
|
showRightButton.value = hasOverflow && !isScrolledToEnd && !isMobile
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debounce resize handler
|
// Debounce resize handler
|
||||||
@@ -106,6 +115,8 @@ const handleResize = () => {
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// Add resize listener for tabs indicator
|
// Add resize listener for tabs indicator
|
||||||
window.addEventListener('resize', handleResize)
|
window.addEventListener('resize', handleResize)
|
||||||
|
// Add scroll listener for tabs container
|
||||||
|
tabsContainerRef.value?.addEventListener('scroll', updateTabsIndicator)
|
||||||
// Initial check for tabs indicator after DOM update
|
// Initial check for tabs indicator after DOM update
|
||||||
await nextTick() // Ensure element is rendered
|
await nextTick() // Ensure element is rendered
|
||||||
updateTabsIndicator()
|
updateTabsIndicator()
|
||||||
@@ -173,6 +184,11 @@ onUnmounted(() => {
|
|||||||
&.right-button {
|
&.right-button {
|
||||||
margin-inline-start: 6px;
|
margin-inline-start: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在移动端隐藏滚动按钮
|
||||||
|
@media (width <= 768px) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-tabs {
|
.header-tabs {
|
||||||
@@ -209,6 +225,18 @@ onUnmounted(() => {
|
|||||||
pointer-events: none; // Allow interaction with content behind it
|
pointer-events: none; // Allow interaction with content behind it
|
||||||
transition: opacity 0.2s ease-in-out;
|
transition: opacity 0.2s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show indicator when class is applied
|
||||||
|
&.show-indicator::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在移动端隐藏渐变指示器
|
||||||
|
@media (width <= 768px) {
|
||||||
|
&::after {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-tab-icon {
|
.header-tab-icon {
|
||||||
|
|||||||
Reference in New Issue
Block a user