feat: 更新多个组件的背景样式为透明度背景

This commit is contained in:
jxxghp
2026-08-09 12:35:09 +08:00
parent 4b70b98ffc
commit f080da1ebb
7 changed files with 51 additions and 29 deletions

View File

@@ -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%;
}

View File

@@ -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%);
}

View File

@@ -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);
}
/**

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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')" />

View File

@@ -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 {