mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-12 00:54:42 +08:00
feat: 更新多个组件的背景样式为透明度背景
This commit is contained in:
@@ -593,7 +593,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
.media-card-placeholder {
|
||||
aspect-ratio: 2 / 3;
|
||||
background: rgb(var(--v-theme-surface-variant));
|
||||
background: rgba(var(--v-theme-on-surface), 0.08);
|
||||
block-size: 100%;
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ function goArtistDetail() {
|
||||
<div style="padding-block-end: 150%">
|
||||
<div class="absolute inset-0 flex h-full w-full flex-col items-center p-2">
|
||||
<div class="relative mt-2 mb-4 flex h-1/2 w-full justify-center">
|
||||
<VAvatar size="100" color="surface-variant">
|
||||
<VAvatar size="100" class="music-artist-card-avatar">
|
||||
<VImg v-if="showImage" :src="imageUrl" cover @error="imageLoadError = true" />
|
||||
<VIcon v-else icon="mdi-account-music" size="48" color="medium-emphasis" />
|
||||
</VAvatar>
|
||||
@@ -60,6 +60,10 @@ function goArtistDetail() {
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
.music-artist-card-avatar {
|
||||
background: rgba(var(--v-theme-on-surface), 0.08);
|
||||
}
|
||||
|
||||
.music-artist-card {
|
||||
background-image: linear-gradient(45deg, rgba(var(--v-theme-background), 0.3), rgba(var(--v-theme-surface), 0.3) 60%);
|
||||
}
|
||||
|
||||
@@ -540,9 +540,10 @@ function handleCardClick() {
|
||||
<template #image v-if="display.smAndUp.value">
|
||||
<div
|
||||
v-if="showPlaceholder"
|
||||
class="subscribe-card-placeholder d-flex align-center justify-center"
|
||||
class="subscribe-card-placeholder d-flex align-center justify-center relative"
|
||||
>
|
||||
<VIcon :icon="placeholderIcon" size="64" color="medium-emphasis" />
|
||||
<div class="absolute inset-0 outline-none subscribe-card-background"></div>
|
||||
</div>
|
||||
<VImg
|
||||
v-else
|
||||
@@ -568,9 +569,10 @@ function handleCardClick() {
|
||||
<div class="subscribe-card-mobile-media">
|
||||
<div
|
||||
v-if="showPlaceholder"
|
||||
class="subscribe-card-placeholder d-flex align-center justify-center"
|
||||
class="subscribe-card-placeholder d-flex align-center justify-center relative"
|
||||
>
|
||||
<VIcon :icon="placeholderIcon" size="64" color="medium-emphasis" />
|
||||
<div class="absolute inset-0 outline-none subscribe-card-background"></div>
|
||||
</div>
|
||||
<VImg
|
||||
v-else
|
||||
@@ -697,7 +699,7 @@ function handleCardClick() {
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
<VCardText class="flex min-w-0 justify-space-between align-center flex-wrap px-3">
|
||||
<VCardText class="flex min-w-0 justify-space-between align-center flex-wrap px-3 mt-auto">
|
||||
<div class="flex min-w-0 max-w-full align-center">
|
||||
<VIcon
|
||||
v-if="props.media?.total_episode && props.sortable"
|
||||
@@ -976,7 +978,7 @@ function handleCardClick() {
|
||||
.subscribe-card-placeholder {
|
||||
block-size: 100%;
|
||||
inline-size: 100%;
|
||||
background: rgb(var(--v-theme-surface-variant));
|
||||
background: rgba(var(--v-theme-on-surface), 0.08);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ import { formatFileSize } from '@/@core/utils/formatters'
|
||||
import { VCardTitle, VChip } from 'vuetify/lib/components/index.mjs'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import MediaIdSelector from '../misc/MediaIdSelector.vue'
|
||||
import { numberValidator } from '@/@validators'
|
||||
import { isValidMediaSourceId } from '@/utils/mediaId'
|
||||
import { useGlobalSettingsStore } from '@/stores'
|
||||
|
||||
// 多语言支持
|
||||
@@ -25,19 +25,25 @@ const globalSettingsStore = useGlobalSettingsStore()
|
||||
const globalSettings = globalSettingsStore.globalSettings
|
||||
|
||||
// 当前识别类型
|
||||
const mediaSource = ref<MediaDataSource>(
|
||||
['themoviedb', 'douban', 'bangumi', 'anilist'].includes(globalSettings.RECOGNIZE_SOURCE)
|
||||
? globalSettings.RECOGNIZE_SOURCE
|
||||
: 'themoviedb',
|
||||
)
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
media: Object as PropType<MediaInfo>,
|
||||
torrent: Object as PropType<TorrentInfo>,
|
||||
})
|
||||
|
||||
// 可选的媒体数据源
|
||||
const SUPPORTED_MEDIA_SOURCES: MediaDataSource[] = ['themoviedb', 'douban', 'bangumi', 'anilist', 'musicbrainz']
|
||||
|
||||
// 当前识别类型:优先使用媒体自身的数据源,否则使用全局识别来源
|
||||
const mediaSource = computed<MediaDataSource>(() => {
|
||||
const source = props.media?.source as MediaDataSource | undefined
|
||||
if (source && SUPPORTED_MEDIA_SOURCES.includes(source)) return source
|
||||
if (SUPPORTED_MEDIA_SOURCES.includes(globalSettings.RECOGNIZE_SOURCE as MediaDataSource)) {
|
||||
return globalSettings.RECOGNIZE_SOURCE as MediaDataSource
|
||||
}
|
||||
return 'themoviedb'
|
||||
})
|
||||
|
||||
// 定义成功和失败事件
|
||||
const emit = defineEmits(['done', 'error', 'close'])
|
||||
|
||||
@@ -65,6 +71,17 @@ const showAdvancedOptions = ref(false)
|
||||
// 当前数据源的原生媒体ID
|
||||
const mediaId = ref<string | undefined>(undefined)
|
||||
|
||||
// 音乐媒体自带 MusicBrainz ID,打开对话框时预填到高级选项中辅助识别
|
||||
watch(
|
||||
() => props.media,
|
||||
media => {
|
||||
if (media && media.source === 'musicbrainz' && media.media_id) {
|
||||
mediaId.value = media.media_id
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// 当前数据源对应的原生ID标签。
|
||||
const mediaIdLabel = computed(() => {
|
||||
const labels: Record<MediaDataSource, string> = {
|
||||
@@ -302,7 +319,7 @@ onMounted(() => {
|
||||
v-model="mediaId"
|
||||
:label="mediaIdLabel"
|
||||
:placeholder="t('dialog.reorganize.mediaIdPlaceholder')"
|
||||
:rules="[numberValidator]"
|
||||
:rules="[(value: any) => isValidMediaSourceId(value, mediaSource.value) || t('dialog.reorganize.mediaIdInvalid')]"
|
||||
append-inner-icon="mdi-magnify"
|
||||
:hint="t('dialog.reorganize.mediaIdHint')"
|
||||
persistent-hint
|
||||
|
||||
@@ -98,18 +98,17 @@ watch(
|
||||
<style lang="scss" scoped>
|
||||
.vue-music-back {
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(180deg, rgba(var(--v-theme-background), 0) 50%, rgba(var(--v-theme-background), 1) 100%),
|
||||
linear-gradient(0deg, rgba(var(--v-theme-background), 0) 80%, rgba(var(--v-theme-background), 1) 100%),
|
||||
linear-gradient(90deg, rgba(var(--v-theme-background), 0) 50%, rgba(var(--v-theme-background), 1) 100%),
|
||||
linear-gradient(270deg, rgba(var(--v-theme-background), 0) 50%, rgba(var(--v-theme-background), 1) 100%);
|
||||
margin-block-start: calc(-70px - env(safe-area-inset-top));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.vue-music-back-image {
|
||||
background-image: none;
|
||||
filter: blur(2px);
|
||||
}
|
||||
|
||||
.music-detail-transparent .vue-music-back-overlay,
|
||||
@@ -119,10 +118,10 @@ watch(
|
||||
|
||||
.music-detail-transparent .vue-music-back-image,
|
||||
.music-detail-glass .vue-music-back-image {
|
||||
mask-composite: intersect;
|
||||
mask-image:
|
||||
linear-gradient(to bottom, transparent 0%, #000 16%, #000 58%, transparent 100%),
|
||||
linear-gradient(to right, transparent 0%, #000 10%, #000 90%, transparent 100%);
|
||||
mask-composite: intersect;
|
||||
opacity: 0.82;
|
||||
}
|
||||
|
||||
@@ -144,9 +143,9 @@ watch(
|
||||
|
||||
.music-poster {
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto;
|
||||
border-radius: var(--app-surface-radius);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 10%);
|
||||
flex: 0 0 auto;
|
||||
inline-size: 9rem;
|
||||
}
|
||||
|
||||
@@ -156,7 +155,7 @@ watch(
|
||||
|
||||
.music-poster-placeholder {
|
||||
aspect-ratio: 1;
|
||||
background: rgb(var(--v-theme-surface-variant));
|
||||
background: rgba(var(--v-theme-on-surface), 0.08);
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
@@ -164,8 +163,8 @@ watch(
|
||||
display: flex;
|
||||
flex: 1 1 0%;
|
||||
flex-direction: column;
|
||||
min-inline-size: 0;
|
||||
margin-block-start: 1rem;
|
||||
min-inline-size: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -193,10 +192,10 @@ watch(
|
||||
|
||||
.music-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-shrink: 0;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,12 +232,12 @@ watch(() => [props.source, props.mediaid], loadMusicDetail, { immediate: true })
|
||||
<span class="ms-1">MusicBrainz</span>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="albumTracks.length" class="music-section">
|
||||
<h2 class="music-section-heading">{{ t('music.albumTracks') }}</h2>
|
||||
<MusicTrackList :tracks="albumTracks" :active-media-id="music.media_id" hide-artists />
|
||||
</div>
|
||||
<div v-if="albumTracks.length" class="music-section">
|
||||
<h2 class="music-section-heading">{{ t('music.albumTracks') }}</h2>
|
||||
<MusicTrackList :tracks="albumTracks" :active-media-id="music.media_id" hide-artists />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="primaryArtistId" class="music-section">
|
||||
<MusicArtistSlideView :apipath="`music/artist/${primaryArtistId}/related`" :title="t('music.relatedArtists')" />
|
||||
|
||||
@@ -2072,7 +2072,7 @@ onUnmounted(() => {
|
||||
justify-content: center;
|
||||
inline-size: 100%;
|
||||
block-size: 100%;
|
||||
background: rgb(var(--v-theme-surface-variant));
|
||||
background: rgba(var(--v-theme-on-surface), 0.08);
|
||||
}
|
||||
|
||||
.transfer-history-mobile-record__poster-type {
|
||||
|
||||
Reference in New Issue
Block a user